From bf343f6274a7fe65b0e9b45a115d50b272c61af3 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:23:51 +0700 Subject: [PATCH 01/76] chore: forked pallet nfts --- pallets/nfts/src/benchmarking.rs | 2 +- pallets/nfts/src/common_functions.rs | 4 +- pallets/nfts/src/features/approvals.rs | 3 +- pallets/nfts/src/features/atomic_swap.rs | 4 +- pallets/nfts/src/features/attributes.rs | 3 +- pallets/nfts/src/features/buy_sell.rs | 3 +- .../src/features/create_delete_collection.rs | 3 +- .../nfts/src/features/create_delete_item.rs | 3 +- pallets/nfts/src/features/lock.rs | 4 +- pallets/nfts/src/features/metadata.rs | 4 +- pallets/nfts/src/features/roles.rs | 4 +- pallets/nfts/src/features/settings.rs | 3 +- pallets/nfts/src/features/transfer.rs | 4 +- pallets/nfts/src/impl_nonfungibles.rs | 9 ++-- pallets/nfts/src/lib.rs | 10 ++-- pallets/nfts/src/migration.rs | 4 +- pallets/nfts/src/mock.rs | 48 +++++++++---------- pallets/nfts/src/tests.rs | 3 +- pallets/nfts/src/types.rs | 24 +--------- 19 files changed, 49 insertions(+), 93 deletions(-) diff --git a/pallets/nfts/src/benchmarking.rs b/pallets/nfts/src/benchmarking.rs index 8fa87557c..bc81096b4 100644 --- a/pallets/nfts/src/benchmarking.rs +++ b/pallets/nfts/src/benchmarking.rs @@ -19,6 +19,7 @@ #![cfg(feature = "runtime-benchmarks")] +use super::*; use enumflags2::{BitFlag, BitFlags}; use frame_benchmarking::v1::{ account, benchmarks_instance_pallet, whitelist_account, whitelisted_caller, BenchmarkError, @@ -31,7 +32,6 @@ use frame_support::{ use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin as SystemOrigin}; use sp_runtime::traits::{Bounded, One}; -use super::*; use crate::Pallet as Nfts; const SEED: u32 = 0; diff --git a/pallets/nfts/src/common_functions.rs b/pallets/nfts/src/common_functions.rs index f51de1922..2c4778c14 100644 --- a/pallets/nfts/src/common_functions.rs +++ b/pallets/nfts/src/common_functions.rs @@ -17,12 +17,10 @@ //! Various pieces of common functionality. +use crate::*; use alloc::vec::Vec; - use frame_support::pallet_prelude::*; -use crate::*; - impl, I: 'static> Pallet { /// Get the owner of the item, if the item exists. pub fn owner(collection: T::CollectionId, item: T::ItemId) -> Option { diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index ad5d93c2e..053fa6716 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -19,9 +19,8 @@ //! The bitflag [`PalletFeature::Approvals`] needs to be set in [`Config::Features`] for NFTs //! to have the functionality defined in this module. -use frame_support::pallet_prelude::*; - use crate::*; +use frame_support::pallet_prelude::*; impl, I: 'static> Pallet { /// Approves the transfer of an item to a delegate. diff --git a/pallets/nfts/src/features/atomic_swap.rs b/pallets/nfts/src/features/atomic_swap.rs index 31c93fba8..830283b73 100644 --- a/pallets/nfts/src/features/atomic_swap.rs +++ b/pallets/nfts/src/features/atomic_swap.rs @@ -20,13 +20,12 @@ //! The bitflag [`PalletFeature::Swaps`] needs to be set in [`Config::Features`] for NFTs //! to have the functionality defined in this module. +use crate::*; use frame_support::{ pallet_prelude::*, traits::{Currency, ExistenceRequirement::KeepAlive}, }; -use crate::*; - impl, I: 'static> Pallet { /// Creates a new swap offer for the specified item. /// @@ -102,7 +101,6 @@ impl, I: 'static> Pallet { Ok(()) } - /// Cancels the specified swap offer. /// /// This function is used to cancel the specified swap offer created by the `caller` account. If diff --git a/pallets/nfts/src/features/attributes.rs b/pallets/nfts/src/features/attributes.rs index ab0cdc68b..28f7bd2c5 100644 --- a/pallets/nfts/src/features/attributes.rs +++ b/pallets/nfts/src/features/attributes.rs @@ -20,9 +20,8 @@ //! The bitflag [`PalletFeature::Attributes`] needs to be set in [`Config::Features`] for NFTs //! to have the functionality defined in this module. -use frame_support::pallet_prelude::*; - use crate::*; +use frame_support::pallet_prelude::*; impl, I: 'static> Pallet { /// Sets the attribute of an item or a collection. diff --git a/pallets/nfts/src/features/buy_sell.rs b/pallets/nfts/src/features/buy_sell.rs index 8cf86f79a..d6ec6f50d 100644 --- a/pallets/nfts/src/features/buy_sell.rs +++ b/pallets/nfts/src/features/buy_sell.rs @@ -20,13 +20,12 @@ //! The bitflag [`PalletFeature::Trading`] needs to be set in the [`Config::Features`] for NFTs //! to have the functionality defined in this module. +use crate::*; use frame_support::{ pallet_prelude::*, traits::{Currency, ExistenceRequirement, ExistenceRequirement::KeepAlive}, }; -use crate::*; - impl, I: 'static> Pallet { /// Pays the specified tips to the corresponding receivers. /// diff --git a/pallets/nfts/src/features/create_delete_collection.rs b/pallets/nfts/src/features/create_delete_collection.rs index 348ec6b92..f03df7fdd 100644 --- a/pallets/nfts/src/features/create_delete_collection.rs +++ b/pallets/nfts/src/features/create_delete_collection.rs @@ -18,9 +18,8 @@ //! This module contains helper methods to perform functionality associated with creating and //! destroying collections for the NFTs pallet. -use frame_support::pallet_prelude::*; - use crate::*; +use frame_support::pallet_prelude::*; impl, I: 'static> Pallet { /// Create a new collection with the given `collection`, `owner`, `admin`, `config`, `deposit`, diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index e9843b2e7..37f64ae1b 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -18,9 +18,8 @@ //! This module contains helper methods to perform functionality associated with minting and burning //! items for the NFTs pallet. -use frame_support::{pallet_prelude::*, traits::ExistenceRequirement}; - use crate::*; +use frame_support::{pallet_prelude::*, traits::ExistenceRequirement}; impl, I: 'static> Pallet { /// Mint a new unique item with the given `collection`, `item`, and other minting configuration diff --git a/pallets/nfts/src/features/lock.rs b/pallets/nfts/src/features/lock.rs index 4649f4a01..1c3c9c867 100644 --- a/pallets/nfts/src/features/lock.rs +++ b/pallets/nfts/src/features/lock.rs @@ -18,9 +18,8 @@ //! This module contains helper methods to configure locks on collections and items for the NFTs //! pallet. -use frame_support::pallet_prelude::*; - use crate::*; +use frame_support::pallet_prelude::*; impl, I: 'static> Pallet { /// Locks a collection with specified settings. @@ -30,6 +29,7 @@ impl, I: 'static> Pallet { /// /// Note: it's possible only to lock the setting, but not to unlock it after. + /// /// - `origin`: The origin of the transaction, representing the account attempting to lock the /// collection. /// - `collection`: The identifier of the collection to be locked. diff --git a/pallets/nfts/src/features/metadata.rs b/pallets/nfts/src/features/metadata.rs index b3d16b12c..260061603 100644 --- a/pallets/nfts/src/features/metadata.rs +++ b/pallets/nfts/src/features/metadata.rs @@ -17,12 +17,10 @@ //! This module contains helper methods to configure the metadata of collections and items. +use crate::*; use alloc::vec::Vec; - use frame_support::pallet_prelude::*; -use crate::*; - impl, I: 'static> Pallet { /// Sets the metadata for a specific item within a collection. /// diff --git a/pallets/nfts/src/features/roles.rs b/pallets/nfts/src/features/roles.rs index 053eaf0b0..aa6394f70 100644 --- a/pallets/nfts/src/features/roles.rs +++ b/pallets/nfts/src/features/roles.rs @@ -17,12 +17,10 @@ //! This module contains helper methods to configure account roles for existing collections. +use crate::*; use alloc::{collections::btree_map::BTreeMap, vec::Vec}; - use frame_support::pallet_prelude::*; -use crate::*; - impl, I: 'static> Pallet { /// Set the team roles for a specific collection. /// diff --git a/pallets/nfts/src/features/settings.rs b/pallets/nfts/src/features/settings.rs index 9c7ac7ca2..d4f7533ff 100644 --- a/pallets/nfts/src/features/settings.rs +++ b/pallets/nfts/src/features/settings.rs @@ -17,9 +17,8 @@ //! This module provides helper methods to configure collection settings for the NFTs pallet. -use frame_support::pallet_prelude::*; - use crate::*; +use frame_support::pallet_prelude::*; impl, I: 'static> Pallet { /// Forcefully change the configuration of a collection. diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index b7223a7c3..bba834483 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -18,9 +18,8 @@ //! This module contains helper methods to perform the transfer functionalities //! of the NFTs pallet. -use frame_support::pallet_prelude::*; - use crate::*; +use frame_support::pallet_prelude::*; impl, I: 'static> Pallet { /// Transfer an NFT to the specified destination account. @@ -161,7 +160,6 @@ impl, I: 'static> Pallet { Ok(()) }) } - /// Set or unset the ownership acceptance for an account regarding a specific collection. /// /// - `who`: The account for which to set or unset the ownership acceptance. diff --git a/pallets/nfts/src/impl_nonfungibles.rs b/pallets/nfts/src/impl_nonfungibles.rs index 362cccd93..c90655aad 100644 --- a/pallets/nfts/src/impl_nonfungibles.rs +++ b/pallets/nfts/src/impl_nonfungibles.rs @@ -17,6 +17,7 @@ //! Implementations for `nonfungibles` traits. +use super::*; use frame_support::{ ensure, storage::KeyPrefixIterator, @@ -25,11 +26,9 @@ use frame_support::{ }; use sp_runtime::{DispatchError, DispatchResult}; -use super::*; - impl, I: 'static> Inspect<::AccountId> for Pallet { - type CollectionId = T::CollectionId; type ItemId = T::ItemId; + type CollectionId = T::CollectionId; fn owner( collection: &Self::CollectionId, @@ -141,11 +140,9 @@ impl, I: 'static> InspectRole<::AccountId> for P fn is_issuer(collection: &Self::CollectionId, who: &::AccountId) -> bool { Self::has_role(collection, who, CollectionRole::Issuer) } - fn is_admin(collection: &Self::CollectionId, who: &::AccountId) -> bool { Self::has_role(collection, who, CollectionRole::Admin) } - fn is_freezer(collection: &Self::CollectionId, who: &::AccountId) -> bool { Self::has_role(collection, who, CollectionRole::Freezer) } @@ -472,9 +469,9 @@ impl, I: 'static> Trading> for Pallet impl, I: 'static> InspectEnumerable for Pallet { type CollectionsIterator = KeyPrefixIterator<>::CollectionId>; type ItemsIterator = KeyPrefixIterator<>::ItemId>; - type OwnedInCollectionIterator = KeyPrefixIterator<>::ItemId>; type OwnedIterator = KeyPrefixIterator<(>::CollectionId, >::ItemId)>; + type OwnedInCollectionIterator = KeyPrefixIterator<>::ItemId>; /// Returns an iterator of the collections in existence. /// diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index 89bfb9637..4e5493a3c 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -51,18 +51,18 @@ pub mod weights; extern crate alloc; use alloc::{boxed::Box, vec, vec::Vec}; - use codec::{Decode, Encode}; use frame_support::traits::{ tokens::Locker, BalanceStatus::Reserved, Currency, EnsureOriginWithArg, Incrementable, ReservableCurrency, }; use frame_system::Config as SystemConfig; -pub use pallet::*; use sp_runtime::{ traits::{IdentifyAccount, Saturating, StaticLookup, Verify, Zero}, RuntimeDebug, }; + +pub use pallet::*; pub use types::*; pub use weights::WeightInfo; @@ -74,11 +74,10 @@ type AccountIdLookupOf = <::Lookup as StaticLookup>::Sourc #[frame_support::pallet] pub mod pallet { + use super::*; use frame_support::{pallet_prelude::*, traits::ExistenceRequirement}; use frame_system::pallet_prelude::*; - use super::*; - /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); @@ -109,17 +108,14 @@ pub mod pallet { fn collection(i: u16) -> CollectionId { i.into() } - fn item(i: u16) -> ItemId { i.into() } - fn signer() -> (sp_runtime::MultiSigner, sp_runtime::AccountId32) { let public = sp_io::crypto::sr25519_generate(0.into(), None); let account = sp_runtime::MultiSigner::Sr25519(public).into_account(); (public.into(), account) } - fn sign(signer: &sp_runtime::MultiSigner, message: &[u8]) -> sp_runtime::MultiSignature { sp_runtime::MultiSignature::Sr25519( sp_io::crypto::sr25519_sign(0.into(), &signer.clone().try_into().unwrap(), message) diff --git a/pallets/nfts/src/migration.rs b/pallets/nfts/src/migration.rs index af611bf16..8f82e0922 100644 --- a/pallets/nfts/src/migration.rs +++ b/pallets/nfts/src/migration.rs @@ -15,13 +15,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +use super::*; use frame_support::traits::OnRuntimeUpgrade; use log; + #[cfg(feature = "try-runtime")] use sp_runtime::TryRuntimeError; -use super::*; - pub mod v1 { use frame_support::{pallet_prelude::*, weights::Weight}; diff --git a/pallets/nfts/src/mock.rs b/pallets/nfts/src/mock.rs index 5532be8f4..5b589f591 100644 --- a/pallets/nfts/src/mock.rs +++ b/pallets/nfts/src/mock.rs @@ -17,6 +17,9 @@ //! Test environment for Nfts pallet. +use super::*; +use crate as pallet_nfts; + use frame_support::{ construct_runtime, derive_impl, parameter_types, traits::{AsEnsureOriginWithArg, ConstU32, ConstU64}, @@ -27,9 +30,6 @@ use sp_runtime::{ BuildStorage, MultiSignature, }; -use super::*; -use crate as pallet_nfts; - type Block = frame_system::mocking::MockBlock; construct_runtime!( @@ -47,10 +47,10 @@ pub type AccountId = ::AccountId; #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { - type AccountData = pallet_balances::AccountData; type AccountId = AccountId; - type Block = Block; type Lookup = IdentityLookup; + type Block = Block; + type AccountData = pallet_balances::AccountData; } #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] @@ -63,35 +63,35 @@ parameter_types! { } impl Config for Test { - type ApprovalsLimit = ConstU32<10>; - type AttributeDepositBase = ConstU64<1>; - type CollectionDeposit = ConstU64<2>; + type RuntimeEvent = RuntimeEvent; type CollectionId = u32; - type CreateOrigin = AsEnsureOriginWithArg>; + type ItemId = u32; type Currency = Balances; - type DepositPerByte = ConstU64<1>; - type Features = Features; + type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = frame_system::EnsureRoot; - #[cfg(feature = "runtime-benchmarks")] - type Helper = (); - type ItemAttributesApprovalsLimit = ConstU32<2>; + type Locker = (); + type CollectionDeposit = ConstU64<2>; type ItemDeposit = ConstU64<1>; - type ItemId = u32; + type MetadataDepositBase = ConstU64<1>; + type AttributeDepositBase = ConstU64<1>; + type DepositPerByte = ConstU64<1>; + type StringLimit = ConstU32<50>; type KeyLimit = ConstU32<50>; - type Locker = (); - type MaxAttributesPerCall = ConstU32<2>; - type MaxDeadlineDuration = ConstU64<10000>; + type ValueLimit = ConstU32<50>; + type ApprovalsLimit = ConstU32<10>; + type ItemAttributesApprovalsLimit = ConstU32<2>; type MaxTips = ConstU32<10>; - type MetadataDepositBase = ConstU64<1>; - /// Using `AccountPublic` here makes it trivial to convert to `AccountId` via `into_account()`. - type OffchainPublic = AccountPublic; + type MaxDeadlineDuration = ConstU64<10000>; + type MaxAttributesPerCall = ConstU32<2>; + type Features = Features; /// Off-chain = signature On-chain - therefore no conversion needed. /// It needs to be From for benchmarking. type OffchainSignature = Signature; - type RuntimeEvent = RuntimeEvent; - type StringLimit = ConstU32<50>; - type ValueLimit = ConstU32<50>; + /// Using `AccountPublic` here makes it trivial to convert to `AccountId` via `into_account()`. + type OffchainPublic = AccountPublic; type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); } pub(crate) fn new_test_ext() -> sp_io::TestExternalities { diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 44f2f32ae..e1b598ca4 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -17,6 +17,7 @@ //! Tests for Nfts pallet. +use crate::{mock::*, Event, SystemConfig, *}; use enumflags2::BitFlags; use frame_support::{ assert_noop, assert_ok, @@ -32,8 +33,6 @@ use sp_runtime::{ MultiSignature, MultiSigner, }; -use crate::{mock::*, Event, SystemConfig, *}; - type AccountIdOf = ::AccountId; fn account(id: u8) -> AccountIdOf { diff --git a/pallets/nfts/src/types.rs b/pallets/nfts/src/types.rs index f08f1d097..1687a0352 100644 --- a/pallets/nfts/src/types.rs +++ b/pallets/nfts/src/types.rs @@ -17,8 +17,9 @@ //! This module contains various basic types and data structures used in the NFTs pallet. +use super::*; +use crate::macros::*; use alloc::{vec, vec::Vec}; - use codec::EncodeLike; use enumflags2::{bitflags, BitFlags}; use frame_support::{ @@ -29,9 +30,6 @@ use frame_support::{ use frame_system::pallet_prelude::BlockNumberFor; use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter}; -use super::*; -use crate::macros::*; - /// A type alias for handling balance deposits. pub(super) type DepositBalanceOf = <>::Currency as Currency<::AccountId>>::Balance; @@ -278,15 +276,12 @@ impl CollectionSettings { pub fn all_enabled() -> Self { Self(BitFlags::EMPTY) } - pub fn get_disabled(&self) -> BitFlags { self.0 } - pub fn is_disabled(&self, setting: CollectionSetting) -> bool { self.0.contains(setting) } - pub fn from_disabled(settings: BitFlags) -> Self { Self(settings) } @@ -382,15 +377,12 @@ impl CollectionConfig bool { !self.settings.is_disabled(setting) } - pub fn has_disabled_setting(&self, setting: CollectionSetting) -> bool { self.settings.is_disabled(setting) } - pub fn enable_setting(&mut self, setting: CollectionSetting) { self.settings.0.remove(setting); } - pub fn disable_setting(&mut self, setting: CollectionSetting) { self.settings.0.insert(setting); } @@ -417,15 +409,12 @@ impl ItemSettings { pub fn all_enabled() -> Self { Self(BitFlags::EMPTY) } - pub fn get_disabled(&self) -> BitFlags { self.0 } - pub fn is_disabled(&self, setting: ItemSetting) -> bool { self.0.contains(setting) } - pub fn from_disabled(settings: BitFlags) -> Self { Self(settings) } @@ -446,19 +435,15 @@ impl ItemConfig { pub fn is_setting_enabled(&self, setting: ItemSetting) -> bool { !self.settings.is_disabled(setting) } - pub fn has_disabled_setting(&self, setting: ItemSetting) -> bool { self.settings.is_disabled(setting) } - pub fn has_disabled_settings(&self) -> bool { !self.settings.get_disabled().is_empty() } - pub fn enable_setting(&mut self, setting: ItemSetting) { self.settings.0.remove(setting); } - pub fn disable_setting(&mut self, setting: ItemSetting) { self.settings.0.insert(setting); } @@ -487,11 +472,9 @@ impl PalletFeatures { pub fn all_enabled() -> Self { Self(BitFlags::EMPTY) } - pub fn from_disabled(features: BitFlags) -> Self { Self(features) } - pub fn is_enabled(&self, feature: PalletFeature) -> bool { !self.0.contains(feature) } @@ -519,15 +502,12 @@ impl CollectionRoles { pub fn none() -> Self { Self(BitFlags::EMPTY) } - pub fn has_role(&self, role: CollectionRole) -> bool { self.0.contains(role) } - pub fn add_role(&mut self, role: CollectionRole) { self.0.insert(role); } - pub fn max_roles() -> u8 { let all: BitFlags = BitFlags::all(); all.len() as u8 From 958b9e8d827131ab13565bcf1172a6575f0fe008 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:24:10 +0700 Subject: [PATCH 02/76] fix: formatting --- pallets/nfts/src/benchmarking.rs | 2 +- pallets/nfts/src/common_functions.rs | 4 +- pallets/nfts/src/features/approvals.rs | 3 +- pallets/nfts/src/features/atomic_swap.rs | 4 +- pallets/nfts/src/features/attributes.rs | 3 +- pallets/nfts/src/features/buy_sell.rs | 3 +- .../src/features/create_delete_collection.rs | 3 +- .../nfts/src/features/create_delete_item.rs | 3 +- pallets/nfts/src/features/lock.rs | 4 +- pallets/nfts/src/features/metadata.rs | 4 +- pallets/nfts/src/features/roles.rs | 4 +- pallets/nfts/src/features/settings.rs | 3 +- pallets/nfts/src/features/transfer.rs | 4 +- pallets/nfts/src/impl_nonfungibles.rs | 9 ++-- pallets/nfts/src/lib.rs | 10 ++-- pallets/nfts/src/migration.rs | 4 +- pallets/nfts/src/mock.rs | 48 +++++++++---------- pallets/nfts/src/tests.rs | 3 +- pallets/nfts/src/types.rs | 24 +++++++++- 19 files changed, 93 insertions(+), 49 deletions(-) diff --git a/pallets/nfts/src/benchmarking.rs b/pallets/nfts/src/benchmarking.rs index bc81096b4..8fa87557c 100644 --- a/pallets/nfts/src/benchmarking.rs +++ b/pallets/nfts/src/benchmarking.rs @@ -19,7 +19,6 @@ #![cfg(feature = "runtime-benchmarks")] -use super::*; use enumflags2::{BitFlag, BitFlags}; use frame_benchmarking::v1::{ account, benchmarks_instance_pallet, whitelist_account, whitelisted_caller, BenchmarkError, @@ -32,6 +31,7 @@ use frame_support::{ use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin as SystemOrigin}; use sp_runtime::traits::{Bounded, One}; +use super::*; use crate::Pallet as Nfts; const SEED: u32 = 0; diff --git a/pallets/nfts/src/common_functions.rs b/pallets/nfts/src/common_functions.rs index 2c4778c14..f51de1922 100644 --- a/pallets/nfts/src/common_functions.rs +++ b/pallets/nfts/src/common_functions.rs @@ -17,10 +17,12 @@ //! Various pieces of common functionality. -use crate::*; use alloc::vec::Vec; + use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Get the owner of the item, if the item exists. pub fn owner(collection: T::CollectionId, item: T::ItemId) -> Option { diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index 053fa6716..ad5d93c2e 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -19,9 +19,10 @@ //! The bitflag [`PalletFeature::Approvals`] needs to be set in [`Config::Features`] for NFTs //! to have the functionality defined in this module. -use crate::*; use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Approves the transfer of an item to a delegate. /// diff --git a/pallets/nfts/src/features/atomic_swap.rs b/pallets/nfts/src/features/atomic_swap.rs index 830283b73..31c93fba8 100644 --- a/pallets/nfts/src/features/atomic_swap.rs +++ b/pallets/nfts/src/features/atomic_swap.rs @@ -20,12 +20,13 @@ //! The bitflag [`PalletFeature::Swaps`] needs to be set in [`Config::Features`] for NFTs //! to have the functionality defined in this module. -use crate::*; use frame_support::{ pallet_prelude::*, traits::{Currency, ExistenceRequirement::KeepAlive}, }; +use crate::*; + impl, I: 'static> Pallet { /// Creates a new swap offer for the specified item. /// @@ -101,6 +102,7 @@ impl, I: 'static> Pallet { Ok(()) } + /// Cancels the specified swap offer. /// /// This function is used to cancel the specified swap offer created by the `caller` account. If diff --git a/pallets/nfts/src/features/attributes.rs b/pallets/nfts/src/features/attributes.rs index 28f7bd2c5..ab0cdc68b 100644 --- a/pallets/nfts/src/features/attributes.rs +++ b/pallets/nfts/src/features/attributes.rs @@ -20,9 +20,10 @@ //! The bitflag [`PalletFeature::Attributes`] needs to be set in [`Config::Features`] for NFTs //! to have the functionality defined in this module. -use crate::*; use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Sets the attribute of an item or a collection. /// diff --git a/pallets/nfts/src/features/buy_sell.rs b/pallets/nfts/src/features/buy_sell.rs index d6ec6f50d..8cf86f79a 100644 --- a/pallets/nfts/src/features/buy_sell.rs +++ b/pallets/nfts/src/features/buy_sell.rs @@ -20,12 +20,13 @@ //! The bitflag [`PalletFeature::Trading`] needs to be set in the [`Config::Features`] for NFTs //! to have the functionality defined in this module. -use crate::*; use frame_support::{ pallet_prelude::*, traits::{Currency, ExistenceRequirement, ExistenceRequirement::KeepAlive}, }; +use crate::*; + impl, I: 'static> Pallet { /// Pays the specified tips to the corresponding receivers. /// diff --git a/pallets/nfts/src/features/create_delete_collection.rs b/pallets/nfts/src/features/create_delete_collection.rs index f03df7fdd..348ec6b92 100644 --- a/pallets/nfts/src/features/create_delete_collection.rs +++ b/pallets/nfts/src/features/create_delete_collection.rs @@ -18,9 +18,10 @@ //! This module contains helper methods to perform functionality associated with creating and //! destroying collections for the NFTs pallet. -use crate::*; use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Create a new collection with the given `collection`, `owner`, `admin`, `config`, `deposit`, /// and `event`. diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index 37f64ae1b..e9843b2e7 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -18,9 +18,10 @@ //! This module contains helper methods to perform functionality associated with minting and burning //! items for the NFTs pallet. -use crate::*; use frame_support::{pallet_prelude::*, traits::ExistenceRequirement}; +use crate::*; + impl, I: 'static> Pallet { /// Mint a new unique item with the given `collection`, `item`, and other minting configuration /// details. diff --git a/pallets/nfts/src/features/lock.rs b/pallets/nfts/src/features/lock.rs index 1c3c9c867..4649f4a01 100644 --- a/pallets/nfts/src/features/lock.rs +++ b/pallets/nfts/src/features/lock.rs @@ -18,9 +18,10 @@ //! This module contains helper methods to configure locks on collections and items for the NFTs //! pallet. -use crate::*; use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Locks a collection with specified settings. /// @@ -29,7 +30,6 @@ impl, I: 'static> Pallet { /// /// Note: it's possible only to lock the setting, but not to unlock it after. - /// /// - `origin`: The origin of the transaction, representing the account attempting to lock the /// collection. /// - `collection`: The identifier of the collection to be locked. diff --git a/pallets/nfts/src/features/metadata.rs b/pallets/nfts/src/features/metadata.rs index 260061603..b3d16b12c 100644 --- a/pallets/nfts/src/features/metadata.rs +++ b/pallets/nfts/src/features/metadata.rs @@ -17,10 +17,12 @@ //! This module contains helper methods to configure the metadata of collections and items. -use crate::*; use alloc::vec::Vec; + use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Sets the metadata for a specific item within a collection. /// diff --git a/pallets/nfts/src/features/roles.rs b/pallets/nfts/src/features/roles.rs index aa6394f70..053eaf0b0 100644 --- a/pallets/nfts/src/features/roles.rs +++ b/pallets/nfts/src/features/roles.rs @@ -17,10 +17,12 @@ //! This module contains helper methods to configure account roles for existing collections. -use crate::*; use alloc::{collections::btree_map::BTreeMap, vec::Vec}; + use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Set the team roles for a specific collection. /// diff --git a/pallets/nfts/src/features/settings.rs b/pallets/nfts/src/features/settings.rs index d4f7533ff..9c7ac7ca2 100644 --- a/pallets/nfts/src/features/settings.rs +++ b/pallets/nfts/src/features/settings.rs @@ -17,9 +17,10 @@ //! This module provides helper methods to configure collection settings for the NFTs pallet. -use crate::*; use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Forcefully change the configuration of a collection. /// diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index bba834483..b7223a7c3 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -18,9 +18,10 @@ //! This module contains helper methods to perform the transfer functionalities //! of the NFTs pallet. -use crate::*; use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Transfer an NFT to the specified destination account. /// @@ -160,6 +161,7 @@ impl, I: 'static> Pallet { Ok(()) }) } + /// Set or unset the ownership acceptance for an account regarding a specific collection. /// /// - `who`: The account for which to set or unset the ownership acceptance. diff --git a/pallets/nfts/src/impl_nonfungibles.rs b/pallets/nfts/src/impl_nonfungibles.rs index c90655aad..362cccd93 100644 --- a/pallets/nfts/src/impl_nonfungibles.rs +++ b/pallets/nfts/src/impl_nonfungibles.rs @@ -17,7 +17,6 @@ //! Implementations for `nonfungibles` traits. -use super::*; use frame_support::{ ensure, storage::KeyPrefixIterator, @@ -26,9 +25,11 @@ use frame_support::{ }; use sp_runtime::{DispatchError, DispatchResult}; +use super::*; + impl, I: 'static> Inspect<::AccountId> for Pallet { - type ItemId = T::ItemId; type CollectionId = T::CollectionId; + type ItemId = T::ItemId; fn owner( collection: &Self::CollectionId, @@ -140,9 +141,11 @@ impl, I: 'static> InspectRole<::AccountId> for P fn is_issuer(collection: &Self::CollectionId, who: &::AccountId) -> bool { Self::has_role(collection, who, CollectionRole::Issuer) } + fn is_admin(collection: &Self::CollectionId, who: &::AccountId) -> bool { Self::has_role(collection, who, CollectionRole::Admin) } + fn is_freezer(collection: &Self::CollectionId, who: &::AccountId) -> bool { Self::has_role(collection, who, CollectionRole::Freezer) } @@ -469,9 +472,9 @@ impl, I: 'static> Trading> for Pallet impl, I: 'static> InspectEnumerable for Pallet { type CollectionsIterator = KeyPrefixIterator<>::CollectionId>; type ItemsIterator = KeyPrefixIterator<>::ItemId>; + type OwnedInCollectionIterator = KeyPrefixIterator<>::ItemId>; type OwnedIterator = KeyPrefixIterator<(>::CollectionId, >::ItemId)>; - type OwnedInCollectionIterator = KeyPrefixIterator<>::ItemId>; /// Returns an iterator of the collections in existence. /// diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index 4e5493a3c..89bfb9637 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -51,18 +51,18 @@ pub mod weights; extern crate alloc; use alloc::{boxed::Box, vec, vec::Vec}; + use codec::{Decode, Encode}; use frame_support::traits::{ tokens::Locker, BalanceStatus::Reserved, Currency, EnsureOriginWithArg, Incrementable, ReservableCurrency, }; use frame_system::Config as SystemConfig; +pub use pallet::*; use sp_runtime::{ traits::{IdentifyAccount, Saturating, StaticLookup, Verify, Zero}, RuntimeDebug, }; - -pub use pallet::*; pub use types::*; pub use weights::WeightInfo; @@ -74,10 +74,11 @@ type AccountIdLookupOf = <::Lookup as StaticLookup>::Sourc #[frame_support::pallet] pub mod pallet { - use super::*; use frame_support::{pallet_prelude::*, traits::ExistenceRequirement}; use frame_system::pallet_prelude::*; + use super::*; + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); @@ -108,14 +109,17 @@ pub mod pallet { fn collection(i: u16) -> CollectionId { i.into() } + fn item(i: u16) -> ItemId { i.into() } + fn signer() -> (sp_runtime::MultiSigner, sp_runtime::AccountId32) { let public = sp_io::crypto::sr25519_generate(0.into(), None); let account = sp_runtime::MultiSigner::Sr25519(public).into_account(); (public.into(), account) } + fn sign(signer: &sp_runtime::MultiSigner, message: &[u8]) -> sp_runtime::MultiSignature { sp_runtime::MultiSignature::Sr25519( sp_io::crypto::sr25519_sign(0.into(), &signer.clone().try_into().unwrap(), message) diff --git a/pallets/nfts/src/migration.rs b/pallets/nfts/src/migration.rs index 8f82e0922..af611bf16 100644 --- a/pallets/nfts/src/migration.rs +++ b/pallets/nfts/src/migration.rs @@ -15,13 +15,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::*; use frame_support::traits::OnRuntimeUpgrade; use log; - #[cfg(feature = "try-runtime")] use sp_runtime::TryRuntimeError; +use super::*; + pub mod v1 { use frame_support::{pallet_prelude::*, weights::Weight}; diff --git a/pallets/nfts/src/mock.rs b/pallets/nfts/src/mock.rs index 5b589f591..5532be8f4 100644 --- a/pallets/nfts/src/mock.rs +++ b/pallets/nfts/src/mock.rs @@ -17,9 +17,6 @@ //! Test environment for Nfts pallet. -use super::*; -use crate as pallet_nfts; - use frame_support::{ construct_runtime, derive_impl, parameter_types, traits::{AsEnsureOriginWithArg, ConstU32, ConstU64}, @@ -30,6 +27,9 @@ use sp_runtime::{ BuildStorage, MultiSignature, }; +use super::*; +use crate as pallet_nfts; + type Block = frame_system::mocking::MockBlock; construct_runtime!( @@ -47,10 +47,10 @@ pub type AccountId = ::AccountId; #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { + type AccountData = pallet_balances::AccountData; type AccountId = AccountId; - type Lookup = IdentityLookup; type Block = Block; - type AccountData = pallet_balances::AccountData; + type Lookup = IdentityLookup; } #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] @@ -63,35 +63,35 @@ parameter_types! { } impl Config for Test { - type RuntimeEvent = RuntimeEvent; + type ApprovalsLimit = ConstU32<10>; + type AttributeDepositBase = ConstU64<1>; + type CollectionDeposit = ConstU64<2>; type CollectionId = u32; - type ItemId = u32; - type Currency = Balances; type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type DepositPerByte = ConstU64<1>; + type Features = Features; type ForceOrigin = frame_system::EnsureRoot; - type Locker = (); - type CollectionDeposit = ConstU64<2>; + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); + type ItemAttributesApprovalsLimit = ConstU32<2>; type ItemDeposit = ConstU64<1>; - type MetadataDepositBase = ConstU64<1>; - type AttributeDepositBase = ConstU64<1>; - type DepositPerByte = ConstU64<1>; - type StringLimit = ConstU32<50>; + type ItemId = u32; type KeyLimit = ConstU32<50>; - type ValueLimit = ConstU32<50>; - type ApprovalsLimit = ConstU32<10>; - type ItemAttributesApprovalsLimit = ConstU32<2>; - type MaxTips = ConstU32<10>; - type MaxDeadlineDuration = ConstU64<10000>; + type Locker = (); type MaxAttributesPerCall = ConstU32<2>; - type Features = Features; + type MaxDeadlineDuration = ConstU64<10000>; + type MaxTips = ConstU32<10>; + type MetadataDepositBase = ConstU64<1>; + /// Using `AccountPublic` here makes it trivial to convert to `AccountId` via `into_account()`. + type OffchainPublic = AccountPublic; /// Off-chain = signature On-chain - therefore no conversion needed. /// It needs to be From for benchmarking. type OffchainSignature = Signature; - /// Using `AccountPublic` here makes it trivial to convert to `AccountId` via `into_account()`. - type OffchainPublic = AccountPublic; + type RuntimeEvent = RuntimeEvent; + type StringLimit = ConstU32<50>; + type ValueLimit = ConstU32<50>; type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type Helper = (); } pub(crate) fn new_test_ext() -> sp_io::TestExternalities { diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index e1b598ca4..44f2f32ae 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -17,7 +17,6 @@ //! Tests for Nfts pallet. -use crate::{mock::*, Event, SystemConfig, *}; use enumflags2::BitFlags; use frame_support::{ assert_noop, assert_ok, @@ -33,6 +32,8 @@ use sp_runtime::{ MultiSignature, MultiSigner, }; +use crate::{mock::*, Event, SystemConfig, *}; + type AccountIdOf = ::AccountId; fn account(id: u8) -> AccountIdOf { diff --git a/pallets/nfts/src/types.rs b/pallets/nfts/src/types.rs index 1687a0352..f08f1d097 100644 --- a/pallets/nfts/src/types.rs +++ b/pallets/nfts/src/types.rs @@ -17,9 +17,8 @@ //! This module contains various basic types and data structures used in the NFTs pallet. -use super::*; -use crate::macros::*; use alloc::{vec, vec::Vec}; + use codec::EncodeLike; use enumflags2::{bitflags, BitFlags}; use frame_support::{ @@ -30,6 +29,9 @@ use frame_support::{ use frame_system::pallet_prelude::BlockNumberFor; use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter}; +use super::*; +use crate::macros::*; + /// A type alias for handling balance deposits. pub(super) type DepositBalanceOf = <>::Currency as Currency<::AccountId>>::Balance; @@ -276,12 +278,15 @@ impl CollectionSettings { pub fn all_enabled() -> Self { Self(BitFlags::EMPTY) } + pub fn get_disabled(&self) -> BitFlags { self.0 } + pub fn is_disabled(&self, setting: CollectionSetting) -> bool { self.0.contains(setting) } + pub fn from_disabled(settings: BitFlags) -> Self { Self(settings) } @@ -377,12 +382,15 @@ impl CollectionConfig bool { !self.settings.is_disabled(setting) } + pub fn has_disabled_setting(&self, setting: CollectionSetting) -> bool { self.settings.is_disabled(setting) } + pub fn enable_setting(&mut self, setting: CollectionSetting) { self.settings.0.remove(setting); } + pub fn disable_setting(&mut self, setting: CollectionSetting) { self.settings.0.insert(setting); } @@ -409,12 +417,15 @@ impl ItemSettings { pub fn all_enabled() -> Self { Self(BitFlags::EMPTY) } + pub fn get_disabled(&self) -> BitFlags { self.0 } + pub fn is_disabled(&self, setting: ItemSetting) -> bool { self.0.contains(setting) } + pub fn from_disabled(settings: BitFlags) -> Self { Self(settings) } @@ -435,15 +446,19 @@ impl ItemConfig { pub fn is_setting_enabled(&self, setting: ItemSetting) -> bool { !self.settings.is_disabled(setting) } + pub fn has_disabled_setting(&self, setting: ItemSetting) -> bool { self.settings.is_disabled(setting) } + pub fn has_disabled_settings(&self) -> bool { !self.settings.get_disabled().is_empty() } + pub fn enable_setting(&mut self, setting: ItemSetting) { self.settings.0.remove(setting); } + pub fn disable_setting(&mut self, setting: ItemSetting) { self.settings.0.insert(setting); } @@ -472,9 +487,11 @@ impl PalletFeatures { pub fn all_enabled() -> Self { Self(BitFlags::EMPTY) } + pub fn from_disabled(features: BitFlags) -> Self { Self(features) } + pub fn is_enabled(&self, feature: PalletFeature) -> bool { !self.0.contains(feature) } @@ -502,12 +519,15 @@ impl CollectionRoles { pub fn none() -> Self { Self(BitFlags::EMPTY) } + pub fn has_role(&self, role: CollectionRole) -> bool { self.0.contains(role) } + pub fn add_role(&mut self, role: CollectionRole) { self.0.insert(role); } + pub fn max_roles() -> u8 { let all: BitFlags = BitFlags::all(); all.len() as u8 From 293b02ecfe42ade43ef88830848accbf202d8f18 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:47:40 +0700 Subject: [PATCH 03/76] feat: add nonfungibles implementation --- Cargo.lock | 1 + pallets/api/Cargo.toml | 3 + pallets/api/src/fungibles/tests.rs | 286 ++++++++++++++++---------- pallets/api/src/lib.rs | 1 + pallets/api/src/mock.rs | 74 ++++++- pallets/api/src/nonfungibles/mod.rs | 260 +++++++++++++++++++++++ pallets/api/src/nonfungibles/tests.rs | 183 ++++++++++++++++ pallets/api/src/nonfungibles/types.rs | 61 ++++++ 8 files changed, 750 insertions(+), 119 deletions(-) create mode 100644 pallets/api/src/nonfungibles/mod.rs create mode 100644 pallets/api/src/nonfungibles/tests.rs create mode 100644 pallets/api/src/nonfungibles/types.rs diff --git a/Cargo.lock b/Cargo.lock index d2bf2acec..6f98f910e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7366,6 +7366,7 @@ dependencies = [ "log", "pallet-assets", "pallet-balances", + "pallet-nfts", "parity-scale-codec", "pop-chain-extension", "scale-info", diff --git a/pallets/api/Cargo.toml b/pallets/api/Cargo.toml index 55a007895..5d3987244 100644 --- a/pallets/api/Cargo.toml +++ b/pallets/api/Cargo.toml @@ -22,6 +22,7 @@ frame-benchmarking.workspace = true frame-support.workspace = true frame-system.workspace = true pallet-assets.workspace = true +pallet-nfts.workspace = true sp-runtime.workspace = true sp-std.workspace = true @@ -37,6 +38,7 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-assets/runtime-benchmarks", + "pallet-nfts/runtime-benchmarks", "pop-chain-extension/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] @@ -47,6 +49,7 @@ std = [ "frame-system/std", "pallet-assets/std", "pallet-balances/std", + "pallet-nfts/std", "pop-chain-extension/std", "scale-info/std", "sp-core/std", diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index f5c560bb7..6e181a6f7 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -83,17 +83,21 @@ fn transfer_works() { let to = BOB; for origin in vec![root(), none()] { - assert_noop!(Fungibles::transfer(origin, token, to, value), BadOrigin); + assert_noop!(Fungibles::transfer(origin, token, account(to), value), BadOrigin); } // Check error works for `Assets::transfer_keep_alive()`. - assert_noop!(Fungibles::transfer(signed(from), token, to, value), AssetsError::Unknown); + assert_noop!( + Fungibles::transfer(signed(from), token, account(to), value), + AssetsError::Unknown + ); assets::create_and_mint_to(from, token, from, value * 2); - let balance_before_transfer = Assets::balance(token, &to); - assert_ok!(Fungibles::transfer(signed(from), token, to, value)); - let balance_after_transfer = Assets::balance(token, &to); + let balance_before_transfer = Assets::balance(token, &account(to)); + assert_ok!(Fungibles::transfer(signed(from), token, account(to), value)); + let balance_after_transfer = Assets::balance(token, &account(to)); assert_eq!(balance_after_transfer, balance_before_transfer + value); System::assert_last_event( - Event::Transfer { token, from: Some(from), to: Some(to), value }.into(), + Event::Transfer { token, from: Some(account(from)), to: Some(account(to)), value } + .into(), ); }); } @@ -108,26 +112,36 @@ fn transfer_from_works() { let spender = CHARLIE; for origin in vec![root(), none()] { - assert_noop!(Fungibles::transfer_from(origin, token, from, to, value), BadOrigin); + assert_noop!( + Fungibles::transfer_from(origin, token, account(from), account(to), value), + BadOrigin + ); } // Check error works for `Assets::transfer_approved()`. assert_noop!( - Fungibles::transfer_from(signed(spender), token, from, to, value), + Fungibles::transfer_from(signed(spender), token, account(from), account(to), value), AssetsError::Unknown ); // Approve `spender` to transfer up to `value`. assets::create_mint_and_approve(spender, token, from, value * 2, spender, value); // Successfully call transfer from. - let from_balance_before_transfer = Assets::balance(token, &from); - let to_balance_before_transfer = Assets::balance(token, &to); - assert_ok!(Fungibles::transfer_from(signed(spender), token, from, to, value)); - let from_balance_after_transfer = Assets::balance(token, &from); - let to_balance_after_transfer = Assets::balance(token, &to); + let from_balance_before_transfer = Assets::balance(token, &account(from)); + let to_balance_before_transfer = Assets::balance(token, &account(to)); + assert_ok!(Fungibles::transfer_from( + signed(spender), + token, + account(from), + account(to), + value + )); + let from_balance_after_transfer = Assets::balance(token, &account(from)); + let to_balance_after_transfer = Assets::balance(token, &account(to)); // Check that `to` has received the `value` tokens from `from`. assert_eq!(to_balance_after_transfer, to_balance_before_transfer + value); assert_eq!(from_balance_after_transfer, from_balance_before_transfer - value); System::assert_last_event( - Event::Transfer { token, from: Some(from), to: Some(to), value }.into(), + Event::Transfer { token, from: Some(account(from)), to: Some(account(to)), value } + .into(), ); }); } @@ -144,7 +158,7 @@ mod approve { for origin in vec![root(), none()] { assert_noop!( - Fungibles::approve(origin, token, spender, value), + Fungibles::approve(origin, token, account(spender), value), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } @@ -161,20 +175,20 @@ mod approve { for origin in vec![root(), none()] { assert_noop!( - Fungibles::approve(origin, token, spender, value), + Fungibles::approve(origin, token, account(spender), value), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } // Check error works for `Assets::approve_transfer()` in `Greater` match arm. assert_noop!( - Fungibles::approve(signed(owner), token, spender, value), + Fungibles::approve(signed(owner), token, account(spender), value), AssetsError::Unknown.with_weight(WeightInfo::approve(1, 0)) ); assets::create_mint_and_approve(owner, token, owner, value, spender, value); // Check error works for `Assets::cancel_approval()` in `Less` match arm. assert_ok!(Assets::freeze_asset(signed(owner), token)); assert_noop!( - Fungibles::approve(signed(owner), token, spender, value / 2), + Fungibles::approve(signed(owner), token, account(spender), value / 2), AssetsError::AssetNotLive.with_weight(WeightInfo::approve(0, 1)) ); assert_ok!(Assets::thaw_asset(signed(owner), token)); @@ -193,38 +207,61 @@ mod approve { // Approves a value to spend that is higher than the current allowance. assets::create_and_mint_to(owner, token, owner, value); - assert_eq!(Assets::allowance(token, &owner, &spender), 0); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), 0); assert_eq!( - Fungibles::approve(signed(owner), token, spender, value), + Fungibles::approve(signed(owner), token, account(spender), value), Ok(Some(WeightInfo::approve(1, 0)).into()) ); - assert_eq!(Assets::allowance(token, &owner, &spender), value); - System::assert_last_event(Event::Approval { token, owner, spender, value }.into()); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); + System::assert_last_event( + Event::Approval { token, owner: account(owner), spender: account(spender), value } + .into(), + ); // Approves a value to spend that is lower than the current allowance. assert_eq!( - Fungibles::approve(signed(owner), token, spender, value / 2), + Fungibles::approve(signed(owner), token, account(spender), value / 2), Ok(Some(WeightInfo::approve(1, 1)).into()) ); - assert_eq!(Assets::allowance(token, &owner, &spender), value / 2); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value / 2); System::assert_last_event( - Event::Approval { token, owner, spender, value: value / 2 }.into(), + Event::Approval { + token, + owner: account(owner), + spender: account(spender), + value: value / 2, + } + .into(), ); // Approves a value to spend that is equal to the current allowance. assert_eq!( - Fungibles::approve(signed(owner), token, spender, value / 2), + Fungibles::approve(signed(owner), token, account(spender), value / 2), Ok(Some(WeightInfo::approve(0, 0)).into()) ); - assert_eq!(Assets::allowance(token, &owner, &spender), value / 2); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value / 2); System::assert_last_event( - Event::Approval { token, owner, spender, value: value / 2 }.into(), + Event::Approval { + token, + owner: account(owner), + spender: account(spender), + value: value / 2, + } + .into(), ); // Sets allowance to zero. assert_eq!( - Fungibles::approve(signed(owner), token, spender, 0), + Fungibles::approve(signed(owner), token, account(spender), 0), Ok(Some(WeightInfo::approve(0, 1)).into()) ); - assert_eq!(Assets::allowance(token, &owner, &spender), 0); - System::assert_last_event(Event::Approval { token, owner, spender, value: 0 }.into()); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), 0); + System::assert_last_event( + Event::Approval { + token, + owner: account(owner), + spender: account(spender), + value: 0, + } + .into(), + ); }); } } @@ -239,25 +276,34 @@ fn increase_allowance_works() { for origin in vec![root(), none()] { assert_noop!( - Fungibles::increase_allowance(origin, token, spender, value), + Fungibles::increase_allowance(origin, token, account(spender), value), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } // Check error works for `Assets::approve_transfer()`. assert_noop!( - Fungibles::increase_allowance(signed(owner), token, spender, value), + Fungibles::increase_allowance(signed(owner), token, account(spender), value), AssetsError::Unknown.with_weight(AssetsWeightInfo::approve_transfer()) ); assets::create_and_mint_to(owner, token, owner, value); - assert_eq!(0, Assets::allowance(token, &owner, &spender)); - assert_ok!(Fungibles::increase_allowance(signed(owner), token, spender, value)); - assert_eq!(Assets::allowance(token, &owner, &spender), value); - System::assert_last_event(Event::Approval { token, owner, spender, value }.into()); + assert_eq!(0, Assets::allowance(token, &account(owner), &account(spender))); + assert_ok!(Fungibles::increase_allowance(signed(owner), token, account(spender), value)); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); + System::assert_last_event( + Event::Approval { token, owner: account(owner), spender: account(spender), value } + .into(), + ); // Additive. - assert_ok!(Fungibles::increase_allowance(signed(owner), token, spender, value)); - assert_eq!(Assets::allowance(token, &owner, &spender), value * 2); + assert_ok!(Fungibles::increase_allowance(signed(owner), token, account(spender), value)); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value * 2); System::assert_last_event( - Event::Approval { token, owner, spender, value: value * 2 }.into(), + Event::Approval { + token, + owner: account(owner), + spender: account(spender), + value: value * 2, + } + .into(), ); }); } @@ -272,40 +318,46 @@ fn decrease_allowance_works() { for origin in vec![root(), none()] { assert_noop!( - Fungibles::decrease_allowance(origin, token, spender, 0), + Fungibles::decrease_allowance(origin, token, account(spender), 0), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } assets::create_mint_and_approve(owner, token, owner, value, spender, value); - assert_eq!(Assets::allowance(token, &owner, &spender), value); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); // Check error works for `Assets::cancel_approval()`. No error test for `approve_transfer` // because it is not possible. assert_ok!(Assets::freeze_asset(signed(owner), token)); assert_noop!( - Fungibles::decrease_allowance(signed(owner), token, spender, value / 2), + Fungibles::decrease_allowance(signed(owner), token, account(spender), value / 2), AssetsError::AssetNotLive.with_weight(WeightInfo::approve(0, 1)) ); assert_ok!(Assets::thaw_asset(signed(owner), token)); // Owner balance is not changed if decreased by zero. assert_eq!( - Fungibles::decrease_allowance(signed(owner), token, spender, 0), + Fungibles::decrease_allowance(signed(owner), token, account(spender), 0), Ok(Some(WeightInfo::approve(0, 0)).into()) ); - assert_eq!(Assets::allowance(token, &owner, &spender), value); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); // "Unapproved" error is returned if the current allowance is less than amount to decrease // with. assert_noop!( - Fungibles::decrease_allowance(signed(owner), token, spender, value * 2), + Fungibles::decrease_allowance(signed(owner), token, account(spender), value * 2), AssetsError::Unapproved ); // Decrease allowance successfully. assert_eq!( - Fungibles::decrease_allowance(signed(owner), token, spender, value / 2), + Fungibles::decrease_allowance(signed(owner), token, account(spender), value / 2), Ok(Some(WeightInfo::approve(1, 1)).into()) ); - assert_eq!(Assets::allowance(token, &owner, &spender), value / 2); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value / 2); System::assert_last_event( - Event::Approval { token, owner, spender, value: value / 2 }.into(), + Event::Approval { + token, + owner: account(owner), + spender: account(spender), + value: value / 2, + } + .into(), ); }); } @@ -318,14 +370,19 @@ fn create_works() { let admin = ALICE; for origin in vec![root(), none()] { - assert_noop!(Fungibles::create(origin, id, admin, 100), BadOrigin); + assert_noop!(Fungibles::create(origin, id, account(admin), 100), BadOrigin); } assert!(!Assets::asset_exists(id)); - assert_ok!(Fungibles::create(signed(creator), id, admin, 100)); + assert_ok!(Fungibles::create(signed(creator), id, account(admin), 100)); assert!(Assets::asset_exists(id)); - System::assert_last_event(Event::Created { id, creator, admin }.into()); + System::assert_last_event( + Event::Created { id, creator: account(creator), admin: account(admin) }.into(), + ); // Check error works for `Assets::create()`. - assert_noop!(Fungibles::create(signed(creator), id, admin, 100), AssetsError::InUse); + assert_noop!( + Fungibles::create(signed(creator), id, account(admin), 100), + AssetsError::InUse + ); }); } @@ -336,11 +393,11 @@ fn start_destroy_works() { // Check error works for `Assets::start_destroy()`. assert_noop!(Fungibles::start_destroy(signed(ALICE), token), AssetsError::Unknown); - assert_ok!(Assets::create(signed(ALICE), token, ALICE, 1)); + assert_ok!(Assets::create(signed(ALICE), token, account(ALICE), 1)); assert_ok!(Fungibles::start_destroy(signed(ALICE), token)); // Check that the token is not live after starting the destroy process. assert_noop!( - Assets::mint(signed(ALICE), token, ALICE, 10 * UNIT), + Assets::mint(signed(ALICE), token, account(ALICE), 10 * UNIT), AssetsError::AssetNotLive ); }); @@ -359,7 +416,7 @@ fn set_metadata_works() { Fungibles::set_metadata(signed(ALICE), token, name.clone(), symbol.clone(), decimals), AssetsError::Unknown ); - assert_ok!(Assets::create(signed(ALICE), token, ALICE, 1)); + assert_ok!(Assets::create(signed(ALICE), token, account(ALICE), 1)); assert_ok!(Fungibles::set_metadata( signed(ALICE), token, @@ -398,16 +455,16 @@ fn mint_works() { // Check error works for `Assets::mint()`. assert_noop!( - Fungibles::mint(signed(from), token, to, value), + Fungibles::mint(signed(from), token, account(to), value), sp_runtime::TokenError::UnknownAsset ); - assert_ok!(Assets::create(signed(from), token, from, 1)); - let balance_before_mint = Assets::balance(token, &to); - assert_ok!(Fungibles::mint(signed(from), token, to, value)); - let balance_after_mint = Assets::balance(token, &to); + assert_ok!(Assets::create(signed(from), token, account(from), 1)); + let balance_before_mint = Assets::balance(token, &account(to)); + assert_ok!(Fungibles::mint(signed(from), token, account(to), value)); + let balance_after_mint = Assets::balance(token, &account(to)); assert_eq!(balance_after_mint, balance_before_mint + value); System::assert_last_event( - Event::Transfer { token, from: None, to: Some(to), value }.into(), + Event::Transfer { token, from: None, to: Some(account(to)), value }.into(), ); }); } @@ -423,27 +480,30 @@ fn burn_works() { // "BalanceLow" error is returned if token is not created. assert_noop!( - Fungibles::burn(signed(owner), token, from, value), + Fungibles::burn(signed(owner), token, account(from), value), AssetsError::BalanceLow.with_weight(WeightInfo::balance_of()) ); assets::create_and_mint_to(owner, token, from, total_supply); assert_eq!(Assets::total_supply(TOKEN), total_supply); // Check error works for `Assets::burn()`. assert_ok!(Assets::freeze_asset(signed(owner), token)); - assert_noop!(Fungibles::burn(signed(owner), token, from, value), AssetsError::AssetNotLive); + assert_noop!( + Fungibles::burn(signed(owner), token, account(from), value), + AssetsError::AssetNotLive + ); assert_ok!(Assets::thaw_asset(signed(owner), token)); // "BalanceLow" error is returned if the balance is less than amount to burn. assert_noop!( - Fungibles::burn(signed(owner), token, from, total_supply * 2), + Fungibles::burn(signed(owner), token, account(from), total_supply * 2), AssetsError::BalanceLow.with_weight(WeightInfo::balance_of()) ); - let balance_before_burn = Assets::balance(token, &from); - assert_ok!(Fungibles::burn(signed(owner), token, from, value)); + let balance_before_burn = Assets::balance(token, &account(from)); + assert_ok!(Fungibles::burn(signed(owner), token, account(from), value)); assert_eq!(Assets::total_supply(TOKEN), total_supply - value); - let balance_after_burn = Assets::balance(token, &from); + let balance_after_burn = Assets::balance(token, &account(from)); assert_eq!(balance_after_burn, balance_before_burn - value); System::assert_last_event( - Event::Transfer { token, from: Some(from), to: None, value }.into(), + Event::Transfer { token, from: Some(account(from)), to: None, value }.into(), ); }); } @@ -470,17 +530,17 @@ fn balance_of_works() { new_test_ext().execute_with(|| { let value = 1_000 * UNIT; assert_eq!( - Fungibles::read(BalanceOf { token: TOKEN, owner: ALICE }), + Fungibles::read(BalanceOf { token: TOKEN, owner: account(ALICE) }), ReadResult::BalanceOf(Default::default()) ); assets::create_and_mint_to(ALICE, TOKEN, ALICE, value); assert_eq!( - Fungibles::read(BalanceOf { token: TOKEN, owner: ALICE }), + Fungibles::read(BalanceOf { token: TOKEN, owner: account(ALICE) }), ReadResult::BalanceOf(value) ); assert_eq!( - Fungibles::read(BalanceOf { token: TOKEN, owner: ALICE }).encode(), - Assets::balance(TOKEN, ALICE).encode(), + Fungibles::read(BalanceOf { token: TOKEN, owner: account(ALICE) }).encode(), + Assets::balance(TOKEN, account(ALICE)).encode(), ); }); } @@ -490,17 +550,30 @@ fn allowance_works() { new_test_ext().execute_with(|| { let value = 1_000 * UNIT; assert_eq!( - Fungibles::read(Allowance { token: TOKEN, owner: ALICE, spender: BOB }), + Fungibles::read(Allowance { + token: TOKEN, + owner: account(ALICE), + spender: account(BOB) + }), ReadResult::Allowance(Default::default()) ); assets::create_mint_and_approve(ALICE, TOKEN, ALICE, value * 2, BOB, value); assert_eq!( - Fungibles::read(Allowance { token: TOKEN, owner: ALICE, spender: BOB }), + Fungibles::read(Allowance { + token: TOKEN, + owner: account(ALICE), + spender: account(BOB) + }), ReadResult::Allowance(value) ); assert_eq!( - Fungibles::read(Allowance { token: TOKEN, owner: ALICE, spender: BOB }).encode(), - Assets::allowance(TOKEN, &ALICE, &BOB).encode(), + Fungibles::read(Allowance { + token: TOKEN, + owner: account(ALICE), + spender: account(BOB) + }) + .encode(), + Assets::allowance(TOKEN, &account(ALICE), &account(BOB)).encode(), ); }); } @@ -534,7 +607,7 @@ fn token_metadata_works() { fn token_exists_works() { new_test_ext().execute_with(|| { assert_eq!(Fungibles::read(TokenExists(TOKEN)), ReadResult::TokenExists(false)); - assert_ok!(Assets::create(signed(ALICE), TOKEN, ALICE, 1)); + assert_ok!(Assets::create(signed(ALICE), TOKEN, account(ALICE), 1)); assert_eq!(Fungibles::read(TokenExists(TOKEN)), ReadResult::TokenExists(true)); assert_eq!( Fungibles::read(TokenExists(TOKEN)).encode(), @@ -543,8 +616,8 @@ fn token_exists_works() { }); } -fn signed(account: AccountId) -> RuntimeOrigin { - RuntimeOrigin::signed(account) +fn signed(account_id: u8) -> RuntimeOrigin { + RuntimeOrigin::signed(account(account_id)) } fn root() -> RuntimeOrigin { @@ -559,36 +632,31 @@ fn none() -> RuntimeOrigin { mod assets { use super::*; - pub(super) fn create_and_mint_to( - owner: AccountId, - token: TokenId, - to: AccountId, - value: Balance, - ) { - assert_ok!(Assets::create(signed(owner), token, owner, 1)); - assert_ok!(Assets::mint(signed(owner), token, to, value)); + pub(super) fn create_and_mint_to(owner: u8, token: TokenId, to: u8, value: Balance) { + assert_ok!(Assets::create(signed(owner), token, account(owner), 1)); + assert_ok!(Assets::mint(signed(owner), token, account(to), value)); } pub(super) fn create_mint_and_approve( - owner: AccountId, + owner: u8, token: TokenId, - to: AccountId, + to: u8, mint: Balance, - spender: AccountId, + spender: u8, approve: Balance, ) { create_and_mint_to(owner, token, to, mint); - assert_ok!(Assets::approve_transfer(signed(to), token, spender, approve,)); + assert_ok!(Assets::approve_transfer(signed(to), token, account(spender), approve,)); } pub(super) fn create_and_set_metadata( - owner: AccountId, + owner: u8, token: TokenId, name: Vec, symbol: Vec, decimals: u8, ) { - assert_ok!(Assets::create(signed(owner), token, owner, 1)); + assert_ok!(Assets::create(signed(owner), token, account(owner), 1)); assert_ok!(Assets::set_metadata(signed(owner), token, name, symbol, decimals)); } } @@ -613,11 +681,11 @@ mod read_weights { fn new() -> Self { Self { total_supply: Fungibles::weight(&TotalSupply(TOKEN)), - balance_of: Fungibles::weight(&BalanceOf { token: TOKEN, owner: ALICE }), + balance_of: Fungibles::weight(&BalanceOf { token: TOKEN, owner: account(ALICE) }), allowance: Fungibles::weight(&Allowance { token: TOKEN, - owner: ALICE, - spender: BOB, + owner: account(ALICE), + spender: account(BOB), }), token_name: Fungibles::weight(&TokenName(TOKEN)), token_symbol: Fungibles::weight(&TokenSymbol(TOKEN)), @@ -699,15 +767,15 @@ mod ensure_codec_indexes { [ (TotalSupply::(Default::default()), 0u8, "TotalSupply"), ( - BalanceOf:: { token: Default::default(), owner: Default::default() }, + BalanceOf:: { token: Default::default(), owner: account(Default::default()) }, 1, "BalanceOf", ), ( Allowance:: { token: Default::default(), - owner: Default::default(), - spender: Default::default(), + owner: account(Default::default()), + spender: account(Default::default()), }, 2, "Allowance", @@ -731,7 +799,7 @@ mod ensure_codec_indexes { ( transfer { token: Default::default(), - to: Default::default(), + to: account(Default::default()), value: Default::default(), }, 3u8, @@ -740,8 +808,8 @@ mod ensure_codec_indexes { ( transfer_from { token: Default::default(), - from: Default::default(), - to: Default::default(), + from: account(Default::default()), + to: account(Default::default()), value: Default::default(), }, 4, @@ -750,7 +818,7 @@ mod ensure_codec_indexes { ( approve { token: Default::default(), - spender: Default::default(), + spender: account(Default::default()), value: Default::default(), }, 5, @@ -759,7 +827,7 @@ mod ensure_codec_indexes { ( increase_allowance { token: Default::default(), - spender: Default::default(), + spender: account(Default::default()), value: Default::default(), }, 6, @@ -768,7 +836,7 @@ mod ensure_codec_indexes { ( decrease_allowance { token: Default::default(), - spender: Default::default(), + spender: account(Default::default()), value: Default::default(), }, 7, @@ -777,7 +845,7 @@ mod ensure_codec_indexes { ( create { id: Default::default(), - admin: Default::default(), + admin: account(Default::default()), min_balance: Default::default(), }, 11, @@ -798,7 +866,7 @@ mod ensure_codec_indexes { ( mint { token: Default::default(), - account: Default::default(), + account: account(Default::default()), value: Default::default(), }, 19, @@ -807,7 +875,7 @@ mod ensure_codec_indexes { ( burn { token: Default::default(), - account: Default::default(), + account: account(Default::default()), value: Default::default(), }, 20, diff --git a/pallets/api/src/lib.rs b/pallets/api/src/lib.rs index d94d19788..e3d706e2d 100644 --- a/pallets/api/src/lib.rs +++ b/pallets/api/src/lib.rs @@ -7,6 +7,7 @@ pub mod extension; pub mod fungibles; #[cfg(test)] mod mock; +pub mod nonfungibles; /// Trait for performing reads of runtime state. pub trait Read { diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs index 42c8bf0e2..920d590f9 100644 --- a/pallets/api/src/mock.rs +++ b/pallets/api/src/mock.rs @@ -1,25 +1,28 @@ use frame_support::{ derive_impl, parameter_types, - traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, Everything}, + traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, ConstU64, Everything}, }; use frame_system::{EnsureRoot, EnsureSigned}; +use pallet_nfts::PalletFeatures; use sp_core::H256; use sp_runtime::{ - traits::{BlakeTwo256, IdentityLookup}, - BuildStorage, + traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Verify}, + BuildStorage, MultiSignature, }; -pub(crate) const ALICE: AccountId = 1; -pub(crate) const BOB: AccountId = 2; -pub(crate) const CHARLIE: AccountId = 3; +pub(crate) const ALICE: u8 = 1; +pub(crate) const BOB: u8 = 2; +pub(crate) const CHARLIE: u8 = 3; pub(crate) const INIT_AMOUNT: Balance = 100_000_000 * UNIT; pub(crate) const UNIT: Balance = 10_000_000_000; type Block = frame_system::mocking::MockBlock; -pub(crate) type AccountId = u64; +pub(crate) type AccountId = ::AccountId; pub(crate) type Balance = u128; // For terminology in tests. pub(crate) type TokenId = u32; +type Signature = MultiSignature; +type AccountPublic = ::Signer; // Configure a mock runtime to test the pallet. frame_support::construct_runtime!( @@ -29,6 +32,8 @@ frame_support::construct_runtime!( Assets: pallet_assets::, Balances: pallet_balances, Fungibles: crate::fungibles, + Nfts: pallet_nfts, + NonFungibles: crate::nonfungibles } ); @@ -91,10 +96,10 @@ impl pallet_assets::Config for Test { #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); type CallbackHandle = (); - type CreateOrigin = AsEnsureOriginWithArg>; + type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; type Extra = (); - type ForceOrigin = EnsureRoot; + type ForceOrigin = EnsureRoot; type Freezer = (); type MetadataDepositBase = ConstU128<1>; type MetadataDepositPerByte = ConstU128<1>; @@ -110,13 +115,62 @@ impl crate::fungibles::Config for Test { type WeightInfo = (); } +parameter_types! { + pub storage Features: PalletFeatures = PalletFeatures::all_enabled(); +} + +impl pallet_nfts::Config for Test { + type ApprovalsLimit = ConstU32<10>; + type AttributeDepositBase = ConstU128<1>; + type CollectionDeposit = ConstU128<2>; + type CollectionId = u32; + type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type DepositPerByte = ConstU128<1>; + type Features = Features; + type ForceOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); + type ItemAttributesApprovalsLimit = ConstU32<2>; + type ItemDeposit = ConstU128<1>; + type ItemId = u32; + type KeyLimit = ConstU32<50>; + type Locker = (); + type MaxAttributesPerCall = ConstU32<2>; + type MaxDeadlineDuration = ConstU64<10000>; + type MaxTips = ConstU32<10>; + type MetadataDepositBase = ConstU128<1>; + /// Using `AccountPublic` here makes it trivial to convert to `AccountId` via `into_account()`. + type OffchainPublic = AccountPublic; + /// Off-chain = signature On-chain - therefore no conversion needed. + /// It needs to be From for benchmarking. + type OffchainSignature = Signature; + type RuntimeEvent = RuntimeEvent; + type StringLimit = ConstU32<50>; + type ValueLimit = ConstU32<50>; + type WeightInfo = (); +} + +impl crate::nonfungibles::Config for Test { + type RuntimeEvent = RuntimeEvent; +} + +/// Initialize a new account ID. +pub(crate) fn account(id: u8) -> AccountId { + [id; 32].into() +} + pub(crate) fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::::default() .build_storage() .expect("Frame system builds valid default genesis config"); pallet_balances::GenesisConfig:: { - balances: vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT), (CHARLIE, INIT_AMOUNT)], + balances: vec![ + (account(ALICE), INIT_AMOUNT), + (account(BOB), INIT_AMOUNT), + (account(CHARLIE), INIT_AMOUNT), + ], } .assimilate_storage(&mut t) .expect("Pallet balances storage can be assimilated"); diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs new file mode 100644 index 000000000..cac0cbbab --- /dev/null +++ b/pallets/api/src/nonfungibles/mod.rs @@ -0,0 +1,260 @@ +//! The non-fungibles pallet offers a streamlined interface for interacting with non-fungible +//! assets. The goal is to provide a simplified, consistent API that adheres to standards in the +//! smart contract space. + +use frame_support::traits::nonfungibles_v2::InspectEnumerable; +pub use pallet::*; +use pallet_nfts::WeightInfo; +use sp_runtime::traits::StaticLookup; + +#[cfg(test)] +mod tests; +mod types; + +#[frame_support::pallet] +pub mod pallet { + use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; + use frame_system::pallet_prelude::*; + use sp_std::vec::Vec; + use types::{AccountIdOf, CollectionIdOf, ItemDetails, ItemIdOf, NftsOf, NftsWeightInfoOf}; + + use super::*; + + /// State reads for the fungibles API with required input. + #[derive(Encode, Decode, Debug, MaxEncodedLen)] + #[repr(u8)] + #[allow(clippy::unnecessary_cast)] + pub enum Read { + /// Returns the owner of an item. + #[codec(index = 0)] + OwnerOf { collection: CollectionIdOf, item: ItemIdOf }, + /// Returns the owner of a collection. + #[codec(index = 1)] + CollectionOwner(CollectionIdOf), + /// Number of items existing in a concrete collection. + #[codec(index = 2)] + TotalSupply(CollectionIdOf), + /// Returns the total number of items in the collection owned by the account. + #[codec(index = 3)] + BalanceOf { collection: CollectionIdOf, owner: AccountIdOf }, + /// Returns the details of a collection. + #[codec(index = 4)] + Collection(CollectionIdOf), + /// Returns the details of an item. + #[codec(index = 5)] + Item { collection: CollectionIdOf, item: ItemIdOf }, + /// Whether a spender is allowed to transfer an item or items from owner. + #[codec(index = 6)] + Allowance { spender: AccountIdOf, collection: CollectionIdOf, item: ItemIdOf }, + } + + /// Configure the pallet by specifying the parameters and types on which it depends. + #[pallet::config] + pub trait Config: frame_system::Config + pallet_nfts::Config { + /// Because this pallet emits events, it depends on the runtime's definition of an event. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + } + + #[pallet::pallet] + pub struct Pallet(_); + + /// The events that can be emitted. + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Event emitted when allowance by `owner` to `spender` canceled. + CancelApproval { + /// The collection ID. + collection: CollectionIdOf, + /// the item ID. + item: ItemIdOf, + /// The beneficiary of the allowance. + spender: AccountIdOf, + }, + /// Event emitted when allowance by `owner` to `spender` changes. + Approval { + /// The collection ID. + collection: CollectionIdOf, + /// the item ID. + item: ItemIdOf, + /// The owner providing the allowance. + owner: AccountIdOf, + /// The beneficiary of the allowance. + spender: AccountIdOf, + }, + /// Event emitted when new item is minted to the account. + Mint { + /// The owner of the item. + to: AccountIdOf, + /// The collection ID. + collection: CollectionIdOf, + /// the item ID. + item: ItemIdOf, + }, + /// Event emitted when item is burned. + Burn { + /// The collection ID. + collection: CollectionIdOf, + /// the item ID. + item: ItemIdOf, + }, + /// Event emitted when an item transfer occurs. + Transfer { + /// The collection ID. + collection: CollectionIdOf, + /// the item ID. + item: ItemIdOf, + /// The source of the transfer. + from: AccountIdOf, + /// The recipient of the transfer. + to: AccountIdOf, + }, + } + + #[pallet::call] + impl Pallet { + /// Create a new non-fungible token to the collection. + /// + /// # Parameters + /// - `to` - The owner of the collection item. + /// - `collection` - The collection ID. + /// - `item` - The item ID. + #[pallet::call_index(0)] + #[pallet::weight(NftsWeightInfoOf::::mint())] + pub fn mint( + origin: OriginFor, + to: AccountIdOf, + collection: CollectionIdOf, + item: ItemIdOf, + ) -> DispatchResult { + NftsOf::::mint(origin, collection, item, T::Lookup::unlookup(to.clone()), None)?; + Self::deposit_event(Event::Mint { to, collection, item }); + Ok(()) + } + + /// Destroy a new non-fungible token to the collection. + /// + /// # Parameters + /// - `collection` - The collection ID. + /// - `item` - The item ID. + #[pallet::call_index(1)] + #[pallet::weight(NftsWeightInfoOf::::burn())] + pub fn burn( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + ) -> DispatchResult { + NftsOf::::burn(origin, collection, item)?; + Self::deposit_event(Event::Burn { collection, item }); + Ok(()) + } + + /// Transfer a token from one account to the another account. + /// + /// # Parameters + /// - `collection` - The collection ID. + /// - `item` - The item ID. + /// - `to` - The recipient account. + #[pallet::call_index(2)] + #[pallet::weight(NftsWeightInfoOf::::transfer())] + pub fn transfer( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + to: AccountIdOf, + ) -> DispatchResult { + let from = ensure_signed(origin.clone())?; + NftsOf::::transfer(origin, collection, item, T::Lookup::unlookup(to.clone()))?; + Self::deposit_event(Event::Transfer { from, to, collection, item }); + Ok(()) + } + + /// Delegate a permission to perform actions on the collection item to an account. + /// + /// # Parameters + /// - `collection` - The collection ID. + /// - `item` - The item ID. + /// - `spender` - The account that is allowed to transfer the collection item. + #[pallet::call_index(3)] + #[pallet::weight(NftsWeightInfoOf::::approve_transfer())] + pub fn approve( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + spender: AccountIdOf, + ) -> DispatchResult { + let owner = ensure_signed(origin.clone())?; + NftsOf::::approve_transfer( + origin, + collection, + item, + T::Lookup::unlookup(spender.clone()), + None, + )?; + Self::deposit_event(Event::Approval { collection, item, spender, owner }); + Ok(()) + } + + /// Cancel one of the transfer approvals for a specific item. + /// + /// # Parameters + /// - `collection` - The collection ID. + /// - `item` - The item ID. + /// - `spender` - The account that is revoked permission to transfer the collection item. + #[pallet::call_index(4)] + #[pallet::weight(NftsWeightInfoOf::::cancel_approval())] + pub fn cancel_approval( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + spender: AccountIdOf, + ) -> DispatchResult { + NftsOf::::cancel_approval( + origin, + collection, + item, + T::Lookup::unlookup(spender.clone()), + )?; + Self::deposit_event(Event::CancelApproval { collection, item, spender }); + Ok(()) + } + } + + impl Pallet { + /// Reads fungible asset state based on the provided value. + /// + /// This function matches the value to determine the type of state query and returns the + /// encoded result. + /// + /// # Parameter + /// - `value` - An instance of `Read`, which specifies the type of state query and the + /// associated parameters. + pub fn read_state(value: Read) -> Vec { + use Read::*; + match value { + OwnerOf { collection, item } => NftsOf::::owner(collection, item).encode(), + CollectionOwner(collection) => NftsOf::::collection_owner(collection).encode(), + TotalSupply(collection) => (NftsOf::::items(&collection).count() as u8).encode(), + Collection(collection) => pallet_nfts::Collection::::get(&collection).encode(), + Item { collection, item } => pallet_nfts::Item::::get(collection, item).encode(), + Allowance { collection, item, spender } => + Self::allowance(collection, item, spender).encode(), + BalanceOf { collection, owner } => + (NftsOf::::owned_in_collection(&collection, &owner).count() as u8).encode(), + } + } + + /// Check if the `spender` is approved to transfer the collection item + pub(super) fn allowance( + collection: CollectionIdOf, + item: ItemIdOf, + spender: AccountIdOf, + ) -> bool { + let data = pallet_nfts::Item::::get(collection, item).encode(); + if let Ok(detail) = ItemDetails::::decode(&mut data.as_slice()) { + return detail.approvals.contains_key(&spender); + } + false + } + } +} diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs new file mode 100644 index 000000000..9e9da5c27 --- /dev/null +++ b/pallets/api/src/nonfungibles/tests.rs @@ -0,0 +1,183 @@ +use codec::Encode; +use frame_support::{assert_ok, traits::nonfungibles_v2::InspectEnumerable}; +use frame_system::pallet_prelude::BlockNumberFor; +use pallet_nfts::{CollectionConfig, CollectionSettings, MintSettings}; + +use super::types::*; +use crate::{ + mock::*, + nonfungibles::{Event, Read::*}, +}; + +const ITEM: u32 = 1; + +#[test] +fn mint_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let collection = create_collection(owner.clone()); + // Successfully mint a new collection item. + assert_ok!(NonFungibles::mint(signed(owner.clone()), owner.clone(), collection, ITEM)); + System::assert_last_event(Event::Mint { to: owner, collection, item: ITEM }.into()); + }); +} + +#[test] +fn burn_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let (collection, item) = create_collection_mint(owner.clone(), ITEM); + // Successfully burn an existing new collection item. + assert_ok!(NonFungibles::burn(signed(owner.clone()), collection, ITEM)); + System::assert_last_event(Event::Burn { collection, item }.into()); + }); +} + +#[test] +fn transfer() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let dest = account(BOB); + let (collection, item) = create_collection_mint(owner.clone(), ITEM); + // Successfully burn an existing new collection item. + assert_ok!(NonFungibles::transfer(signed(owner.clone()), collection, ITEM, dest.clone())); + System::assert_last_event( + Event::Transfer { collection, item, from: owner, to: dest }.into(), + ); + }); +} + +#[test] +fn approve_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let spender = account(BOB); + let (collection, item) = create_collection_mint(owner.clone(), ITEM); + // Successfully approve `spender` to transfer the collection item. + assert_ok!(NonFungibles::approve(signed(owner.clone()), collection, item, spender.clone())); + System::assert_last_event( + Event::Approval { collection, item, owner, spender: spender.clone() }.into(), + ); + // Successfully transfer the item by the delegated account `spender`. + assert_ok!(Nfts::transfer(signed(spender.clone()), collection, item, spender)); + }); +} + +#[test] +fn cancel_approval_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let spender = account(BOB); + let (collection, item) = + create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); + // Successfully cancel the transfer approval of `spender` by `owner`. + assert_ok!(NonFungibles::cancel_approval(signed(owner), collection, item, spender.clone())); + // Failed to transfer the item by `spender` without permission. + assert!(Nfts::transfer(signed(spender.clone()), collection, item, spender).is_err()); + }); +} + +#[test] +fn owner_of_works() {} + +#[test] +fn collection_owner_works() { + new_test_ext().execute_with(|| { + let collection = create_collection(account(ALICE)); + assert_eq!( + NonFungibles::read_state(CollectionOwner(collection)), + Nfts::collection_owner(collection).encode() + ); + }); +} + +#[test] +fn total_supply_works() { + new_test_ext().execute_with(|| { + let (collection, _) = create_collection_mint(account(ALICE), ITEM); + assert_eq!( + NonFungibles::read_state(TotalSupply(collection)), + (Nfts::items(&collection).count() as u8).encode() + ); + }); +} + +#[test] +fn collection_works() { + new_test_ext().execute_with(|| { + let (collection, _) = create_collection_mint(account(ALICE), ITEM); + assert_eq!( + NonFungibles::read_state(Collection(collection)), + pallet_nfts::Collection::::get(&collection).encode(), + ); + }); +} + +#[test] +fn balance_of_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let (collection, _) = create_collection_mint(owner.clone(), ITEM); + assert_eq!( + NonFungibles::read_state(BalanceOf { collection, owner: owner.clone() }), + (Nfts::owned_in_collection(&collection, &owner).count() as u8).encode() + ); + }); +} + +#[test] +fn allowance_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let spender = account(BOB); + let (collection, item) = + create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); + assert_eq!( + NonFungibles::read_state(Allowance { spender: spender.clone(), collection, item }), + super::Pallet::::allowance(collection, item, spender).encode() + ); + }); +} + +fn signed(account: AccountId) -> RuntimeOrigin { + RuntimeOrigin::signed(account) +} + +fn create_collection_mint_and_approve( + owner: AccountIdOf, + item: ItemIdOf, + spender: AccountIdOf, +) -> (u32, u32) { + let (collection, item) = create_collection_mint(owner.clone(), item); + assert_ok!(Nfts::approve_transfer(signed(owner), collection, item, spender, None)); + (collection, item) +} + +fn create_collection_mint(owner: AccountIdOf, item: ItemIdOf) -> (u32, u32) { + let collection = create_collection(owner.clone()); + assert_ok!(Nfts::mint(signed(owner.clone()), collection, item, owner, None)); + (collection, item) +} + +fn create_collection(owner: AccountIdOf) -> u32 { + let next_id = next_collection_id(); + assert_ok!(Nfts::create( + signed(owner.clone()), + owner.clone(), + collection_config_with_all_settings_enabled() + )); + next_id +} + +fn next_collection_id() -> u32 { + pallet_nfts::NextCollectionId::::get().unwrap_or_default() +} + +fn collection_config_with_all_settings_enabled( +) -> CollectionConfig, CollectionIdOf> { + CollectionConfig { + settings: CollectionSettings::all_enabled(), + max_supply: None, + mint_settings: MintSettings::default(), + } +} diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs new file mode 100644 index 000000000..0174ef77b --- /dev/null +++ b/pallets/api/src/nonfungibles/types.rs @@ -0,0 +1,61 @@ +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; +use frame_system::pallet_prelude::BlockNumberFor; +use scale_info::TypeInfo; +use sp_runtime::BoundedBTreeMap; + +use super::Config; + +pub(super) type AccountIdOf = ::AccountId; + +pub(super) type NftsOf = pallet_nfts::Pallet; + +/// Weight information for extrinsics in this pallet. +pub(super) type NftsWeightInfoOf = ::WeightInfo; + +/// A type alias for the collection ID. +pub(super) type CollectionIdOf = + as Inspect<::AccountId>>::CollectionId; + +/// A type alias for the collection item ID. +pub(super) type ItemIdOf = + as Inspect<::AccountId>>::ItemId; + +// TODO: Even though this serves the `allowance` method, it creates the maintenance cost. + +/// A type that holds the deposit for a single item. +pub(super) type ItemDepositOf = + ItemDeposit, ::AccountId>; + +/// A type alias for handling balance deposits. +pub(super) type DepositBalanceOf = <::Currency as Currency< + ::AccountId, +>>::Balance; + +/// A type alias for keeping track of approvals used by a single item. +pub(super) type ApprovalsOf = BoundedBTreeMap< + AccountIdOf, + Option>, + ::ApprovalsLimit, +>; + +/// Information concerning the ownership of a single unique item. +#[derive(Clone, Encode, Decode, Eq, PartialEq, TypeInfo, MaxEncodedLen)] +pub(super) struct ItemDetails { + /// The owner of this item. + pub(super) owner: AccountIdOf, + /// The approved transferrer of this item, if one is set. + pub(super) approvals: ApprovalsOf, + /// The amount held in the pallet's default account for this item. Free-hold items will have + /// this as zero. + pub(super) deposit: ItemDepositOf, +} + +/// Information about the reserved item deposit. +#[derive(Clone, Encode, Decode, Eq, PartialEq, TypeInfo, MaxEncodedLen)] +pub struct ItemDeposit { + /// A depositor account. + pub(super) account: AccountId, + /// An amount that gets reserved. + pub(super) amount: DepositBalance, +} From 4c0acaf6e907237b5fd51b4596148687e57baf86 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:12:39 +0700 Subject: [PATCH 04/76] chore: add nfts pallet --- Cargo.lock | 2 +- pallets/api/src/nonfungibles/mod.rs | 171 +++++++++--- pallets/api/src/nonfungibles/tests.rs | 367 +++++++++++++------------- pallets/api/src/nonfungibles/types.rs | 57 ++-- pallets/nfts/Cargo.toml | 1 - 5 files changed, 357 insertions(+), 241 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f98f910e..ed534195c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7366,7 +7366,7 @@ dependencies = [ "log", "pallet-assets", "pallet-balances", - "pallet-nfts", + "pallet-nfts 31.0.0", "parity-scale-codec", "pop-chain-extension", "scale-info", diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index cac0cbbab..c5e8cffbe 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -2,10 +2,9 @@ //! assets. The goal is to provide a simplified, consistent API that adheres to standards in the //! smart contract space. -use frame_support::traits::nonfungibles_v2::InspectEnumerable; pub use pallet::*; use pallet_nfts::WeightInfo; -use sp_runtime::traits::StaticLookup; +use sp_runtime::{traits::StaticLookup, RuntimeDebug}; #[cfg(test)] mod tests; @@ -16,12 +15,16 @@ pub mod pallet { use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; use frame_system::pallet_prelude::*; use sp_std::vec::Vec; - use types::{AccountIdOf, CollectionIdOf, ItemDetails, ItemIdOf, NftsOf, NftsWeightInfoOf}; + use types::{ + AccountIdOf, BalanceOf, CollectionDetailsFor, CollectionIdOf, ItemDetailsFor, ItemIdOf, + NftsOf, NftsWeightInfoOf, + }; use super::*; - /// State reads for the fungibles API with required input. + /// State reads for the non-fungibles API with required input. #[derive(Encode, Decode, Debug, MaxEncodedLen)] + #[cfg_attr(feature = "std", derive(PartialEq, Clone))] #[repr(u8)] #[allow(clippy::unnecessary_cast)] pub enum Read { @@ -45,7 +48,41 @@ pub mod pallet { Item { collection: CollectionIdOf, item: ItemIdOf }, /// Whether a spender is allowed to transfer an item or items from owner. #[codec(index = 6)] - Allowance { spender: AccountIdOf, collection: CollectionIdOf, item: ItemIdOf }, + Allowance { + collection: CollectionIdOf, + owner: AccountIdOf, + operator: AccountIdOf, + item: Option>, + }, + } + + /// Results of state reads for the non-fungibles API. + #[derive(Debug)] + #[cfg_attr(feature = "std", derive(PartialEq, Clone))] + pub enum ReadResult { + OwnerOf(Option>), + CollectionOwner(Option>), + TotalSupply(u32), + BalanceOf(BalanceOf), + Collection(Option>), + Item(Option>), + Allowance(bool), + } + + impl ReadResult { + /// Encodes the result. + pub fn encode(&self) -> Vec { + use ReadResult::*; + match self { + OwnerOf(result) => result.encode(), + CollectionOwner(result) => result.encode(), + TotalSupply(result) => result.encode(), + BalanceOf(result) => result.encode(), + Collection(result) => result.encode(), + Item(result) => result.encode(), + Allowance(result) => result.encode(), + } + } } /// Configure the pallet by specifying the parameters and types on which it depends. @@ -55,6 +92,32 @@ pub mod pallet { type RuntimeEvent: From> + IsType<::RuntimeEvent>; } + #[pallet::storage] + type AccountBalance = StorageNMap< + Key = ( + // Collection ID + NMapKey>, + // Collection Owner ID + NMapKey>, + ), + Value = BalanceOf, + QueryKind = ValueQuery, + >; + + #[pallet::storage] + type Allowances = StorageNMap< + Key = ( + // Collection ID + NMapKey>, + // Collection Owner ID + NMapKey>, + // Collection Operator ID + NMapKey>, + ), + Value = bool, + QueryKind = ValueQuery, + >; + #[pallet::pallet] pub struct Pallet(_); @@ -221,40 +284,86 @@ pub mod pallet { } impl Pallet { - /// Reads fungible asset state based on the provided value. - /// - /// This function matches the value to determine the type of state query and returns the - /// encoded result. - /// - /// # Parameter - /// - `value` - An instance of `Read`, which specifies the type of state query and the - /// associated parameters. - pub fn read_state(value: Read) -> Vec { - use Read::*; - match value { - OwnerOf { collection, item } => NftsOf::::owner(collection, item).encode(), - CollectionOwner(collection) => NftsOf::::collection_owner(collection).encode(), - TotalSupply(collection) => (NftsOf::::items(&collection).count() as u8).encode(), - Collection(collection) => pallet_nfts::Collection::::get(&collection).encode(), - Item { collection, item } => pallet_nfts::Item::::get(collection, item).encode(), - Allowance { collection, item, spender } => - Self::allowance(collection, item, spender).encode(), - BalanceOf { collection, owner } => - (NftsOf::::owned_in_collection(&collection, &owner).count() as u8).encode(), - } + /// Check if the `spender` is approved to transfer the collection item. + pub(super) fn allowance( + collection: CollectionIdOf, + owner: AccountIdOf, + operator: AccountIdOf, + maybe_item: Option>, + ) -> bool { + // Check if has a permission to transfer all collection items. + Allowances::::get((collection, owner, operator.clone())) || + maybe_item + .and_then(|item| Some(Self::allowance_item(collection, operator, item))) + .unwrap_or(false) } - /// Check if the `spender` is approved to transfer the collection item - pub(super) fn allowance( + // Check the permission for the single item. + pub(super) fn allowance_item( collection: CollectionIdOf, + operator: AccountIdOf, item: ItemIdOf, - spender: AccountIdOf, ) -> bool { let data = pallet_nfts::Item::::get(collection, item).encode(); - if let Ok(detail) = ItemDetails::::decode(&mut data.as_slice()) { - return detail.approvals.contains_key(&spender); + if let Ok(detail) = ItemDetailsFor::::decode(&mut data.as_slice()) { + return detail.approvals.contains_key(&operator); } false } } + + impl crate::Read for Pallet { + /// The type of read requested. + type Read = Read; + /// The type or result returned. + type Result = ReadResult; + + /// Determines the weight of the requested read, used to charge the appropriate weight + /// before the read is performed. + /// + /// # Parameters + /// - `request` - The read request. + fn weight(_request: &Self::Read) -> Weight { + Default::default() + } + + /// Performs the requested read and returns the result. + /// + /// # Parameters + /// - `request` - The read request. + fn read(value: Self::Read) -> Self::Result { + use Read::*; + match value { + OwnerOf { collection, item } => + ReadResult::OwnerOf(NftsOf::::owner(collection, item)), + CollectionOwner(collection) => + ReadResult::CollectionOwner(NftsOf::::collection_owner(collection)), + TotalSupply(collection) => { + let data = pallet_nfts::Collection::::get(collection).encode(); + ReadResult::TotalSupply( + CollectionDetailsFor::::decode(&mut data.as_slice()) + .map(|detail| detail.items) + .unwrap_or_default(), + ) + }, + Collection(collection) => { + let data = pallet_nfts::Collection::::get(collection).encode(); + ReadResult::Collection( + Option::>::decode(&mut data.as_slice()) + .unwrap_or(None), + ) + }, + Item { collection, item } => { + let data = pallet_nfts::Item::::get(collection, item).encode(); + ReadResult::Item( + Option::>::decode(&mut data.as_slice()).unwrap_or(None), + ) + }, + Allowance { collection, owner, operator, item } => + ReadResult::Allowance(Self::allowance(collection, owner, operator, item)), + BalanceOf { collection, owner } => + ReadResult::BalanceOf(AccountBalance::::get((collection, owner))), + } + } + } } diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index 9e9da5c27..54d855167 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -1,183 +1,184 @@ -use codec::Encode; -use frame_support::{assert_ok, traits::nonfungibles_v2::InspectEnumerable}; -use frame_system::pallet_prelude::BlockNumberFor; -use pallet_nfts::{CollectionConfig, CollectionSettings, MintSettings}; - -use super::types::*; -use crate::{ - mock::*, - nonfungibles::{Event, Read::*}, -}; - -const ITEM: u32 = 1; - -#[test] -fn mint_works() { - new_test_ext().execute_with(|| { - let owner = account(ALICE); - let collection = create_collection(owner.clone()); - // Successfully mint a new collection item. - assert_ok!(NonFungibles::mint(signed(owner.clone()), owner.clone(), collection, ITEM)); - System::assert_last_event(Event::Mint { to: owner, collection, item: ITEM }.into()); - }); -} - -#[test] -fn burn_works() { - new_test_ext().execute_with(|| { - let owner = account(ALICE); - let (collection, item) = create_collection_mint(owner.clone(), ITEM); - // Successfully burn an existing new collection item. - assert_ok!(NonFungibles::burn(signed(owner.clone()), collection, ITEM)); - System::assert_last_event(Event::Burn { collection, item }.into()); - }); -} - -#[test] -fn transfer() { - new_test_ext().execute_with(|| { - let owner = account(ALICE); - let dest = account(BOB); - let (collection, item) = create_collection_mint(owner.clone(), ITEM); - // Successfully burn an existing new collection item. - assert_ok!(NonFungibles::transfer(signed(owner.clone()), collection, ITEM, dest.clone())); - System::assert_last_event( - Event::Transfer { collection, item, from: owner, to: dest }.into(), - ); - }); -} - -#[test] -fn approve_works() { - new_test_ext().execute_with(|| { - let owner = account(ALICE); - let spender = account(BOB); - let (collection, item) = create_collection_mint(owner.clone(), ITEM); - // Successfully approve `spender` to transfer the collection item. - assert_ok!(NonFungibles::approve(signed(owner.clone()), collection, item, spender.clone())); - System::assert_last_event( - Event::Approval { collection, item, owner, spender: spender.clone() }.into(), - ); - // Successfully transfer the item by the delegated account `spender`. - assert_ok!(Nfts::transfer(signed(spender.clone()), collection, item, spender)); - }); -} - -#[test] -fn cancel_approval_works() { - new_test_ext().execute_with(|| { - let owner = account(ALICE); - let spender = account(BOB); - let (collection, item) = - create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); - // Successfully cancel the transfer approval of `spender` by `owner`. - assert_ok!(NonFungibles::cancel_approval(signed(owner), collection, item, spender.clone())); - // Failed to transfer the item by `spender` without permission. - assert!(Nfts::transfer(signed(spender.clone()), collection, item, spender).is_err()); - }); -} - -#[test] -fn owner_of_works() {} - -#[test] -fn collection_owner_works() { - new_test_ext().execute_with(|| { - let collection = create_collection(account(ALICE)); - assert_eq!( - NonFungibles::read_state(CollectionOwner(collection)), - Nfts::collection_owner(collection).encode() - ); - }); -} - -#[test] -fn total_supply_works() { - new_test_ext().execute_with(|| { - let (collection, _) = create_collection_mint(account(ALICE), ITEM); - assert_eq!( - NonFungibles::read_state(TotalSupply(collection)), - (Nfts::items(&collection).count() as u8).encode() - ); - }); -} - -#[test] -fn collection_works() { - new_test_ext().execute_with(|| { - let (collection, _) = create_collection_mint(account(ALICE), ITEM); - assert_eq!( - NonFungibles::read_state(Collection(collection)), - pallet_nfts::Collection::::get(&collection).encode(), - ); - }); -} - -#[test] -fn balance_of_works() { - new_test_ext().execute_with(|| { - let owner = account(ALICE); - let (collection, _) = create_collection_mint(owner.clone(), ITEM); - assert_eq!( - NonFungibles::read_state(BalanceOf { collection, owner: owner.clone() }), - (Nfts::owned_in_collection(&collection, &owner).count() as u8).encode() - ); - }); -} - -#[test] -fn allowance_works() { - new_test_ext().execute_with(|| { - let owner = account(ALICE); - let spender = account(BOB); - let (collection, item) = - create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); - assert_eq!( - NonFungibles::read_state(Allowance { spender: spender.clone(), collection, item }), - super::Pallet::::allowance(collection, item, spender).encode() - ); - }); -} - -fn signed(account: AccountId) -> RuntimeOrigin { - RuntimeOrigin::signed(account) -} - -fn create_collection_mint_and_approve( - owner: AccountIdOf, - item: ItemIdOf, - spender: AccountIdOf, -) -> (u32, u32) { - let (collection, item) = create_collection_mint(owner.clone(), item); - assert_ok!(Nfts::approve_transfer(signed(owner), collection, item, spender, None)); - (collection, item) -} - -fn create_collection_mint(owner: AccountIdOf, item: ItemIdOf) -> (u32, u32) { - let collection = create_collection(owner.clone()); - assert_ok!(Nfts::mint(signed(owner.clone()), collection, item, owner, None)); - (collection, item) -} - -fn create_collection(owner: AccountIdOf) -> u32 { - let next_id = next_collection_id(); - assert_ok!(Nfts::create( - signed(owner.clone()), - owner.clone(), - collection_config_with_all_settings_enabled() - )); - next_id -} - -fn next_collection_id() -> u32 { - pallet_nfts::NextCollectionId::::get().unwrap_or_default() -} - -fn collection_config_with_all_settings_enabled( -) -> CollectionConfig, CollectionIdOf> { - CollectionConfig { - settings: CollectionSettings::all_enabled(), - max_supply: None, - mint_settings: MintSettings::default(), - } -} +// TODO +// use codec::Encode; +// use frame_support::{assert_ok, traits::nonfungibles_v2::InspectEnumerable}; +// use frame_system::pallet_prelude::BlockNumberFor; +// use pallet_nfts::{CollectionConfig, CollectionSettings, MintSettings}; + +// use super::types::*; +// use crate::{ +// mock::*, +// nonfungibles::{Event, Read::*}, +// }; + +// const ITEM: u32 = 1; + +// #[test] +// fn mint_works() { +// new_test_ext().execute_with(|| { +// let owner = account(ALICE); +// let collection = create_collection(owner.clone()); +// // Successfully mint a new collection item. +// assert_ok!(NonFungibles::mint(signed(owner.clone()), owner.clone(), collection, ITEM)); +// System::assert_last_event(Event::Mint { to: owner, collection, item: ITEM }.into()); +// }); +// } + +// #[test] +// fn burn_works() { +// new_test_ext().execute_with(|| { +// let owner = account(ALICE); +// let (collection, item) = create_collection_mint(owner.clone(), ITEM); +// // Successfully burn an existing new collection item. +// assert_ok!(NonFungibles::burn(signed(owner.clone()), collection, ITEM)); +// System::assert_last_event(Event::Burn { collection, item }.into()); +// }); +// } + +// #[test] +// fn transfer() { +// new_test_ext().execute_with(|| { +// let owner = account(ALICE); +// let dest = account(BOB); +// let (collection, item) = create_collection_mint(owner.clone(), ITEM); +// // Successfully burn an existing new collection item. +// assert_ok!(NonFungibles::transfer(signed(owner.clone()), collection, ITEM, dest.clone())); +// System::assert_last_event( +// Event::Transfer { collection, item, from: owner, to: dest }.into(), +// ); +// }); +// } + +// #[test] +// fn approve_works() { +// new_test_ext().execute_with(|| { +// let owner = account(ALICE); +// let spender = account(BOB); +// let (collection, item) = create_collection_mint(owner.clone(), ITEM); +// // Successfully approve `spender` to transfer the collection item. +// assert_ok!(NonFungibles::approve(signed(owner.clone()), collection, item, spender.clone())); +// System::assert_last_event( +// Event::Approval { collection, item, owner, spender: spender.clone() }.into(), +// ); +// // Successfully transfer the item by the delegated account `spender`. +// assert_ok!(Nfts::transfer(signed(spender.clone()), collection, item, spender)); +// }); +// } + +// #[test] +// fn cancel_approval_works() { +// new_test_ext().execute_with(|| { +// let owner = account(ALICE); +// let spender = account(BOB); +// let (collection, item) = +// create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); +// // Successfully cancel the transfer approval of `spender` by `owner`. +// assert_ok!(NonFungibles::cancel_approval(signed(owner), collection, item, spender.clone())); +// // Failed to transfer the item by `spender` without permission. +// assert!(Nfts::transfer(signed(spender.clone()), collection, item, spender).is_err()); +// }); +// } + +// #[test] +// fn owner_of_works() {} + +// #[test] +// fn collection_owner_works() { +// new_test_ext().execute_with(|| { +// let collection = create_collection(account(ALICE)); +// assert_eq!( +// NonFungibles::read_state(CollectionOwner(collection)), +// Nfts::collection_owner(collection).encode() +// ); +// }); +// } + +// #[test] +// fn total_supply_works() { +// new_test_ext().execute_with(|| { +// let (collection, _) = create_collection_mint(account(ALICE), ITEM); +// assert_eq!( +// NonFungibles::read_state(TotalSupply(collection)), +// (Nfts::items(&collection).count() as u8).encode() +// ); +// }); +// } + +// #[test] +// fn collection_works() { +// new_test_ext().execute_with(|| { +// let (collection, _) = create_collection_mint(account(ALICE), ITEM); +// assert_eq!( +// NonFungibles::read_state(Collection(collection)), +// pallet_nfts::Collection::::get(&collection).encode(), +// ); +// }); +// } + +// #[test] +// fn balance_of_works() { +// new_test_ext().execute_with(|| { +// let owner = account(ALICE); +// let (collection, _) = create_collection_mint(owner.clone(), ITEM); +// assert_eq!( +// NonFungibles::read_state(BalanceOf { collection, owner: owner.clone() }), +// (Nfts::owned_in_collection(&collection, &owner).count() as u8).encode() +// ); +// }); +// } + +// #[test] +// fn allowance_works() { +// new_test_ext().execute_with(|| { +// let owner = account(ALICE); +// let spender = account(BOB); +// let (collection, item) = +// create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); +// assert_eq!( +// NonFungibles::read_state(Allowance { spender: spender.clone(), collection, item }), +// super::Pallet::::allowance(collection, item, spender).encode() +// ); +// }); +// } + +// fn signed(account: AccountId) -> RuntimeOrigin { +// RuntimeOrigin::signed(account) +// } + +// fn create_collection_mint_and_approve( +// owner: AccountIdOf, +// item: ItemIdOf, +// spender: AccountIdOf, +// ) -> (u32, u32) { +// let (collection, item) = create_collection_mint(owner.clone(), item); +// assert_ok!(Nfts::approve_transfer(signed(owner), collection, item, spender, None)); +// (collection, item) +// } + +// fn create_collection_mint(owner: AccountIdOf, item: ItemIdOf) -> (u32, u32) { +// let collection = create_collection(owner.clone()); +// assert_ok!(Nfts::mint(signed(owner.clone()), collection, item, owner, None)); +// (collection, item) +// } + +// fn create_collection(owner: AccountIdOf) -> u32 { +// let next_id = next_collection_id(); +// assert_ok!(Nfts::create( +// signed(owner.clone()), +// owner.clone(), +// collection_config_with_all_settings_enabled() +// )); +// next_id +// } + +// fn next_collection_id() -> u32 { +// pallet_nfts::NextCollectionId::::get().unwrap_or_default() +// } + +// fn collection_config_with_all_settings_enabled( +// ) -> CollectionConfig, CollectionIdOf> { +// CollectionConfig { +// settings: CollectionSettings::all_enabled(), +// max_supply: None, +// mint_settings: MintSettings::default(), +// } +// } diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs index 0174ef77b..a55a8ec26 100644 --- a/pallets/api/src/nonfungibles/types.rs +++ b/pallets/api/src/nonfungibles/types.rs @@ -4,34 +4,22 @@ use frame_system::pallet_prelude::BlockNumberFor; use scale_info::TypeInfo; use sp_runtime::BoundedBTreeMap; -use super::Config; +use super::*; pub(super) type AccountIdOf = ::AccountId; - pub(super) type NftsOf = pallet_nfts::Pallet; - /// Weight information for extrinsics in this pallet. pub(super) type NftsWeightInfoOf = ::WeightInfo; - /// A type alias for the collection ID. pub(super) type CollectionIdOf = - as Inspect<::AccountId>>::CollectionId; - + as Inspect<::AccountId>>::CollectionId; /// A type alias for the collection item ID. pub(super) type ItemIdOf = - as Inspect<::AccountId>>::ItemId; - -// TODO: Even though this serves the `allowance` method, it creates the maintenance cost. - -/// A type that holds the deposit for a single item. -pub(super) type ItemDepositOf = - ItemDeposit, ::AccountId>; - + as Inspect<::AccountId>>::ItemId; /// A type alias for handling balance deposits. -pub(super) type DepositBalanceOf = <::Currency as Currency< +pub(super) type BalanceOf = <::Currency as Currency< ::AccountId, >>::Balance; - /// A type alias for keeping track of approvals used by a single item. pub(super) type ApprovalsOf = BoundedBTreeMap< AccountIdOf, @@ -39,23 +27,42 @@ pub(super) type ApprovalsOf = BoundedBTreeMap< ::ApprovalsLimit, >; +pub(super) type ItemDetailsFor = ItemDetails, BalanceOf, ApprovalsOf>; +pub(super) type CollectionDetailsFor = CollectionDetails, BalanceOf>; + /// Information concerning the ownership of a single unique item. -#[derive(Clone, Encode, Decode, Eq, PartialEq, TypeInfo, MaxEncodedLen)] -pub(super) struct ItemDetails { +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct ItemDetails { /// The owner of this item. - pub(super) owner: AccountIdOf, + pub owner: AccountId, /// The approved transferrer of this item, if one is set. - pub(super) approvals: ApprovalsOf, + pub approvals: Approvals, /// The amount held in the pallet's default account for this item. Free-hold items will have /// this as zero. - pub(super) deposit: ItemDepositOf, + pub deposit: Deposit, } - /// Information about the reserved item deposit. -#[derive(Clone, Encode, Decode, Eq, PartialEq, TypeInfo, MaxEncodedLen)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct ItemDeposit { /// A depositor account. - pub(super) account: AccountId, + account: AccountId, /// An amount that gets reserved. - pub(super) amount: DepositBalance, + amount: DepositBalance, +} +/// Information about a collection. +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct CollectionDetails { + /// Collection's owner. + pub owner: AccountId, + /// The total balance deposited by the owner for all the storage data associated with this + /// collection. Used by `destroy`. + pub owner_deposit: DepositBalance, + /// The total number of outstanding items of this collection. + pub items: u32, + /// The total number of outstanding item metadata of this collection. + pub item_metadatas: u32, + /// The total number of outstanding item configs of this collection. + pub item_configs: u32, + /// The total number of attributes for this collection. + pub attributes: u32, } diff --git a/pallets/nfts/Cargo.toml b/pallets/nfts/Cargo.toml index f23b50f00..7644a35ba 100644 --- a/pallets/nfts/Cargo.toml +++ b/pallets/nfts/Cargo.toml @@ -9,7 +9,6 @@ readme = "README.md" repository.workspace = true version = "31.0.0" - [package.metadata.docs.rs] targets = [ "x86_64-unknown-linux-gnu" ] From b4420cb53585ce149f5cdfbe1937b617aad4df55 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 15 Oct 2024 21:23:52 +0700 Subject: [PATCH 05/76] feat: add new storage items to pallet-nfts --- pallets/api/src/nonfungibles/mod.rs | 101 +++--------------- pallets/api/src/nonfungibles/types.rs | 68 +++--------- pallets/nfts/src/common_functions.rs | 7 +- pallets/nfts/src/features/approvals.rs | 85 ++++++++++++++- .../src/features/create_delete_collection.rs | 3 + .../nfts/src/features/create_delete_item.rs | 6 ++ pallets/nfts/src/features/transfer.rs | 8 ++ pallets/nfts/src/lib.rs | 88 ++++++++++++++- 8 files changed, 220 insertions(+), 146 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index c5e8cffbe..cf2b14e7e 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -4,7 +4,7 @@ pub use pallet::*; use pallet_nfts::WeightInfo; -use sp_runtime::{traits::StaticLookup, RuntimeDebug}; +use sp_runtime::traits::StaticLookup; #[cfg(test)] mod tests; @@ -16,8 +16,8 @@ pub mod pallet { use frame_system::pallet_prelude::*; use sp_std::vec::Vec; use types::{ - AccountIdOf, BalanceOf, CollectionDetailsFor, CollectionIdOf, ItemDetailsFor, ItemIdOf, - NftsOf, NftsWeightInfoOf, + AccountIdOf, CollectionDetailsFor, CollectionIdOf, ItemDetailsFor, ItemIdOf, NftsOf, + NftsWeightInfoOf, }; use super::*; @@ -63,7 +63,7 @@ pub mod pallet { OwnerOf(Option>), CollectionOwner(Option>), TotalSupply(u32), - BalanceOf(BalanceOf), + BalanceOf(u32), Collection(Option>), Item(Option>), Allowance(bool), @@ -92,32 +92,6 @@ pub mod pallet { type RuntimeEvent: From> + IsType<::RuntimeEvent>; } - #[pallet::storage] - type AccountBalance = StorageNMap< - Key = ( - // Collection ID - NMapKey>, - // Collection Owner ID - NMapKey>, - ), - Value = BalanceOf, - QueryKind = ValueQuery, - >; - - #[pallet::storage] - type Allowances = StorageNMap< - Key = ( - // Collection ID - NMapKey>, - // Collection Owner ID - NMapKey>, - // Collection Operator ID - NMapKey>, - ), - Value = bool, - QueryKind = ValueQuery, - >; - #[pallet::pallet] pub struct Pallet(_); @@ -283,35 +257,6 @@ pub mod pallet { } } - impl Pallet { - /// Check if the `spender` is approved to transfer the collection item. - pub(super) fn allowance( - collection: CollectionIdOf, - owner: AccountIdOf, - operator: AccountIdOf, - maybe_item: Option>, - ) -> bool { - // Check if has a permission to transfer all collection items. - Allowances::::get((collection, owner, operator.clone())) || - maybe_item - .and_then(|item| Some(Self::allowance_item(collection, operator, item))) - .unwrap_or(false) - } - - // Check the permission for the single item. - pub(super) fn allowance_item( - collection: CollectionIdOf, - operator: AccountIdOf, - item: ItemIdOf, - ) -> bool { - let data = pallet_nfts::Item::::get(collection, item).encode(); - if let Ok(detail) = ItemDetailsFor::::decode(&mut data.as_slice()) { - return detail.approvals.contains_key(&operator); - } - false - } - } - impl crate::Read for Pallet { /// The type of read requested. type Read = Read; @@ -338,31 +283,19 @@ pub mod pallet { ReadResult::OwnerOf(NftsOf::::owner(collection, item)), CollectionOwner(collection) => ReadResult::CollectionOwner(NftsOf::::collection_owner(collection)), - TotalSupply(collection) => { - let data = pallet_nfts::Collection::::get(collection).encode(); - ReadResult::TotalSupply( - CollectionDetailsFor::::decode(&mut data.as_slice()) - .map(|detail| detail.items) - .unwrap_or_default(), - ) - }, - Collection(collection) => { - let data = pallet_nfts::Collection::::get(collection).encode(); - ReadResult::Collection( - Option::>::decode(&mut data.as_slice()) - .unwrap_or(None), - ) - }, - Item { collection, item } => { - let data = pallet_nfts::Item::::get(collection, item).encode(); - ReadResult::Item( - Option::>::decode(&mut data.as_slice()).unwrap_or(None), - ) - }, - Allowance { collection, owner, operator, item } => - ReadResult::Allowance(Self::allowance(collection, owner, operator, item)), - BalanceOf { collection, owner } => - ReadResult::BalanceOf(AccountBalance::::get((collection, owner))), + TotalSupply(collection) => ReadResult::TotalSupply( + NftsOf::::collection_items(collection).unwrap_or_default(), + ), + Collection(collection) => + ReadResult::Collection(pallet_nfts::Collection::::get(collection)), + Item { collection, item } => + ReadResult::Item(pallet_nfts::Item::::get(collection, item)), + Allowance { collection, owner, operator, item } => ReadResult::Allowance( + NftsOf::::allowance(collection, item, owner, operator).unwrap_or(false), + ), + BalanceOf { collection, owner } => ReadResult::BalanceOf( + pallet_nfts::AccountBalance::::get((collection, owner)), + ), } } } diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs index a55a8ec26..f81ea5359 100644 --- a/pallets/api/src/nonfungibles/types.rs +++ b/pallets/api/src/nonfungibles/types.rs @@ -1,68 +1,28 @@ -use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; use frame_system::pallet_prelude::BlockNumberFor; -use scale_info::TypeInfo; +use pallet_nfts::{CollectionDetails, ItemDeposit, ItemDetails}; use sp_runtime::BoundedBTreeMap; -use super::*; - -pub(super) type AccountIdOf = ::AccountId; +// Type aliases for pallet-nfts. pub(super) type NftsOf = pallet_nfts::Pallet; -/// Weight information for extrinsics in this pallet. pub(super) type NftsWeightInfoOf = ::WeightInfo; -/// A type alias for the collection ID. +// Type aliases for pallet-nfts storage items. +pub(super) type AccountIdOf = ::AccountId; +pub(super) type BalanceOf = <>::Currency as Currency< + ::AccountId, +>>::Balance; pub(super) type CollectionIdOf = as Inspect<::AccountId>>::CollectionId; -/// A type alias for the collection item ID. pub(super) type ItemIdOf = as Inspect<::AccountId>>::ItemId; -/// A type alias for handling balance deposits. -pub(super) type BalanceOf = <::Currency as Currency< - ::AccountId, ->>::Balance; -/// A type alias for keeping track of approvals used by a single item. -pub(super) type ApprovalsOf = BoundedBTreeMap< +type ApprovalsOf = BoundedBTreeMap< AccountIdOf, Option>, ::ApprovalsLimit, >; - -pub(super) type ItemDetailsFor = ItemDetails, BalanceOf, ApprovalsOf>; -pub(super) type CollectionDetailsFor = CollectionDetails, BalanceOf>; - -/// Information concerning the ownership of a single unique item. -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub struct ItemDetails { - /// The owner of this item. - pub owner: AccountId, - /// The approved transferrer of this item, if one is set. - pub approvals: Approvals, - /// The amount held in the pallet's default account for this item. Free-hold items will have - /// this as zero. - pub deposit: Deposit, -} -/// Information about the reserved item deposit. -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub struct ItemDeposit { - /// A depositor account. - account: AccountId, - /// An amount that gets reserved. - amount: DepositBalance, -} -/// Information about a collection. -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub struct CollectionDetails { - /// Collection's owner. - pub owner: AccountId, - /// The total balance deposited by the owner for all the storage data associated with this - /// collection. Used by `destroy`. - pub owner_deposit: DepositBalance, - /// The total number of outstanding items of this collection. - pub items: u32, - /// The total number of outstanding item metadata of this collection. - pub item_metadatas: u32, - /// The total number of outstanding item configs of this collection. - pub item_configs: u32, - /// The total number of attributes for this collection. - pub attributes: u32, -} +// TODO: Multi-instances. +pub(super) type ItemDepositOf = ItemDeposit, AccountIdOf>; +pub(super) type CollectionDetailsFor = + CollectionDetails, BalanceOf>; +pub(super) type ItemDetailsFor = + ItemDetails, ItemDepositOf, ApprovalsOf>; diff --git a/pallets/nfts/src/common_functions.rs b/pallets/nfts/src/common_functions.rs index f51de1922..6fe483f1a 100644 --- a/pallets/nfts/src/common_functions.rs +++ b/pallets/nfts/src/common_functions.rs @@ -34,6 +34,11 @@ impl, I: 'static> Pallet { Collection::::get(collection).map(|i| i.owner) } + /// Get the total number of items in the collection, if the collection exists. + pub fn collection_items(collection: T::CollectionId) -> Option { + Collection::::get(collection).map(|i| i.items) + } + /// Validates the signature of the given data with the provided signer's account ID. /// /// # Errors @@ -46,7 +51,7 @@ impl, I: 'static> Pallet { signer: &T::AccountId, ) -> DispatchResult { if signature.verify(&**data, &signer) { - return Ok(()) + return Ok(()); } // NOTE: for security reasons modern UIs implicitly wrap the data requested to sign into diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index ad5d93c2e..f626a9fe9 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -65,7 +65,6 @@ impl, I: 'static> Pallet { if let Some(check_origin) = maybe_check_origin { ensure!(check_origin == details.owner, Error::::NoPermission); } - let now = frame_system::Pallet::::block_number(); let deadline = maybe_deadline.map(|d| d.saturating_add(now)); @@ -74,15 +73,13 @@ impl, I: 'static> Pallet { .try_insert(delegate.clone(), deadline) .map_err(|_| Error::::ReachedApprovalLimit)?; Item::::insert(&collection, &item, &details); - Self::deposit_event(Event::TransferApproved { collection, - item, + item: Some(item), owner: details.owner, delegate, deadline, }); - Ok(()) } @@ -129,7 +126,7 @@ impl, I: 'static> Pallet { Self::deposit_event(Event::ApprovalCancelled { collection, - item, + item: Some(item), owner: details.owner, delegate, }); @@ -173,4 +170,82 @@ impl, I: 'static> Pallet { Ok(()) } + + pub(crate) fn do_approve_transfer_collection( + maybe_check_origin: Option, + collection: T::CollectionId, + delegate: T::AccountId, + ) -> DispatchResult { + ensure!( + Self::is_pallet_feature_enabled(PalletFeature::Approvals), + Error::::MethodDisabled + ); + let collection_owner = + Self::collection_owner(collection).ok_or(Error::::UnknownCollection)?; + + let collection_config = Self::get_collection_config(&collection)?; + ensure!( + collection_config.is_setting_enabled(CollectionSetting::TransferableItems), + Error::::ItemsNonTransferable + ); + + if let Some(check_origin) = maybe_check_origin { + ensure!(check_origin == collection_owner, Error::::NoPermission); + } + + Allowances::::mutate((&collection, &collection_owner, &delegate), |allowance| { + *allowance = true; + }); + + Self::deposit_event(Event::TransferApproved { + collection, + item: None, + owner: collection_owner, + delegate, + deadline: None, + }); + Ok(()) + } + + pub(crate) fn do_cancel_approval_collection( + maybe_check_origin: Option, + collection: T::CollectionId, + delegate: T::AccountId, + ) -> DispatchResult { + let collection_owner = + Self::collection_owner(collection).ok_or(Error::::UnknownCollection)?; + + if let Some(check_origin) = maybe_check_origin { + ensure!(check_origin == collection_owner, Error::::NoPermission); + } + + Allowances::::remove((&collection, &collection_owner, &delegate)); + + Self::deposit_event(Event::ApprovalCancelled { + collection, + owner: collection_owner, + item: None, + delegate, + }); + + Ok(()) + } + + pub fn allowance( + collection: T::CollectionId, + item: Option, + owner: T::AccountId, + delegate: T::AccountId, + ) -> Option { + // Check if a `delegate` has a permission to spend the collection. + if Allowances::::get((&collection, &owner, &delegate)) { + return Some(true); + } + // Check if a `delegate` has a permission to spend the collection item. + item.map(|item| { + Item::::get(&collection, &item) + .map(|detail| detail.approvals.contains_key(&delegate)) + }) + .unwrap_or_default() + } } diff --git a/pallets/nfts/src/features/create_delete_collection.rs b/pallets/nfts/src/features/create_delete_collection.rs index 348ec6b92..2ea5cd732 100644 --- a/pallets/nfts/src/features/create_delete_collection.rs +++ b/pallets/nfts/src/features/create_delete_collection.rs @@ -137,6 +137,9 @@ impl, I: 'static> Pallet { } } + let _ = + AccountBalance::::clear_prefix((collection,), collection_details.items, None); + let _ = Allowances::::clear_prefix((collection,), collection_details.items, None); CollectionAccount::::remove(&collection_details.owner, &collection); T::Currency::unreserve(&collection_details.owner, collection_details.owner_deposit); CollectionConfigOf::::remove(&collection); diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index e9843b2e7..036a63b70 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -69,6 +69,9 @@ impl, I: 'static> Pallet { } collection_details.items.saturating_inc(); + AccountBalance::::mutate((collection, &mint_to), |balance| { + balance.saturating_inc(); + }); let collection_config = Self::get_collection_config(&collection)?; let deposit_amount = match collection_config @@ -263,6 +266,9 @@ impl, I: 'static> Pallet { ItemPriceOf::::remove(&collection, &item); PendingSwapOf::::remove(&collection, &item); ItemAttributesApprovalsOf::::remove(&collection, &item); + AccountBalance::::mutate((collection, &owner), |balance| { + balance.saturating_dec(); + }); if remove_config { ItemConfigOf::::remove(&collection, &item); diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index b7223a7c3..0aa83fe8a 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -87,6 +87,14 @@ impl, I: 'static> Pallet { // Perform the transfer with custom details using the provided closure. with_details(&collection_details, &mut details)?; + // Update account balances. + AccountBalance::::mutate((collection, &details.owner), |balance| { + balance.saturating_dec(); + }); + AccountBalance::::mutate((collection, &dest), |balance| { + balance.saturating_dec(); + }); + // Update account ownership information. Account::::remove((&details.owner, &collection, &item)); Account::::insert((&dest, &collection, &item), ()); diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index 89bfb9637..9f4d3aedd 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -402,6 +402,36 @@ pub mod pallet { pub type CollectionConfigOf, I: 'static = ()> = StorageMap<_, Blake2_128Concat, T::CollectionId, CollectionConfigFor, OptionQuery>; + /// Number of collection items that accounts own. + #[pallet::storage] + pub type AccountBalance, I: 'static = ()> = StorageNMap< + _, + ( + // Collection Id. + NMapKey, + // Collection Owner Id. + NMapKey, + ), + u32, + ValueQuery, + >; + + /// Permission for the delegate to transfer all owner's items within a collection. + #[pallet::storage] + pub type Allowances, I: 'static = ()> = StorageNMap< + _, + ( + // Collection ID. + NMapKey, + // Collection Owner Id. + NMapKey, + // Delegate Id. + NMapKey, + ), + bool, + ValueQuery, + >; + /// Config of an item. #[pallet::storage] pub type ItemConfigOf, I: 'static = ()> = StorageDoubleMap< @@ -460,7 +490,7 @@ pub mod pallet { /// a `delegate`. TransferApproved { collection: T::CollectionId, - item: T::ItemId, + item: Option, owner: T::AccountId, delegate: T::AccountId, deadline: Option>, @@ -469,7 +499,7 @@ pub mod pallet { /// `collection` was cancelled by its `owner`. ApprovalCancelled { collection: T::CollectionId, - item: T::ItemId, + item: Option, owner: T::AccountId, delegate: T::AccountId, }, @@ -1931,6 +1961,60 @@ pub mod pallet { Self::validate_signature(&Encode::encode(&data), &signature, &signer)?; Self::do_set_attributes_pre_signed(origin, data, signer) } + + /// Approve an item to be transferred by a delegated third-party account. + /// + /// Origin must be either `ForceOrigin` or Signed and the sender should be the Owner of the + /// `item`. + /// + /// - `collection`: The collection of the item to be approved for delegated transfer. + /// - `item`: The item to be approved for delegated transfer. + /// - `delegate`: The account to delegate permission to transfer the item. + /// + /// Emits `TransferApproved` on success. + /// + /// Weight: `O(1)` + #[pallet::call_index(39)] + #[pallet::weight(T::WeightInfo::approve_transfer())] + pub fn approve_transfer_collection( + origin: OriginFor, + collection: T::CollectionId, + delegate: AccountIdLookupOf, + ) -> DispatchResult { + let maybe_check_origin = T::ForceOrigin::try_origin(origin) + .map(|_| None) + .or_else(|origin| ensure_signed(origin).map(Some).map_err(DispatchError::from))?; + let delegate = T::Lookup::lookup(delegate)?; + Self::do_approve_transfer_collection(maybe_check_origin, collection, delegate) + } + + /// Cancel one of the transfer approvals for a specific item. + /// + /// Origin must be either: + /// - the `Force` origin; + /// - `Signed` with the signer being the Owner of the `item`; + /// + /// Arguments: + /// - `collection`: The collection of the item of whose approval will be cancelled. + /// - `item`: The item of the collection of whose approval will be cancelled. + /// - `delegate`: The account that is going to loose their approval. + /// + /// Emits `ApprovalCancelled` on success. + /// + /// Weight: `O(1)` + #[pallet::call_index(40)] + #[pallet::weight(T::WeightInfo::cancel_approval())] + pub fn cancel_approval_collection( + origin: OriginFor, + collection: T::CollectionId, + delegate: AccountIdLookupOf, + ) -> DispatchResult { + let maybe_check_origin = T::ForceOrigin::try_origin(origin) + .map(|_| None) + .or_else(|origin| ensure_signed(origin).map(Some).map_err(DispatchError::from))?; + let delegate = T::Lookup::lookup(delegate)?; + Self::do_cancel_approval_collection(maybe_check_origin, collection, delegate) + } } } From 0ad3e31366e21fdaa2d4b61dd26f5cd8f73f4119 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 16 Oct 2024 22:30:14 +0700 Subject: [PATCH 06/76] feat: check allowance --- pallets/api/src/nonfungibles/mod.rs | 102 +++++++------------------ pallets/nfts/src/features/approvals.rs | 28 ++++--- pallets/nfts/src/features/transfer.rs | 6 +- pallets/nfts/src/lib.rs | 94 ++++++----------------- pallets/nfts/src/tests.rs | 93 +++++++++++++--------- 5 files changed, 128 insertions(+), 195 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index cf2b14e7e..bc728ac8c 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -62,7 +62,7 @@ pub mod pallet { pub enum ReadResult { OwnerOf(Option>), CollectionOwner(Option>), - TotalSupply(u32), + TotalSupply(u128), BalanceOf(u32), Collection(Option>), Item(Option>), @@ -99,25 +99,18 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// Event emitted when allowance by `owner` to `spender` canceled. - CancelApproval { - /// The collection ID. - collection: CollectionIdOf, - /// the item ID. - item: ItemIdOf, - /// The beneficiary of the allowance. - spender: AccountIdOf, - }, - /// Event emitted when allowance by `owner` to `spender` changes. + /// Event emitted when allowance by `owner` to `operator` changes. Approval { /// The collection ID. collection: CollectionIdOf, - /// the item ID. - item: ItemIdOf, /// The owner providing the allowance. owner: AccountIdOf, /// The beneficiary of the allowance. - spender: AccountIdOf, + operator: AccountIdOf, + /// The item which is (dis)approved. `None` for all owner's items. + item: Option>, + /// Whether allowance is set or removed. + approved: bool, }, /// Event emitted when new item is minted to the account. Mint { @@ -150,12 +143,6 @@ pub mod pallet { #[pallet::call] impl Pallet { - /// Create a new non-fungible token to the collection. - /// - /// # Parameters - /// - `to` - The owner of the collection item. - /// - `collection` - The collection ID. - /// - `item` - The item ID. #[pallet::call_index(0)] #[pallet::weight(NftsWeightInfoOf::::mint())] pub fn mint( @@ -169,11 +156,6 @@ pub mod pallet { Ok(()) } - /// Destroy a new non-fungible token to the collection. - /// - /// # Parameters - /// - `collection` - The collection ID. - /// - `item` - The item ID. #[pallet::call_index(1)] #[pallet::weight(NftsWeightInfoOf::::burn())] pub fn burn( @@ -186,12 +168,6 @@ pub mod pallet { Ok(()) } - /// Transfer a token from one account to the another account. - /// - /// # Parameters - /// - `collection` - The collection ID. - /// - `item` - The item ID. - /// - `to` - The recipient account. #[pallet::call_index(2)] #[pallet::weight(NftsWeightInfoOf::::transfer())] pub fn transfer( @@ -206,53 +182,33 @@ pub mod pallet { Ok(()) } - /// Delegate a permission to perform actions on the collection item to an account. - /// - /// # Parameters - /// - `collection` - The collection ID. - /// - `item` - The item ID. - /// - `spender` - The account that is allowed to transfer the collection item. #[pallet::call_index(3)] #[pallet::weight(NftsWeightInfoOf::::approve_transfer())] pub fn approve( origin: OriginFor, collection: CollectionIdOf, - item: ItemIdOf, - spender: AccountIdOf, + item: Option>, + operator: AccountIdOf, + approved: bool, ) -> DispatchResult { let owner = ensure_signed(origin.clone())?; - NftsOf::::approve_transfer( - origin, - collection, - item, - T::Lookup::unlookup(spender.clone()), - None, - )?; - Self::deposit_event(Event::Approval { collection, item, spender, owner }); - Ok(()) - } - - /// Cancel one of the transfer approvals for a specific item. - /// - /// # Parameters - /// - `collection` - The collection ID. - /// - `item` - The item ID. - /// - `spender` - The account that is revoked permission to transfer the collection item. - #[pallet::call_index(4)] - #[pallet::weight(NftsWeightInfoOf::::cancel_approval())] - pub fn cancel_approval( - origin: OriginFor, - collection: CollectionIdOf, - item: ItemIdOf, - spender: AccountIdOf, - ) -> DispatchResult { - NftsOf::::cancel_approval( - origin, - collection, - item, - T::Lookup::unlookup(spender.clone()), - )?; - Self::deposit_event(Event::CancelApproval { collection, item, spender }); + if approved { + NftsOf::::approve_transfer( + origin, + collection, + item, + T::Lookup::unlookup(operator.clone()), + None, + )?; + } else { + NftsOf::::cancel_approval( + origin, + collection, + item, + T::Lookup::unlookup(operator.clone()), + )?; + } + Self::deposit_event(Event::Approval { collection, item, operator, owner, approved }); Ok(()) } } @@ -284,14 +240,14 @@ pub mod pallet { CollectionOwner(collection) => ReadResult::CollectionOwner(NftsOf::::collection_owner(collection)), TotalSupply(collection) => ReadResult::TotalSupply( - NftsOf::::collection_items(collection).unwrap_or_default(), + NftsOf::::collection_items(collection).unwrap_or_default().into(), ), Collection(collection) => ReadResult::Collection(pallet_nfts::Collection::::get(collection)), Item { collection, item } => ReadResult::Item(pallet_nfts::Item::::get(collection, item)), Allowance { collection, owner, operator, item } => ReadResult::Allowance( - NftsOf::::allowance(collection, item, owner, operator).unwrap_or(false), + NftsOf::::allowance(&collection, &item, &owner, &operator).is_ok(), ), BalanceOf { collection, owner } => ReadResult::BalanceOf( pallet_nfts::AccountBalance::::get((collection, owner)), diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index f626a9fe9..979035fa6 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -232,20 +232,26 @@ impl, I: 'static> Pallet { } pub fn allowance( - collection: T::CollectionId, - item: Option, - owner: T::AccountId, - delegate: T::AccountId, - ) -> Option { + collection: &T::CollectionId, + item: &Option, + owner: &T::AccountId, + delegate: &T::AccountId, + ) -> Result<(), DispatchError> { // Check if a `delegate` has a permission to spend the collection. if Allowances::::get((&collection, &owner, &delegate)) { - return Some(true); + return Ok(()); } // Check if a `delegate` has a permission to spend the collection item. - item.map(|item| { - Item::::get(&collection, &item) - .map(|detail| detail.approvals.contains_key(&delegate)) - }) - .unwrap_or_default() + if let Some(item) = item { + let details = + Item::::get(&collection, &item).ok_or(Error::::UnknownItem)?; + + let deadline = details.approvals.get(&delegate).ok_or(Error::::NoPermission)?; + if let Some(d) = deadline { + let block_number = frame_system::Pallet::::block_number(); + ensure!(block_number <= *d, Error::::ApprovalExpired); + } + }; + Ok(()) } } diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index 0aa83fe8a..04d9f4fe8 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -92,7 +92,7 @@ impl, I: 'static> Pallet { balance.saturating_dec(); }); AccountBalance::::mutate((collection, &dest), |balance| { - balance.saturating_dec(); + balance.saturating_inc(); }); // Update account ownership information. @@ -145,7 +145,7 @@ impl, I: 'static> Pallet { // Check if the `origin` is the current owner of the collection. ensure!(origin == details.owner, Error::::NoPermission); if details.owner == new_owner { - return Ok(()) + return Ok(()); } // Move the deposit to the new owner. @@ -220,7 +220,7 @@ impl, I: 'static> Pallet { Collection::::try_mutate(collection, |maybe_details| { let details = maybe_details.as_mut().ok_or(Error::::UnknownCollection)?; if details.owner == owner { - return Ok(()) + return Ok(()); } // Move the deposit to the new owner. diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index 9f4d3aedd..146892935 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -1060,12 +1060,7 @@ pub mod pallet { Self::do_transfer(collection, item, dest, |_, details| { if details.owner != origin { - let deadline = - details.approvals.get(&origin).ok_or(Error::::NoPermission)?; - if let Some(d) = deadline { - let block_number = frame_system::Pallet::::block_number(); - ensure!(block_number <= *d, Error::::ApprovalExpired); - } + Self::allowance(&collection, &Some(item), &details.owner, &origin)?; } Ok(()) }) @@ -1120,10 +1115,10 @@ pub mod pallet { if T::Currency::reserve(&details.deposit.account, deposit - old).is_err() { // NOTE: No alterations made to collection_details in this iteration so far, // so this is OK to do. - continue + continue; } } else { - continue + continue; } details.deposit.amount = deposit; Item::::insert(&collection, &item, &details); @@ -1322,7 +1317,7 @@ pub mod pallet { pub fn approve_transfer( origin: OriginFor, collection: T::CollectionId, - item: T::ItemId, + maybe_item: Option, delegate: AccountIdLookupOf, maybe_deadline: Option>, ) -> DispatchResult { @@ -1330,13 +1325,17 @@ pub mod pallet { .map(|_| None) .or_else(|origin| ensure_signed(origin).map(Some).map_err(DispatchError::from))?; let delegate = T::Lookup::lookup(delegate)?; - Self::do_approve_transfer( - maybe_check_origin, - collection, - item, - delegate, - maybe_deadline, - ) + match maybe_item { + Some(item) => Self::do_approve_transfer( + maybe_check_origin, + collection, + item, + delegate, + maybe_deadline, + ), + None => + Self::do_approve_transfer_collection(maybe_check_origin, collection, delegate), + } } /// Cancel one of the transfer approvals for a specific item. @@ -1358,14 +1357,19 @@ pub mod pallet { pub fn cancel_approval( origin: OriginFor, collection: T::CollectionId, - item: T::ItemId, + maybe_item: Option, delegate: AccountIdLookupOf, ) -> DispatchResult { let maybe_check_origin = T::ForceOrigin::try_origin(origin) .map(|_| None) .or_else(|origin| ensure_signed(origin).map(Some).map_err(DispatchError::from))?; let delegate = T::Lookup::lookup(delegate)?; - Self::do_cancel_approval(maybe_check_origin, collection, item, delegate) + match maybe_item { + Some(item) => + Self::do_cancel_approval(maybe_check_origin, collection, item, delegate), + None => + Self::do_cancel_approval_collection(maybe_check_origin, collection, delegate), + } } /// Cancel all the approvals of a specific item. @@ -1961,60 +1965,6 @@ pub mod pallet { Self::validate_signature(&Encode::encode(&data), &signature, &signer)?; Self::do_set_attributes_pre_signed(origin, data, signer) } - - /// Approve an item to be transferred by a delegated third-party account. - /// - /// Origin must be either `ForceOrigin` or Signed and the sender should be the Owner of the - /// `item`. - /// - /// - `collection`: The collection of the item to be approved for delegated transfer. - /// - `item`: The item to be approved for delegated transfer. - /// - `delegate`: The account to delegate permission to transfer the item. - /// - /// Emits `TransferApproved` on success. - /// - /// Weight: `O(1)` - #[pallet::call_index(39)] - #[pallet::weight(T::WeightInfo::approve_transfer())] - pub fn approve_transfer_collection( - origin: OriginFor, - collection: T::CollectionId, - delegate: AccountIdLookupOf, - ) -> DispatchResult { - let maybe_check_origin = T::ForceOrigin::try_origin(origin) - .map(|_| None) - .or_else(|origin| ensure_signed(origin).map(Some).map_err(DispatchError::from))?; - let delegate = T::Lookup::lookup(delegate)?; - Self::do_approve_transfer_collection(maybe_check_origin, collection, delegate) - } - - /// Cancel one of the transfer approvals for a specific item. - /// - /// Origin must be either: - /// - the `Force` origin; - /// - `Signed` with the signer being the Owner of the `item`; - /// - /// Arguments: - /// - `collection`: The collection of the item of whose approval will be cancelled. - /// - `item`: The item of the collection of whose approval will be cancelled. - /// - `delegate`: The account that is going to loose their approval. - /// - /// Emits `ApprovalCancelled` on success. - /// - /// Weight: `O(1)` - #[pallet::call_index(40)] - #[pallet::weight(T::WeightInfo::cancel_approval())] - pub fn cancel_approval_collection( - origin: OriginFor, - collection: T::CollectionId, - delegate: AccountIdLookupOf, - ) -> DispatchResult { - let maybe_check_origin = T::ForceOrigin::try_origin(origin) - .map(|_| None) - .or_else(|origin| ensure_signed(origin).map(Some).map_err(DispatchError::from))?; - let delegate = T::Lookup::lookup(delegate)?; - Self::do_cancel_approval_collection(maybe_check_origin, collection, delegate) - } } } diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 44f2f32ae..4002c48ee 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -487,7 +487,7 @@ fn transfer_should_work() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(3)), 0, - 42, + Some(42), account(2), None )); @@ -1777,7 +1777,7 @@ fn approval_lifecycle_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), None )); @@ -1791,7 +1791,7 @@ fn approval_lifecycle_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(4)), 0, - 42, + Some(42), account(2), None )); @@ -1819,7 +1819,7 @@ fn approval_lifecycle_works() { Nfts::approve_transfer( RuntimeOrigin::signed(account(1)), collection_id, - 1, + Some(1), account(2), None ), @@ -1847,30 +1847,35 @@ fn cancel_approval_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), None )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 1, 42, account(3)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 1, Some(42), account(3)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 43, account(3)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, Some(43), account(3)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(3)), 0, 42, account(3)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(3)), 0, Some(42), account(3)), Error::::NoPermission ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(4)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, Some(42), account(4)), Error::::NotDelegate ); - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); + assert_ok!(Nfts::cancel_approval( + RuntimeOrigin::signed(account(2)), + 0, + Some(42), + account(3) + )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, Some(42), account(3)), Error::::NotDelegate ); @@ -1887,18 +1892,23 @@ fn cancel_approval_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), Some(2) )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(5)), 0, 42, account(3)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(5)), 0, Some(42), account(3)), Error::::NoPermission ); System::set_block_number(current_block + 3); // 5 can cancel the approval since the deadline has passed. - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(5)), 0, 42, account(3))); + assert_ok!(Nfts::cancel_approval( + RuntimeOrigin::signed(account(5)), + 0, + Some(42), + account(3) + )); assert_eq!(approvals(0, 69), vec![]); }); } @@ -1924,21 +1934,21 @@ fn approving_multiple_accounts_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), None )); assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(4), None )); assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(5), Some(2) )); @@ -1979,14 +1989,20 @@ fn approvals_limit_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(i), None )); } // the limit is 10 assert_noop!( - Nfts::approve_transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(14), None), + Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + Some(42), + account(14), + None + ), Error::::ReachedApprovalLimit ); }); @@ -2015,7 +2031,7 @@ fn approval_deadline_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), Some(2) )); @@ -2034,7 +2050,7 @@ fn approval_deadline_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(4)), 0, - 42, + Some(42), account(6), Some(4) )); @@ -2063,26 +2079,31 @@ fn cancel_approval_works_with_admin() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), None )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 1, 42, account(1)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 1, Some(42), account(1)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 43, account(1)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, Some(43), account(1)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(4)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, Some(42), account(4)), Error::::NotDelegate ); - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); + assert_ok!(Nfts::cancel_approval( + RuntimeOrigin::signed(account(2)), + 0, + Some(42), + account(3) + )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(1)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, Some(42), account(1)), Error::::NotDelegate ); }); @@ -2107,26 +2128,26 @@ fn cancel_approval_works_with_force() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), None )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::root(), 1, 42, account(1)), + Nfts::cancel_approval(RuntimeOrigin::root(), 1, Some(42), account(1)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::root(), 0, 43, account(1)), + Nfts::cancel_approval(RuntimeOrigin::root(), 0, Some(43), account(1)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, account(4)), + Nfts::cancel_approval(RuntimeOrigin::root(), 0, Some(42), account(4)), Error::::NotDelegate ); - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, account(3))); + assert_ok!(Nfts::cancel_approval(RuntimeOrigin::root(), 0, Some(42), account(3))); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, account(1)), + Nfts::cancel_approval(RuntimeOrigin::root(), 0, Some(42), account(1)), Error::::NotDelegate ); }); @@ -2151,14 +2172,14 @@ fn clear_all_transfer_approvals_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), None )); assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(4), None )); @@ -3169,7 +3190,7 @@ fn pallet_level_feature_flags_should_work() { Nfts::approve_transfer( RuntimeOrigin::signed(user_id.clone()), collection_id, - item_id, + Some(item_id), account(2), None ), From cf363a2f60cf454f8b15d605a00e4b5b93cf2054 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 00:03:43 +0700 Subject: [PATCH 07/76] test(nfts): check account balance & test total supply --- pallets/nfts/src/tests.rs | 61 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 4002c48ee..f75c25d88 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -164,6 +164,7 @@ fn basic_minting_should_work() { )); assert_eq!(collections(), vec![(account(1), 0)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); + assert_eq!(AccountBalance::::get((0, account(1))), 1); assert_eq!(items(), vec![(account(1), 0, 42)]); assert_ok!(Nfts::force_create( @@ -173,6 +174,7 @@ fn basic_minting_should_work() { )); assert_eq!(collections(), vec![(account(1), 0), (account(2), 1)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(2)), 1, 69, account(1), None)); + assert_eq!(AccountBalance::::get((1, account(1))), 1); assert_eq!(items(), vec![(account(1), 0, 42), (account(1), 1, 69)]); }); } @@ -204,6 +206,7 @@ fn lifecycle_should_work() { account(10), default_item_config() )); + assert_eq!(AccountBalance::::get((0, account(10))), 1); assert_eq!(Balances::reserved_balance(&account(1)), 6); assert_ok!(Nfts::force_mint( RuntimeOrigin::signed(account(1)), @@ -212,8 +215,10 @@ fn lifecycle_should_work() { account(20), default_item_config() )); + assert_eq!(AccountBalance::::get((0, account(20))), 1); assert_eq!(Balances::reserved_balance(&account(1)), 7); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 70, account(1), None)); + assert_eq!(AccountBalance::::get((0, account(1))), 1); assert_eq!(items(), vec![(account(1), 0, 70), (account(10), 0, 42), (account(20), 0, 69)]); assert_eq!(Collection::::get(0).unwrap().items, 3); assert_eq!(Collection::::get(0).unwrap().item_metadatas, 0); @@ -221,6 +226,8 @@ fn lifecycle_should_work() { assert_eq!(Balances::reserved_balance(&account(1)), 8); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 70, account(2))); + assert_eq!(AccountBalance::::get((0, account(1))), 0); + assert_eq!(AccountBalance::::get((0, account(2))), 1); assert_eq!(Balances::reserved_balance(&account(1)), 8); assert_eq!(Balances::reserved_balance(&account(2)), 0); @@ -238,6 +245,7 @@ fn lifecycle_should_work() { Nfts::destroy(RuntimeOrigin::signed(account(1)), 0, w), Error::::CollectionNotEmpty ); + assert_eq!(AccountBalance::::get((0, account(1))), 0); assert_ok!(Nfts::set_attribute( RuntimeOrigin::signed(account(1)), @@ -248,7 +256,9 @@ fn lifecycle_should_work() { bvec![0], )); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(10)), 0, 42)); + assert_eq!(AccountBalance::::get((0, account(10))), 0); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(20)), 0, 69)); + assert_eq!(AccountBalance::::get((0, account(10))), 0); assert_ok!(Nfts::burn(RuntimeOrigin::root(), 0, 70)); let w = Nfts::get_destroy_witness(&0).unwrap(); @@ -256,6 +266,7 @@ fn lifecycle_should_work() { assert_eq!(w.item_metadatas, 0); assert_eq!(w.item_configs, 0); assert_ok!(Nfts::destroy(RuntimeOrigin::signed(account(1)), 0, w)); + assert_eq!(AccountBalance::::get((0, account(1))), 0); assert_eq!(Balances::reserved_balance(&account(1)), 0); assert!(!Collection::::contains_key(0)); @@ -305,6 +316,7 @@ fn destroy_should_work() { )); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(2), None)); + assert_eq!(AccountBalance::::get((0, account(2))), 1); assert_noop!( Nfts::destroy( RuntimeOrigin::signed(account(1)), @@ -323,6 +335,7 @@ fn destroy_should_work() { 0, Nfts::get_destroy_witness(&0).unwrap() )); + assert_eq!(AccountBalance::::get((0, account(1))), 0); assert!(!ItemConfigOf::::contains_key(0, 42)); assert_eq!(ItemConfigOf::::iter_prefix(0).count() as u32, 0); }); @@ -337,6 +350,7 @@ fn mint_should_work() { default_collection_config() )); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); + assert_eq!(AccountBalance::::get((0, account(1))), 1); assert_eq!(Nfts::owner(0, 42).unwrap(), account(1)); assert_eq!(collections(), vec![(account(1), 0)]); assert_eq!(items(), vec![(account(1), 0, 42)]); @@ -402,6 +416,7 @@ fn mint_should_work() { account(2), Some(MintWitness { mint_price: Some(1), ..Default::default() }) )); + assert_eq!(AccountBalance::::get((0, account(2))), 1); assert_eq!(Balances::total_balance(&account(2)), 99); // validate types @@ -440,6 +455,7 @@ fn mint_should_work() { account(2), Some(MintWitness { owned_item: Some(43), ..Default::default() }) )); + assert_eq!(AccountBalance::::get((1, account(2))), 1); assert!(events().contains(&Event::::PalletAttributeSet { collection: 0, item: Some(43), @@ -478,6 +494,8 @@ fn transfer_should_work() { )); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); + assert_eq!(AccountBalance::::get((0, account(2))), 0); + assert_eq!(AccountBalance::::get((0, account(3))), 1); assert_eq!(items(), vec![(account(3), 0, 42)]); assert_noop!( Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4)), @@ -492,7 +510,9 @@ fn transfer_should_work() { None )); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4))); - + assert_eq!(AccountBalance::::get((0, account(2))), 0); + assert_eq!(AccountBalance::::get((0, account(3))), 0); + assert_eq!(AccountBalance::::get((0, account(4))), 1); // validate we can't transfer non-transferable items let collection_id = 1; assert_ok!(Nfts::force_create( @@ -1746,15 +1766,17 @@ fn burn_works() { account(5), default_item_config() )); + assert_eq!(AccountBalance::::get((0, account(5))), 2); assert_eq!(Balances::reserved_balance(account(1)), 2); assert_noop!( Nfts::burn(RuntimeOrigin::signed(account(0)), 0, 42), Error::::NoPermission ); - assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 42)); + assert_eq!(AccountBalance::::get((0, account(5))), 1); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 69)); + assert_eq!(AccountBalance::::get((0, account(5))), 0); assert_eq!(Balances::reserved_balance(account(1)), 0); }); } @@ -2209,6 +2231,36 @@ fn clear_all_transfer_approvals_works() { }); } +#[test] +fn total_supply_should_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let user_id = account(1); + let total_items = 10; + + // no collection. + assert_eq!(Nfts::collection_items(collection_id), None); + + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + user_id.clone(), + default_collection_config() + )); + + // mint items and validate the total supply. + (0..total_items).into_iter().for_each(|i| { + assert_ok!(Nfts::force_mint( + RuntimeOrigin::root(), + collection_id, + i, + user_id.clone(), + ItemConfig::default() + )); + }); + assert_eq!(Nfts::collection_items(collection_id), Some(total_items)); + }); +} + #[test] fn max_supply_should_work() { new_test_ext().execute_with(|| { @@ -2545,6 +2597,7 @@ fn buy_item_should_work() { item_1, price_1 + 1, )); + assert_eq!(AccountBalance::::get((collection_id, user_2.clone())), 1); // validate the new owner & balances let item = Item::::get(collection_id, item_1).unwrap(); @@ -2912,6 +2965,8 @@ fn claim_swap_should_work() { default_item_config(), )); + assert_eq!(AccountBalance::::get((collection_id, user_1.clone())), 2); + assert_eq!(AccountBalance::::get((collection_id, user_2.clone())), 3); assert_ok!(Nfts::create_swap( RuntimeOrigin::signed(user_1.clone()), collection_id, @@ -3002,6 +3057,8 @@ fn claim_swap_should_work() { item_1, Some(price_with_direction.clone()), )); + assert_eq!(AccountBalance::::get((collection_id, user_1.clone())), 2); + assert_eq!(AccountBalance::::get((collection_id, user_2.clone())), 3); // validate the new owner let item = Item::::get(collection_id, item_1).unwrap(); From 24495972ec2e4d17de9acc256f92635186cd35c3 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 00:39:53 +0700 Subject: [PATCH 08/76] test(nfts): allowance works --- pallets/api/src/nonfungibles/mod.rs | 2 +- pallets/nfts/src/features/approvals.rs | 8 +++- pallets/nfts/src/lib.rs | 2 +- pallets/nfts/src/tests.rs | 57 ++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index bc728ac8c..4b6558e90 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -247,7 +247,7 @@ pub mod pallet { Item { collection, item } => ReadResult::Item(pallet_nfts::Item::::get(collection, item)), Allowance { collection, owner, operator, item } => ReadResult::Allowance( - NftsOf::::allowance(&collection, &item, &owner, &operator).is_ok(), + NftsOf::::check_allowance(&collection, &item, &owner, &operator).is_ok(), ), BalanceOf { collection, owner } => ReadResult::BalanceOf( pallet_nfts::AccountBalance::::get((collection, owner)), diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index 979035fa6..89b8fc6a1 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -231,7 +231,7 @@ impl, I: 'static> Pallet { Ok(()) } - pub fn allowance( + pub fn check_allowance( collection: &T::CollectionId, item: &Option, owner: &T::AccountId, @@ -239,6 +239,9 @@ impl, I: 'static> Pallet { ) -> Result<(), DispatchError> { // Check if a `delegate` has a permission to spend the collection. if Allowances::::get((&collection, &owner, &delegate)) { + if let Some(item) = item { + Item::::get(&collection, &item).ok_or(Error::::UnknownItem)?; + }; return Ok(()); } // Check if a `delegate` has a permission to spend the collection item. @@ -251,7 +254,8 @@ impl, I: 'static> Pallet { let block_number = frame_system::Pallet::::block_number(); ensure!(block_number <= *d, Error::::ApprovalExpired); } + return Ok(()); }; - Ok(()) + Err(Error::::NoPermission.into()) } } diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index 146892935..c7d826b54 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -1060,7 +1060,7 @@ pub mod pallet { Self::do_transfer(collection, item, dest, |_, details| { if details.owner != origin { - Self::allowance(&collection, &Some(item), &details.owner, &origin)?; + Self::check_allowance(&collection, &Some(item), &details.owner, &origin)?; } Ok(()) }) diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index f75c25d88..5ad13e6ed 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -1850,6 +1850,63 @@ fn approval_lifecycle_works() { }); } +#[test] +fn allowance_works() { + new_test_ext().execute_with(|| { + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); + + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(1)), + 0, + None, + account(2), + None + )); + + // collection transfer approved. + assert_noop!( + Nfts::check_allowance(&0, &Some(43), &account(1), &account(2)), + Error::::UnknownItem + ); + assert_noop!( + Nfts::check_allowance(&0, &Some(42), &account(1), &account(3)), + Error::::NoPermission + ); + assert_ok!(Nfts::check_allowance(&0, &None, &account(1), &account(2))); + assert_ok!(Nfts::check_allowance(&0, &Some(42), &account(1), &account(2))); + + // collection item transfer approved. + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + Some(42), + account(3), + None + )); + + assert_noop!( + Nfts::check_allowance(&0, &Some(43), &account(2), &account(3)), + Error::::UnknownItem + ); + assert_noop!( + Nfts::check_allowance(&0, &Some(42), &account(2), &account(4)), + Error::::NoPermission + ); + assert_ok!(Nfts::check_allowance(&0, &Some(42), &account(2), &account(3))); + }); +} + #[test] fn cancel_approval_works() { new_test_ext().execute_with(|| { From 9de384ea091145b9e4b1563be0bc473c4f28640f Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 00:40:34 +0700 Subject: [PATCH 09/76] refactor(test): check_allowance_works --- pallets/nfts/src/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 5ad13e6ed..9c3cce0d4 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -1851,7 +1851,7 @@ fn approval_lifecycle_works() { } #[test] -fn allowance_works() { +fn check_allowance_works() { new_test_ext().execute_with(|| { assert_ok!(Nfts::force_create( RuntimeOrigin::root(), From 58d4c92587fc85ae6291044302846aa12737c018 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 10:18:49 +0700 Subject: [PATCH 10/76] fix(nfts): cancel / approve collection transfer --- pallets/nfts/src/features/approvals.rs | 27 ++++------ pallets/nfts/src/tests.rs | 72 ++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 20 deletions(-) diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index 89b8fc6a1..05696fee5 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -180,27 +180,24 @@ impl, I: 'static> Pallet { Self::is_pallet_feature_enabled(PalletFeature::Approvals), Error::::MethodDisabled ); - let collection_owner = - Self::collection_owner(collection).ok_or(Error::::UnknownCollection)?; - + if !Collection::::contains_key(collection) { + return Err(Error::::UnknownCollection.into()); + } let collection_config = Self::get_collection_config(&collection)?; ensure!( collection_config.is_setting_enabled(CollectionSetting::TransferableItems), Error::::ItemsNonTransferable ); - if let Some(check_origin) = maybe_check_origin { - ensure!(check_origin == collection_owner, Error::::NoPermission); - } - - Allowances::::mutate((&collection, &collection_owner, &delegate), |allowance| { + let origin = maybe_check_origin.ok_or(Error::::WrongOrigin)?; + Allowances::::mutate((&collection, &origin, &delegate), |allowance| { *allowance = true; }); Self::deposit_event(Event::TransferApproved { collection, item: None, - owner: collection_owner, + owner: origin, delegate, deadline: None, }); @@ -212,18 +209,16 @@ impl, I: 'static> Pallet { collection: T::CollectionId, delegate: T::AccountId, ) -> DispatchResult { - let collection_owner = - Self::collection_owner(collection).ok_or(Error::::UnknownCollection)?; - - if let Some(check_origin) = maybe_check_origin { - ensure!(check_origin == collection_owner, Error::::NoPermission); + if !Collection::::contains_key(collection) { + return Err(Error::::UnknownCollection.into()); } - Allowances::::remove((&collection, &collection_owner, &delegate)); + let origin = maybe_check_origin.ok_or(Error::::WrongOrigin)?; + Allowances::::remove((&collection, &origin, &delegate)); Self::deposit_event(Event::ApprovalCancelled { collection, - owner: collection_owner, + owner: origin, item: None, delegate, }); diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 9c3cce0d4..07f2a74de 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -1876,12 +1876,12 @@ fn check_allowance_works() { // collection transfer approved. assert_noop!( - Nfts::check_allowance(&0, &Some(43), &account(1), &account(2)), - Error::::UnknownItem + Nfts::check_allowance(&1, &None, &account(1), &account(2)), + Error::::NoPermission ); assert_noop!( - Nfts::check_allowance(&0, &Some(42), &account(1), &account(3)), - Error::::NoPermission + Nfts::check_allowance(&1, &Some(43), &account(1), &account(2)), + Error::::UnknownItem ); assert_ok!(Nfts::check_allowance(&0, &None, &account(1), &account(2))); assert_ok!(Nfts::check_allowance(&0, &Some(42), &account(1), &account(2))); @@ -1992,6 +1992,43 @@ fn cancel_approval_works() { }); } +#[test] +fn cancel_approval_collection_works() { + new_test_ext().execute_with(|| { + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); + + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + None, + account(3), + None + )); + assert_noop!( + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 1, None, account(3)), + Error::::UnknownCollection + ); + + assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, None, account(3))); + + assert_noop!( + Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4)), + Error::::NoPermission + ); + }); +} + #[test] fn approving_multiple_accounts_works() { new_test_ext().execute_with(|| { @@ -2087,6 +2124,33 @@ fn approvals_limit_works() { }); } +#[test] +fn approval_collection_works() { + new_test_ext().execute_with(|| { + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); + + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(1)), + 0, + None, + account(3), + None + )); + assert_eq!(Allowances::::get((0, account(1), account(3))), true); + }); +} + #[test] fn approval_deadline_works() { new_test_ext().execute_with(|| { From df1f6a6537217d5ec19b028945f763f085c72382 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:17:38 +0700 Subject: [PATCH 11/76] test(nfts): cancel approval collection --- pallets/nfts/src/tests.rs | 49 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 07f2a74de..4fbec4de9 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -2021,6 +2021,13 @@ fn cancel_approval_collection_works() { ); assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, None, account(3))); + assert!(events().contains(&Event::::ApprovalCancelled { + collection: 0, + item: None, + owner: account(2), + delegate: account(3) + })); + assert_eq!(Allowances::::get((0, account(2), account(3))), false); assert_noop!( Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4)), @@ -2127,6 +2134,11 @@ fn approvals_limit_works() { #[test] fn approval_collection_works() { new_test_ext().execute_with(|| { + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), account(1), @@ -2140,14 +2152,47 @@ fn approval_collection_works() { default_item_config() )); - assert_ok!(Nfts::approve_transfer( + // Error::ItemsNonTransferable. + assert_ok!(Nfts::lock_collection( RuntimeOrigin::signed(account(1)), + 1, + CollectionSettings::from_disabled(CollectionSetting::TransferableItems.into()) + )); + assert_noop!( + Nfts::approve_transfer(RuntimeOrigin::signed(account(1)), 1, None, account(2), None), + Error::::ItemsNonTransferable + ); + + // Error::MethodDisabled. + Features::set(&PalletFeatures::from_disabled(PalletFeature::Approvals.into())); + assert_noop!( + Nfts::approve_transfer(RuntimeOrigin::signed(account(1)), 1, None, account(2), None), + Error::::MethodDisabled + ); + Features::set(&PalletFeatures::all_enabled()); + + // Error::UnknownCollection. + assert_noop!( + Nfts::approve_transfer(RuntimeOrigin::signed(account(2)), 2, None, account(3), None), + Error::::UnknownCollection + ); + + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), 0, None, account(3), None )); - assert_eq!(Allowances::::get((0, account(1), account(3))), true); + assert!(events().contains(&Event::::TransferApproved { + collection: 0, + item: None, + owner: account(2), + delegate: account(3), + deadline: None + })); + assert_eq!(Allowances::::get((0, account(2), account(3))), true); + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4))); }); } From fea02597f558c0a6369fdd14c49a9fed2a87123a Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:23:23 +0700 Subject: [PATCH 12/76] test(nfts): update approval test cases --- pallets/nfts/src/tests.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 4fbec4de9..10c95bd6c 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -1993,7 +1993,7 @@ fn cancel_approval_works() { } #[test] -fn cancel_approval_collection_works() { +fn cancel_approval_collection_works_with_admin() { new_test_ext().execute_with(|| { assert_ok!(Nfts::force_create( RuntimeOrigin::root(), @@ -2132,7 +2132,7 @@ fn approvals_limit_works() { } #[test] -fn approval_collection_works() { +fn approval_collection_works_with_admin() { new_test_ext().execute_with(|| { assert_ok!(Nfts::force_create( RuntimeOrigin::root(), @@ -2163,14 +2163,6 @@ fn approval_collection_works() { Error::::ItemsNonTransferable ); - // Error::MethodDisabled. - Features::set(&PalletFeatures::from_disabled(PalletFeature::Approvals.into())); - assert_noop!( - Nfts::approve_transfer(RuntimeOrigin::signed(account(1)), 1, None, account(2), None), - Error::::MethodDisabled - ); - Features::set(&PalletFeatures::all_enabled()); - // Error::UnknownCollection. assert_noop!( Nfts::approve_transfer(RuntimeOrigin::signed(account(2)), 2, None, account(3), None), From 84a7fe340dae20ac1e3e214de899975ba2e97a17 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 17:18:20 +0700 Subject: [PATCH 13/76] feat(nfts): get attribute read method --- pallets/api/src/nonfungibles/mod.rs | 105 ++++++++++++++++++-------- pallets/api/src/nonfungibles/types.rs | 6 +- 2 files changed, 78 insertions(+), 33 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index 4b6558e90..83d23585a 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -14,10 +14,11 @@ mod types; pub mod pallet { use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; use frame_system::pallet_prelude::*; + use pallet_nfts::MintWitness; use sp_std::vec::Vec; use types::{ - AccountIdOf, CollectionDetailsFor, CollectionIdOf, ItemDetailsFor, ItemIdOf, NftsOf, - NftsWeightInfoOf, + AccountIdOf, AttributeNamespaceOf, BalanceOf, CollectionDetailsFor, CollectionIdOf, + ItemDetailsFor, ItemIdOf, ItemPriceOf, NftsOf, NftsWeightInfoOf, }; use super::*; @@ -54,6 +55,14 @@ pub mod pallet { operator: AccountIdOf, item: Option>, }, + /// Returns the attribute of `item` for the given `key`. + #[codec(index = 6)] + GetAttribute { + collection: CollectionIdOf, + item: Option>, + namespace: AttributeNamespaceOf, + key: BoundedVec, + }, } /// Results of state reads for the non-fungibles API. @@ -67,6 +76,7 @@ pub mod pallet { Collection(Option>), Item(Option>), Allowance(bool), + GetAttribute(Option>), } impl ReadResult { @@ -81,6 +91,7 @@ pub mod pallet { Collection(result) => result.encode(), Item(result) => result.encode(), Allowance(result) => result.encode(), + GetAttribute(result) => result.encode(), } } } @@ -103,46 +114,46 @@ pub mod pallet { Approval { /// The collection ID. collection: CollectionIdOf, + /// The item which is (dis)approved. `None` for all owner's items. + item: Option>, /// The owner providing the allowance. owner: AccountIdOf, /// The beneficiary of the allowance. operator: AccountIdOf, - /// The item which is (dis)approved. `None` for all owner's items. - item: Option>, /// Whether allowance is set or removed. approved: bool, }, - /// Event emitted when new item is minted to the account. - Mint { - /// The owner of the item. - to: AccountIdOf, - /// The collection ID. - collection: CollectionIdOf, - /// the item ID. - item: ItemIdOf, - }, - /// Event emitted when item is burned. - Burn { - /// The collection ID. - collection: CollectionIdOf, - /// the item ID. - item: ItemIdOf, - }, - /// Event emitted when an item transfer occurs. + /// Event emitted when a token transfer occurs. + // Differing style: event name abides by the PSP22 standard. Transfer { /// The collection ID. collection: CollectionIdOf, - /// the item ID. + /// The collection item ID. item: ItemIdOf, - /// The source of the transfer. - from: AccountIdOf, - /// The recipient of the transfer. - to: AccountIdOf, + /// The source of the transfer. `None` when minting. + from: Option>, + /// The recipient of the transfer. `None` when burning. + to: Option>, + /// The amount minted. + value: Option>, }, } #[pallet::call] impl Pallet { + #[pallet::call_index(20)] + #[pallet::weight(NftsWeightInfoOf::::create())] + pub fn create(_origin: OriginFor) -> DispatchResult { + Ok(()) + } + + // TODO: Fix weight + #[pallet::call_index(21)] + #[pallet::weight(NftsWeightInfoOf::::create())] + pub fn destroy(_origin: OriginFor) -> DispatchResult { + Ok(()) + } + #[pallet::call_index(0)] #[pallet::weight(NftsWeightInfoOf::::mint())] pub fn mint( @@ -150,9 +161,24 @@ pub mod pallet { to: AccountIdOf, collection: CollectionIdOf, item: ItemIdOf, + mint_price: Option>, ) -> DispatchResult { - NftsOf::::mint(origin, collection, item, T::Lookup::unlookup(to.clone()), None)?; - Self::deposit_event(Event::Mint { to, collection, item }); + let account = ensure_signed(origin.clone())?; + let witness_data = MintWitness { mint_price, owned_item: Some(item) }; + NftsOf::::mint( + origin, + collection, + item, + T::Lookup::unlookup(to.clone()), + Some(witness_data), + )?; + Self::deposit_event(Event::Transfer { + collection, + item, + from: None, + to: Some(account), + value: mint_price, + }); Ok(()) } @@ -163,8 +189,15 @@ pub mod pallet { collection: CollectionIdOf, item: ItemIdOf, ) -> DispatchResult { + let account = ensure_signed(origin.clone())?; NftsOf::::burn(origin, collection, item)?; - Self::deposit_event(Event::Burn { collection, item }); + Self::deposit_event(Event::Transfer { + collection, + item, + from: Some(account), + to: None, + value: None, + }); Ok(()) } @@ -178,12 +211,18 @@ pub mod pallet { ) -> DispatchResult { let from = ensure_signed(origin.clone())?; NftsOf::::transfer(origin, collection, item, T::Lookup::unlookup(to.clone()))?; - Self::deposit_event(Event::Transfer { from, to, collection, item }); + Self::deposit_event(Event::Transfer { + collection, + item, + from: Some(from), + to: Some(to), + value: None, + }); Ok(()) } #[pallet::call_index(3)] - #[pallet::weight(NftsWeightInfoOf::::approve_transfer())] + #[pallet::weight(NftsWeightInfoOf::::approve_transfer() + NftsWeightInfoOf::::cancel_approval())] pub fn approve( origin: OriginFor, collection: CollectionIdOf, @@ -252,6 +291,10 @@ pub mod pallet { BalanceOf { collection, owner } => ReadResult::BalanceOf( pallet_nfts::AccountBalance::::get((collection, owner)), ), + GetAttribute { collection, item, namespace, key } => ReadResult::GetAttribute( + pallet_nfts::Attribute::::get((collection, item, namespace, key)) + .map(|attribute| attribute.0), + ), } } } diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs index f81ea5359..da9491715 100644 --- a/pallets/api/src/nonfungibles/types.rs +++ b/pallets/api/src/nonfungibles/types.rs @@ -1,6 +1,6 @@ use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; use frame_system::pallet_prelude::BlockNumberFor; -use pallet_nfts::{CollectionDetails, ItemDeposit, ItemDetails}; +use pallet_nfts::{AttributeNamespace, CollectionDetails, ItemDeposit, ItemDetails}; use sp_runtime::BoundedBTreeMap; // Type aliases for pallet-nfts. @@ -15,14 +15,16 @@ pub(super) type CollectionIdOf = as Inspect<::AccountId>>::CollectionId; pub(super) type ItemIdOf = as Inspect<::AccountId>>::ItemId; -type ApprovalsOf = BoundedBTreeMap< +pub(super) type ApprovalsOf = BoundedBTreeMap< AccountIdOf, Option>, ::ApprovalsLimit, >; +pub(super) type ItemPriceOf = BalanceOf; // TODO: Multi-instances. pub(super) type ItemDepositOf = ItemDeposit, AccountIdOf>; pub(super) type CollectionDetailsFor = CollectionDetails, BalanceOf>; pub(super) type ItemDetailsFor = ItemDetails, ItemDepositOf, ApprovalsOf>; +pub(super) type AttributeNamespaceOf = AttributeNamespace>; From 1bb5a98b1f96e0c11e84b95329c5137fa2aeef2a Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 19:45:16 +0700 Subject: [PATCH 14/76] feat(nonfungibles + nfts): add new methods to manage attributes --- Cargo.lock | 8 +- pallets/api/src/nonfungibles/mod.rs | 198 ++++++++++++++---- pallets/api/src/nonfungibles/types.rs | 17 +- pallets/nfts/src/features/approvals.rs | 4 +- .../src/features/create_delete_collection.rs | 4 +- .../nfts/src/features/create_delete_item.rs | 4 +- pallets/nfts/src/features/transfer.rs | 4 +- pallets/nfts/src/lib.rs | 18 +- pallets/nfts/src/tests.rs | 66 +++--- 9 files changed, 228 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed534195c..48f7b34c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 4 +version = 3 [[package]] name = "Inflector" @@ -822,7 +822,7 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object 0.36.4", + "object 0.36.0", "rustc-demangle", ] @@ -7195,9 +7195,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index 83d23585a..efef2386b 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -14,11 +14,14 @@ mod types; pub mod pallet { use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; use frame_system::pallet_prelude::*; - use pallet_nfts::MintWitness; + use pallet_nfts::{ + CancelAttributesApprovalWitness, CollectionConfig, CollectionSettings, DestroyWitness, + MintSettings, MintWitness, + }; use sp_std::vec::Vec; use types::{ AccountIdOf, AttributeNamespaceOf, BalanceOf, CollectionDetailsFor, CollectionIdOf, - ItemDetailsFor, ItemIdOf, ItemPriceOf, NftsOf, NftsWeightInfoOf, + CreateCollectionConfigFor, ItemDetailsFor, ItemIdOf, ItemPriceOf, NftsOf, NftsWeightInfoOf, }; use super::*; @@ -29,24 +32,12 @@ pub mod pallet { #[repr(u8)] #[allow(clippy::unnecessary_cast)] pub enum Read { - /// Returns the owner of an item. - #[codec(index = 0)] - OwnerOf { collection: CollectionIdOf, item: ItemIdOf }, - /// Returns the owner of a collection. - #[codec(index = 1)] - CollectionOwner(CollectionIdOf), /// Number of items existing in a concrete collection. #[codec(index = 2)] TotalSupply(CollectionIdOf), /// Returns the total number of items in the collection owned by the account. #[codec(index = 3)] BalanceOf { collection: CollectionIdOf, owner: AccountIdOf }, - /// Returns the details of a collection. - #[codec(index = 4)] - Collection(CollectionIdOf), - /// Returns the details of an item. - #[codec(index = 5)] - Item { collection: CollectionIdOf, item: ItemIdOf }, /// Whether a spender is allowed to transfer an item or items from owner. #[codec(index = 6)] Allowance { @@ -55,6 +46,9 @@ pub mod pallet { operator: AccountIdOf, item: Option>, }, + /// Returns the owner of an item. + #[codec(index = 0)] + OwnerOf { collection: CollectionIdOf, item: ItemIdOf }, /// Returns the attribute of `item` for the given `key`. #[codec(index = 6)] GetAttribute { @@ -63,20 +57,29 @@ pub mod pallet { namespace: AttributeNamespaceOf, key: BoundedVec, }, + /// Returns the owner of a collection. + #[codec(index = 1)] + CollectionOwner(CollectionIdOf), + /// Returns the details of a collection. + #[codec(index = 4)] + Collection(CollectionIdOf), + /// Returns the details of an item. + #[codec(index = 5)] + Item { collection: CollectionIdOf, item: ItemIdOf }, } /// Results of state reads for the non-fungibles API. #[derive(Debug)] #[cfg_attr(feature = "std", derive(PartialEq, Clone))] pub enum ReadResult { - OwnerOf(Option>), - CollectionOwner(Option>), TotalSupply(u128), BalanceOf(u32), - Collection(Option>), - Item(Option>), Allowance(bool), + OwnerOf(Option>), GetAttribute(Option>), + CollectionOwner(Option>), + Collection(Option>), + Item(Option>), } impl ReadResult { @@ -141,19 +144,6 @@ pub mod pallet { #[pallet::call] impl Pallet { - #[pallet::call_index(20)] - #[pallet::weight(NftsWeightInfoOf::::create())] - pub fn create(_origin: OriginFor) -> DispatchResult { - Ok(()) - } - - // TODO: Fix weight - #[pallet::call_index(21)] - #[pallet::weight(NftsWeightInfoOf::::create())] - pub fn destroy(_origin: OriginFor) -> DispatchResult { - Ok(()) - } - #[pallet::call_index(0)] #[pallet::weight(NftsWeightInfoOf::::mint())] pub fn mint( @@ -250,6 +240,131 @@ pub mod pallet { Self::deposit_event(Event::Approval { collection, item, operator, owner, approved }); Ok(()) } + + #[pallet::call_index(4)] + #[pallet::weight(NftsWeightInfoOf::::create())] + pub fn create( + origin: OriginFor, + admin: AccountIdOf, + config: CreateCollectionConfigFor, + ) -> DispatchResult { + let collection_config = CollectionConfig { + settings: CollectionSettings::all_enabled(), + max_supply: config.max_supply, + mint_settings: MintSettings { + mint_type: config.mint_type, + start_block: config.start_block, + end_block: config.end_block, + ..MintSettings::default() + }, + }; + NftsOf::::create(origin, T::Lookup::unlookup(admin.clone()), collection_config)?; + Ok(()) + } + + #[pallet::call_index(5)] + #[pallet::weight(NftsWeightInfoOf::::destroy( + witness.item_metadatas, + witness.item_configs, + witness.attributes, + ))] + pub fn destroy( + origin: OriginFor, + collection: CollectionIdOf, + witness: DestroyWitness, + ) -> DispatchResultWithPostInfo { + NftsOf::::destroy(origin, collection, witness) + } + + #[pallet::call_index(6)] + #[pallet::weight(NftsWeightInfoOf::::set_attribute())] + pub fn set_attribute( + origin: OriginFor, + collection: CollectionIdOf, + item: Option>, + namespace: AttributeNamespaceOf, + key: BoundedVec, + value: BoundedVec, + ) -> DispatchResult { + NftsOf::::set_attribute(origin, collection, item, namespace, key, value) + } + + #[pallet::call_index(7)] + #[pallet::weight(NftsWeightInfoOf::::clear_attribute())] + pub fn clear_attribute( + origin: OriginFor, + collection: CollectionIdOf, + item: Option>, + namespace: AttributeNamespaceOf, + key: BoundedVec, + ) -> DispatchResult { + NftsOf::::clear_attribute(origin, collection, item, namespace, key) + } + + #[pallet::call_index(8)] + #[pallet::weight(NftsWeightInfoOf::::set_metadata())] + pub fn set_metadata( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + data: BoundedVec, + ) -> DispatchResult { + NftsOf::::set_metadata(origin, collection, item, data) + } + + #[pallet::call_index(9)] + #[pallet::weight(NftsWeightInfoOf::::clear_metadata())] + pub fn clear_metadata( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + ) -> DispatchResult { + NftsOf::::clear_metadata(origin, collection, item) + } + + #[pallet::call_index(10)] + #[pallet::weight(NftsWeightInfoOf::::approve_item_attributes())] + pub fn approve_item_attributes( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + delegate: AccountIdOf, + ) -> DispatchResult { + NftsOf::::approve_item_attributes( + origin, + collection, + item, + T::Lookup::unlookup(delegate.clone()), + ) + } + + #[pallet::call_index(11)] + #[pallet::weight(NftsWeightInfoOf::::cancel_item_attributes_approval(witness.account_attributes))] + pub fn cancel_item_attributes_approval( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + delegate: AccountIdOf, + witness: CancelAttributesApprovalWitness, + ) -> DispatchResult { + NftsOf::::cancel_item_attributes_approval( + origin, + collection, + item, + T::Lookup::unlookup(delegate.clone()), + witness, + ) + } + + #[pallet::call_index(12)] + #[pallet::weight(NftsWeightInfoOf::::set_collection_max_supply())] + pub fn set_max_supply( + origin: OriginFor, + collection: CollectionIdOf, + max_supply: u32, + ) -> DispatchResult { + NftsOf::::set_collection_max_supply(origin, collection, max_supply) + } } impl crate::Read for Pallet { @@ -274,27 +389,26 @@ pub mod pallet { fn read(value: Self::Read) -> Self::Result { use Read::*; match value { - OwnerOf { collection, item } => - ReadResult::OwnerOf(NftsOf::::owner(collection, item)), - CollectionOwner(collection) => - ReadResult::CollectionOwner(NftsOf::::collection_owner(collection)), TotalSupply(collection) => ReadResult::TotalSupply( NftsOf::::collection_items(collection).unwrap_or_default().into(), ), - Collection(collection) => - ReadResult::Collection(pallet_nfts::Collection::::get(collection)), - Item { collection, item } => - ReadResult::Item(pallet_nfts::Item::::get(collection, item)), + BalanceOf { collection, owner } => + ReadResult::BalanceOf(pallet_nfts::AccountBalance::::get(collection, owner)), Allowance { collection, owner, operator, item } => ReadResult::Allowance( NftsOf::::check_allowance(&collection, &item, &owner, &operator).is_ok(), ), - BalanceOf { collection, owner } => ReadResult::BalanceOf( - pallet_nfts::AccountBalance::::get((collection, owner)), - ), + OwnerOf { collection, item } => + ReadResult::OwnerOf(NftsOf::::owner(collection, item)), GetAttribute { collection, item, namespace, key } => ReadResult::GetAttribute( pallet_nfts::Attribute::::get((collection, item, namespace, key)) .map(|attribute| attribute.0), ), + CollectionOwner(collection) => + ReadResult::CollectionOwner(NftsOf::::collection_owner(collection)), + Collection(collection) => + ReadResult::Collection(pallet_nfts::Collection::::get(collection)), + Item { collection, item } => + ReadResult::Item(pallet_nfts::Item::::get(collection, item)), } } } diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs index da9491715..8c53ffd33 100644 --- a/pallets/api/src/nonfungibles/types.rs +++ b/pallets/api/src/nonfungibles/types.rs @@ -1,7 +1,9 @@ +use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; use frame_system::pallet_prelude::BlockNumberFor; -use pallet_nfts::{AttributeNamespace, CollectionDetails, ItemDeposit, ItemDetails}; -use sp_runtime::BoundedBTreeMap; +use pallet_nfts::{AttributeNamespace, CollectionDetails, ItemDeposit, ItemDetails, MintType}; +use scale_info::TypeInfo; +use sp_runtime::{BoundedBTreeMap, RuntimeDebug}; // Type aliases for pallet-nfts. pub(super) type NftsOf = pallet_nfts::Pallet; @@ -28,3 +30,14 @@ pub(super) type CollectionDetailsFor = pub(super) type ItemDetailsFor = ItemDetails, ItemDepositOf, ApprovalsOf>; pub(super) type AttributeNamespaceOf = AttributeNamespace>; +pub(super) type CreateCollectionConfigFor = + CreateCollectionConfig, BlockNumberFor, CollectionIdOf>; + +#[derive(Clone, Copy, Decode, Encode, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] +pub struct CreateCollectionConfig { + pub max_supply: Option, + pub mint_type: MintType, + pub price: Option, + pub start_block: Option, + pub end_block: Option, +} diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index 05696fee5..6d71c1a22 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -171,7 +171,7 @@ impl, I: 'static> Pallet { Ok(()) } - pub(crate) fn do_approve_transfer_collection( + pub(crate) fn do_approve_collection( maybe_check_origin: Option, collection: T::CollectionId, delegate: T::AccountId, @@ -204,7 +204,7 @@ impl, I: 'static> Pallet { Ok(()) } - pub(crate) fn do_cancel_approval_collection( + pub(crate) fn do_cancel_collection( maybe_check_origin: Option, collection: T::CollectionId, delegate: T::AccountId, diff --git a/pallets/nfts/src/features/create_delete_collection.rs b/pallets/nfts/src/features/create_delete_collection.rs index 2ea5cd732..b7efd03ac 100644 --- a/pallets/nfts/src/features/create_delete_collection.rs +++ b/pallets/nfts/src/features/create_delete_collection.rs @@ -137,8 +137,10 @@ impl, I: 'static> Pallet { } } + // TODO: Do we need another storage item to keep track of number of holders of a + // collection let _ = - AccountBalance::::clear_prefix((collection,), collection_details.items, None); + AccountBalance::::clear_prefix(collection, collection_details.items, None); let _ = Allowances::::clear_prefix((collection,), collection_details.items, None); CollectionAccount::::remove(&collection_details.owner, &collection); T::Currency::unreserve(&collection_details.owner, collection_details.owner_deposit); diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index 036a63b70..cc29f8dab 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -69,7 +69,7 @@ impl, I: 'static> Pallet { } collection_details.items.saturating_inc(); - AccountBalance::::mutate((collection, &mint_to), |balance| { + AccountBalance::::mutate(collection, &mint_to, |balance| { balance.saturating_inc(); }); @@ -266,7 +266,7 @@ impl, I: 'static> Pallet { ItemPriceOf::::remove(&collection, &item); PendingSwapOf::::remove(&collection, &item); ItemAttributesApprovalsOf::::remove(&collection, &item); - AccountBalance::::mutate((collection, &owner), |balance| { + AccountBalance::::mutate(collection, &owner, |balance| { balance.saturating_dec(); }); diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index 04d9f4fe8..3b25b0145 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -88,10 +88,10 @@ impl, I: 'static> Pallet { with_details(&collection_details, &mut details)?; // Update account balances. - AccountBalance::::mutate((collection, &details.owner), |balance| { + AccountBalance::::mutate(collection, &details.owner, |balance| { balance.saturating_dec(); }); - AccountBalance::::mutate((collection, &dest), |balance| { + AccountBalance::::mutate(collection, &dest, |balance| { balance.saturating_inc(); }); diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index c7d826b54..bc8b67b61 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -404,14 +404,12 @@ pub mod pallet { /// Number of collection items that accounts own. #[pallet::storage] - pub type AccountBalance, I: 'static = ()> = StorageNMap< + pub type AccountBalance, I: 'static = ()> = StorageDoubleMap< _, - ( - // Collection Id. - NMapKey, - // Collection Owner Id. - NMapKey, - ), + Twox64Concat, + T::CollectionId, + Blake2_128Concat, + T::AccountId, u32, ValueQuery, >; @@ -1333,8 +1331,7 @@ pub mod pallet { delegate, maybe_deadline, ), - None => - Self::do_approve_transfer_collection(maybe_check_origin, collection, delegate), + None => Self::do_approve_collection(maybe_check_origin, collection, delegate), } } @@ -1367,8 +1364,7 @@ pub mod pallet { match maybe_item { Some(item) => Self::do_cancel_approval(maybe_check_origin, collection, item, delegate), - None => - Self::do_cancel_approval_collection(maybe_check_origin, collection, delegate), + None => Self::do_cancel_collection(maybe_check_origin, collection, delegate), } } diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 10c95bd6c..397a715c2 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -164,7 +164,7 @@ fn basic_minting_should_work() { )); assert_eq!(collections(), vec![(account(1), 0)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); - assert_eq!(AccountBalance::::get((0, account(1))), 1); + assert_eq!(AccountBalance::::get(0, account(1)), 1); assert_eq!(items(), vec![(account(1), 0, 42)]); assert_ok!(Nfts::force_create( @@ -174,7 +174,7 @@ fn basic_minting_should_work() { )); assert_eq!(collections(), vec![(account(1), 0), (account(2), 1)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(2)), 1, 69, account(1), None)); - assert_eq!(AccountBalance::::get((1, account(1))), 1); + assert_eq!(AccountBalance::::get(1, account(1)), 1); assert_eq!(items(), vec![(account(1), 0, 42), (account(1), 1, 69)]); }); } @@ -206,7 +206,7 @@ fn lifecycle_should_work() { account(10), default_item_config() )); - assert_eq!(AccountBalance::::get((0, account(10))), 1); + assert_eq!(AccountBalance::::get(0, account(10)), 1); assert_eq!(Balances::reserved_balance(&account(1)), 6); assert_ok!(Nfts::force_mint( RuntimeOrigin::signed(account(1)), @@ -215,10 +215,10 @@ fn lifecycle_should_work() { account(20), default_item_config() )); - assert_eq!(AccountBalance::::get((0, account(20))), 1); + assert_eq!(AccountBalance::::get(0, account(20)), 1); assert_eq!(Balances::reserved_balance(&account(1)), 7); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 70, account(1), None)); - assert_eq!(AccountBalance::::get((0, account(1))), 1); + assert_eq!(AccountBalance::::get(0, account(1)), 1); assert_eq!(items(), vec![(account(1), 0, 70), (account(10), 0, 42), (account(20), 0, 69)]); assert_eq!(Collection::::get(0).unwrap().items, 3); assert_eq!(Collection::::get(0).unwrap().item_metadatas, 0); @@ -226,8 +226,8 @@ fn lifecycle_should_work() { assert_eq!(Balances::reserved_balance(&account(1)), 8); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 70, account(2))); - assert_eq!(AccountBalance::::get((0, account(1))), 0); - assert_eq!(AccountBalance::::get((0, account(2))), 1); + assert_eq!(AccountBalance::::get(0, account(1)), 0); + assert_eq!(AccountBalance::::get(0, account(2)), 1); assert_eq!(Balances::reserved_balance(&account(1)), 8); assert_eq!(Balances::reserved_balance(&account(2)), 0); @@ -245,7 +245,7 @@ fn lifecycle_should_work() { Nfts::destroy(RuntimeOrigin::signed(account(1)), 0, w), Error::::CollectionNotEmpty ); - assert_eq!(AccountBalance::::get((0, account(1))), 0); + assert_eq!(AccountBalance::::get(0, account(1)), 0); assert_ok!(Nfts::set_attribute( RuntimeOrigin::signed(account(1)), @@ -256,9 +256,9 @@ fn lifecycle_should_work() { bvec![0], )); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(10)), 0, 42)); - assert_eq!(AccountBalance::::get((0, account(10))), 0); + assert_eq!(AccountBalance::::get(0, account(10)), 0); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(20)), 0, 69)); - assert_eq!(AccountBalance::::get((0, account(10))), 0); + assert_eq!(AccountBalance::::get(0, account(10)), 0); assert_ok!(Nfts::burn(RuntimeOrigin::root(), 0, 70)); let w = Nfts::get_destroy_witness(&0).unwrap(); @@ -266,7 +266,7 @@ fn lifecycle_should_work() { assert_eq!(w.item_metadatas, 0); assert_eq!(w.item_configs, 0); assert_ok!(Nfts::destroy(RuntimeOrigin::signed(account(1)), 0, w)); - assert_eq!(AccountBalance::::get((0, account(1))), 0); + assert_eq!(AccountBalance::::get(0, account(1)), 0); assert_eq!(Balances::reserved_balance(&account(1)), 0); assert!(!Collection::::contains_key(0)); @@ -316,7 +316,14 @@ fn destroy_should_work() { )); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(2), None)); - assert_eq!(AccountBalance::::get((0, account(2))), 1); + assert_eq!(AccountBalance::::get(0, account(2)), 1); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + None, + account(3), + None + )); assert_noop!( Nfts::destroy( RuntimeOrigin::signed(account(1)), @@ -335,7 +342,8 @@ fn destroy_should_work() { 0, Nfts::get_destroy_witness(&0).unwrap() )); - assert_eq!(AccountBalance::::get((0, account(1))), 0); + assert_eq!(AccountBalance::::iter_prefix(0).count(), 0); + assert_eq!(Allowances::::iter_prefix((0,)).count(), 0); assert!(!ItemConfigOf::::contains_key(0, 42)); assert_eq!(ItemConfigOf::::iter_prefix(0).count() as u32, 0); }); @@ -350,7 +358,7 @@ fn mint_should_work() { default_collection_config() )); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); - assert_eq!(AccountBalance::::get((0, account(1))), 1); + assert_eq!(AccountBalance::::get(0, account(1)), 1); assert_eq!(Nfts::owner(0, 42).unwrap(), account(1)); assert_eq!(collections(), vec![(account(1), 0)]); assert_eq!(items(), vec![(account(1), 0, 42)]); @@ -416,7 +424,7 @@ fn mint_should_work() { account(2), Some(MintWitness { mint_price: Some(1), ..Default::default() }) )); - assert_eq!(AccountBalance::::get((0, account(2))), 1); + assert_eq!(AccountBalance::::get(0, account(2)), 1); assert_eq!(Balances::total_balance(&account(2)), 99); // validate types @@ -455,7 +463,7 @@ fn mint_should_work() { account(2), Some(MintWitness { owned_item: Some(43), ..Default::default() }) )); - assert_eq!(AccountBalance::::get((1, account(2))), 1); + assert_eq!(AccountBalance::::get(1, account(2)), 1); assert!(events().contains(&Event::::PalletAttributeSet { collection: 0, item: Some(43), @@ -494,8 +502,8 @@ fn transfer_should_work() { )); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); - assert_eq!(AccountBalance::::get((0, account(2))), 0); - assert_eq!(AccountBalance::::get((0, account(3))), 1); + assert_eq!(AccountBalance::::get(0, account(2)), 0); + assert_eq!(AccountBalance::::get(0, account(3)), 1); assert_eq!(items(), vec![(account(3), 0, 42)]); assert_noop!( Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4)), @@ -510,9 +518,9 @@ fn transfer_should_work() { None )); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4))); - assert_eq!(AccountBalance::::get((0, account(2))), 0); - assert_eq!(AccountBalance::::get((0, account(3))), 0); - assert_eq!(AccountBalance::::get((0, account(4))), 1); + assert_eq!(AccountBalance::::get(0, account(2)), 0); + assert_eq!(AccountBalance::::get(0, account(3)), 0); + assert_eq!(AccountBalance::::get(0, account(4)), 1); // validate we can't transfer non-transferable items let collection_id = 1; assert_ok!(Nfts::force_create( @@ -1766,7 +1774,7 @@ fn burn_works() { account(5), default_item_config() )); - assert_eq!(AccountBalance::::get((0, account(5))), 2); + assert_eq!(AccountBalance::::get(0, account(5)), 2); assert_eq!(Balances::reserved_balance(account(1)), 2); assert_noop!( @@ -1774,9 +1782,9 @@ fn burn_works() { Error::::NoPermission ); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 42)); - assert_eq!(AccountBalance::::get((0, account(5))), 1); + assert_eq!(AccountBalance::::get(0, account(5)), 1); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 69)); - assert_eq!(AccountBalance::::get((0, account(5))), 0); + assert_eq!(AccountBalance::::get(0, account(5)), 0); assert_eq!(Balances::reserved_balance(account(1)), 0); }); } @@ -2755,7 +2763,7 @@ fn buy_item_should_work() { item_1, price_1 + 1, )); - assert_eq!(AccountBalance::::get((collection_id, user_2.clone())), 1); + assert_eq!(AccountBalance::::get(collection_id, user_2.clone()), 1); // validate the new owner & balances let item = Item::::get(collection_id, item_1).unwrap(); @@ -3123,8 +3131,8 @@ fn claim_swap_should_work() { default_item_config(), )); - assert_eq!(AccountBalance::::get((collection_id, user_1.clone())), 2); - assert_eq!(AccountBalance::::get((collection_id, user_2.clone())), 3); + assert_eq!(AccountBalance::::get(collection_id, user_1.clone()), 2); + assert_eq!(AccountBalance::::get(collection_id, user_2.clone()), 3); assert_ok!(Nfts::create_swap( RuntimeOrigin::signed(user_1.clone()), collection_id, @@ -3215,8 +3223,8 @@ fn claim_swap_should_work() { item_1, Some(price_with_direction.clone()), )); - assert_eq!(AccountBalance::::get((collection_id, user_1.clone())), 2); - assert_eq!(AccountBalance::::get((collection_id, user_2.clone())), 3); + assert_eq!(AccountBalance::::get(collection_id, user_1.clone()), 2); + assert_eq!(AccountBalance::::get(collection_id, user_2.clone()), 3); // validate the new owner let item = Item::::get(collection_id, item_1).unwrap(); From 7bc9a1176cd5700655414fe886c042cc1b9f6ed3 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 18 Oct 2024 10:04:01 +0700 Subject: [PATCH 15/76] refactor(nfts): toml lock file --- Cargo.lock | 20 ++++++++++---------- pallets/nfts/Cargo.toml | 7 +++---- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 48f7b34c7..71903ca0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7366,7 +7366,7 @@ dependencies = [ "log", "pallet-assets", "pallet-balances", - "pallet-nfts 31.0.0", + "pallet-nfts 0.1.0", "parity-scale-codec", "pop-chain-extension", "scale-info", @@ -8240,39 +8240,39 @@ dependencies = [ [[package]] name = "pallet-nfts" -version = "30.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e1cd476809de3840e19091a083d5a79178af1f108ad489706e1f9e04c8836a4" +version = "0.1.0" dependencies = [ "enumflags2", "frame-benchmarking", "frame-support", "frame-system", "log", + "pallet-balances", "parity-scale-codec", "scale-info", "sp-core", "sp-io", + "sp-keystore", "sp-runtime", - "sp-std", ] [[package]] name = "pallet-nfts" -version = "31.0.0" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e1cd476809de3840e19091a083d5a79178af1f108ad489706e1f9e04c8836a4" dependencies = [ "enumflags2", "frame-benchmarking", "frame-support", "frame-system", "log", - "pallet-balances", "parity-scale-codec", "scale-info", "sp-core", "sp-io", - "sp-keystore", "sp-runtime", + "sp-std", ] [[package]] @@ -10857,7 +10857,7 @@ dependencies = [ "pallet-message-queue", "pallet-multisig", "pallet-nft-fractionalization", - "pallet-nfts 31.0.0", + "pallet-nfts 0.1.0", "pallet-nfts-runtime-api", "pallet-preimage", "pallet-proxy", @@ -11002,7 +11002,7 @@ dependencies = [ "pallet-message-queue", "pallet-multisig", "pallet-nft-fractionalization", - "pallet-nfts 31.0.0", + "pallet-nfts 0.1.0", "pallet-nfts-runtime-api", "pallet-preimage", "pallet-proxy", diff --git a/pallets/nfts/Cargo.toml b/pallets/nfts/Cargo.toml index 7644a35ba..60b3b7465 100644 --- a/pallets/nfts/Cargo.toml +++ b/pallets/nfts/Cargo.toml @@ -6,8 +6,7 @@ homepage = "https://substrate.io" license.workspace = true name = "pallet-nfts" readme = "README.md" -repository.workspace = true -version = "31.0.0" +version = "0.1.0" [package.metadata.docs.rs] targets = [ "x86_64-unknown-linux-gnu" ] @@ -27,8 +26,8 @@ sp-io.workspace = true sp-runtime.workspace = true [dev-dependencies] -pallet-balances = { default-features = true, workspace = true } -sp-keystore = { default-features = true, workspace = true } +pallet-balances.workspace = true +sp-keystore.workspace = true [features] default = [ "std" ] From 9a6aca06387427398ca18624ad19beae0b6bdf34 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 18 Oct 2024 10:06:00 +0700 Subject: [PATCH 16/76] fix(pallet-api): propagate try-runtime feature --- pallets/api/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pallets/api/Cargo.toml b/pallets/api/Cargo.toml index 5d3987244..31ccc076d 100644 --- a/pallets/api/Cargo.toml +++ b/pallets/api/Cargo.toml @@ -60,5 +60,6 @@ std = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", + "pallet-nfts/try-runtime", "sp-runtime/try-runtime", ] From ba9162959dfa79801938a72817f6780f06069570 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 18 Oct 2024 17:36:29 +0700 Subject: [PATCH 17/76] fix(api/nonfungibles): unit tests --- pallets/api/src/nonfungibles/mod.rs | 4 +- pallets/api/src/nonfungibles/tests.rs | 407 ++++++++++++++------------ 2 files changed, 225 insertions(+), 186 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index efef2386b..9655bbeab 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -72,7 +72,7 @@ pub mod pallet { #[derive(Debug)] #[cfg_attr(feature = "std", derive(PartialEq, Clone))] pub enum ReadResult { - TotalSupply(u128), + TotalSupply(u32), BalanceOf(u32), Allowance(bool), OwnerOf(Option>), @@ -390,7 +390,7 @@ pub mod pallet { use Read::*; match value { TotalSupply(collection) => ReadResult::TotalSupply( - NftsOf::::collection_items(collection).unwrap_or_default().into(), + NftsOf::::collection_items(collection).unwrap_or_default(), ), BalanceOf { collection, owner } => ReadResult::BalanceOf(pallet_nfts::AccountBalance::::get(collection, owner)), diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index 54d855167..d757508af 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -1,184 +1,223 @@ -// TODO -// use codec::Encode; -// use frame_support::{assert_ok, traits::nonfungibles_v2::InspectEnumerable}; -// use frame_system::pallet_prelude::BlockNumberFor; -// use pallet_nfts::{CollectionConfig, CollectionSettings, MintSettings}; - -// use super::types::*; -// use crate::{ -// mock::*, -// nonfungibles::{Event, Read::*}, -// }; - -// const ITEM: u32 = 1; - -// #[test] -// fn mint_works() { -// new_test_ext().execute_with(|| { -// let owner = account(ALICE); -// let collection = create_collection(owner.clone()); -// // Successfully mint a new collection item. -// assert_ok!(NonFungibles::mint(signed(owner.clone()), owner.clone(), collection, ITEM)); -// System::assert_last_event(Event::Mint { to: owner, collection, item: ITEM }.into()); -// }); -// } - -// #[test] -// fn burn_works() { -// new_test_ext().execute_with(|| { -// let owner = account(ALICE); -// let (collection, item) = create_collection_mint(owner.clone(), ITEM); -// // Successfully burn an existing new collection item. -// assert_ok!(NonFungibles::burn(signed(owner.clone()), collection, ITEM)); -// System::assert_last_event(Event::Burn { collection, item }.into()); -// }); -// } - -// #[test] -// fn transfer() { -// new_test_ext().execute_with(|| { -// let owner = account(ALICE); -// let dest = account(BOB); -// let (collection, item) = create_collection_mint(owner.clone(), ITEM); -// // Successfully burn an existing new collection item. -// assert_ok!(NonFungibles::transfer(signed(owner.clone()), collection, ITEM, dest.clone())); -// System::assert_last_event( -// Event::Transfer { collection, item, from: owner, to: dest }.into(), -// ); -// }); -// } - -// #[test] -// fn approve_works() { -// new_test_ext().execute_with(|| { -// let owner = account(ALICE); -// let spender = account(BOB); -// let (collection, item) = create_collection_mint(owner.clone(), ITEM); -// // Successfully approve `spender` to transfer the collection item. -// assert_ok!(NonFungibles::approve(signed(owner.clone()), collection, item, spender.clone())); -// System::assert_last_event( -// Event::Approval { collection, item, owner, spender: spender.clone() }.into(), -// ); -// // Successfully transfer the item by the delegated account `spender`. -// assert_ok!(Nfts::transfer(signed(spender.clone()), collection, item, spender)); -// }); -// } - -// #[test] -// fn cancel_approval_works() { -// new_test_ext().execute_with(|| { -// let owner = account(ALICE); -// let spender = account(BOB); -// let (collection, item) = -// create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); -// // Successfully cancel the transfer approval of `spender` by `owner`. -// assert_ok!(NonFungibles::cancel_approval(signed(owner), collection, item, spender.clone())); -// // Failed to transfer the item by `spender` without permission. -// assert!(Nfts::transfer(signed(spender.clone()), collection, item, spender).is_err()); -// }); -// } - -// #[test] -// fn owner_of_works() {} - -// #[test] -// fn collection_owner_works() { -// new_test_ext().execute_with(|| { -// let collection = create_collection(account(ALICE)); -// assert_eq!( -// NonFungibles::read_state(CollectionOwner(collection)), -// Nfts::collection_owner(collection).encode() -// ); -// }); -// } - -// #[test] -// fn total_supply_works() { -// new_test_ext().execute_with(|| { -// let (collection, _) = create_collection_mint(account(ALICE), ITEM); -// assert_eq!( -// NonFungibles::read_state(TotalSupply(collection)), -// (Nfts::items(&collection).count() as u8).encode() -// ); -// }); -// } - -// #[test] -// fn collection_works() { -// new_test_ext().execute_with(|| { -// let (collection, _) = create_collection_mint(account(ALICE), ITEM); -// assert_eq!( -// NonFungibles::read_state(Collection(collection)), -// pallet_nfts::Collection::::get(&collection).encode(), -// ); -// }); -// } - -// #[test] -// fn balance_of_works() { -// new_test_ext().execute_with(|| { -// let owner = account(ALICE); -// let (collection, _) = create_collection_mint(owner.clone(), ITEM); -// assert_eq!( -// NonFungibles::read_state(BalanceOf { collection, owner: owner.clone() }), -// (Nfts::owned_in_collection(&collection, &owner).count() as u8).encode() -// ); -// }); -// } - -// #[test] -// fn allowance_works() { -// new_test_ext().execute_with(|| { -// let owner = account(ALICE); -// let spender = account(BOB); -// let (collection, item) = -// create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); -// assert_eq!( -// NonFungibles::read_state(Allowance { spender: spender.clone(), collection, item }), -// super::Pallet::::allowance(collection, item, spender).encode() -// ); -// }); -// } - -// fn signed(account: AccountId) -> RuntimeOrigin { -// RuntimeOrigin::signed(account) -// } - -// fn create_collection_mint_and_approve( -// owner: AccountIdOf, -// item: ItemIdOf, -// spender: AccountIdOf, -// ) -> (u32, u32) { -// let (collection, item) = create_collection_mint(owner.clone(), item); -// assert_ok!(Nfts::approve_transfer(signed(owner), collection, item, spender, None)); -// (collection, item) -// } - -// fn create_collection_mint(owner: AccountIdOf, item: ItemIdOf) -> (u32, u32) { -// let collection = create_collection(owner.clone()); -// assert_ok!(Nfts::mint(signed(owner.clone()), collection, item, owner, None)); -// (collection, item) -// } - -// fn create_collection(owner: AccountIdOf) -> u32 { -// let next_id = next_collection_id(); -// assert_ok!(Nfts::create( -// signed(owner.clone()), -// owner.clone(), -// collection_config_with_all_settings_enabled() -// )); -// next_id -// } - -// fn next_collection_id() -> u32 { -// pallet_nfts::NextCollectionId::::get().unwrap_or_default() -// } - -// fn collection_config_with_all_settings_enabled( -// ) -> CollectionConfig, CollectionIdOf> { -// CollectionConfig { -// settings: CollectionSettings::all_enabled(), -// max_supply: None, -// mint_settings: MintSettings::default(), -// } -// } +use codec::Encode; +use frame_support::{assert_ok, traits::nonfungibles_v2::InspectEnumerable}; +use frame_system::pallet_prelude::BlockNumberFor; +use pallet_nfts::{AccountBalance, CollectionConfig, CollectionSettings, MintSettings}; + +use super::types::{AccountIdOf, CollectionIdOf, ItemIdOf}; +use crate::{ + mock::*, + nonfungibles::{Event, Read::*}, + Read, +}; + +const ITEM: u32 = 1; + +#[test] +fn mint_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let collection = create_collection(owner.clone()); + // Successfully mint a new collection item. + assert_ok!(NonFungibles::mint( + signed(owner.clone()), + owner.clone(), + collection, + ITEM, + None + )); + System::assert_last_event( + Event::Transfer { collection, item: ITEM, from: None, to: Some(owner), value: None } + .into(), + ); + }); +} + +#[test] +fn burn_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let (collection, item) = create_collection_mint(owner.clone(), ITEM); + // Successfully burn an existing new collection item. + assert_ok!(NonFungibles::burn(signed(owner.clone()), collection, ITEM)); + System::assert_last_event( + Event::Transfer { collection, item, from: Some(owner), to: None, value: None }.into(), + ); + }); +} + +#[test] +fn transfer() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let dest = account(BOB); + let (collection, item) = create_collection_mint(owner.clone(), ITEM); + // Successfully burn an existing new collection item. + assert_ok!(NonFungibles::transfer(signed(owner.clone()), collection, ITEM, dest.clone())); + System::assert_last_event( + Event::Transfer { collection, item, from: Some(owner), to: Some(dest), value: None } + .into(), + ); + }); +} + +#[test] +fn approve_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let operator = account(BOB); + let (collection, item) = create_collection_mint(owner.clone(), ITEM); + // Successfully approve `spender` to transfer the collection item. + assert_ok!(NonFungibles::approve( + signed(owner.clone()), + collection, + Some(item), + operator.clone(), + true + )); + System::assert_last_event( + Event::Approval { + collection, + item: Some(item), + owner, + operator: operator.clone(), + approved: true, + } + .into(), + ); + // Successfully transfer the item by the delegated account `spender`. + assert_ok!(Nfts::transfer(signed(operator.clone()), collection, item, operator)); + }); +} + +#[test] +fn cancel_approval_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let spender = account(BOB); + let (collection, item) = + create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); + // Successfully cancel the transfer approval of `spender` by `owner`. + assert_ok!(NonFungibles::approve( + signed(owner), + collection, + Some(item), + spender.clone(), + false + )); + // Failed to transfer the item by `spender` without permission. + assert!(Nfts::transfer(signed(spender.clone()), collection, item, spender).is_err()); + }); +} + +#[test] +fn owner_of_works() {} + +#[test] +fn collection_owner_works() { + new_test_ext().execute_with(|| { + let collection = create_collection(account(ALICE)); + assert_eq!( + NonFungibles::read(CollectionOwner(collection)).encode(), + Nfts::collection_owner(collection).encode() + ); + }); +} + +#[test] +fn total_supply_works() { + new_test_ext().execute_with(|| { + let (collection, _) = create_collection_mint(account(ALICE), ITEM); + assert_eq!( + NonFungibles::read(TotalSupply(collection)).encode(), + Nfts::collection_items(collection).unwrap_or_default().encode() + ); + }); +} + +#[test] +fn collection_works() { + new_test_ext().execute_with(|| { + let (collection, _) = create_collection_mint(account(ALICE), ITEM); + assert_eq!( + NonFungibles::read(Collection(collection)).encode(), + pallet_nfts::Collection::::get(&collection).encode(), + ); + }); +} + +#[test] +fn balance_of_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let (collection, _) = create_collection_mint(owner.clone(), ITEM); + assert_eq!( + NonFungibles::read(BalanceOf { collection, owner: owner.clone() }).encode(), + AccountBalance::::get(collection, owner).encode() + ); + }); +} + +#[test] +fn allowance_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let operator = account(BOB); + let (collection, item) = + create_collection_mint_and_approve(owner.clone(), ITEM, operator.clone()); + assert_eq!( + NonFungibles::read(Allowance { + collection, + item: Some(item), + owner: owner.clone(), + operator: operator.clone(), + }) + .encode(), + Nfts::check_allowance(&collection, &Some(item), &owner, &operator) + .is_ok() + .encode() + ); + }); +} + +fn signed(account: AccountId) -> RuntimeOrigin { + RuntimeOrigin::signed(account) +} + +fn create_collection_mint_and_approve( + owner: AccountIdOf, + item: ItemIdOf, + spender: AccountIdOf, +) -> (u32, u32) { + let (collection, item) = create_collection_mint(owner.clone(), item); + assert_ok!(Nfts::approve_transfer(signed(owner), collection, Some(item), spender, None)); + (collection, item) +} + +fn create_collection_mint(owner: AccountIdOf, item: ItemIdOf) -> (u32, u32) { + let collection = create_collection(owner.clone()); + assert_ok!(Nfts::mint(signed(owner.clone()), collection, item, owner, None)); + (collection, item) +} + +fn create_collection(owner: AccountIdOf) -> u32 { + let next_id = next_collection_id(); + assert_ok!(Nfts::create( + signed(owner.clone()), + owner.clone(), + collection_config_with_all_settings_enabled() + )); + next_id +} + +fn next_collection_id() -> u32 { + pallet_nfts::NextCollectionId::::get().unwrap_or_default() +} + +fn collection_config_with_all_settings_enabled( +) -> CollectionConfig, CollectionIdOf> { + CollectionConfig { + settings: CollectionSettings::all_enabled(), + max_supply: None, + mint_settings: MintSettings::default(), + } +} From 83d86c295690e0ed5a91169c8a4131fbac28f141 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:15:11 +0700 Subject: [PATCH 18/76] test(api/nonfungibles): encoding_read_result --- pallets/api/src/nonfungibles/mod.rs | 10 +-- pallets/api/src/nonfungibles/tests.rs | 109 ++++++++++++++++++++++++-- pallets/nfts/src/types.rs | 22 +++--- 3 files changed, 120 insertions(+), 21 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index 9655bbeab..eb88bfa67 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -137,8 +137,8 @@ pub mod pallet { from: Option>, /// The recipient of the transfer. `None` when burning. to: Option>, - /// The amount minted. - value: Option>, + /// The price of the collection item. + price: Option>, }, } @@ -167,7 +167,7 @@ pub mod pallet { item, from: None, to: Some(account), - value: mint_price, + price: mint_price, }); Ok(()) } @@ -186,7 +186,7 @@ pub mod pallet { item, from: Some(account), to: None, - value: None, + price: None, }); Ok(()) } @@ -206,7 +206,7 @@ pub mod pallet { item, from: Some(from), to: Some(to), - value: None, + price: None, }); Ok(()) } diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index d757508af..063ceee33 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -1,23 +1,119 @@ use codec::Encode; -use frame_support::{assert_ok, traits::nonfungibles_v2::InspectEnumerable}; +use frame_support::assert_ok; use frame_system::pallet_prelude::BlockNumberFor; use pallet_nfts::{AccountBalance, CollectionConfig, CollectionSettings, MintSettings}; use super::types::{AccountIdOf, CollectionIdOf, ItemIdOf}; use crate::{ mock::*, - nonfungibles::{Event, Read::*}, + nonfungibles::{Event, Read::*, ReadResult}, Read, }; const ITEM: u32 = 1; +mod encoding_read_result { + use pallet_nfts::{CollectionDetails, ItemDeposit, ItemDetails}; + use sp_runtime::{BoundedBTreeMap, BoundedVec}; + + use super::*; + + #[test] + fn total_supply() { + let total_supply: u32 = 1_000_000; + assert_eq!(ReadResult::TotalSupply::(total_supply).encode(), total_supply.encode()); + } + + #[test] + fn balance_of() { + let balance: u32 = 100; + assert_eq!(ReadResult::BalanceOf::(balance).encode(), balance.encode()); + } + + #[test] + fn allowance() { + let allowance = false; + assert_eq!(ReadResult::Allowance::(allowance).encode(), allowance.encode()); + } + + #[test] + fn owner_of() { + let mut owner = Some(account(ALICE)); + assert_eq!(ReadResult::OwnerOf::(owner.clone()).encode(), owner.encode()); + owner = None; + assert_eq!(ReadResult::OwnerOf::(owner.clone()).encode(), owner.encode()); + } + + #[test] + fn get_attribute() { + let mut attribute = Some(BoundedVec::truncate_from("some attribute".as_bytes().to_vec())); + assert_eq!( + ReadResult::GetAttribute::(attribute.clone()).encode(), + attribute.encode() + ); + attribute = None; + assert_eq!( + ReadResult::GetAttribute::(attribute.clone()).encode(), + attribute.encode() + ); + } + + #[test] + fn collection_owner() { + let mut collection_owner = Some(account(ALICE)); + assert_eq!( + ReadResult::CollectionOwner::(collection_owner.clone()).encode(), + collection_owner.encode() + ); + collection_owner = None; + assert_eq!( + ReadResult::CollectionOwner::(collection_owner.clone()).encode(), + collection_owner.encode() + ); + } + + #[test] + fn collection() { + let mut collection_details = Some(CollectionDetails { + owner: account(ALICE), + owner_deposit: 0, + items: 0, + item_metadatas: 0, + item_configs: 0, + attributes: 0, + }); + assert_eq!( + ReadResult::Collection::(collection_details.clone()).encode(), + collection_details.encode() + ); + collection_details = None; + assert_eq!( + ReadResult::Collection::(collection_details.clone()).encode(), + collection_details.encode() + ); + } + + #[test] + fn item() { + let mut item_details = Some(ItemDetails { + owner: account(ALICE), + approvals: BoundedBTreeMap::default(), + deposit: ItemDeposit { amount: 0, account: account(BOB) }, + }); + assert_eq!(ReadResult::Item::(item_details.clone()).encode(), item_details.encode()); + item_details = None; + assert_eq!(ReadResult::Item::(item_details.clone()).encode(), item_details.encode()); + } +} + #[test] fn mint_works() { new_test_ext().execute_with(|| { let owner = account(ALICE); let collection = create_collection(owner.clone()); // Successfully mint a new collection item. + let balance_before_mint = AccountBalance::::get(collection.clone(), owner.clone()); + // assert_ok!(NonFungibles::mint( signed(owner.clone()), owner.clone(), @@ -25,8 +121,11 @@ fn mint_works() { ITEM, None )); + let balance_after_mint = AccountBalance::::get(collection.clone(), owner.clone()); + assert_eq!(balance_after_mint, 1); + assert_eq!(balance_after_mint - balance_before_mint, 1); System::assert_last_event( - Event::Transfer { collection, item: ITEM, from: None, to: Some(owner), value: None } + Event::Transfer { collection, item: ITEM, from: None, to: Some(owner), price: None } .into(), ); }); @@ -40,7 +139,7 @@ fn burn_works() { // Successfully burn an existing new collection item. assert_ok!(NonFungibles::burn(signed(owner.clone()), collection, ITEM)); System::assert_last_event( - Event::Transfer { collection, item, from: Some(owner), to: None, value: None }.into(), + Event::Transfer { collection, item, from: Some(owner), to: None, price: None }.into(), ); }); } @@ -54,7 +153,7 @@ fn transfer() { // Successfully burn an existing new collection item. assert_ok!(NonFungibles::transfer(signed(owner.clone()), collection, ITEM, dest.clone())); System::assert_last_event( - Event::Transfer { collection, item, from: Some(owner), to: Some(dest), value: None } + Event::Transfer { collection, item, from: Some(owner), to: Some(dest), price: None } .into(), ); }); diff --git a/pallets/nfts/src/types.rs b/pallets/nfts/src/types.rs index f08f1d097..061352c09 100644 --- a/pallets/nfts/src/types.rs +++ b/pallets/nfts/src/types.rs @@ -94,18 +94,18 @@ pub(super) type PreSignedAttributesOf = PreSignedAttributes< #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct CollectionDetails { /// Collection's owner. - pub(super) owner: AccountId, + pub owner: AccountId, /// The total balance deposited by the owner for all the storage data associated with this /// collection. Used by `destroy`. - pub(super) owner_deposit: DepositBalance, + pub owner_deposit: DepositBalance, /// The total number of outstanding items of this collection. - pub(super) items: u32, + pub items: u32, /// The total number of outstanding item metadata of this collection. - pub(super) item_metadatas: u32, + pub item_metadatas: u32, /// The total number of outstanding item configs of this collection. - pub(super) item_configs: u32, + pub item_configs: u32, /// The total number of attributes for this collection. - pub(super) attributes: u32, + pub attributes: u32, } /// Witness data for the destroy transactions. @@ -145,21 +145,21 @@ pub struct MintWitness { #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo, MaxEncodedLen)] pub struct ItemDetails { /// The owner of this item. - pub(super) owner: AccountId, + pub owner: AccountId, /// The approved transferrer of this item, if one is set. - pub(super) approvals: Approvals, + pub approvals: Approvals, /// The amount held in the pallet's default account for this item. Free-hold items will have /// this as zero. - pub(super) deposit: Deposit, + pub deposit: Deposit, } /// Information about the reserved item deposit. #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct ItemDeposit { /// A depositor account. - pub(super) account: AccountId, + pub account: AccountId, /// An amount that gets reserved. - pub(super) amount: DepositBalance, + pub amount: DepositBalance, } /// Information about the collection's metadata. From cf9c69749e2a7e17ba3e61c03ab2384ffc75c545 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:51:50 +0700 Subject: [PATCH 19/76] refactor(api/nonfungibles): pallet tests --- pallets/api/src/nonfungibles/tests.rs | 243 +++++++++++++++----------- 1 file changed, 143 insertions(+), 100 deletions(-) diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index 063ceee33..05c82f60b 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -1,7 +1,11 @@ use codec::Encode; -use frame_support::assert_ok; +use frame_support::{assert_noop, assert_ok}; use frame_system::pallet_prelude::BlockNumberFor; -use pallet_nfts::{AccountBalance, CollectionConfig, CollectionSettings, MintSettings}; +use pallet_nfts::{ + AccountBalance, CollectionConfig, CollectionDetails, CollectionSettings, ItemDeposit, + ItemDetails, MintSettings, +}; +use sp_runtime::{BoundedBTreeMap, BoundedVec, DispatchError::BadOrigin}; use super::types::{AccountIdOf, CollectionIdOf, ItemIdOf}; use crate::{ @@ -12,10 +16,9 @@ use crate::{ const ITEM: u32 = 1; -mod encoding_read_result { - use pallet_nfts::{CollectionDetails, ItemDeposit, ItemDetails}; - use sp_runtime::{BoundedBTreeMap, BoundedVec}; +type NftsError = pallet_nfts::Error; +mod encoding_read_result { use super::*; #[test] @@ -107,53 +110,72 @@ mod encoding_read_result { } #[test] -fn mint_works() { +fn transfer() { new_test_ext().execute_with(|| { - let owner = account(ALICE); - let collection = create_collection(owner.clone()); - // Successfully mint a new collection item. - let balance_before_mint = AccountBalance::::get(collection.clone(), owner.clone()); - // - assert_ok!(NonFungibles::mint( - signed(owner.clone()), - owner.clone(), - collection, - ITEM, - None - )); - let balance_after_mint = AccountBalance::::get(collection.clone(), owner.clone()); - assert_eq!(balance_after_mint, 1); - assert_eq!(balance_after_mint - balance_before_mint, 1); + let owner = ALICE; + let dest = BOB; + + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + for origin in vec![root(), none()] { + assert_noop!( + NonFungibles::transfer(origin, collection, item, account(dest)), + BadOrigin + ); + } + // Successfully burn an existing new collection item. + let balance_before_transfer = AccountBalance::::get(collection, &account(dest)); + assert_ok!(NonFungibles::transfer(signed(owner), collection, ITEM, account(dest))); + let balance_after_transfer = AccountBalance::::get(collection, &account(dest)); + assert_eq!(AccountBalance::::get(collection, &account(owner)), 0); + assert_eq!(balance_after_transfer - balance_before_transfer, 1); System::assert_last_event( - Event::Transfer { collection, item: ITEM, from: None, to: Some(owner), price: None } - .into(), + Event::Transfer { + collection, + item, + from: Some(account(owner)), + to: Some(account(dest)), + price: None, + } + .into(), ); }); } #[test] -fn burn_works() { +fn mint_works() { new_test_ext().execute_with(|| { - let owner = account(ALICE); - let (collection, item) = create_collection_mint(owner.clone(), ITEM); - // Successfully burn an existing new collection item. - assert_ok!(NonFungibles::burn(signed(owner.clone()), collection, ITEM)); + let owner = ALICE; + let collection = nfts::create_collection(owner); + + // Successfully mint a new collection item. + let balance_before_mint = AccountBalance::::get(collection, account(owner)); + assert_ok!(NonFungibles::mint(signed(owner), account(owner), collection, ITEM, None)); + let balance_after_mint = AccountBalance::::get(collection, account(owner)); + assert_eq!(balance_after_mint, 1); + assert_eq!(balance_after_mint - balance_before_mint, 1); System::assert_last_event( - Event::Transfer { collection, item, from: Some(owner), to: None, price: None }.into(), + Event::Transfer { + collection, + item: ITEM, + from: None, + to: Some(account(owner)), + price: None, + } + .into(), ); }); } #[test] -fn transfer() { +fn burn_works() { new_test_ext().execute_with(|| { - let owner = account(ALICE); - let dest = account(BOB); - let (collection, item) = create_collection_mint(owner.clone(), ITEM); + let owner = ALICE; + // Successfully burn an existing new collection item. - assert_ok!(NonFungibles::transfer(signed(owner.clone()), collection, ITEM, dest.clone())); + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + assert_ok!(NonFungibles::burn(signed(owner), collection, ITEM)); System::assert_last_event( - Event::Transfer { collection, item, from: Some(owner), to: Some(dest), price: None } + Event::Transfer { collection, item, from: Some(account(owner)), to: None, price: None } .into(), ); }); @@ -162,59 +184,63 @@ fn transfer() { #[test] fn approve_works() { new_test_ext().execute_with(|| { - let owner = account(ALICE); - let operator = account(BOB); - let (collection, item) = create_collection_mint(owner.clone(), ITEM); - // Successfully approve `spender` to transfer the collection item. + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + // Successfully approve `oeprator` to transfer the collection item. assert_ok!(NonFungibles::approve( - signed(owner.clone()), + signed(owner), collection, Some(item), - operator.clone(), + account(operator), true )); System::assert_last_event( Event::Approval { collection, item: Some(item), - owner, - operator: operator.clone(), + owner: account(owner), + operator: account(operator), approved: true, } .into(), ); - // Successfully transfer the item by the delegated account `spender`. - assert_ok!(Nfts::transfer(signed(operator.clone()), collection, item, operator)); + // Successfully transfer the item by the delegated account `operator`. + assert_ok!(Nfts::transfer(signed(operator), collection, item, account(operator))); }); } #[test] fn cancel_approval_works() { new_test_ext().execute_with(|| { - let owner = account(ALICE); - let spender = account(BOB); - let (collection, item) = - create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); - // Successfully cancel the transfer approval of `spender` by `owner`. + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); + // Successfully cancel the transfer approval of `operator` by `owner`. assert_ok!(NonFungibles::approve( signed(owner), collection, Some(item), - spender.clone(), + account(operator), false )); - // Failed to transfer the item by `spender` without permission. - assert!(Nfts::transfer(signed(spender.clone()), collection, item, spender).is_err()); + // Failed to transfer the item by `operator` without permission. + assert_noop!( + Nfts::transfer(signed(operator), collection, item, account(operator)), + NftsError::NoPermission + ); }); } #[test] -fn owner_of_works() {} +fn owner_of_works() { + unimplemented!() +} #[test] fn collection_owner_works() { new_test_ext().execute_with(|| { - let collection = create_collection(account(ALICE)); + let collection = nfts::create_collection(ALICE); assert_eq!( NonFungibles::read(CollectionOwner(collection)).encode(), Nfts::collection_owner(collection).encode() @@ -225,7 +251,7 @@ fn collection_owner_works() { #[test] fn total_supply_works() { new_test_ext().execute_with(|| { - let (collection, _) = create_collection_mint(account(ALICE), ITEM); + let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!( NonFungibles::read(TotalSupply(collection)).encode(), Nfts::collection_items(collection).unwrap_or_default().encode() @@ -236,7 +262,7 @@ fn total_supply_works() { #[test] fn collection_works() { new_test_ext().execute_with(|| { - let (collection, _) = create_collection_mint(account(ALICE), ITEM); + let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!( NonFungibles::read(Collection(collection)).encode(), pallet_nfts::Collection::::get(&collection).encode(), @@ -247,11 +273,11 @@ fn collection_works() { #[test] fn balance_of_works() { new_test_ext().execute_with(|| { - let owner = account(ALICE); - let (collection, _) = create_collection_mint(owner.clone(), ITEM); + let owner = ALICE; + let (collection, _) = nfts::create_collection_mint(owner, ITEM); assert_eq!( - NonFungibles::read(BalanceOf { collection, owner: owner.clone() }).encode(), - AccountBalance::::get(collection, owner).encode() + NonFungibles::read(BalanceOf { collection, owner: account(owner) }).encode(), + AccountBalance::::get(collection, account(owner)).encode() ); }); } @@ -259,64 +285,81 @@ fn balance_of_works() { #[test] fn allowance_works() { new_test_ext().execute_with(|| { - let owner = account(ALICE); - let operator = account(BOB); - let (collection, item) = - create_collection_mint_and_approve(owner.clone(), ITEM, operator.clone()); + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); assert_eq!( NonFungibles::read(Allowance { collection, item: Some(item), - owner: owner.clone(), - operator: operator.clone(), + owner: account(owner), + operator: account(operator), }) .encode(), - Nfts::check_allowance(&collection, &Some(item), &owner, &operator) + Nfts::check_allowance(&collection, &Some(item), &account(owner), &account(operator)) .is_ok() .encode() ); }); } -fn signed(account: AccountId) -> RuntimeOrigin { - RuntimeOrigin::signed(account) +fn signed(account_id: u8) -> RuntimeOrigin { + RuntimeOrigin::signed(account(account_id)) } -fn create_collection_mint_and_approve( - owner: AccountIdOf, - item: ItemIdOf, - spender: AccountIdOf, -) -> (u32, u32) { - let (collection, item) = create_collection_mint(owner.clone(), item); - assert_ok!(Nfts::approve_transfer(signed(owner), collection, Some(item), spender, None)); - (collection, item) +fn root() -> RuntimeOrigin { + RuntimeOrigin::root() } -fn create_collection_mint(owner: AccountIdOf, item: ItemIdOf) -> (u32, u32) { - let collection = create_collection(owner.clone()); - assert_ok!(Nfts::mint(signed(owner.clone()), collection, item, owner, None)); - (collection, item) +fn none() -> RuntimeOrigin { + RuntimeOrigin::none() } -fn create_collection(owner: AccountIdOf) -> u32 { - let next_id = next_collection_id(); - assert_ok!(Nfts::create( - signed(owner.clone()), - owner.clone(), - collection_config_with_all_settings_enabled() - )); - next_id -} +mod nfts { + use super::*; -fn next_collection_id() -> u32 { - pallet_nfts::NextCollectionId::::get().unwrap_or_default() -} + pub(super) fn create_collection_mint_and_approve( + owner: u8, + item: ItemIdOf, + operator: u8, + ) -> (u32, u32) { + let (collection, item) = create_collection_mint(owner, item); + assert_ok!(Nfts::approve_transfer( + signed(owner), + collection, + Some(item), + account(operator), + None + )); + (collection, item) + } + + pub(super) fn create_collection_mint(owner: u8, item: ItemIdOf) -> (u32, u32) { + let collection = create_collection(owner); + assert_ok!(Nfts::mint(signed(owner), collection, item, account(owner), None)); + (collection, item) + } + + pub(super) fn create_collection(owner: u8) -> u32 { + let next_id = next_collection_id(); + assert_ok!(Nfts::create( + signed(owner), + account(owner), + collection_config_with_all_settings_enabled() + )); + next_id + } + + pub(super) fn next_collection_id() -> u32 { + pallet_nfts::NextCollectionId::::get().unwrap_or_default() + } -fn collection_config_with_all_settings_enabled( -) -> CollectionConfig, CollectionIdOf> { - CollectionConfig { - settings: CollectionSettings::all_enabled(), - max_supply: None, - mint_settings: MintSettings::default(), + pub(super) fn collection_config_with_all_settings_enabled( + ) -> CollectionConfig, CollectionIdOf> { + CollectionConfig { + settings: CollectionSettings::all_enabled(), + max_supply: None, + mint_settings: MintSettings::default(), + } } } From b61c5f1c340b74dd338de55677a6528fe354797e Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:30:10 +0700 Subject: [PATCH 20/76] test(nonfungibles): add tests and remove collection owner read --- pallets/api/src/nonfungibles/mod.rs | 70 ++++--- pallets/api/src/nonfungibles/tests.rs | 267 +++++++++++++++++++++++--- pallets/api/src/nonfungibles/types.rs | 2 + 3 files changed, 286 insertions(+), 53 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index eb88bfa67..7377048fc 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -12,7 +12,7 @@ mod types; #[frame_support::pallet] pub mod pallet { - use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; + use frame_support::{dispatch::DispatchResult, pallet_prelude::*, traits::Incrementable}; use frame_system::pallet_prelude::*; use pallet_nfts::{ CancelAttributesApprovalWitness, CollectionConfig, CollectionSettings, DestroyWitness, @@ -21,7 +21,8 @@ pub mod pallet { use sp_std::vec::Vec; use types::{ AccountIdOf, AttributeNamespaceOf, BalanceOf, CollectionDetailsFor, CollectionIdOf, - CreateCollectionConfigFor, ItemDetailsFor, ItemIdOf, ItemPriceOf, NftsOf, NftsWeightInfoOf, + CreateCollectionConfigFor, ItemDetailsFor, ItemIdOf, ItemPriceOf, NextCollectionIdOf, + NftsOf, NftsWeightInfoOf, }; use super::*; @@ -32,54 +33,62 @@ pub mod pallet { #[repr(u8)] #[allow(clippy::unnecessary_cast)] pub enum Read { - /// Number of items existing in a concrete collection. - #[codec(index = 2)] + /// Total item supply of a collection. + #[codec(index = 0)] TotalSupply(CollectionIdOf), - /// Returns the total number of items in the collection owned by the account. - #[codec(index = 3)] + /// Account balance for a specified collection. + #[codec(index = 1)] BalanceOf { collection: CollectionIdOf, owner: AccountIdOf }, - /// Whether a spender is allowed to transfer an item or items from owner. - #[codec(index = 6)] + /// Allowance for an operator approved by an owner, for a specified collection or item. + #[codec(index = 2)] Allowance { collection: CollectionIdOf, owner: AccountIdOf, operator: AccountIdOf, item: Option>, }, - /// Returns the owner of an item. - #[codec(index = 0)] + /// Owner of a specified collection item. + #[codec(index = 3)] OwnerOf { collection: CollectionIdOf, item: ItemIdOf }, - /// Returns the attribute of `item` for the given `key`. - #[codec(index = 6)] + /// Attribute value of a collection item. + #[codec(index = 4)] GetAttribute { collection: CollectionIdOf, item: Option>, namespace: AttributeNamespaceOf, key: BoundedVec, }, - /// Returns the owner of a collection. - #[codec(index = 1)] - CollectionOwner(CollectionIdOf), - /// Returns the details of a collection. - #[codec(index = 4)] + /// Details of a collection. + #[codec(index = 6)] Collection(CollectionIdOf), - /// Returns the details of an item. - #[codec(index = 5)] + /// Details of a collection item. + #[codec(index = 7)] Item { collection: CollectionIdOf, item: ItemIdOf }, + /// Next collection ID. + #[codec(index = 8)] + NextCollectionId, } /// Results of state reads for the non-fungibles API. #[derive(Debug)] #[cfg_attr(feature = "std", derive(PartialEq, Clone))] pub enum ReadResult { + /// Total item supply of a collection. TotalSupply(u32), + /// Account balance for a specified collection. BalanceOf(u32), + /// Allowance for an operator approved by an owner, for a specified collection or item. Allowance(bool), + /// Owner of a specified collection owner. OwnerOf(Option>), + /// Attribute value of a collection item. GetAttribute(Option>), - CollectionOwner(Option>), + /// Details of a collection. Collection(Option>), + /// Details of a collection item. Item(Option>), + /// Next collection ID. + NextCollectionId(Option>), } impl ReadResult { @@ -88,13 +97,13 @@ pub mod pallet { use ReadResult::*; match self { OwnerOf(result) => result.encode(), - CollectionOwner(result) => result.encode(), TotalSupply(result) => result.encode(), BalanceOf(result) => result.encode(), Collection(result) => result.encode(), Item(result) => result.encode(), Allowance(result) => result.encode(), GetAttribute(result) => result.encode(), + NextCollectionId(result) => result.encode(), } } } @@ -140,6 +149,15 @@ pub mod pallet { /// The price of the collection item. price: Option>, }, + /// Event emitted when a collection is created. + Created { + /// The collection identifier. + id: CollectionIdOf, + /// The creator of the collection. + creator: AccountIdOf, + /// The administrator of the collection. + admin: AccountIdOf, + }, } #[pallet::call] @@ -248,6 +266,10 @@ pub mod pallet { admin: AccountIdOf, config: CreateCollectionConfigFor, ) -> DispatchResult { + let id = NextCollectionIdOf::::get() + .or(T::CollectionId::initial_value()) + .ok_or(pallet_nfts::Error::::UnknownCollection)?; + let creator = ensure_signed(origin.clone())?; let collection_config = CollectionConfig { settings: CollectionSettings::all_enabled(), max_supply: config.max_supply, @@ -259,6 +281,7 @@ pub mod pallet { }, }; NftsOf::::create(origin, T::Lookup::unlookup(admin.clone()), collection_config)?; + Self::deposit_event(Event::Created { id, admin, creator }); Ok(()) } @@ -403,12 +426,13 @@ pub mod pallet { pallet_nfts::Attribute::::get((collection, item, namespace, key)) .map(|attribute| attribute.0), ), - CollectionOwner(collection) => - ReadResult::CollectionOwner(NftsOf::::collection_owner(collection)), Collection(collection) => ReadResult::Collection(pallet_nfts::Collection::::get(collection)), Item { collection, item } => ReadResult::Item(pallet_nfts::Item::::get(collection, item)), + NextCollectionId => ReadResult::NextCollectionId( + NextCollectionIdOf::::get().or(T::CollectionId::initial_value()), + ), } } } diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index 05c82f60b..e89ba0bd2 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -1,5 +1,5 @@ use codec::Encode; -use frame_support::{assert_noop, assert_ok}; +use frame_support::{assert_noop, assert_ok, traits::Incrementable}; use frame_system::pallet_prelude::BlockNumberFor; use pallet_nfts::{ AccountBalance, CollectionConfig, CollectionDetails, CollectionSettings, ItemDeposit, @@ -7,7 +7,7 @@ use pallet_nfts::{ }; use sp_runtime::{BoundedBTreeMap, BoundedVec, DispatchError::BadOrigin}; -use super::types::{AccountIdOf, CollectionIdOf, ItemIdOf}; +use super::types::{CollectionIdOf, ItemIdOf}; use crate::{ mock::*, nonfungibles::{Event, Read::*, ReadResult}, @@ -61,20 +61,6 @@ mod encoding_read_result { ); } - #[test] - fn collection_owner() { - let mut collection_owner = Some(account(ALICE)); - assert_eq!( - ReadResult::CollectionOwner::(collection_owner.clone()).encode(), - collection_owner.encode() - ); - collection_owner = None; - assert_eq!( - ReadResult::CollectionOwner::(collection_owner.clone()).encode(), - collection_owner.encode() - ); - } - #[test] fn collection() { let mut collection_details = Some(CollectionDetails { @@ -107,6 +93,20 @@ mod encoding_read_result { item_details = None; assert_eq!(ReadResult::Item::(item_details.clone()).encode(), item_details.encode()); } + + #[test] + fn next_collection_id_works() { + let mut next_collection_id = Some(0); + assert_eq!( + ReadResult::NextCollectionId::(next_collection_id).encode(), + next_collection_id.encode() + ); + next_collection_id = None; + assert_eq!( + ReadResult::NextCollectionId::(next_collection_id).encode(), + next_collection_id.encode() + ); + } } #[test] @@ -232,33 +232,212 @@ fn cancel_approval_works() { }); } +#[test] +fn set_max_supply_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let collection = nfts::create_collection(owner); + assert_ok!(NonFungibles::set_max_supply(signed(owner), collection, 10)); + (0..10).into_iter().for_each(|i| { + assert_ok!(Nfts::mint(signed(owner), collection, i, account(owner), None)); + }); + assert_noop!( + Nfts::mint(signed(owner), collection, 42, account(owner), None), + NftsError::MaxSupplyReached + ); + }); +} + #[test] fn owner_of_works() { - unimplemented!() + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!( + NonFungibles::read(OwnerOf { collection, item }).encode(), + Nfts::owner(collection, item).encode() + ); + }); +} + +#[test] +fn get_attribute_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); + let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); + let mut result: Option::ValueLimit>> = None; + // No attribute set. + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item: Some(item), + namespace: pallet_nfts::AttributeNamespace::CollectionOwner, + key: attribute.clone() + }) + .encode(), + result.encode() + ); + // Successfully get an existing attribute. + result = Some(value.clone()); + assert_ok!(Nfts::set_attribute( + signed(ALICE), + collection, + Some(item), + pallet_nfts::AttributeNamespace::CollectionOwner, + attribute.clone(), + value, + )); + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item: Some(item), + namespace: pallet_nfts::AttributeNamespace::CollectionOwner, + key: attribute + }) + .encode(), + result.encode() + ); + }); } #[test] -fn collection_owner_works() { +fn clear_attribute_works() { new_test_ext().execute_with(|| { - let collection = nfts::create_collection(ALICE); + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); + let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let mut result: Option::ValueLimit>> = None; + assert_ok!(Nfts::set_attribute( + signed(ALICE), + collection, + Some(item), + pallet_nfts::AttributeNamespace::CollectionOwner, + attribute.clone(), + BoundedVec::truncate_from("some value".as_bytes().to_vec()) + )); + // Successfully clear an attribute. + assert_ok!(Nfts::clear_attribute( + signed(ALICE), + collection, + Some(item), + pallet_nfts::AttributeNamespace::CollectionOwner, + attribute.clone(), + )); assert_eq!( - NonFungibles::read(CollectionOwner(collection)).encode(), - Nfts::collection_owner(collection).encode() + NonFungibles::read(GetAttribute { + collection, + item: Some(item), + namespace: pallet_nfts::AttributeNamespace::CollectionOwner, + key: attribute + }) + .encode(), + result.encode() ); }); } #[test] -fn total_supply_works() { +fn approve_item_attribute_works() { new_test_ext().execute_with(|| { - let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); + let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); + let mut result: Option::ValueLimit>> = None; + // Successfully approve delegate to set attributes. + assert_ok!(Nfts::approve_item_attributes(signed(ALICE), collection, item, account(BOB))); + assert_ok!(Nfts::set_attribute( + signed(BOB), + collection, + Some(item), + pallet_nfts::AttributeNamespace::Account(account(BOB)), + attribute.clone(), + value.clone() + )); + result = Some(value); + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item: Some(item), + namespace: pallet_nfts::AttributeNamespace::Account(account(BOB)), + key: attribute + }) + .encode(), + result.encode() + ); + }); +} + +#[test] +fn cancel_item_attribute_approval_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); + let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); + let mut result: Option::ValueLimit>> = None; + // Successfully approve delegate to set attributes. + assert_ok!(Nfts::approve_item_attributes(signed(ALICE), collection, item, account(BOB))); + assert_ok!(Nfts::set_attribute( + signed(BOB), + collection, + Some(item), + pallet_nfts::AttributeNamespace::Account(account(BOB)), + attribute.clone(), + value.clone() + )); + assert_ok!(Nfts::cancel_item_attributes_approval( + signed(ALICE), + collection, + item, + account(BOB), + pallet_nfts::CancelAttributesApprovalWitness { account_attributes: 1 } + )); + assert_noop!( + Nfts::set_attribute( + signed(BOB), + collection, + Some(item), + pallet_nfts::AttributeNamespace::Account(account(BOB)), + attribute.clone(), + value.clone() + ), + NftsError::NoPermission + ); + }); +} + +#[test] +fn next_collection_id_works() { + new_test_ext().execute_with(|| { + let _ = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); assert_eq!( - NonFungibles::read(TotalSupply(collection)).encode(), - Nfts::collection_items(collection).unwrap_or_default().encode() + NonFungibles::read(NextCollectionId).encode(), + pallet_nfts::NextCollectionId::::get() + .or(CollectionIdOf::::initial_value()) + .encode(), ); }); } +#[test] +fn total_supply_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let collection = nfts::create_collection(owner); + (0..10).into_iter().for_each(|i| { + assert_ok!(Nfts::mint(signed(owner), collection, i, account(owner), None)); + assert_eq!(NonFungibles::read(TotalSupply(collection)).encode(), (i + 1).encode()); + assert_eq!( + NonFungibles::read(TotalSupply(collection)).encode(), + Nfts::collection_items(collection).unwrap_or_default().encode() + ); + }); + }); +} + #[test] fn collection_works() { new_test_ext().execute_with(|| { @@ -271,23 +450,51 @@ fn collection_works() { } #[test] -fn balance_of_works() { +fn item_works() { new_test_ext().execute_with(|| { - let owner = ALICE; - let (collection, _) = nfts::create_collection_mint(owner, ITEM); + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!( - NonFungibles::read(BalanceOf { collection, owner: account(owner) }).encode(), - AccountBalance::::get(collection, account(owner)).encode() + NonFungibles::read(Item { collection, item }).encode(), + pallet_nfts::Item::::get(&collection, &item).encode(), ); }); } +#[test] +fn balance_of_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let collection = nfts::create_collection(owner); + (0..10).into_iter().for_each(|i| { + assert_ok!(Nfts::mint(signed(owner), collection, i, account(owner), None)); + assert_eq!( + NonFungibles::read(BalanceOf { collection, owner: account(owner) }).encode(), + (i + 1).encode() + ); + assert_eq!( + NonFungibles::read(BalanceOf { collection, owner: account(owner) }).encode(), + AccountBalance::::get(collection, account(owner)).encode() + ); + }); + }); +} + #[test] fn allowance_works() { new_test_ext().execute_with(|| { let owner = ALICE; let operator = BOB; let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); + assert_eq!( + NonFungibles::read(Allowance { + collection, + item: Some(item), + owner: account(owner), + operator: account(operator), + }) + .encode(), + true.encode() + ); assert_eq!( NonFungibles::read(Allowance { collection, diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs index 8c53ffd33..f57ee6976 100644 --- a/pallets/api/src/nonfungibles/types.rs +++ b/pallets/api/src/nonfungibles/types.rs @@ -7,12 +7,14 @@ use sp_runtime::{BoundedBTreeMap, RuntimeDebug}; // Type aliases for pallet-nfts. pub(super) type NftsOf = pallet_nfts::Pallet; +pub(super) type NftsErrorOf = pallet_nfts::Error; pub(super) type NftsWeightInfoOf = ::WeightInfo; // Type aliases for pallet-nfts storage items. pub(super) type AccountIdOf = ::AccountId; pub(super) type BalanceOf = <>::Currency as Currency< ::AccountId, >>::Balance; +pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId; pub(super) type CollectionIdOf = as Inspect<::AccountId>>::CollectionId; pub(super) type ItemIdOf = From 86ff5d8cc080de0726aa124f9ad7bb3011628e29 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 12 Nov 2024 01:17:21 +0700 Subject: [PATCH 21/76] chore: update pallet & runtime --- pallets/api/src/fungibles/tests.rs | 286 ++++------- pallets/api/src/mock.rs | 61 ++- pallets/api/src/nonfungibles/mod.rs | 184 ++++--- pallets/api/src/nonfungibles/tests.rs | 285 +++++----- pallets/api/src/nonfungibles/types.rs | 30 +- pallets/nfts/Cargo.toml | 1 + pallets/nfts/src/benchmarking.rs | 12 +- pallets/nfts/src/common_functions.rs | 8 + pallets/nfts/src/features/approvals.rs | 31 +- pallets/nfts/src/tests.rs | 18 +- pallets/nfts/src/types.rs | 10 +- pallets/nfts/src/weights.rs | 685 +++++++++++++------------ runtime/devnet/src/config/api/mod.rs | 189 ++++++- runtime/devnet/src/config/assets.rs | 13 +- runtime/devnet/src/lib.rs | 5 +- 15 files changed, 964 insertions(+), 854 deletions(-) diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index 6e181a6f7..f5c560bb7 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -83,21 +83,17 @@ fn transfer_works() { let to = BOB; for origin in vec![root(), none()] { - assert_noop!(Fungibles::transfer(origin, token, account(to), value), BadOrigin); + assert_noop!(Fungibles::transfer(origin, token, to, value), BadOrigin); } // Check error works for `Assets::transfer_keep_alive()`. - assert_noop!( - Fungibles::transfer(signed(from), token, account(to), value), - AssetsError::Unknown - ); + assert_noop!(Fungibles::transfer(signed(from), token, to, value), AssetsError::Unknown); assets::create_and_mint_to(from, token, from, value * 2); - let balance_before_transfer = Assets::balance(token, &account(to)); - assert_ok!(Fungibles::transfer(signed(from), token, account(to), value)); - let balance_after_transfer = Assets::balance(token, &account(to)); + let balance_before_transfer = Assets::balance(token, &to); + assert_ok!(Fungibles::transfer(signed(from), token, to, value)); + let balance_after_transfer = Assets::balance(token, &to); assert_eq!(balance_after_transfer, balance_before_transfer + value); System::assert_last_event( - Event::Transfer { token, from: Some(account(from)), to: Some(account(to)), value } - .into(), + Event::Transfer { token, from: Some(from), to: Some(to), value }.into(), ); }); } @@ -112,36 +108,26 @@ fn transfer_from_works() { let spender = CHARLIE; for origin in vec![root(), none()] { - assert_noop!( - Fungibles::transfer_from(origin, token, account(from), account(to), value), - BadOrigin - ); + assert_noop!(Fungibles::transfer_from(origin, token, from, to, value), BadOrigin); } // Check error works for `Assets::transfer_approved()`. assert_noop!( - Fungibles::transfer_from(signed(spender), token, account(from), account(to), value), + Fungibles::transfer_from(signed(spender), token, from, to, value), AssetsError::Unknown ); // Approve `spender` to transfer up to `value`. assets::create_mint_and_approve(spender, token, from, value * 2, spender, value); // Successfully call transfer from. - let from_balance_before_transfer = Assets::balance(token, &account(from)); - let to_balance_before_transfer = Assets::balance(token, &account(to)); - assert_ok!(Fungibles::transfer_from( - signed(spender), - token, - account(from), - account(to), - value - )); - let from_balance_after_transfer = Assets::balance(token, &account(from)); - let to_balance_after_transfer = Assets::balance(token, &account(to)); + let from_balance_before_transfer = Assets::balance(token, &from); + let to_balance_before_transfer = Assets::balance(token, &to); + assert_ok!(Fungibles::transfer_from(signed(spender), token, from, to, value)); + let from_balance_after_transfer = Assets::balance(token, &from); + let to_balance_after_transfer = Assets::balance(token, &to); // Check that `to` has received the `value` tokens from `from`. assert_eq!(to_balance_after_transfer, to_balance_before_transfer + value); assert_eq!(from_balance_after_transfer, from_balance_before_transfer - value); System::assert_last_event( - Event::Transfer { token, from: Some(account(from)), to: Some(account(to)), value } - .into(), + Event::Transfer { token, from: Some(from), to: Some(to), value }.into(), ); }); } @@ -158,7 +144,7 @@ mod approve { for origin in vec![root(), none()] { assert_noop!( - Fungibles::approve(origin, token, account(spender), value), + Fungibles::approve(origin, token, spender, value), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } @@ -175,20 +161,20 @@ mod approve { for origin in vec![root(), none()] { assert_noop!( - Fungibles::approve(origin, token, account(spender), value), + Fungibles::approve(origin, token, spender, value), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } // Check error works for `Assets::approve_transfer()` in `Greater` match arm. assert_noop!( - Fungibles::approve(signed(owner), token, account(spender), value), + Fungibles::approve(signed(owner), token, spender, value), AssetsError::Unknown.with_weight(WeightInfo::approve(1, 0)) ); assets::create_mint_and_approve(owner, token, owner, value, spender, value); // Check error works for `Assets::cancel_approval()` in `Less` match arm. assert_ok!(Assets::freeze_asset(signed(owner), token)); assert_noop!( - Fungibles::approve(signed(owner), token, account(spender), value / 2), + Fungibles::approve(signed(owner), token, spender, value / 2), AssetsError::AssetNotLive.with_weight(WeightInfo::approve(0, 1)) ); assert_ok!(Assets::thaw_asset(signed(owner), token)); @@ -207,61 +193,38 @@ mod approve { // Approves a value to spend that is higher than the current allowance. assets::create_and_mint_to(owner, token, owner, value); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), 0); + assert_eq!(Assets::allowance(token, &owner, &spender), 0); assert_eq!( - Fungibles::approve(signed(owner), token, account(spender), value), + Fungibles::approve(signed(owner), token, spender, value), Ok(Some(WeightInfo::approve(1, 0)).into()) ); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); - System::assert_last_event( - Event::Approval { token, owner: account(owner), spender: account(spender), value } - .into(), - ); + assert_eq!(Assets::allowance(token, &owner, &spender), value); + System::assert_last_event(Event::Approval { token, owner, spender, value }.into()); // Approves a value to spend that is lower than the current allowance. assert_eq!( - Fungibles::approve(signed(owner), token, account(spender), value / 2), + Fungibles::approve(signed(owner), token, spender, value / 2), Ok(Some(WeightInfo::approve(1, 1)).into()) ); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value / 2); + assert_eq!(Assets::allowance(token, &owner, &spender), value / 2); System::assert_last_event( - Event::Approval { - token, - owner: account(owner), - spender: account(spender), - value: value / 2, - } - .into(), + Event::Approval { token, owner, spender, value: value / 2 }.into(), ); // Approves a value to spend that is equal to the current allowance. assert_eq!( - Fungibles::approve(signed(owner), token, account(spender), value / 2), + Fungibles::approve(signed(owner), token, spender, value / 2), Ok(Some(WeightInfo::approve(0, 0)).into()) ); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value / 2); + assert_eq!(Assets::allowance(token, &owner, &spender), value / 2); System::assert_last_event( - Event::Approval { - token, - owner: account(owner), - spender: account(spender), - value: value / 2, - } - .into(), + Event::Approval { token, owner, spender, value: value / 2 }.into(), ); // Sets allowance to zero. assert_eq!( - Fungibles::approve(signed(owner), token, account(spender), 0), + Fungibles::approve(signed(owner), token, spender, 0), Ok(Some(WeightInfo::approve(0, 1)).into()) ); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), 0); - System::assert_last_event( - Event::Approval { - token, - owner: account(owner), - spender: account(spender), - value: 0, - } - .into(), - ); + assert_eq!(Assets::allowance(token, &owner, &spender), 0); + System::assert_last_event(Event::Approval { token, owner, spender, value: 0 }.into()); }); } } @@ -276,34 +239,25 @@ fn increase_allowance_works() { for origin in vec![root(), none()] { assert_noop!( - Fungibles::increase_allowance(origin, token, account(spender), value), + Fungibles::increase_allowance(origin, token, spender, value), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } // Check error works for `Assets::approve_transfer()`. assert_noop!( - Fungibles::increase_allowance(signed(owner), token, account(spender), value), + Fungibles::increase_allowance(signed(owner), token, spender, value), AssetsError::Unknown.with_weight(AssetsWeightInfo::approve_transfer()) ); assets::create_and_mint_to(owner, token, owner, value); - assert_eq!(0, Assets::allowance(token, &account(owner), &account(spender))); - assert_ok!(Fungibles::increase_allowance(signed(owner), token, account(spender), value)); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); - System::assert_last_event( - Event::Approval { token, owner: account(owner), spender: account(spender), value } - .into(), - ); + assert_eq!(0, Assets::allowance(token, &owner, &spender)); + assert_ok!(Fungibles::increase_allowance(signed(owner), token, spender, value)); + assert_eq!(Assets::allowance(token, &owner, &spender), value); + System::assert_last_event(Event::Approval { token, owner, spender, value }.into()); // Additive. - assert_ok!(Fungibles::increase_allowance(signed(owner), token, account(spender), value)); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value * 2); + assert_ok!(Fungibles::increase_allowance(signed(owner), token, spender, value)); + assert_eq!(Assets::allowance(token, &owner, &spender), value * 2); System::assert_last_event( - Event::Approval { - token, - owner: account(owner), - spender: account(spender), - value: value * 2, - } - .into(), + Event::Approval { token, owner, spender, value: value * 2 }.into(), ); }); } @@ -318,46 +272,40 @@ fn decrease_allowance_works() { for origin in vec![root(), none()] { assert_noop!( - Fungibles::decrease_allowance(origin, token, account(spender), 0), + Fungibles::decrease_allowance(origin, token, spender, 0), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } assets::create_mint_and_approve(owner, token, owner, value, spender, value); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); + assert_eq!(Assets::allowance(token, &owner, &spender), value); // Check error works for `Assets::cancel_approval()`. No error test for `approve_transfer` // because it is not possible. assert_ok!(Assets::freeze_asset(signed(owner), token)); assert_noop!( - Fungibles::decrease_allowance(signed(owner), token, account(spender), value / 2), + Fungibles::decrease_allowance(signed(owner), token, spender, value / 2), AssetsError::AssetNotLive.with_weight(WeightInfo::approve(0, 1)) ); assert_ok!(Assets::thaw_asset(signed(owner), token)); // Owner balance is not changed if decreased by zero. assert_eq!( - Fungibles::decrease_allowance(signed(owner), token, account(spender), 0), + Fungibles::decrease_allowance(signed(owner), token, spender, 0), Ok(Some(WeightInfo::approve(0, 0)).into()) ); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); + assert_eq!(Assets::allowance(token, &owner, &spender), value); // "Unapproved" error is returned if the current allowance is less than amount to decrease // with. assert_noop!( - Fungibles::decrease_allowance(signed(owner), token, account(spender), value * 2), + Fungibles::decrease_allowance(signed(owner), token, spender, value * 2), AssetsError::Unapproved ); // Decrease allowance successfully. assert_eq!( - Fungibles::decrease_allowance(signed(owner), token, account(spender), value / 2), + Fungibles::decrease_allowance(signed(owner), token, spender, value / 2), Ok(Some(WeightInfo::approve(1, 1)).into()) ); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value / 2); + assert_eq!(Assets::allowance(token, &owner, &spender), value / 2); System::assert_last_event( - Event::Approval { - token, - owner: account(owner), - spender: account(spender), - value: value / 2, - } - .into(), + Event::Approval { token, owner, spender, value: value / 2 }.into(), ); }); } @@ -370,19 +318,14 @@ fn create_works() { let admin = ALICE; for origin in vec![root(), none()] { - assert_noop!(Fungibles::create(origin, id, account(admin), 100), BadOrigin); + assert_noop!(Fungibles::create(origin, id, admin, 100), BadOrigin); } assert!(!Assets::asset_exists(id)); - assert_ok!(Fungibles::create(signed(creator), id, account(admin), 100)); + assert_ok!(Fungibles::create(signed(creator), id, admin, 100)); assert!(Assets::asset_exists(id)); - System::assert_last_event( - Event::Created { id, creator: account(creator), admin: account(admin) }.into(), - ); + System::assert_last_event(Event::Created { id, creator, admin }.into()); // Check error works for `Assets::create()`. - assert_noop!( - Fungibles::create(signed(creator), id, account(admin), 100), - AssetsError::InUse - ); + assert_noop!(Fungibles::create(signed(creator), id, admin, 100), AssetsError::InUse); }); } @@ -393,11 +336,11 @@ fn start_destroy_works() { // Check error works for `Assets::start_destroy()`. assert_noop!(Fungibles::start_destroy(signed(ALICE), token), AssetsError::Unknown); - assert_ok!(Assets::create(signed(ALICE), token, account(ALICE), 1)); + assert_ok!(Assets::create(signed(ALICE), token, ALICE, 1)); assert_ok!(Fungibles::start_destroy(signed(ALICE), token)); // Check that the token is not live after starting the destroy process. assert_noop!( - Assets::mint(signed(ALICE), token, account(ALICE), 10 * UNIT), + Assets::mint(signed(ALICE), token, ALICE, 10 * UNIT), AssetsError::AssetNotLive ); }); @@ -416,7 +359,7 @@ fn set_metadata_works() { Fungibles::set_metadata(signed(ALICE), token, name.clone(), symbol.clone(), decimals), AssetsError::Unknown ); - assert_ok!(Assets::create(signed(ALICE), token, account(ALICE), 1)); + assert_ok!(Assets::create(signed(ALICE), token, ALICE, 1)); assert_ok!(Fungibles::set_metadata( signed(ALICE), token, @@ -455,16 +398,16 @@ fn mint_works() { // Check error works for `Assets::mint()`. assert_noop!( - Fungibles::mint(signed(from), token, account(to), value), + Fungibles::mint(signed(from), token, to, value), sp_runtime::TokenError::UnknownAsset ); - assert_ok!(Assets::create(signed(from), token, account(from), 1)); - let balance_before_mint = Assets::balance(token, &account(to)); - assert_ok!(Fungibles::mint(signed(from), token, account(to), value)); - let balance_after_mint = Assets::balance(token, &account(to)); + assert_ok!(Assets::create(signed(from), token, from, 1)); + let balance_before_mint = Assets::balance(token, &to); + assert_ok!(Fungibles::mint(signed(from), token, to, value)); + let balance_after_mint = Assets::balance(token, &to); assert_eq!(balance_after_mint, balance_before_mint + value); System::assert_last_event( - Event::Transfer { token, from: None, to: Some(account(to)), value }.into(), + Event::Transfer { token, from: None, to: Some(to), value }.into(), ); }); } @@ -480,30 +423,27 @@ fn burn_works() { // "BalanceLow" error is returned if token is not created. assert_noop!( - Fungibles::burn(signed(owner), token, account(from), value), + Fungibles::burn(signed(owner), token, from, value), AssetsError::BalanceLow.with_weight(WeightInfo::balance_of()) ); assets::create_and_mint_to(owner, token, from, total_supply); assert_eq!(Assets::total_supply(TOKEN), total_supply); // Check error works for `Assets::burn()`. assert_ok!(Assets::freeze_asset(signed(owner), token)); - assert_noop!( - Fungibles::burn(signed(owner), token, account(from), value), - AssetsError::AssetNotLive - ); + assert_noop!(Fungibles::burn(signed(owner), token, from, value), AssetsError::AssetNotLive); assert_ok!(Assets::thaw_asset(signed(owner), token)); // "BalanceLow" error is returned if the balance is less than amount to burn. assert_noop!( - Fungibles::burn(signed(owner), token, account(from), total_supply * 2), + Fungibles::burn(signed(owner), token, from, total_supply * 2), AssetsError::BalanceLow.with_weight(WeightInfo::balance_of()) ); - let balance_before_burn = Assets::balance(token, &account(from)); - assert_ok!(Fungibles::burn(signed(owner), token, account(from), value)); + let balance_before_burn = Assets::balance(token, &from); + assert_ok!(Fungibles::burn(signed(owner), token, from, value)); assert_eq!(Assets::total_supply(TOKEN), total_supply - value); - let balance_after_burn = Assets::balance(token, &account(from)); + let balance_after_burn = Assets::balance(token, &from); assert_eq!(balance_after_burn, balance_before_burn - value); System::assert_last_event( - Event::Transfer { token, from: Some(account(from)), to: None, value }.into(), + Event::Transfer { token, from: Some(from), to: None, value }.into(), ); }); } @@ -530,17 +470,17 @@ fn balance_of_works() { new_test_ext().execute_with(|| { let value = 1_000 * UNIT; assert_eq!( - Fungibles::read(BalanceOf { token: TOKEN, owner: account(ALICE) }), + Fungibles::read(BalanceOf { token: TOKEN, owner: ALICE }), ReadResult::BalanceOf(Default::default()) ); assets::create_and_mint_to(ALICE, TOKEN, ALICE, value); assert_eq!( - Fungibles::read(BalanceOf { token: TOKEN, owner: account(ALICE) }), + Fungibles::read(BalanceOf { token: TOKEN, owner: ALICE }), ReadResult::BalanceOf(value) ); assert_eq!( - Fungibles::read(BalanceOf { token: TOKEN, owner: account(ALICE) }).encode(), - Assets::balance(TOKEN, account(ALICE)).encode(), + Fungibles::read(BalanceOf { token: TOKEN, owner: ALICE }).encode(), + Assets::balance(TOKEN, ALICE).encode(), ); }); } @@ -550,30 +490,17 @@ fn allowance_works() { new_test_ext().execute_with(|| { let value = 1_000 * UNIT; assert_eq!( - Fungibles::read(Allowance { - token: TOKEN, - owner: account(ALICE), - spender: account(BOB) - }), + Fungibles::read(Allowance { token: TOKEN, owner: ALICE, spender: BOB }), ReadResult::Allowance(Default::default()) ); assets::create_mint_and_approve(ALICE, TOKEN, ALICE, value * 2, BOB, value); assert_eq!( - Fungibles::read(Allowance { - token: TOKEN, - owner: account(ALICE), - spender: account(BOB) - }), + Fungibles::read(Allowance { token: TOKEN, owner: ALICE, spender: BOB }), ReadResult::Allowance(value) ); assert_eq!( - Fungibles::read(Allowance { - token: TOKEN, - owner: account(ALICE), - spender: account(BOB) - }) - .encode(), - Assets::allowance(TOKEN, &account(ALICE), &account(BOB)).encode(), + Fungibles::read(Allowance { token: TOKEN, owner: ALICE, spender: BOB }).encode(), + Assets::allowance(TOKEN, &ALICE, &BOB).encode(), ); }); } @@ -607,7 +534,7 @@ fn token_metadata_works() { fn token_exists_works() { new_test_ext().execute_with(|| { assert_eq!(Fungibles::read(TokenExists(TOKEN)), ReadResult::TokenExists(false)); - assert_ok!(Assets::create(signed(ALICE), TOKEN, account(ALICE), 1)); + assert_ok!(Assets::create(signed(ALICE), TOKEN, ALICE, 1)); assert_eq!(Fungibles::read(TokenExists(TOKEN)), ReadResult::TokenExists(true)); assert_eq!( Fungibles::read(TokenExists(TOKEN)).encode(), @@ -616,8 +543,8 @@ fn token_exists_works() { }); } -fn signed(account_id: u8) -> RuntimeOrigin { - RuntimeOrigin::signed(account(account_id)) +fn signed(account: AccountId) -> RuntimeOrigin { + RuntimeOrigin::signed(account) } fn root() -> RuntimeOrigin { @@ -632,31 +559,36 @@ fn none() -> RuntimeOrigin { mod assets { use super::*; - pub(super) fn create_and_mint_to(owner: u8, token: TokenId, to: u8, value: Balance) { - assert_ok!(Assets::create(signed(owner), token, account(owner), 1)); - assert_ok!(Assets::mint(signed(owner), token, account(to), value)); + pub(super) fn create_and_mint_to( + owner: AccountId, + token: TokenId, + to: AccountId, + value: Balance, + ) { + assert_ok!(Assets::create(signed(owner), token, owner, 1)); + assert_ok!(Assets::mint(signed(owner), token, to, value)); } pub(super) fn create_mint_and_approve( - owner: u8, + owner: AccountId, token: TokenId, - to: u8, + to: AccountId, mint: Balance, - spender: u8, + spender: AccountId, approve: Balance, ) { create_and_mint_to(owner, token, to, mint); - assert_ok!(Assets::approve_transfer(signed(to), token, account(spender), approve,)); + assert_ok!(Assets::approve_transfer(signed(to), token, spender, approve,)); } pub(super) fn create_and_set_metadata( - owner: u8, + owner: AccountId, token: TokenId, name: Vec, symbol: Vec, decimals: u8, ) { - assert_ok!(Assets::create(signed(owner), token, account(owner), 1)); + assert_ok!(Assets::create(signed(owner), token, owner, 1)); assert_ok!(Assets::set_metadata(signed(owner), token, name, symbol, decimals)); } } @@ -681,11 +613,11 @@ mod read_weights { fn new() -> Self { Self { total_supply: Fungibles::weight(&TotalSupply(TOKEN)), - balance_of: Fungibles::weight(&BalanceOf { token: TOKEN, owner: account(ALICE) }), + balance_of: Fungibles::weight(&BalanceOf { token: TOKEN, owner: ALICE }), allowance: Fungibles::weight(&Allowance { token: TOKEN, - owner: account(ALICE), - spender: account(BOB), + owner: ALICE, + spender: BOB, }), token_name: Fungibles::weight(&TokenName(TOKEN)), token_symbol: Fungibles::weight(&TokenSymbol(TOKEN)), @@ -767,15 +699,15 @@ mod ensure_codec_indexes { [ (TotalSupply::(Default::default()), 0u8, "TotalSupply"), ( - BalanceOf:: { token: Default::default(), owner: account(Default::default()) }, + BalanceOf:: { token: Default::default(), owner: Default::default() }, 1, "BalanceOf", ), ( Allowance:: { token: Default::default(), - owner: account(Default::default()), - spender: account(Default::default()), + owner: Default::default(), + spender: Default::default(), }, 2, "Allowance", @@ -799,7 +731,7 @@ mod ensure_codec_indexes { ( transfer { token: Default::default(), - to: account(Default::default()), + to: Default::default(), value: Default::default(), }, 3u8, @@ -808,8 +740,8 @@ mod ensure_codec_indexes { ( transfer_from { token: Default::default(), - from: account(Default::default()), - to: account(Default::default()), + from: Default::default(), + to: Default::default(), value: Default::default(), }, 4, @@ -818,7 +750,7 @@ mod ensure_codec_indexes { ( approve { token: Default::default(), - spender: account(Default::default()), + spender: Default::default(), value: Default::default(), }, 5, @@ -827,7 +759,7 @@ mod ensure_codec_indexes { ( increase_allowance { token: Default::default(), - spender: account(Default::default()), + spender: Default::default(), value: Default::default(), }, 6, @@ -836,7 +768,7 @@ mod ensure_codec_indexes { ( decrease_allowance { token: Default::default(), - spender: account(Default::default()), + spender: Default::default(), value: Default::default(), }, 7, @@ -845,7 +777,7 @@ mod ensure_codec_indexes { ( create { id: Default::default(), - admin: account(Default::default()), + admin: Default::default(), min_balance: Default::default(), }, 11, @@ -866,7 +798,7 @@ mod ensure_codec_indexes { ( mint { token: Default::default(), - account: account(Default::default()), + account: Default::default(), value: Default::default(), }, 19, @@ -875,7 +807,7 @@ mod ensure_codec_indexes { ( burn { token: Default::default(), - account: account(Default::default()), + account: Default::default(), value: Default::default(), }, 20, diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs index 920d590f9..8a4ad27d0 100644 --- a/pallets/api/src/mock.rs +++ b/pallets/api/src/mock.rs @@ -1,28 +1,28 @@ +use codec::{Decode, Encode}; use frame_support::{ derive_impl, parameter_types, traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, ConstU64, Everything}, }; use frame_system::{EnsureRoot, EnsureSigned}; use pallet_nfts::PalletFeatures; +use scale_info::TypeInfo; use sp_core::H256; use sp_runtime::{ - traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Verify}, - BuildStorage, MultiSignature, + traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Lazy, Verify}, + BuildStorage, }; -pub(crate) const ALICE: u8 = 1; -pub(crate) const BOB: u8 = 2; -pub(crate) const CHARLIE: u8 = 3; +pub(crate) const ALICE: AccountId = 1; +pub(crate) const BOB: AccountId = 2; +pub(crate) const CHARLIE: AccountId = 3; pub(crate) const INIT_AMOUNT: Balance = 100_000_000 * UNIT; pub(crate) const UNIT: Balance = 10_000_000_000; type Block = frame_system::mocking::MockBlock; -pub(crate) type AccountId = ::AccountId; +pub(crate) type AccountId = u64; pub(crate) type Balance = u128; // For terminology in tests. pub(crate) type TokenId = u32; -type Signature = MultiSignature; -type AccountPublic = ::Signer; // Configure a mock runtime to test the pallet. frame_support::construct_runtime!( @@ -99,7 +99,7 @@ impl pallet_assets::Config for Test { type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; type Extra = (); - type ForceOrigin = EnsureRoot; + type ForceOrigin = EnsureRoot; type Freezer = (); type MetadataDepositBase = ConstU128<1>; type MetadataDepositPerByte = ConstU128<1>; @@ -119,12 +119,35 @@ parameter_types! { pub storage Features: PalletFeatures = PalletFeatures::all_enabled(); } +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, TypeInfo)] +pub struct Noop; + +impl IdentifyAccount for Noop { + type AccountId = AccountId; + + fn into_account(self) -> Self::AccountId { + 0 + } +} + +impl Verify for Noop { + type Signer = Noop; + + fn verify>( + &self, + _msg: L, + _signer: &::AccountId, + ) -> bool { + false + } +} + impl pallet_nfts::Config for Test { type ApprovalsLimit = ConstU32<10>; type AttributeDepositBase = ConstU128<1>; type CollectionDeposit = ConstU128<2>; type CollectionId = u32; - type CreateOrigin = AsEnsureOriginWithArg>; + type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; type DepositPerByte = ConstU128<1>; type Features = Features; @@ -140,11 +163,8 @@ impl pallet_nfts::Config for Test { type MaxDeadlineDuration = ConstU64<10000>; type MaxTips = ConstU32<10>; type MetadataDepositBase = ConstU128<1>; - /// Using `AccountPublic` here makes it trivial to convert to `AccountId` via `into_account()`. - type OffchainPublic = AccountPublic; - /// Off-chain = signature On-chain - therefore no conversion needed. - /// It needs to be From for benchmarking. - type OffchainSignature = Signature; + type OffchainPublic = Noop; + type OffchainSignature = Noop; type RuntimeEvent = RuntimeEvent; type StringLimit = ConstU32<50>; type ValueLimit = ConstU32<50>; @@ -155,22 +175,13 @@ impl crate::nonfungibles::Config for Test { type RuntimeEvent = RuntimeEvent; } -/// Initialize a new account ID. -pub(crate) fn account(id: u8) -> AccountId { - [id; 32].into() -} - pub(crate) fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::::default() .build_storage() .expect("Frame system builds valid default genesis config"); pallet_balances::GenesisConfig:: { - balances: vec![ - (account(ALICE), INIT_AMOUNT), - (account(BOB), INIT_AMOUNT), - (account(CHARLIE), INIT_AMOUNT), - ], + balances: vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT), (CHARLIE, INIT_AMOUNT)], } .assimilate_storage(&mut t) .expect("Pallet balances storage can be assimilated"); diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index 7377048fc..1a5b07b89 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -5,24 +5,22 @@ pub use pallet::*; use pallet_nfts::WeightInfo; use sp_runtime::traits::StaticLookup; +pub use types::*; #[cfg(test)] mod tests; -mod types; +pub mod types; #[frame_support::pallet] pub mod pallet { use frame_support::{dispatch::DispatchResult, pallet_prelude::*, traits::Incrementable}; use frame_system::pallet_prelude::*; - use pallet_nfts::{ - CancelAttributesApprovalWitness, CollectionConfig, CollectionSettings, DestroyWitness, - MintSettings, MintWitness, - }; + use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness, MintWitness}; + use sp_runtime::BoundedVec; use sp_std::vec::Vec; use types::{ - AccountIdOf, AttributeNamespaceOf, BalanceOf, CollectionDetailsFor, CollectionIdOf, - CreateCollectionConfigFor, ItemDetailsFor, ItemIdOf, ItemPriceOf, NextCollectionIdOf, - NftsOf, NftsWeightInfoOf, + AccountIdOf, AttributeNamespaceOf, BalanceOf, CollectionConfigFor, CollectionDetailsFor, + CollectionIdOf, ItemIdOf, ItemPriceOf, NextCollectionIdOf, NftsOf, NftsWeightInfoOf, }; use super::*; @@ -48,25 +46,24 @@ pub mod pallet { item: Option>, }, /// Owner of a specified collection item. - #[codec(index = 3)] + #[codec(index = 5)] OwnerOf { collection: CollectionIdOf, item: ItemIdOf }, - /// Attribute value of a collection item. - #[codec(index = 4)] + /// Attribute value of a collection item. (Error: bounded collection is not partial) + #[codec(index = 6)] GetAttribute { collection: CollectionIdOf, - item: Option>, + item: ItemIdOf, namespace: AttributeNamespaceOf, key: BoundedVec, }, /// Details of a collection. - #[codec(index = 6)] + #[codec(index = 9)] Collection(CollectionIdOf), - /// Details of a collection item. - #[codec(index = 7)] - Item { collection: CollectionIdOf, item: ItemIdOf }, /// Next collection ID. - #[codec(index = 8)] + #[codec(index = 10)] NextCollectionId, + #[codec(index = 11)] + ItemMetadata { collection: CollectionIdOf, item: ItemIdOf }, } /// Results of state reads for the non-fungibles API. @@ -74,7 +71,7 @@ pub mod pallet { #[cfg_attr(feature = "std", derive(PartialEq, Clone))] pub enum ReadResult { /// Total item supply of a collection. - TotalSupply(u32), + TotalSupply(u128), /// Account balance for a specified collection. BalanceOf(u32), /// Allowance for an operator approved by an owner, for a specified collection or item. @@ -82,13 +79,13 @@ pub mod pallet { /// Owner of a specified collection owner. OwnerOf(Option>), /// Attribute value of a collection item. - GetAttribute(Option>), + GetAttribute(Option>), /// Details of a collection. Collection(Option>), - /// Details of a collection item. - Item(Option>), /// Next collection ID. NextCollectionId(Option>), + /// Collection item metadata. + ItemMetadata(Option>), } impl ReadResult { @@ -100,10 +97,10 @@ pub mod pallet { TotalSupply(result) => result.encode(), BalanceOf(result) => result.encode(), Collection(result) => result.encode(), - Item(result) => result.encode(), Allowance(result) => result.encode(), GetAttribute(result) => result.encode(), NextCollectionId(result) => result.encode(), + ItemMetadata(result) => result.encode(), } } } @@ -162,54 +159,7 @@ pub mod pallet { #[pallet::call] impl Pallet { - #[pallet::call_index(0)] - #[pallet::weight(NftsWeightInfoOf::::mint())] - pub fn mint( - origin: OriginFor, - to: AccountIdOf, - collection: CollectionIdOf, - item: ItemIdOf, - mint_price: Option>, - ) -> DispatchResult { - let account = ensure_signed(origin.clone())?; - let witness_data = MintWitness { mint_price, owned_item: Some(item) }; - NftsOf::::mint( - origin, - collection, - item, - T::Lookup::unlookup(to.clone()), - Some(witness_data), - )?; - Self::deposit_event(Event::Transfer { - collection, - item, - from: None, - to: Some(account), - price: mint_price, - }); - Ok(()) - } - - #[pallet::call_index(1)] - #[pallet::weight(NftsWeightInfoOf::::burn())] - pub fn burn( - origin: OriginFor, - collection: CollectionIdOf, - item: ItemIdOf, - ) -> DispatchResult { - let account = ensure_signed(origin.clone())?; - NftsOf::::burn(origin, collection, item)?; - Self::deposit_event(Event::Transfer { - collection, - item, - from: Some(account), - to: None, - price: None, - }); - Ok(()) - } - - #[pallet::call_index(2)] + #[pallet::call_index(3)] #[pallet::weight(NftsWeightInfoOf::::transfer())] pub fn transfer( origin: OriginFor, @@ -229,7 +179,7 @@ pub mod pallet { Ok(()) } - #[pallet::call_index(3)] + #[pallet::call_index(4)] #[pallet::weight(NftsWeightInfoOf::::approve_transfer() + NftsWeightInfoOf::::cancel_approval())] pub fn approve( origin: OriginFor, @@ -259,33 +209,25 @@ pub mod pallet { Ok(()) } - #[pallet::call_index(4)] + #[pallet::call_index(7)] #[pallet::weight(NftsWeightInfoOf::::create())] pub fn create( origin: OriginFor, admin: AccountIdOf, - config: CreateCollectionConfigFor, + config: CollectionConfigFor, ) -> DispatchResult { + // TODO: re-evaluate next collection id in nfts pallet. The `Incrementable` trait causes + // issues for setting it to xcm's `Location`. This can easily be done differently. let id = NextCollectionIdOf::::get() .or(T::CollectionId::initial_value()) .ok_or(pallet_nfts::Error::::UnknownCollection)?; let creator = ensure_signed(origin.clone())?; - let collection_config = CollectionConfig { - settings: CollectionSettings::all_enabled(), - max_supply: config.max_supply, - mint_settings: MintSettings { - mint_type: config.mint_type, - start_block: config.start_block, - end_block: config.end_block, - ..MintSettings::default() - }, - }; - NftsOf::::create(origin, T::Lookup::unlookup(admin.clone()), collection_config)?; + NftsOf::::create(origin, T::Lookup::unlookup(admin.clone()), config)?; Self::deposit_event(Event::Created { id, admin, creator }); Ok(()) } - #[pallet::call_index(5)] + #[pallet::call_index(8)] #[pallet::weight(NftsWeightInfoOf::::destroy( witness.item_metadatas, witness.item_configs, @@ -299,7 +241,7 @@ pub mod pallet { NftsOf::::destroy(origin, collection, witness) } - #[pallet::call_index(6)] + #[pallet::call_index(12)] #[pallet::weight(NftsWeightInfoOf::::set_attribute())] pub fn set_attribute( origin: OriginFor, @@ -312,7 +254,7 @@ pub mod pallet { NftsOf::::set_attribute(origin, collection, item, namespace, key, value) } - #[pallet::call_index(7)] + #[pallet::call_index(13)] #[pallet::weight(NftsWeightInfoOf::::clear_attribute())] pub fn clear_attribute( origin: OriginFor, @@ -324,7 +266,7 @@ pub mod pallet { NftsOf::::clear_attribute(origin, collection, item, namespace, key) } - #[pallet::call_index(8)] + #[pallet::call_index(14)] #[pallet::weight(NftsWeightInfoOf::::set_metadata())] pub fn set_metadata( origin: OriginFor, @@ -335,7 +277,7 @@ pub mod pallet { NftsOf::::set_metadata(origin, collection, item, data) } - #[pallet::call_index(9)] + #[pallet::call_index(15)] #[pallet::weight(NftsWeightInfoOf::::clear_metadata())] pub fn clear_metadata( origin: OriginFor, @@ -345,7 +287,7 @@ pub mod pallet { NftsOf::::clear_metadata(origin, collection, item) } - #[pallet::call_index(10)] + #[pallet::call_index(16)] #[pallet::weight(NftsWeightInfoOf::::approve_item_attributes())] pub fn approve_item_attributes( origin: OriginFor, @@ -361,7 +303,7 @@ pub mod pallet { ) } - #[pallet::call_index(11)] + #[pallet::call_index(17)] #[pallet::weight(NftsWeightInfoOf::::cancel_item_attributes_approval(witness.account_attributes))] pub fn cancel_item_attributes_approval( origin: OriginFor, @@ -379,7 +321,7 @@ pub mod pallet { ) } - #[pallet::call_index(12)] + #[pallet::call_index(18)] #[pallet::weight(NftsWeightInfoOf::::set_collection_max_supply())] pub fn set_max_supply( origin: OriginFor, @@ -388,6 +330,53 @@ pub mod pallet { ) -> DispatchResult { NftsOf::::set_collection_max_supply(origin, collection, max_supply) } + + #[pallet::call_index(19)] + #[pallet::weight(NftsWeightInfoOf::::mint())] + pub fn mint( + origin: OriginFor, + to: AccountIdOf, + collection: CollectionIdOf, + item: ItemIdOf, + witness: MintWitness, ItemPriceOf>, + ) -> DispatchResult { + let account = ensure_signed(origin.clone())?; + let mint_price = witness.mint_price; + NftsOf::::mint( + origin, + collection, + item, + T::Lookup::unlookup(to.clone()), + Some(witness), + )?; + Self::deposit_event(Event::Transfer { + collection, + item, + from: None, + to: Some(account), + price: mint_price, + }); + Ok(()) + } + + #[pallet::call_index(20)] + #[pallet::weight(NftsWeightInfoOf::::burn())] + pub fn burn( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + ) -> DispatchResult { + let account = ensure_signed(origin.clone())?; + NftsOf::::burn(origin, collection, item)?; + Self::deposit_event(Event::Transfer { + collection, + item, + from: Some(account), + to: None, + price: None, + }); + Ok(()) + } } impl crate::Read for Pallet { @@ -413,7 +402,7 @@ pub mod pallet { use Read::*; match value { TotalSupply(collection) => ReadResult::TotalSupply( - NftsOf::::collection_items(collection).unwrap_or_default(), + NftsOf::::collection_items(collection).unwrap_or_default() as u128, ), BalanceOf { collection, owner } => ReadResult::BalanceOf(pallet_nfts::AccountBalance::::get(collection, owner)), @@ -423,13 +412,14 @@ pub mod pallet { OwnerOf { collection, item } => ReadResult::OwnerOf(NftsOf::::owner(collection, item)), GetAttribute { collection, item, namespace, key } => ReadResult::GetAttribute( - pallet_nfts::Attribute::::get((collection, item, namespace, key)) - .map(|attribute| attribute.0), + pallet_nfts::Attribute::::get((collection, Some(item), namespace, key)) + .map(|attribute| attribute.0.into()), ), Collection(collection) => ReadResult::Collection(pallet_nfts::Collection::::get(collection)), - Item { collection, item } => - ReadResult::Item(pallet_nfts::Item::::get(collection, item)), + ItemMetadata { collection, item } => ReadResult::ItemMetadata( + NftsOf::::item_metadata(collection, item).map(|metadata| metadata.into()), + ), NextCollectionId => ReadResult::NextCollectionId( NextCollectionIdOf::::get().or(T::CollectionId::initial_value()), ), diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index e89ba0bd2..79d484a2f 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -2,10 +2,10 @@ use codec::Encode; use frame_support::{assert_noop, assert_ok, traits::Incrementable}; use frame_system::pallet_prelude::BlockNumberFor; use pallet_nfts::{ - AccountBalance, CollectionConfig, CollectionDetails, CollectionSettings, ItemDeposit, - ItemDetails, MintSettings, + AccountBalance, CollectionConfig, CollectionDetails, CollectionSettings, DestroyWitness, + MintSettings, MintWitness, }; -use sp_runtime::{BoundedBTreeMap, BoundedVec, DispatchError::BadOrigin}; +use sp_runtime::{BoundedVec, DispatchError::BadOrigin}; use super::types::{CollectionIdOf, ItemIdOf}; use crate::{ @@ -23,7 +23,7 @@ mod encoding_read_result { #[test] fn total_supply() { - let total_supply: u32 = 1_000_000; + let total_supply: u128 = 1_000_000; assert_eq!(ReadResult::TotalSupply::(total_supply).encode(), total_supply.encode()); } @@ -41,7 +41,7 @@ mod encoding_read_result { #[test] fn owner_of() { - let mut owner = Some(account(ALICE)); + let mut owner = Some(ALICE); assert_eq!(ReadResult::OwnerOf::(owner.clone()).encode(), owner.encode()); owner = None; assert_eq!(ReadResult::OwnerOf::(owner.clone()).encode(), owner.encode()); @@ -49,7 +49,7 @@ mod encoding_read_result { #[test] fn get_attribute() { - let mut attribute = Some(BoundedVec::truncate_from("some attribute".as_bytes().to_vec())); + let mut attribute = Some("some attribute".as_bytes().to_vec()); assert_eq!( ReadResult::GetAttribute::(attribute.clone()).encode(), attribute.encode() @@ -64,7 +64,7 @@ mod encoding_read_result { #[test] fn collection() { let mut collection_details = Some(CollectionDetails { - owner: account(ALICE), + owner: ALICE, owner_deposit: 0, items: 0, item_metadatas: 0, @@ -82,18 +82,6 @@ mod encoding_read_result { ); } - #[test] - fn item() { - let mut item_details = Some(ItemDetails { - owner: account(ALICE), - approvals: BoundedBTreeMap::default(), - deposit: ItemDeposit { amount: 0, account: account(BOB) }, - }); - assert_eq!(ReadResult::Item::(item_details.clone()).encode(), item_details.encode()); - item_details = None; - assert_eq!(ReadResult::Item::(item_details.clone()).encode(), item_details.encode()); - } - #[test] fn next_collection_id_works() { let mut next_collection_id = Some(0); @@ -107,6 +95,14 @@ mod encoding_read_result { next_collection_id.encode() ); } + + #[test] + fn item_metadata_works() { + let mut data = Some("some metadata".as_bytes().to_vec()); + assert_eq!(ReadResult::ItemMetadata::(data.clone()).encode(), data.encode()); + data = None; + assert_eq!(ReadResult::ItemMetadata::(data.clone()).encode(), data.encode()); + } } #[test] @@ -117,26 +113,17 @@ fn transfer() { let (collection, item) = nfts::create_collection_mint(owner, ITEM); for origin in vec![root(), none()] { - assert_noop!( - NonFungibles::transfer(origin, collection, item, account(dest)), - BadOrigin - ); + assert_noop!(NonFungibles::transfer(origin, collection, item, dest), BadOrigin); } // Successfully burn an existing new collection item. - let balance_before_transfer = AccountBalance::::get(collection, &account(dest)); - assert_ok!(NonFungibles::transfer(signed(owner), collection, ITEM, account(dest))); - let balance_after_transfer = AccountBalance::::get(collection, &account(dest)); - assert_eq!(AccountBalance::::get(collection, &account(owner)), 0); + let balance_before_transfer = AccountBalance::::get(collection, &dest); + assert_ok!(NonFungibles::transfer(signed(owner), collection, ITEM, dest)); + let balance_after_transfer = AccountBalance::::get(collection, &dest); + assert_eq!(AccountBalance::::get(collection, &owner), 0); assert_eq!(balance_after_transfer - balance_before_transfer, 1); System::assert_last_event( - Event::Transfer { - collection, - item, - from: Some(account(owner)), - to: Some(account(dest)), - price: None, - } - .into(), + Event::Transfer { collection, item, from: Some(owner), to: Some(dest), price: None } + .into(), ); }); } @@ -148,20 +135,20 @@ fn mint_works() { let collection = nfts::create_collection(owner); // Successfully mint a new collection item. - let balance_before_mint = AccountBalance::::get(collection, account(owner)); - assert_ok!(NonFungibles::mint(signed(owner), account(owner), collection, ITEM, None)); - let balance_after_mint = AccountBalance::::get(collection, account(owner)); + let balance_before_mint = AccountBalance::::get(collection, owner); + assert_ok!(NonFungibles::mint( + signed(owner), + owner, + collection, + ITEM, + MintWitness { mint_price: None, owned_item: None } + )); + let balance_after_mint = AccountBalance::::get(collection, owner); assert_eq!(balance_after_mint, 1); assert_eq!(balance_after_mint - balance_before_mint, 1); System::assert_last_event( - Event::Transfer { - collection, - item: ITEM, - from: None, - to: Some(account(owner)), - price: None, - } - .into(), + Event::Transfer { collection, item: ITEM, from: None, to: Some(owner), price: None } + .into(), ); }); } @@ -175,8 +162,7 @@ fn burn_works() { let (collection, item) = nfts::create_collection_mint(owner, ITEM); assert_ok!(NonFungibles::burn(signed(owner), collection, ITEM)); System::assert_last_event( - Event::Transfer { collection, item, from: Some(account(owner)), to: None, price: None } - .into(), + Event::Transfer { collection, item, from: Some(owner), to: None, price: None }.into(), ); }); } @@ -188,25 +174,13 @@ fn approve_works() { let operator = BOB; let (collection, item) = nfts::create_collection_mint(owner, ITEM); // Successfully approve `oeprator` to transfer the collection item. - assert_ok!(NonFungibles::approve( - signed(owner), - collection, - Some(item), - account(operator), - true - )); + assert_ok!(NonFungibles::approve(signed(owner), collection, Some(item), operator, true)); System::assert_last_event( - Event::Approval { - collection, - item: Some(item), - owner: account(owner), - operator: account(operator), - approved: true, - } - .into(), + Event::Approval { collection, item: Some(item), owner, operator, approved: true } + .into(), ); // Successfully transfer the item by the delegated account `operator`. - assert_ok!(Nfts::transfer(signed(operator), collection, item, account(operator))); + assert_ok!(Nfts::transfer(signed(operator), collection, item, operator)); }); } @@ -217,16 +191,10 @@ fn cancel_approval_works() { let operator = BOB; let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); // Successfully cancel the transfer approval of `operator` by `owner`. - assert_ok!(NonFungibles::approve( - signed(owner), - collection, - Some(item), - account(operator), - false - )); + assert_ok!(NonFungibles::approve(signed(owner), collection, Some(item), operator, false)); // Failed to transfer the item by `operator` without permission. assert_noop!( - Nfts::transfer(signed(operator), collection, item, account(operator)), + Nfts::transfer(signed(operator), collection, item, operator), NftsError::NoPermission ); }); @@ -239,10 +207,10 @@ fn set_max_supply_works() { let collection = nfts::create_collection(owner); assert_ok!(NonFungibles::set_max_supply(signed(owner), collection, 10)); (0..10).into_iter().for_each(|i| { - assert_ok!(Nfts::mint(signed(owner), collection, i, account(owner), None)); + assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); }); assert_noop!( - Nfts::mint(signed(owner), collection, 42, account(owner), None), + Nfts::mint(signed(owner), collection, 42, owner, None), NftsError::MaxSupplyReached ); }); @@ -263,15 +231,14 @@ fn owner_of_works() { fn get_attribute_works() { new_test_ext().execute_with(|| { let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); - assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); - let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); let mut result: Option::ValueLimit>> = None; // No attribute set. assert_eq!( NonFungibles::read(GetAttribute { collection, - item: Some(item), + item, namespace: pallet_nfts::AttributeNamespace::CollectionOwner, key: attribute.clone() }) @@ -291,7 +258,7 @@ fn get_attribute_works() { assert_eq!( NonFungibles::read(GetAttribute { collection, - item: Some(item), + item, namespace: pallet_nfts::AttributeNamespace::CollectionOwner, key: attribute }) @@ -301,13 +268,44 @@ fn get_attribute_works() { }); } +#[test] +fn set_metadata_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + let value = BoundedVec::truncate_from("some metadata".as_bytes().to_vec()); + assert_ok!(NonFungibles::set_metadata(signed(ALICE), collection, item, value.clone())); + assert_eq!( + NonFungibles::read(ItemMetadata { collection, item }).encode(), + Some(value).encode() + ); + }); +} + +#[test] +fn clear_metadata_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_ok!(NonFungibles::set_metadata( + signed(ALICE), + collection, + item, + BoundedVec::truncate_from("some metadata".as_bytes().to_vec()) + )); + assert_ok!(NonFungibles::clear_metadata(signed(ALICE), collection, item)); + assert_eq!( + NonFungibles::read(ItemMetadata { collection, item }).encode(), + ReadResult::::ItemMetadata(None).encode() + ); + }); +} + #[test] fn clear_attribute_works() { new_test_ext().execute_with(|| { let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); - let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); - let mut result: Option::ValueLimit>> = None; + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let result: Option::ValueLimit>> = None; assert_ok!(Nfts::set_attribute( signed(ALICE), collection, @@ -327,7 +325,7 @@ fn clear_attribute_works() { assert_eq!( NonFungibles::read(GetAttribute { collection, - item: Some(item), + item, namespace: pallet_nfts::AttributeNamespace::CollectionOwner, key: attribute }) @@ -342,25 +340,24 @@ fn approve_item_attribute_works() { new_test_ext().execute_with(|| { let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); - let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); - let mut result: Option::ValueLimit>> = None; // Successfully approve delegate to set attributes. - assert_ok!(Nfts::approve_item_attributes(signed(ALICE), collection, item, account(BOB))); + assert_ok!(Nfts::approve_item_attributes(signed(ALICE), collection, item, BOB)); assert_ok!(Nfts::set_attribute( signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(account(BOB)), + pallet_nfts::AttributeNamespace::Account(BOB), attribute.clone(), value.clone() )); - result = Some(value); + let result: Option::ValueLimit>> = Some(value); assert_eq!( NonFungibles::read(GetAttribute { collection, - item: Some(item), - namespace: pallet_nfts::AttributeNamespace::Account(account(BOB)), + item, + namespace: pallet_nfts::AttributeNamespace::Account(BOB), key: attribute }) .encode(), @@ -374,16 +371,15 @@ fn cancel_item_attribute_approval_works() { new_test_ext().execute_with(|| { let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); - let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); - let mut result: Option::ValueLimit>> = None; // Successfully approve delegate to set attributes. - assert_ok!(Nfts::approve_item_attributes(signed(ALICE), collection, item, account(BOB))); + assert_ok!(Nfts::approve_item_attributes(signed(ALICE), collection, item, BOB)); assert_ok!(Nfts::set_attribute( signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(account(BOB)), + pallet_nfts::AttributeNamespace::Account(BOB), attribute.clone(), value.clone() )); @@ -391,7 +387,7 @@ fn cancel_item_attribute_approval_works() { signed(ALICE), collection, item, - account(BOB), + BOB, pallet_nfts::CancelAttributesApprovalWitness { account_attributes: 1 } )); assert_noop!( @@ -399,7 +395,7 @@ fn cancel_item_attribute_approval_works() { signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(account(BOB)), + pallet_nfts::AttributeNamespace::Account(BOB), attribute.clone(), value.clone() ), @@ -428,34 +424,57 @@ fn total_supply_works() { let owner = ALICE; let collection = nfts::create_collection(owner); (0..10).into_iter().for_each(|i| { - assert_ok!(Nfts::mint(signed(owner), collection, i, account(owner), None)); - assert_eq!(NonFungibles::read(TotalSupply(collection)).encode(), (i + 1).encode()); + assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); + assert_eq!( + NonFungibles::read(TotalSupply(collection)).encode(), + ((i + 1) as u128).encode() + ); assert_eq!( NonFungibles::read(TotalSupply(collection)).encode(), - Nfts::collection_items(collection).unwrap_or_default().encode() + (Nfts::collection_items(collection).unwrap_or_default() as u128).encode() ); }); }); } #[test] -fn collection_works() { +fn create_works() { new_test_ext().execute_with(|| { - let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); - assert_eq!( - NonFungibles::read(Collection(collection)).encode(), - pallet_nfts::Collection::::get(&collection).encode(), - ); + let owner = ALICE; + let next_collection_id = pallet_nfts::NextCollectionId::::get().unwrap_or_default(); + assert_ok!(NonFungibles::create( + signed(owner), + owner, + CollectionConfig { + max_supply: None, + mint_settings: MintSettings::default(), + settings: CollectionSettings::all_enabled() + }, + )); + assert_eq!(Nfts::collection_owner(next_collection_id), Some(owner)); }); } #[test] -fn item_works() { +fn destroy_works() { new_test_ext().execute_with(|| { - let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + let collection = nfts::create_collection(ALICE); + assert_ok!(NonFungibles::destroy( + signed(ALICE), + collection, + DestroyWitness { item_metadatas: 0, item_configs: 0, attributes: 0 } + )); + assert_eq!(Nfts::collection_owner(collection), None); + }); +} + +#[test] +fn collection_works() { + new_test_ext().execute_with(|| { + let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!( - NonFungibles::read(Item { collection, item }).encode(), - pallet_nfts::Item::::get(&collection, &item).encode(), + NonFungibles::read(Collection(collection)).encode(), + pallet_nfts::Collection::::get(&collection).encode(), ); }); } @@ -466,14 +485,14 @@ fn balance_of_works() { let owner = ALICE; let collection = nfts::create_collection(owner); (0..10).into_iter().for_each(|i| { - assert_ok!(Nfts::mint(signed(owner), collection, i, account(owner), None)); + assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); assert_eq!( - NonFungibles::read(BalanceOf { collection, owner: account(owner) }).encode(), + NonFungibles::read(BalanceOf { collection, owner }).encode(), (i + 1).encode() ); assert_eq!( - NonFungibles::read(BalanceOf { collection, owner: account(owner) }).encode(), - AccountBalance::::get(collection, account(owner)).encode() + NonFungibles::read(BalanceOf { collection, owner }).encode(), + AccountBalance::::get(collection, owner).encode() ); }); }); @@ -486,32 +505,22 @@ fn allowance_works() { let operator = BOB; let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); assert_eq!( - NonFungibles::read(Allowance { - collection, - item: Some(item), - owner: account(owner), - operator: account(operator), - }) - .encode(), + NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }) + .encode(), true.encode() ); assert_eq!( - NonFungibles::read(Allowance { - collection, - item: Some(item), - owner: account(owner), - operator: account(operator), - }) - .encode(), - Nfts::check_allowance(&collection, &Some(item), &account(owner), &account(operator)) + NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }) + .encode(), + Nfts::check_allowance(&collection, &Some(item), &owner, &operator) .is_ok() .encode() ); }); } -fn signed(account_id: u8) -> RuntimeOrigin { - RuntimeOrigin::signed(account(account_id)) +fn signed(account_id: AccountId) -> RuntimeOrigin { + RuntimeOrigin::signed(account_id) } fn root() -> RuntimeOrigin { @@ -526,32 +535,26 @@ mod nfts { use super::*; pub(super) fn create_collection_mint_and_approve( - owner: u8, + owner: AccountId, item: ItemIdOf, - operator: u8, + operator: AccountId, ) -> (u32, u32) { let (collection, item) = create_collection_mint(owner, item); - assert_ok!(Nfts::approve_transfer( - signed(owner), - collection, - Some(item), - account(operator), - None - )); + assert_ok!(Nfts::approve_transfer(signed(owner), collection, Some(item), operator, None)); (collection, item) } - pub(super) fn create_collection_mint(owner: u8, item: ItemIdOf) -> (u32, u32) { + pub(super) fn create_collection_mint(owner: AccountId, item: ItemIdOf) -> (u32, u32) { let collection = create_collection(owner); - assert_ok!(Nfts::mint(signed(owner), collection, item, account(owner), None)); + assert_ok!(Nfts::mint(signed(owner), collection, item, owner, None)); (collection, item) } - pub(super) fn create_collection(owner: u8) -> u32 { + pub(super) fn create_collection(owner: AccountId) -> u32 { let next_id = next_collection_id(); assert_ok!(Nfts::create( signed(owner), - account(owner), + owner, collection_config_with_all_settings_enabled() )); next_id diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs index f57ee6976..6e686389d 100644 --- a/pallets/api/src/nonfungibles/types.rs +++ b/pallets/api/src/nonfungibles/types.rs @@ -1,13 +1,12 @@ -use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; use frame_system::pallet_prelude::BlockNumberFor; -use pallet_nfts::{AttributeNamespace, CollectionDetails, ItemDeposit, ItemDetails, MintType}; -use scale_info::TypeInfo; -use sp_runtime::{BoundedBTreeMap, RuntimeDebug}; +pub use pallet_nfts::{ + AttributeNamespace, CollectionConfig, CollectionDetails, CollectionSetting, CollectionSettings, + DestroyWitness, ItemDeposit, ItemDetails, ItemSetting, MintSettings, MintType, MintWitness, +}; // Type aliases for pallet-nfts. pub(super) type NftsOf = pallet_nfts::Pallet; -pub(super) type NftsErrorOf = pallet_nfts::Error; pub(super) type NftsWeightInfoOf = ::WeightInfo; // Type aliases for pallet-nfts storage items. pub(super) type AccountIdOf = ::AccountId; @@ -19,27 +18,10 @@ pub(super) type CollectionIdOf = as Inspect<::AccountId>>::CollectionId; pub(super) type ItemIdOf = as Inspect<::AccountId>>::ItemId; -pub(super) type ApprovalsOf = BoundedBTreeMap< - AccountIdOf, - Option>, - ::ApprovalsLimit, ->; pub(super) type ItemPriceOf = BalanceOf; // TODO: Multi-instances. -pub(super) type ItemDepositOf = ItemDeposit, AccountIdOf>; pub(super) type CollectionDetailsFor = CollectionDetails, BalanceOf>; -pub(super) type ItemDetailsFor = - ItemDetails, ItemDepositOf, ApprovalsOf>; pub(super) type AttributeNamespaceOf = AttributeNamespace>; -pub(super) type CreateCollectionConfigFor = - CreateCollectionConfig, BlockNumberFor, CollectionIdOf>; - -#[derive(Clone, Copy, Decode, Encode, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] -pub struct CreateCollectionConfig { - pub max_supply: Option, - pub mint_type: MintType, - pub price: Option, - pub start_block: Option, - pub end_block: Option, -} +pub(super) type CollectionConfigFor = + CollectionConfig, BlockNumberFor, CollectionIdOf>; diff --git a/pallets/nfts/Cargo.toml b/pallets/nfts/Cargo.toml index 60b3b7465..0a882d72a 100644 --- a/pallets/nfts/Cargo.toml +++ b/pallets/nfts/Cargo.toml @@ -44,6 +44,7 @@ std = [ "frame-support/std", "frame-system/std", "log/std", + "pallet-balances/std", "scale-info/std", "sp-core/std", "sp-io/std", diff --git a/pallets/nfts/src/benchmarking.rs b/pallets/nfts/src/benchmarking.rs index 8fa87557c..ab66da26d 100644 --- a/pallets/nfts/src/benchmarking.rs +++ b/pallets/nfts/src/benchmarking.rs @@ -578,9 +578,9 @@ benchmarks_instance_pallet! { let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let deadline = BlockNumberFor::::max_value(); - }: _(SystemOrigin::Signed(caller.clone()), collection, item, delegate_lookup, Some(deadline)) + }: _(SystemOrigin::Signed(caller.clone()), collection, Some(item), delegate_lookup, Some(deadline)) verify { - assert_last_event::(Event::TransferApproved { collection, item, owner: caller, delegate, deadline: Some(deadline) }.into()); + assert_last_event::(Event::TransferApproved { collection, item: Some(item), owner: caller, delegate, deadline: Some(deadline) }.into()); } cancel_approval { @@ -590,10 +590,10 @@ benchmarks_instance_pallet! { let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let origin = SystemOrigin::Signed(caller.clone()).into(); let deadline = BlockNumberFor::::max_value(); - Nfts::::approve_transfer(origin, collection, item, delegate_lookup.clone(), Some(deadline))?; - }: _(SystemOrigin::Signed(caller.clone()), collection, item, delegate_lookup) + Nfts::::approve_transfer(origin, collection, Some(item), delegate_lookup.clone(), Some(deadline))?; + }: _(SystemOrigin::Signed(caller.clone()), collection, Some(item), delegate_lookup) verify { - assert_last_event::(Event::ApprovalCancelled { collection, item, owner: caller, delegate }.into()); + assert_last_event::(Event::ApprovalCancelled { collection, item: Some(item), owner: caller, delegate }.into()); } clear_all_transfer_approvals { @@ -603,7 +603,7 @@ benchmarks_instance_pallet! { let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let origin = SystemOrigin::Signed(caller.clone()).into(); let deadline = BlockNumberFor::::max_value(); - Nfts::::approve_transfer(origin, collection, item, delegate_lookup.clone(), Some(deadline))?; + Nfts::::approve_transfer(origin, collection, Some(item), delegate_lookup.clone(), Some(deadline))?; }: _(SystemOrigin::Signed(caller.clone()), collection, item) verify { assert_last_event::(Event::AllApprovalsCancelled {collection, item, owner: caller}.into()); diff --git a/pallets/nfts/src/common_functions.rs b/pallets/nfts/src/common_functions.rs index 6fe483f1a..89de1f051 100644 --- a/pallets/nfts/src/common_functions.rs +++ b/pallets/nfts/src/common_functions.rs @@ -39,6 +39,14 @@ impl, I: 'static> Pallet { Collection::::get(collection).map(|i| i.items) } + /// Get the metadata of the collection item. + pub fn item_metadata( + collection: T::CollectionId, + item: T::ItemId, + ) -> Option> { + ItemMetadataOf::::get(collection, item).map(|metadata| metadata.data) + } + /// Validates the signature of the given data with the provided signer's account ID. /// /// # Errors diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index 6d71c1a22..e1e79ef4a 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -180,24 +180,26 @@ impl, I: 'static> Pallet { Self::is_pallet_feature_enabled(PalletFeature::Approvals), Error::::MethodDisabled ); - if !Collection::::contains_key(collection) { - return Err(Error::::UnknownCollection.into()); - } + let owner = Self::collection_owner(collection).ok_or(Error::::UnknownCollection)?; + let collection_config = Self::get_collection_config(&collection)?; ensure!( collection_config.is_setting_enabled(CollectionSetting::TransferableItems), Error::::ItemsNonTransferable ); - let origin = maybe_check_origin.ok_or(Error::::WrongOrigin)?; - Allowances::::mutate((&collection, &origin, &delegate), |allowance| { + if let Some(check_origin) = maybe_check_origin { + ensure!(check_origin == owner, Error::::NoPermission); + } + + Allowances::::mutate((&collection, &owner, &delegate), |allowance| { *allowance = true; }); Self::deposit_event(Event::TransferApproved { collection, item: None, - owner: origin, + owner, delegate, deadline: None, }); @@ -209,19 +211,14 @@ impl, I: 'static> Pallet { collection: T::CollectionId, delegate: T::AccountId, ) -> DispatchResult { - if !Collection::::contains_key(collection) { - return Err(Error::::UnknownCollection.into()); - } + let owner = Self::collection_owner(collection).ok_or(Error::::UnknownCollection)?; - let origin = maybe_check_origin.ok_or(Error::::WrongOrigin)?; - Allowances::::remove((&collection, &origin, &delegate)); + if let Some(check_origin) = maybe_check_origin { + ensure!(check_origin == owner, Error::::NoPermission); + } + Allowances::::remove((&collection, &owner, &delegate)); - Self::deposit_event(Event::ApprovalCancelled { - collection, - owner: origin, - item: None, - delegate, - }); + Self::deposit_event(Event::ApprovalCancelled { collection, owner, item: None, delegate }); Ok(()) } diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 397a715c2..4d0f08c93 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -318,7 +318,7 @@ fn destroy_should_work() { assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(2), None)); assert_eq!(AccountBalance::::get(0, account(2)), 1); assert_ok!(Nfts::approve_transfer( - RuntimeOrigin::signed(account(2)), + RuntimeOrigin::signed(account(1)), 0, None, account(3), @@ -2017,22 +2017,22 @@ fn cancel_approval_collection_works_with_admin() { )); assert_ok!(Nfts::approve_transfer( - RuntimeOrigin::signed(account(2)), + RuntimeOrigin::signed(account(1)), 0, None, account(3), None )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 1, None, account(3)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(1)), 1, None, account(3)), Error::::UnknownCollection ); - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, None, account(3))); + assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(1)), 0, None, account(3))); assert!(events().contains(&Event::::ApprovalCancelled { collection: 0, item: None, - owner: account(2), + owner: account(1), delegate: account(3) })); assert_eq!(Allowances::::get((0, account(2), account(3))), false); @@ -2156,7 +2156,7 @@ fn approval_collection_works_with_admin() { RuntimeOrigin::signed(account(1)), 0, 42, - account(2), + account(1), default_item_config() )); @@ -2178,7 +2178,7 @@ fn approval_collection_works_with_admin() { ); assert_ok!(Nfts::approve_transfer( - RuntimeOrigin::signed(account(2)), + RuntimeOrigin::signed(account(1)), 0, None, account(3), @@ -2187,11 +2187,11 @@ fn approval_collection_works_with_admin() { assert!(events().contains(&Event::::TransferApproved { collection: 0, item: None, - owner: account(2), + owner: account(1), delegate: account(3), deadline: None })); - assert_eq!(Allowances::::get((0, account(2), account(3))), true); + assert_eq!(Allowances::::get((0, account(1), account(3))), true); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4))); }); } diff --git a/pallets/nfts/src/types.rs b/pallets/nfts/src/types.rs index 061352c09..941da6cad 100644 --- a/pallets/nfts/src/types.rs +++ b/pallets/nfts/src/types.rs @@ -145,21 +145,21 @@ pub struct MintWitness { #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo, MaxEncodedLen)] pub struct ItemDetails { /// The owner of this item. - pub owner: AccountId, + pub(super) owner: AccountId, /// The approved transferrer of this item, if one is set. - pub approvals: Approvals, + pub(super) approvals: Approvals, /// The amount held in the pallet's default account for this item. Free-hold items will have /// this as zero. - pub deposit: Deposit, + pub(super) deposit: Deposit, } /// Information about the reserved item deposit. #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct ItemDeposit { /// A depositor account. - pub account: AccountId, + pub(super) account: AccountId, /// An amount that gets reserved. - pub amount: DepositBalance, + pub(super) amount: DepositBalance, } /// Information about the collection's metadata. diff --git a/pallets/nfts/src/weights.rs b/pallets/nfts/src/weights.rs index c5fb60a22..c374d6dbc 100644 --- a/pallets/nfts/src/weights.rs +++ b/pallets/nfts/src/weights.rs @@ -1,30 +1,14 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. //! Autogenerated weights for `pallet_nfts` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-04-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 40.0.0 +//! DATE: 2024-10-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `R0GUE`, CPU: `` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// ./target/release/pop-node // benchmark // pallet // --chain=dev @@ -34,12 +18,11 @@ // --no-storage-info // --no-median-slopes // --no-min-squares -// --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/nfts/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./pallets/nfts/src/weights.rs +// --template=./scripts/pallet-weights-template.hbs +// --extrinsic= #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -107,10 +90,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: - // Measured: `216` + // Measured: `105` // Estimated: `3549` - // Minimum execution time: 34_863_000 picoseconds. - Weight::from_parts(36_679_000, 3549) + // Minimum execution time: 27_000_000 picoseconds. + Weight::from_parts(27_000_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -126,10 +109,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_create() -> Weight { // Proof Size summary in bytes: - // Measured: `76` + // Measured: `3` // Estimated: `3549` - // Minimum execution time: 19_631_000 picoseconds. - Weight::from_parts(20_384_000, 3549) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(15_000_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -141,6 +124,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1001 w:1000) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) @@ -152,15 +137,19 @@ impl WeightInfo for SubstrateWeight { /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. - fn destroy(_m: u32, _c: u32, a: u32, ) -> Weight { + fn destroy(m: u32, c: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32204 + a * (366 ±0)` + // Measured: `32216 + a * (366 ±0)` // Estimated: `2523990 + a * (2954 ±0)` - // Minimum execution time: 1_282_083_000 picoseconds. - Weight::from_parts(1_249_191_963, 2523990) - // Standard Error: 4_719 - .saturating_add(Weight::from_parts(6_470_227, 0).saturating_mul(a.into())) - .saturating_add(T::DbWeight::get().reads(1004_u64)) + // Minimum execution time: 982_000_000 picoseconds. + Weight::from_parts(937_587_516, 2523990) + // Standard Error: 12_288 + .saturating_add(Weight::from_parts(34_348, 0).saturating_mul(m.into())) + // Standard Error: 12_288 + .saturating_add(Weight::from_parts(23_800, 0).saturating_mul(c.into())) + // Standard Error: 12_288 + .saturating_add(Weight::from_parts(5_095_505, 0).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(1005_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(1005_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) @@ -174,18 +163,20 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: - // Measured: `455` + // Measured: `382` // Estimated: `4326` - // Minimum execution time: 49_055_000 picoseconds. - Weight::from_parts(50_592_000, 4326) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + // Minimum execution time: 41_000_000 picoseconds. + Weight::from_parts(42_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -195,18 +186,20 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn force_mint() -> Weight { // Proof Size summary in bytes: - // Measured: `455` + // Measured: `382` // Estimated: `4326` - // Minimum execution time: 47_102_000 picoseconds. - Weight::from_parts(48_772_000, 4326) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + // Minimum execution time: 39_000_000 picoseconds. + Weight::from_parts(40_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) @@ -218,22 +211,24 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:0 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: - // Measured: `564` + // Measured: `576` // Estimated: `4326` - // Minimum execution time: 52_968_000 picoseconds. - Weight::from_parts(55_136_000, 4326) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + // Minimum execution time: 46_000_000 picoseconds. + Weight::from_parts(59_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) @@ -245,6 +240,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:2) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) @@ -253,12 +250,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `593` - // Estimated: `4326` - // Minimum execution time: 41_140_000 picoseconds. - Weight::from_parts(43_288_000, 4326) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + // Measured: `605` + // Estimated: `6068` + // Minimum execution time: 38_000_000 picoseconds. + Weight::from_parts(83_000_000, 6068) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) @@ -269,12 +266,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `763 + i * (108 ±0)` + // Measured: `690 + i * (108 ±0)` // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 14_433_000 picoseconds. - Weight::from_parts(14_664_000, 3549) - // Standard Error: 23_078 - .saturating_add(Weight::from_parts(15_911_377, 0).saturating_mul(i.into())) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3549) + // Standard Error: 20_022 + .saturating_add(Weight::from_parts(16_005_327, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -286,10 +283,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 18_307_000 picoseconds. - Weight::from_parts(18_966_000, 3534) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(14_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -299,10 +296,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn unlock_item_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 18_078_000 picoseconds. - Weight::from_parts(18_593_000, 3534) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(14_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -312,10 +309,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn lock_collection() -> Weight { // Proof Size summary in bytes: - // Measured: `340` + // Measured: `267` // Estimated: `3549` - // Minimum execution time: 15_175_000 picoseconds. - Weight::from_parts(15_762_000, 3549) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -329,10 +326,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `562` + // Measured: `417` // Estimated: `3593` - // Minimum execution time: 26_164_000 picoseconds. - Weight::from_parts(27_117_000, 3593) + // Minimum execution time: 18_000_000 picoseconds. + Weight::from_parts(19_000_000, 3593) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -342,10 +339,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: - // Measured: `369` + // Measured: `296` // Estimated: `6078` - // Minimum execution time: 38_523_000 picoseconds. - Weight::from_parts(39_486_000, 6078) + // Minimum execution time: 30_000_000 picoseconds. + Weight::from_parts(31_000_000, 6078) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -355,10 +352,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: - // Measured: `311` + // Measured: `238` // Estimated: `3549` - // Minimum execution time: 15_733_000 picoseconds. - Weight::from_parts(16_227_000, 3549) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 3549) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -368,10 +365,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn force_collection_config() -> Weight { // Proof Size summary in bytes: - // Measured: `276` + // Measured: `203` // Estimated: `3549` - // Minimum execution time: 12_042_000 picoseconds. - Weight::from_parts(12_690_000, 3549) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(9_000_000, 3549) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -381,10 +378,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_properties() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 17_165_000 picoseconds. - Weight::from_parts(17_769_000, 3534) + // Minimum execution time: 12_000_000 picoseconds. + Weight::from_parts(13_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -400,10 +397,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `499` // Estimated: `3944` - // Minimum execution time: 48_862_000 picoseconds. - Weight::from_parts(50_584_000, 3944) + // Minimum execution time: 37_000_000 picoseconds. + Weight::from_parts(38_000_000, 3944) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -413,10 +410,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `344` + // Measured: `271` // Estimated: `3944` - // Minimum execution time: 24_665_000 picoseconds. - Weight::from_parts(25_465_000, 3944) + // Minimum execution time: 19_000_000 picoseconds. + Weight::from_parts(19_000_000, 3944) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -430,30 +427,30 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `983` + // Measured: `943` // Estimated: `3944` - // Minimum execution time: 44_617_000 picoseconds. - Weight::from_parts(46_458_000, 3944) + // Minimum execution time: 35_000_000 picoseconds. + Weight::from_parts(36_000_000, 3944) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) fn approve_item_attributes() -> Weight { // Proof Size summary in bytes: - // Measured: `381` - // Estimated: `4326` - // Minimum execution time: 15_710_000 picoseconds. - Weight::from_parts(16_191_000, 4326) + // Measured: `308` + // Estimated: `4466` + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4466) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1001 w:1000) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -461,12 +458,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1000]`. fn cancel_item_attributes_approval(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `831 + n * (398 ±0)` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 24_447_000 picoseconds. - Weight::from_parts(25_144_000, 4326) - // Standard Error: 4_872 - .saturating_add(Weight::from_parts(6_523_101, 0).saturating_mul(n.into())) + // Measured: `686 + n * (398 ±0)` + // Estimated: `4466 + n * (2954 ±0)` + // Minimum execution time: 18_000_000 picoseconds. + Weight::from_parts(19_000_000, 4466) + // Standard Error: 6_379 + .saturating_add(Weight::from_parts(5_018_740, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -485,10 +482,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `499` // Estimated: `3812` - // Minimum execution time: 39_990_000 picoseconds. - Weight::from_parts(41_098_000, 3812) + // Minimum execution time: 30_000_000 picoseconds. + Weight::from_parts(31_000_000, 3812) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -502,10 +499,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `849` + // Measured: `809` // Estimated: `3812` - // Minimum execution time: 38_030_000 picoseconds. - Weight::from_parts(39_842_000, 3812) + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(29_000_000, 3812) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -519,10 +516,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `398` + // Measured: `325` // Estimated: `3759` - // Minimum execution time: 36_778_000 picoseconds. - Weight::from_parts(38_088_000, 3759) + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(30_000_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -536,10 +533,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `716` + // Measured: `643` // Estimated: `3759` - // Minimum execution time: 36_887_000 picoseconds. - Weight::from_parts(38_406_000, 3759) + // Minimum execution time: 27_000_000 picoseconds. + Weight::from_parts(29_000_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -549,10 +546,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn approve_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `410` + // Measured: `337` // Estimated: `4326` - // Minimum execution time: 18_734_000 picoseconds. - Weight::from_parts(19_267_000, 4326) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(14_000_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -560,10 +557,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn cancel_approval() -> Weight { // Proof Size summary in bytes: - // Measured: `418` + // Measured: `345` // Estimated: `4326` - // Minimum execution time: 16_080_000 picoseconds. - Weight::from_parts(16_603_000, 4326) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4326) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -571,10 +568,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn clear_all_transfer_approvals() -> Weight { // Proof Size summary in bytes: - // Measured: `418` + // Measured: `345` // Estimated: `4326` - // Minimum execution time: 15_013_000 picoseconds. - Weight::from_parts(15_607_000, 4326) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 4326) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -582,10 +579,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn set_accept_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `76` + // Measured: `3` // Estimated: `3517` - // Minimum execution time: 13_077_000 picoseconds. - Weight::from_parts(13_635_000, 3517) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 3517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -595,10 +592,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: - // Measured: `340` + // Measured: `267` // Estimated: `3549` - // Minimum execution time: 17_146_000 picoseconds. - Weight::from_parts(17_453_000, 3549) + // Minimum execution time: 12_000_000 picoseconds. + Weight::from_parts(13_000_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -608,10 +605,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn update_mint_settings() -> Weight { // Proof Size summary in bytes: - // Measured: `323` + // Measured: `250` // Estimated: `3538` - // Minimum execution time: 16_102_000 picoseconds. - Weight::from_parts(16_629_000, 3538) + // Minimum execution time: 12_000_000 picoseconds. + Weight::from_parts(13_000_000, 3538) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -625,10 +622,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn set_price() -> Weight { // Proof Size summary in bytes: - // Measured: `518` + // Measured: `478` // Estimated: `4326` - // Minimum execution time: 22_118_000 picoseconds. - Weight::from_parts(22_849_000, 4326) + // Minimum execution time: 16_000_000 picoseconds. + Weight::from_parts(17_000_000, 4326) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -644,28 +641,30 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:2) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn buy_item() -> Weight { // Proof Size summary in bytes: - // Measured: `705` - // Estimated: `4326` - // Minimum execution time: 50_369_000 picoseconds. - Weight::from_parts(51_816_000, 4326) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + // Measured: `717` + // Estimated: `6068` + // Minimum execution time: 42_000_000 picoseconds. + Weight::from_parts(45_000_000, 6068) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) } /// The range of component `n` is `[0, 10]`. fn pay_tips(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_203_000 picoseconds. - Weight::from_parts(3_710_869, 0) - // Standard Error: 8_094 - .saturating_add(Weight::from_parts(2_201_869, 0).saturating_mul(n.into())) + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(390_532, 0) + // Standard Error: 84_277 + .saturating_add(Weight::from_parts(3_087_492, 0).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:2 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -673,10 +672,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn create_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `494` + // Measured: `421` // Estimated: `7662` - // Minimum execution time: 18_893_000 picoseconds. - Weight::from_parts(19_506_000, 7662) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(15_000_000, 7662) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -686,10 +685,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn cancel_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `513` + // Measured: `440` // Estimated: `4326` - // Minimum execution time: 19_086_000 picoseconds. - Weight::from_parts(19_609_000, 4326) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(14_000_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -705,18 +704,20 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:2 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:4) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:2) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn claim_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `834` + // Measured: `907` // Estimated: `7662` - // Minimum execution time: 84_103_000 picoseconds. - Weight::from_parts(85_325_000, 7662) - .saturating_add(T::DbWeight::get().reads(9_u64)) - .saturating_add(T::DbWeight::get().writes(10_u64)) + // Minimum execution time: 75_000_000 picoseconds. + Weight::from_parts(77_000_000, 7662) + .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(T::DbWeight::get().writes(12_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -726,6 +727,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -739,22 +742,22 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `629` + // Measured: `485` // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 128_363_000 picoseconds. - Weight::from_parts(139_474_918, 6078) - // Standard Error: 79_252 - .saturating_add(Weight::from_parts(31_384_027, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Minimum execution time: 100_000_000 picoseconds. + Weight::from_parts(107_476_765, 6078) + // Standard Error: 61_259 + .saturating_add(Weight::from_parts(27_610_007, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) @@ -766,12 +769,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `659` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 66_688_000 picoseconds. - Weight::from_parts(79_208_379, 4326) - // Standard Error: 74_020 - .saturating_add(Weight::from_parts(31_028_221, 0).saturating_mul(n.into())) + // Measured: `514` + // Estimated: `4466 + n * (2954 ±0)` + // Minimum execution time: 51_000_000 picoseconds. + Weight::from_parts(57_358_180, 4466) + // Standard Error: 54_968 + .saturating_add(Weight::from_parts(27_429_606, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -794,10 +797,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: - // Measured: `216` + // Measured: `105` // Estimated: `3549` - // Minimum execution time: 34_863_000 picoseconds. - Weight::from_parts(36_679_000, 3549) + // Minimum execution time: 27_000_000 picoseconds. + Weight::from_parts(27_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -813,10 +816,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_create() -> Weight { // Proof Size summary in bytes: - // Measured: `76` + // Measured: `3` // Estimated: `3549` - // Minimum execution time: 19_631_000 picoseconds. - Weight::from_parts(20_384_000, 3549) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(15_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -828,6 +831,8 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1001 w:1000) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) @@ -839,15 +844,19 @@ impl WeightInfo for () { /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. - fn destroy(_m: u32, _c: u32, a: u32, ) -> Weight { + fn destroy(m: u32, c: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32204 + a * (366 ±0)` + // Measured: `32216 + a * (366 ±0)` // Estimated: `2523990 + a * (2954 ±0)` - // Minimum execution time: 1_282_083_000 picoseconds. - Weight::from_parts(1_249_191_963, 2523990) - // Standard Error: 4_719 - .saturating_add(Weight::from_parts(6_470_227, 0).saturating_mul(a.into())) - .saturating_add(RocksDbWeight::get().reads(1004_u64)) + // Minimum execution time: 982_000_000 picoseconds. + Weight::from_parts(937_587_516, 2523990) + // Standard Error: 12_288 + .saturating_add(Weight::from_parts(34_348, 0).saturating_mul(m.into())) + // Standard Error: 12_288 + .saturating_add(Weight::from_parts(23_800, 0).saturating_mul(c.into())) + // Standard Error: 12_288 + .saturating_add(Weight::from_parts(5_095_505, 0).saturating_mul(a.into())) + .saturating_add(RocksDbWeight::get().reads(1005_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(RocksDbWeight::get().writes(1005_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(a.into()))) @@ -861,18 +870,20 @@ impl WeightInfo for () { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: - // Measured: `455` + // Measured: `382` // Estimated: `4326` - // Minimum execution time: 49_055_000 picoseconds. - Weight::from_parts(50_592_000, 4326) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + // Minimum execution time: 41_000_000 picoseconds. + Weight::from_parts(42_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -882,18 +893,20 @@ impl WeightInfo for () { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn force_mint() -> Weight { // Proof Size summary in bytes: - // Measured: `455` + // Measured: `382` // Estimated: `4326` - // Minimum execution time: 47_102_000 picoseconds. - Weight::from_parts(48_772_000, 4326) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + // Minimum execution time: 39_000_000 picoseconds. + Weight::from_parts(40_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) @@ -905,22 +918,24 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:0 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: - // Measured: `564` + // Measured: `576` // Estimated: `4326` - // Minimum execution time: 52_968_000 picoseconds. - Weight::from_parts(55_136_000, 4326) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + // Minimum execution time: 46_000_000 picoseconds. + Weight::from_parts(59_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) @@ -932,6 +947,8 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:2) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) @@ -940,12 +957,12 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `593` - // Estimated: `4326` - // Minimum execution time: 41_140_000 picoseconds. - Weight::from_parts(43_288_000, 4326) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + // Measured: `605` + // Estimated: `6068` + // Minimum execution time: 38_000_000 picoseconds. + Weight::from_parts(83_000_000, 6068) + .saturating_add(RocksDbWeight::get().reads(7_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) @@ -956,12 +973,12 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `763 + i * (108 ±0)` + // Measured: `690 + i * (108 ±0)` // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 14_433_000 picoseconds. - Weight::from_parts(14_664_000, 3549) - // Standard Error: 23_078 - .saturating_add(Weight::from_parts(15_911_377, 0).saturating_mul(i.into())) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3549) + // Standard Error: 20_022 + .saturating_add(Weight::from_parts(16_005_327, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -973,10 +990,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 18_307_000 picoseconds. - Weight::from_parts(18_966_000, 3534) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(14_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -986,10 +1003,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn unlock_item_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 18_078_000 picoseconds. - Weight::from_parts(18_593_000, 3534) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(14_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -999,10 +1016,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn lock_collection() -> Weight { // Proof Size summary in bytes: - // Measured: `340` + // Measured: `267` // Estimated: `3549` - // Minimum execution time: 15_175_000 picoseconds. - Weight::from_parts(15_762_000, 3549) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1016,10 +1033,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `562` + // Measured: `417` // Estimated: `3593` - // Minimum execution time: 26_164_000 picoseconds. - Weight::from_parts(27_117_000, 3593) + // Minimum execution time: 18_000_000 picoseconds. + Weight::from_parts(19_000_000, 3593) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -1029,10 +1046,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: - // Measured: `369` + // Measured: `296` // Estimated: `6078` - // Minimum execution time: 38_523_000 picoseconds. - Weight::from_parts(39_486_000, 6078) + // Minimum execution time: 30_000_000 picoseconds. + Weight::from_parts(31_000_000, 6078) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -1042,10 +1059,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: - // Measured: `311` + // Measured: `238` // Estimated: `3549` - // Minimum execution time: 15_733_000 picoseconds. - Weight::from_parts(16_227_000, 3549) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -1055,10 +1072,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn force_collection_config() -> Weight { // Proof Size summary in bytes: - // Measured: `276` + // Measured: `203` // Estimated: `3549` - // Minimum execution time: 12_042_000 picoseconds. - Weight::from_parts(12_690_000, 3549) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(9_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1068,10 +1085,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_properties() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 17_165_000 picoseconds. - Weight::from_parts(17_769_000, 3534) + // Minimum execution time: 12_000_000 picoseconds. + Weight::from_parts(13_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1087,10 +1104,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `499` // Estimated: `3944` - // Minimum execution time: 48_862_000 picoseconds. - Weight::from_parts(50_584_000, 3944) + // Minimum execution time: 37_000_000 picoseconds. + Weight::from_parts(38_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1100,10 +1117,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `344` + // Measured: `271` // Estimated: `3944` - // Minimum execution time: 24_665_000 picoseconds. - Weight::from_parts(25_465_000, 3944) + // Minimum execution time: 19_000_000 picoseconds. + Weight::from_parts(19_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1117,30 +1134,30 @@ impl WeightInfo for () { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `983` + // Measured: `943` // Estimated: `3944` - // Minimum execution time: 44_617_000 picoseconds. - Weight::from_parts(46_458_000, 3944) + // Minimum execution time: 35_000_000 picoseconds. + Weight::from_parts(36_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) fn approve_item_attributes() -> Weight { // Proof Size summary in bytes: - // Measured: `381` - // Estimated: `4326` - // Minimum execution time: 15_710_000 picoseconds. - Weight::from_parts(16_191_000, 4326) + // Measured: `308` + // Estimated: `4466` + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4466) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1001 w:1000) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -1148,12 +1165,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1000]`. fn cancel_item_attributes_approval(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `831 + n * (398 ±0)` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 24_447_000 picoseconds. - Weight::from_parts(25_144_000, 4326) - // Standard Error: 4_872 - .saturating_add(Weight::from_parts(6_523_101, 0).saturating_mul(n.into())) + // Measured: `686 + n * (398 ±0)` + // Estimated: `4466 + n * (2954 ±0)` + // Minimum execution time: 18_000_000 picoseconds. + Weight::from_parts(19_000_000, 4466) + // Standard Error: 6_379 + .saturating_add(Weight::from_parts(5_018_740, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -1172,10 +1189,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `499` // Estimated: `3812` - // Minimum execution time: 39_990_000 picoseconds. - Weight::from_parts(41_098_000, 3812) + // Minimum execution time: 30_000_000 picoseconds. + Weight::from_parts(31_000_000, 3812) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1189,10 +1206,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `849` + // Measured: `809` // Estimated: `3812` - // Minimum execution time: 38_030_000 picoseconds. - Weight::from_parts(39_842_000, 3812) + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(29_000_000, 3812) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1206,10 +1223,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `398` + // Measured: `325` // Estimated: `3759` - // Minimum execution time: 36_778_000 picoseconds. - Weight::from_parts(38_088_000, 3759) + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(30_000_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1223,10 +1240,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `716` + // Measured: `643` // Estimated: `3759` - // Minimum execution time: 36_887_000 picoseconds. - Weight::from_parts(38_406_000, 3759) + // Minimum execution time: 27_000_000 picoseconds. + Weight::from_parts(29_000_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1236,10 +1253,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn approve_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `410` + // Measured: `337` // Estimated: `4326` - // Minimum execution time: 18_734_000 picoseconds. - Weight::from_parts(19_267_000, 4326) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(14_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1247,10 +1264,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn cancel_approval() -> Weight { // Proof Size summary in bytes: - // Measured: `418` + // Measured: `345` // Estimated: `4326` - // Minimum execution time: 16_080_000 picoseconds. - Weight::from_parts(16_603_000, 4326) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1258,10 +1275,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn clear_all_transfer_approvals() -> Weight { // Proof Size summary in bytes: - // Measured: `418` + // Measured: `345` // Estimated: `4326` - // Minimum execution time: 15_013_000 picoseconds. - Weight::from_parts(15_607_000, 4326) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1269,10 +1286,10 @@ impl WeightInfo for () { /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn set_accept_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `76` + // Measured: `3` // Estimated: `3517` - // Minimum execution time: 13_077_000 picoseconds. - Weight::from_parts(13_635_000, 3517) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 3517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1282,10 +1299,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: - // Measured: `340` + // Measured: `267` // Estimated: `3549` - // Minimum execution time: 17_146_000 picoseconds. - Weight::from_parts(17_453_000, 3549) + // Minimum execution time: 12_000_000 picoseconds. + Weight::from_parts(13_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1295,10 +1312,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn update_mint_settings() -> Weight { // Proof Size summary in bytes: - // Measured: `323` + // Measured: `250` // Estimated: `3538` - // Minimum execution time: 16_102_000 picoseconds. - Weight::from_parts(16_629_000, 3538) + // Minimum execution time: 12_000_000 picoseconds. + Weight::from_parts(13_000_000, 3538) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1312,10 +1329,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn set_price() -> Weight { // Proof Size summary in bytes: - // Measured: `518` + // Measured: `478` // Estimated: `4326` - // Minimum execution time: 22_118_000 picoseconds. - Weight::from_parts(22_849_000, 4326) + // Minimum execution time: 16_000_000 picoseconds. + Weight::from_parts(17_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1331,28 +1348,30 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:2) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn buy_item() -> Weight { // Proof Size summary in bytes: - // Measured: `705` - // Estimated: `4326` - // Minimum execution time: 50_369_000 picoseconds. - Weight::from_parts(51_816_000, 4326) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + // Measured: `717` + // Estimated: `6068` + // Minimum execution time: 42_000_000 picoseconds. + Weight::from_parts(45_000_000, 6068) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) } /// The range of component `n` is `[0, 10]`. fn pay_tips(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_203_000 picoseconds. - Weight::from_parts(3_710_869, 0) - // Standard Error: 8_094 - .saturating_add(Weight::from_parts(2_201_869, 0).saturating_mul(n.into())) + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(390_532, 0) + // Standard Error: 84_277 + .saturating_add(Weight::from_parts(3_087_492, 0).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:2 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -1360,10 +1379,10 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn create_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `494` + // Measured: `421` // Estimated: `7662` - // Minimum execution time: 18_893_000 picoseconds. - Weight::from_parts(19_506_000, 7662) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(15_000_000, 7662) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1373,10 +1392,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn cancel_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `513` + // Measured: `440` // Estimated: `4326` - // Minimum execution time: 19_086_000 picoseconds. - Weight::from_parts(19_609_000, 4326) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(14_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1392,18 +1411,20 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:2 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:4) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:2) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn claim_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `834` + // Measured: `907` // Estimated: `7662` - // Minimum execution time: 84_103_000 picoseconds. - Weight::from_parts(85_325_000, 7662) - .saturating_add(RocksDbWeight::get().reads(9_u64)) - .saturating_add(RocksDbWeight::get().writes(10_u64)) + // Minimum execution time: 75_000_000 picoseconds. + Weight::from_parts(77_000_000, 7662) + .saturating_add(RocksDbWeight::get().reads(11_u64)) + .saturating_add(RocksDbWeight::get().writes(12_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -1413,6 +1434,8 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -1426,22 +1449,22 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `629` + // Measured: `485` // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 128_363_000 picoseconds. - Weight::from_parts(139_474_918, 6078) - // Standard Error: 79_252 - .saturating_add(Weight::from_parts(31_384_027, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Minimum execution time: 100_000_000 picoseconds. + Weight::from_parts(107_476_765, 6078) + // Standard Error: 61_259 + .saturating_add(Weight::from_parts(27_610_007, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(6_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) @@ -1453,16 +1476,16 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `659` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 66_688_000 picoseconds. - Weight::from_parts(79_208_379, 4326) - // Standard Error: 74_020 - .saturating_add(Weight::from_parts(31_028_221, 0).saturating_mul(n.into())) + // Measured: `514` + // Estimated: `4466 + n * (2954 ±0)` + // Minimum execution time: 51_000_000 picoseconds. + Weight::from_parts(57_358_180, 4466) + // Standard Error: 54_968 + .saturating_add(Weight::from_parts(27_429_606, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } -} +} \ No newline at end of file diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs index 035a6014f..93f4853f1 100644 --- a/runtime/devnet/src/config/api/mod.rs +++ b/runtime/devnet/src/config/api/mod.rs @@ -2,7 +2,7 @@ use core::marker::PhantomData; use codec::Decode; use cumulus_primitives_core::Weight; -use frame_support::traits::Contains; +use frame_support::traits::{ConstU32, Contains}; pub(crate) use pallet_api::Extension; use pallet_api::{extension::*, Read}; use sp_core::ConstU8; @@ -11,7 +11,9 @@ use sp_std::vec::Vec; use versioning::*; use crate::{ - config::assets::TrustBackedAssetsInstance, fungibles, Runtime, RuntimeCall, RuntimeEvent, + config::{assets::TrustBackedAssetsInstance, xcm::LocalOriginToLocation}, + fungibles, nonfungibles, Balances, Ismp, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, + RuntimeHoldReason, TransactionByteFee, }; mod versioning; @@ -32,6 +34,9 @@ pub enum RuntimeRead { /// Fungible token queries. #[codec(index = 150)] Fungibles(fungibles::Read), + /// Non-fungible token queries. + #[codec(index = 151)] + NonFungibles(nonfungibles::Read), } impl Readable for RuntimeRead { @@ -43,6 +48,7 @@ impl Readable for RuntimeRead { fn weight(&self) -> Weight { match self { RuntimeRead::Fungibles(key) => fungibles::Pallet::weight(key), + RuntimeRead::NonFungibles(key) => nonfungibles::Pallet::weight(key), } } @@ -50,16 +56,20 @@ impl Readable for RuntimeRead { fn read(self) -> Self::Result { match self { RuntimeRead::Fungibles(key) => RuntimeResult::Fungibles(fungibles::Pallet::read(key)), + RuntimeRead::NonFungibles(key) => + RuntimeResult::NonFungibles(nonfungibles::Pallet::read(key)), } } } /// The result of a runtime state read. #[derive(Debug)] -#[cfg_attr(test, derive(PartialEq, Clone))] +#[cfg_attr(feature = "std", derive(PartialEq, Clone))] pub enum RuntimeResult { /// Fungible token read results. Fungibles(fungibles::ReadResult), + /// Non-fungible token read results. + NonFungibles(nonfungibles::ReadResult), } impl RuntimeResult { @@ -67,6 +77,7 @@ impl RuntimeResult { fn encode(&self) -> Vec { match self { RuntimeResult::Fungibles(result) => result.encode(), + RuntimeResult::NonFungibles(result) => result.encode(), } } } @@ -77,6 +88,10 @@ impl fungibles::Config for Runtime { type WeightInfo = fungibles::weights::SubstrateWeight; } +impl nonfungibles::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} + #[derive(Default)] pub struct Config; impl pallet_api::extension::Config for Config { @@ -130,8 +145,8 @@ pub struct Filter(PhantomData); impl> Contains for Filter { fn contains(c: &RuntimeCall) -> bool { - use fungibles::Call::*; - T::BaseCallFilter::contains(c) && + let contain_fungibles: bool = { + use fungibles::Call::*; matches!( c, RuntimeCall::Fungibles( @@ -142,26 +157,63 @@ impl> Contains f create { .. } | set_metadata { .. } | start_destroy { .. } | clear_metadata { .. } | - mint { .. } | burn { .. } + mint { .. } | burn { .. }, + ) + ) + }; + + let contain_nonfungibles: bool = { + use nonfungibles::Call::*; + matches!( + c, + RuntimeCall::NonFungibles( + transfer { .. } | + approve { .. } | create { .. } | + destroy { .. } | set_metadata { .. } | + clear_metadata { .. } | + set_attribute { .. } | + clear_attribute { .. } | + approve_item_attributes { .. } | + cancel_item_attributes_approval { .. } | + mint { .. } | burn { .. } | + set_max_supply { .. }, ) ) + }; + + T::BaseCallFilter::contains(c) && contain_fungibles | contain_nonfungibles } } impl Contains for Filter { fn contains(r: &RuntimeRead) -> bool { - use fungibles::Read::*; - matches!( - r, - RuntimeRead::Fungibles( - TotalSupply(..) | - BalanceOf { .. } | - Allowance { .. } | - TokenName(..) | TokenSymbol(..) | - TokenDecimals(..) | - TokenExists(..) + let contain_fungibles: bool = { + use fungibles::Read::*; + matches!( + r, + RuntimeRead::Fungibles( + TotalSupply(..) | + BalanceOf { .. } | Allowance { .. } | + TokenName(..) | TokenSymbol(..) | + TokenDecimals(..) | TokenExists(..), + ) + ) + }; + let contain_nonfungibles: bool = { + use nonfungibles::Read::*; + matches!( + r, + RuntimeRead::NonFungibles( + TotalSupply(..) | + BalanceOf { .. } | Allowance { .. } | + OwnerOf { .. } | GetAttribute { .. } | + Collection { .. } | NextCollectionId | + ItemMetadata { .. }, + ) ) - ) + }; + + contain_fungibles | contain_nonfungibles } } @@ -169,8 +221,9 @@ impl Contains for Filter { mod tests { use codec::Encode; use pallet_api::fungibles::Call::*; - use sp_core::crypto::AccountId32; - use RuntimeCall::{Balances, Fungibles}; + use pallet_nfts::MintWitness; + use sp_core::{bounded_vec, crypto::AccountId32}; + use RuntimeCall::{Balances, Fungibles, NonFungibles}; use super::*; @@ -181,6 +234,10 @@ mod tests { let value = 1_000; let result = fungibles::ReadResult::::TotalSupply(value); assert_eq!(RuntimeResult::Fungibles(result).encode(), value.encode()); + + let value = 1_000; + let result = nonfungibles::ReadResult::::TotalSupply(value); + assert_eq!(RuntimeResult::NonFungibles(result).encode(), value.encode()); } #[test] @@ -228,6 +285,71 @@ mod tests { } } + #[test] + fn filter_allows_nonfungibles_calls() { + use pallet_api::nonfungibles::{ + types::{CollectionConfig, CollectionSettings, MintSettings}, + Call::*, + }; + use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness}; + + for call in vec![ + NonFungibles(transfer { collection: 0, item: 0, to: ACCOUNT }), + NonFungibles(approve { + collection: 0, + item: Some(0), + operator: ACCOUNT, + approved: false, + }), + NonFungibles(create { + admin: ACCOUNT, + config: CollectionConfig { + max_supply: Some(0), + mint_settings: MintSettings::default(), + settings: CollectionSettings::all_enabled(), + }, + }), + NonFungibles(destroy { + collection: 0, + witness: DestroyWitness { attributes: 0, item_configs: 0, item_metadatas: 0 }, + }), + NonFungibles(set_attribute { + collection: 0, + item: Some(0), + namespace: pallet_nfts::AttributeNamespace::Pallet, + key: bounded_vec![], + value: bounded_vec![], + }), + NonFungibles(clear_attribute { + collection: 0, + item: Some(0), + namespace: pallet_nfts::AttributeNamespace::Pallet, + key: bounded_vec![], + }), + NonFungibles(set_metadata { collection: 0, item: 0, data: bounded_vec![] }), + NonFungibles(clear_metadata { collection: 0, item: 0 }), + NonFungibles(approve_item_attributes { collection: 0, item: 0, delegate: ACCOUNT }), + NonFungibles(cancel_item_attributes_approval { + collection: 0, + item: 0, + delegate: ACCOUNT, + witness: CancelAttributesApprovalWitness { account_attributes: 0 }, + }), + NonFungibles(set_max_supply { collection: 0, max_supply: 0 }), + NonFungibles(mint { + to: ACCOUNT, + collection: 0, + item: 0, + witness: MintWitness { mint_price: None, owned_item: None }, + }), + NonFungibles(burn { collection: 0, item: 0 }), + ] + .iter() + { + assert!(Filter::::contains(call)) + } + } + #[test] fn filter_allows_fungibles_reads() { use super::{fungibles::Read::*, RuntimeRead::*}; @@ -245,4 +367,33 @@ mod tests { assert!(Filter::::contains(&read)) } } + + #[test] + fn filter_allows_nonfungibles_reads() { + use super::{nonfungibles::Read::*, RuntimeRead::*}; + + for read in vec![ + NonFungibles(TotalSupply(1)), + NonFungibles(BalanceOf { collection: 1, owner: ACCOUNT }), + NonFungibles(Allowance { + collection: 1, + item: None, + owner: ACCOUNT, + operator: ACCOUNT, + }), + NonFungibles(OwnerOf { collection: 1, item: 1 }), + NonFungibles(GetAttribute { + collection: 0, + item: 0, + namespace: pallet_nfts::AttributeNamespace::CollectionOwner, + key: bounded_vec![], + }), + NonFungibles(Collection(1)), + NonFungibles(NextCollectionId), + ] + .iter() + { + assert!(Filter::::contains(read)) + } + } } diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 326b7e594..28a51d521 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -6,7 +6,7 @@ use frame_support::{ use frame_system::{EnsureRoot, EnsureSigned}; use pallet_nfts::PalletFeatures; use parachains_common::{AssetIdForTrustBackedAssets, CollectionId, ItemId, Signature}; -use sp_runtime::traits::Verify; +use sp_runtime::traits::{Get, Verify}; use crate::{ deposit, AccountId, Assets, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, @@ -37,6 +37,15 @@ parameter_types! { pub const NftsMaxDeadlineDuration: BlockNumber = 12 * 30 * DAYS; } +#[derive(Debug)] +#[cfg_attr(feature = "std", derive(PartialEq, Clone))] +pub struct KeyLimit; +impl Get for KeyLimit { + fn get() -> u32 { + N + } +} + impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ApprovalsLimit = ConstU32<20>; @@ -56,7 +65,7 @@ impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ItemId = ItemId; // TODO: source from primitives - type KeyLimit = ConstU32<64>; + type KeyLimit = KeyLimit<64>; type Locker = (); type MaxAttributesPerCall = ConstU32<10>; type MaxDeadlineDuration = NftsMaxDeadlineDuration; diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index f539cbdee..1d860f626 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -39,7 +39,7 @@ use frame_system::{ limits::{BlockLength, BlockWeights}, EnsureRoot, }; -use pallet_api::fungibles; +use pallet_api::{fungibles, nonfungibles}; use pallet_balances::Call as BalancesCall; use pallet_ismp::mmr::{Leaf, Proof, ProofKeys}; use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; @@ -637,6 +637,8 @@ mod runtime { // Pop API #[runtime::pallet_index(150)] pub type Fungibles = fungibles::Pallet; + #[runtime::pallet_index(151)] + pub type NonFungibles = nonfungibles::Pallet; } #[cfg(feature = "runtime-benchmarks")] @@ -648,6 +650,7 @@ mod benches { [pallet_session, SessionBench::] [pallet_timestamp, Timestamp] [pallet_message_queue, MessageQueue] + [pallet_nfts, Nfts] [pallet_sudo, Sudo] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] From a651c3ec66b9294a28d1635262d0ea7e63fafe66 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 12 Nov 2024 12:42:12 +0700 Subject: [PATCH 22/76] fix: becnhmark helper --- pallets/api/src/mock.rs | 19 +++++++++++++++++++ runtime/devnet/src/config/api/mod.rs | 7 +++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs index 8a4ad27d0..1e6216f54 100644 --- a/pallets/api/src/mock.rs +++ b/pallets/api/src/mock.rs @@ -142,6 +142,25 @@ impl Verify for Noop { } } +#[cfg(feature = "runtime-benchmarks")] +impl pallet_nfts::pallet::BenchmarkHelper for () { + fn collection(i: u16) -> u32 { + i.into() + } + + fn item(i: u16) -> u32 { + i.into() + } + + fn signer() -> (Noop, u64) { + unimplemented!() + } + + fn sign(signer: &Noop, message: &[u8]) -> Noop { + unimplemented!() + } +} + impl pallet_nfts::Config for Test { type ApprovalsLimit = ConstU32<10>; type AttributeDepositBase = ConstU128<1>; diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs index 93f4853f1..b7c332798 100644 --- a/runtime/devnet/src/config/api/mod.rs +++ b/runtime/devnet/src/config/api/mod.rs @@ -2,7 +2,7 @@ use core::marker::PhantomData; use codec::Decode; use cumulus_primitives_core::Weight; -use frame_support::traits::{ConstU32, Contains}; +use frame_support::traits::Contains; pub(crate) use pallet_api::Extension; use pallet_api::{extension::*, Read}; use sp_core::ConstU8; @@ -11,9 +11,8 @@ use sp_std::vec::Vec; use versioning::*; use crate::{ - config::{assets::TrustBackedAssetsInstance, xcm::LocalOriginToLocation}, - fungibles, nonfungibles, Balances, Ismp, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, - RuntimeHoldReason, TransactionByteFee, + config::assets::TrustBackedAssetsInstance, fungibles, nonfungibles, Runtime, RuntimeCall, + RuntimeEvent, }; mod versioning; From ae9ef78ffff6e311913f82729a9107c92ec27477 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:39:46 +0700 Subject: [PATCH 23/76] feat: multi instances & function comments --- pallets/api/src/mock.rs | 7 +- pallets/api/src/nonfungibles/mod.rs | 172 ++++++++++++++++++++++---- pallets/api/src/nonfungibles/tests.rs | 52 ++++---- pallets/api/src/nonfungibles/types.rs | 27 ---- 4 files changed, 186 insertions(+), 72 deletions(-) delete mode 100644 pallets/api/src/nonfungibles/types.rs diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs index 1e6216f54..d11a8c983 100644 --- a/pallets/api/src/mock.rs +++ b/pallets/api/src/mock.rs @@ -32,7 +32,7 @@ frame_support::construct_runtime!( Assets: pallet_assets::, Balances: pallet_balances, Fungibles: crate::fungibles, - Nfts: pallet_nfts, + Nfts: pallet_nfts::, NonFungibles: crate::nonfungibles } ); @@ -161,7 +161,8 @@ impl pallet_nfts::pallet::BenchmarkHelper for () { } } -impl pallet_nfts::Config for Test { +type NftsInstance = pallet_nfts::Instance1; +impl pallet_nfts::Config for Test { type ApprovalsLimit = ConstU32<10>; type AttributeDepositBase = ConstU128<1>; type CollectionDeposit = ConstU128<2>; @@ -191,7 +192,9 @@ impl pallet_nfts::Config for Test { } impl crate::nonfungibles::Config for Test { + type NftsInstance = NftsInstance; type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); } pub(crate) fn new_test_ext() -> sp_io::TestExternalities { diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index 1a5b07b89..b3370a84a 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -2,14 +2,40 @@ //! assets. The goal is to provide a simplified, consistent API that adheres to standards in the //! smart contract space. +use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; +use frame_system::pallet_prelude::BlockNumberFor; pub use pallet::*; use pallet_nfts::WeightInfo; +pub use pallet_nfts::{ + AttributeNamespace, CollectionConfig, CollectionDetails, CollectionSetting, CollectionSettings, + DestroyWitness, ItemDeposit, ItemDetails, ItemSetting, MintSettings, MintType, MintWitness, +}; use sp_runtime::traits::StaticLookup; -pub use types::*; #[cfg(test)] mod tests; -pub mod types; + +type AccountIdOf = ::AccountId; +type NftsOf = pallet_nfts::Pallet>; +type NftsErrorOf = pallet_nfts::Error>; +type NftsWeightInfoOf = >>::WeightInfo; +type NftsInstanceOf = ::NftsInstance; +type BalanceOf = <>>::Currency as Currency< + ::AccountId, +>>::Balance; +type CollectionIdOf = + as Inspect<::AccountId>>::CollectionId; +type ItemIdOf = as Inspect<::AccountId>>::ItemId; +type ItemPriceOf = BalanceOf; +type CollectionDetailsFor = CollectionDetails, BalanceOf>; +type AttributeNamespaceOf = AttributeNamespace>; +type CollectionConfigFor = + CollectionConfig, BlockNumberFor, CollectionIdOf>; +// Type aliases for storage items. +pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId>; +pub(super) type AccountBalanceOf = pallet_nfts::AccountBalance>; +pub(super) type AttributeOf = pallet_nfts::Attribute>; +pub(super) type CollectionOf = pallet_nfts::Collection>; #[frame_support::pallet] pub mod pallet { @@ -18,10 +44,6 @@ pub mod pallet { use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness, MintWitness}; use sp_runtime::BoundedVec; use sp_std::vec::Vec; - use types::{ - AccountIdOf, AttributeNamespaceOf, BalanceOf, CollectionConfigFor, CollectionDetailsFor, - CollectionIdOf, ItemIdOf, ItemPriceOf, NextCollectionIdOf, NftsOf, NftsWeightInfoOf, - }; use super::*; @@ -31,39 +53,64 @@ pub mod pallet { #[repr(u8)] #[allow(clippy::unnecessary_cast)] pub enum Read { - /// Total item supply of a collection. + /// Total item supply of a specified collection. #[codec(index = 0)] TotalSupply(CollectionIdOf), /// Account balance for a specified collection. #[codec(index = 1)] - BalanceOf { collection: CollectionIdOf, owner: AccountIdOf }, + BalanceOf { + // The collection. + collection: CollectionIdOf, + // The owner of the collection . + owner: AccountIdOf, + }, /// Allowance for an operator approved by an owner, for a specified collection or item. #[codec(index = 2)] Allowance { + // The collection. collection: CollectionIdOf, + // The collection item. + item: Option>, + // The owner of the collection item. owner: AccountIdOf, + // The delegated operator of collection item. operator: AccountIdOf, - item: Option>, }, /// Owner of a specified collection item. #[codec(index = 5)] - OwnerOf { collection: CollectionIdOf, item: ItemIdOf }, - /// Attribute value of a collection item. (Error: bounded collection is not partial) + OwnerOf { + // The collection. + collection: CollectionIdOf, + // The collection item. + item: ItemIdOf, + }, + /// Attribute value of a specified collection item. (Error: bounded collection is not + /// partial) #[codec(index = 6)] GetAttribute { + // The collection. collection: CollectionIdOf, + // The collection item. item: ItemIdOf, + // The namespace of the attribute. namespace: AttributeNamespaceOf, + // The key of the attribute. key: BoundedVec, }, - /// Details of a collection. + /// Details of a specified collection. #[codec(index = 9)] Collection(CollectionIdOf), /// Next collection ID. #[codec(index = 10)] NextCollectionId, + /// Metadata of a specified collection item. #[codec(index = 11)] - ItemMetadata { collection: CollectionIdOf, item: ItemIdOf }, + ItemMetadata { + // The collection. + collection: CollectionIdOf, + // The collection item. + item: ItemIdOf, + }, } /// Results of state reads for the non-fungibles API. @@ -78,13 +125,13 @@ pub mod pallet { Allowance(bool), /// Owner of a specified collection owner. OwnerOf(Option>), - /// Attribute value of a collection item. + /// Attribute value of a specified collection item. GetAttribute(Option>), - /// Details of a collection. + /// Details of a specified collection. Collection(Option>), /// Next collection ID. NextCollectionId(Option>), - /// Collection item metadata. + /// Metadata of a specified collection item. ItemMetadata(Option>), } @@ -107,9 +154,13 @@ pub mod pallet { /// Configure the pallet by specifying the parameters and types on which it depends. #[pallet::config] - pub trait Config: frame_system::Config + pallet_nfts::Config { + pub trait Config: frame_system::Config + pallet_nfts::Config { /// Because this pallet emits events, it depends on the runtime's definition of an event. type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// The instance of pallet-nfts. + type NftsInstance; + /// Weight information for dispatchables in this pallet. + type WeightInfo: WeightInfo; } #[pallet::pallet] @@ -159,6 +210,12 @@ pub mod pallet { #[pallet::call] impl Pallet { + /// Transfers the collection item from the caller's account to account `to`. + /// + /// # Parameters + /// - `collection` - The collection of the item to be transferred. + /// - `item` - The item to be transferred. + /// - `to` - The recipient account. #[pallet::call_index(3)] #[pallet::weight(NftsWeightInfoOf::::transfer())] pub fn transfer( @@ -179,6 +236,13 @@ pub mod pallet { Ok(()) } + /// Approves `operator` to spend the collection item on behalf of the caller. + /// + /// # Parameters + /// - `collection` - The collection of the item to be approved for delegated transfer. + /// - `item` - The item to be approved for delegated transfer. + /// - `operator` - The account that is allowed to spend the collection item. + /// - `approved` - The approval status of the collection item. #[pallet::call_index(4)] #[pallet::weight(NftsWeightInfoOf::::approve_transfer() + NftsWeightInfoOf::::cancel_approval())] pub fn approve( @@ -209,6 +273,12 @@ pub mod pallet { Ok(()) } + /// Issue a new collection of non-fungible items from a public origin. + /// + /// # Parameters + /// - `admin` - The admin of this collection. The admin is the initial address of each + /// member of the collection's admin team. + /// - `config` - The configuration of the collection. #[pallet::call_index(7)] #[pallet::weight(NftsWeightInfoOf::::create())] pub fn create( @@ -220,13 +290,19 @@ pub mod pallet { // issues for setting it to xcm's `Location`. This can easily be done differently. let id = NextCollectionIdOf::::get() .or(T::CollectionId::initial_value()) - .ok_or(pallet_nfts::Error::::UnknownCollection)?; + .ok_or(NftsErrorOf::::UnknownCollection)?; let creator = ensure_signed(origin.clone())?; NftsOf::::create(origin, T::Lookup::unlookup(admin.clone()), config)?; Self::deposit_event(Event::Created { id, admin, creator }); Ok(()) } + /// Destroy a collection of fungible items. + /// + /// # Parameters + /// - `collection` - The identifier of the collection to be destroyed. + /// - `witness` - Information on the items minted in the collection. This must be + /// correct. #[pallet::call_index(8)] #[pallet::weight(NftsWeightInfoOf::::destroy( witness.item_metadatas, @@ -241,6 +317,14 @@ pub mod pallet { NftsOf::::destroy(origin, collection, witness) } + /// Set an attribute for a collection or item. + /// + /// # Parameters + /// - `collection` - The collection whose item's metadata to set. + /// - `maybe_item` - The item whose metadata to set. + /// - `namespace` - Attribute's namespace. + /// - `key` - The key of the attribute. + /// - `value` - The value to which to set the attribute. #[pallet::call_index(12)] #[pallet::weight(NftsWeightInfoOf::::set_attribute())] pub fn set_attribute( @@ -254,6 +338,13 @@ pub mod pallet { NftsOf::::set_attribute(origin, collection, item, namespace, key, value) } + /// Clear an attribute for the collection or item. + /// + /// # Parameters + /// - `collection` - The collection whose item's metadata to clear. + /// - `maybe_item` - The item whose metadata to clear. + /// - `namespace` - Attribute's namespace. + /// - `key` - The key of the attribute. #[pallet::call_index(13)] #[pallet::weight(NftsWeightInfoOf::::clear_attribute())] pub fn clear_attribute( @@ -266,6 +357,12 @@ pub mod pallet { NftsOf::::clear_attribute(origin, collection, item, namespace, key) } + /// Set the metadata for an item. + /// + /// # Parameters + /// - `collection` - The collection whose item's metadata to set. + /// - `item` - The item whose metadata to set. + /// - `data` - The general information of this item. Limited in length by `StringLimit`. #[pallet::call_index(14)] #[pallet::weight(NftsWeightInfoOf::::set_metadata())] pub fn set_metadata( @@ -287,6 +384,12 @@ pub mod pallet { NftsOf::::clear_metadata(origin, collection, item) } + /// Approve item's attributes to be changed by a delegated third-party account. + /// + /// # Parameters + /// - `collection` - The collection of the item. + /// - `item` - The item that holds attributes. + /// - `delegate` - The account to delegate permission to change attributes of the item. #[pallet::call_index(16)] #[pallet::weight(NftsWeightInfoOf::::approve_item_attributes())] pub fn approve_item_attributes( @@ -303,6 +406,14 @@ pub mod pallet { ) } + /// Cancel the previously provided approval to change item's attributes. + /// All the previously set attributes by the `delegate` will be removed. + /// + /// # Parameters + /// - `collection` - Collection that the item is contained within. + /// - `item` - The item that holds attributes. + /// - `delegate` - The previously approved account to remove. + /// - `witness` - A witness data to cancel attributes approval operation. #[pallet::call_index(17)] #[pallet::weight(NftsWeightInfoOf::::cancel_item_attributes_approval(witness.account_attributes))] pub fn cancel_item_attributes_approval( @@ -321,6 +432,11 @@ pub mod pallet { ) } + /// Set the maximum number of items a collection could have. + /// + /// # Parameters + /// - `collection` - The identifier of the collection to change. + /// - `max_supply` - The maximum number of items a collection could have. #[pallet::call_index(18)] #[pallet::weight(NftsWeightInfoOf::::set_collection_max_supply())] pub fn set_max_supply( @@ -331,6 +447,15 @@ pub mod pallet { NftsOf::::set_collection_max_supply(origin, collection, max_supply) } + /// Mint an item of a particular collection. + /// + /// # Parameters + /// - `collection` - The collection of the item to be minted. + /// - `item` - An identifier of the new item. + /// - `mint_to` - Account into which the item will be minted. + /// - `witness_data` - When the mint type is `HolderOf(collection_id)`, then the owned + /// item_id from that collection needs to be provided within the witness data object. If + /// the mint price is set, then it should be additionally confirmed in the `witness_data`. #[pallet::call_index(19)] #[pallet::weight(NftsWeightInfoOf::::mint())] pub fn mint( @@ -359,6 +484,11 @@ pub mod pallet { Ok(()) } + /// Destroy a single collection item. + /// + /// # Parameters + /// - `collection` - The collection of the item to be burned. + /// - `item` - The item to be burned. #[pallet::call_index(20)] #[pallet::weight(NftsWeightInfoOf::::burn())] pub fn burn( @@ -405,18 +535,18 @@ pub mod pallet { NftsOf::::collection_items(collection).unwrap_or_default() as u128, ), BalanceOf { collection, owner } => - ReadResult::BalanceOf(pallet_nfts::AccountBalance::::get(collection, owner)), + ReadResult::BalanceOf(AccountBalanceOf::::get(collection, owner)), Allowance { collection, owner, operator, item } => ReadResult::Allowance( NftsOf::::check_allowance(&collection, &item, &owner, &operator).is_ok(), ), OwnerOf { collection, item } => ReadResult::OwnerOf(NftsOf::::owner(collection, item)), GetAttribute { collection, item, namespace, key } => ReadResult::GetAttribute( - pallet_nfts::Attribute::::get((collection, Some(item), namespace, key)) + AttributeOf::::get((collection, Some(item), namespace, key)) .map(|attribute| attribute.0.into()), ), Collection(collection) => - ReadResult::Collection(pallet_nfts::Collection::::get(collection)), + ReadResult::Collection(CollectionOf::::get(collection)), ItemMetadata { collection, item } => ReadResult::ItemMetadata( NftsOf::::item_metadata(collection, item).map(|metadata| metadata.into()), ), diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index 79d484a2f..290f49f23 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -1,22 +1,24 @@ use codec::Encode; -use frame_support::{assert_noop, assert_ok, traits::Incrementable}; -use frame_system::pallet_prelude::BlockNumberFor; -use pallet_nfts::{ - AccountBalance, CollectionConfig, CollectionDetails, CollectionSettings, DestroyWitness, - MintSettings, MintWitness, +use frame_support::{ + assert_noop, assert_ok, + sp_runtime::{BoundedVec, DispatchError::BadOrigin}, + traits::Incrementable, }; -use sp_runtime::{BoundedVec, DispatchError::BadOrigin}; -use super::types::{CollectionIdOf, ItemIdOf}; use crate::{ mock::*, - nonfungibles::{Event, Read::*, ReadResult}, + nonfungibles::{ + AccountBalanceOf, BlockNumberFor, CollectionConfig, CollectionDetails, CollectionIdOf, + CollectionOf, CollectionSettings, DestroyWitness, ItemIdOf, MintSettings, MintWitness, + NextCollectionIdOf, NftsInstanceOf, Read::*, ReadResult, + }, Read, }; const ITEM: u32 = 1; -type NftsError = pallet_nfts::Error; +type NftsError = pallet_nfts::Error>; +type Event = crate::nonfungibles::Event; mod encoding_read_result { use super::*; @@ -116,10 +118,10 @@ fn transfer() { assert_noop!(NonFungibles::transfer(origin, collection, item, dest), BadOrigin); } // Successfully burn an existing new collection item. - let balance_before_transfer = AccountBalance::::get(collection, &dest); + let balance_before_transfer = AccountBalanceOf::::get(collection, &dest); assert_ok!(NonFungibles::transfer(signed(owner), collection, ITEM, dest)); - let balance_after_transfer = AccountBalance::::get(collection, &dest); - assert_eq!(AccountBalance::::get(collection, &owner), 0); + let balance_after_transfer = AccountBalanceOf::::get(collection, &dest); + assert_eq!(AccountBalanceOf::::get(collection, &owner), 0); assert_eq!(balance_after_transfer - balance_before_transfer, 1); System::assert_last_event( Event::Transfer { collection, item, from: Some(owner), to: Some(dest), price: None } @@ -135,7 +137,7 @@ fn mint_works() { let collection = nfts::create_collection(owner); // Successfully mint a new collection item. - let balance_before_mint = AccountBalance::::get(collection, owner); + let balance_before_mint = AccountBalanceOf::::get(collection, owner); assert_ok!(NonFungibles::mint( signed(owner), owner, @@ -143,7 +145,7 @@ fn mint_works() { ITEM, MintWitness { mint_price: None, owned_item: None } )); - let balance_after_mint = AccountBalance::::get(collection, owner); + let balance_after_mint = AccountBalanceOf::::get(collection, owner); assert_eq!(balance_after_mint, 1); assert_eq!(balance_after_mint - balance_before_mint, 1); System::assert_last_event( @@ -233,7 +235,9 @@ fn get_attribute_works() { let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); - let mut result: Option::ValueLimit>> = None; + let mut result: Option< + BoundedVec>>::ValueLimit>, + > = None; // No attribute set. assert_eq!( NonFungibles::read(GetAttribute { @@ -305,7 +309,9 @@ fn clear_attribute_works() { let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); - let result: Option::ValueLimit>> = None; + let result: Option< + BoundedVec>>::ValueLimit>, + > = None; assert_ok!(Nfts::set_attribute( signed(ALICE), collection, @@ -352,7 +358,9 @@ fn approve_item_attribute_works() { attribute.clone(), value.clone() )); - let result: Option::ValueLimit>> = Some(value); + let result: Option< + BoundedVec>>::ValueLimit>, + > = Some(value); assert_eq!( NonFungibles::read(GetAttribute { collection, @@ -411,7 +419,7 @@ fn next_collection_id_works() { assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); assert_eq!( NonFungibles::read(NextCollectionId).encode(), - pallet_nfts::NextCollectionId::::get() + NextCollectionIdOf::::get() .or(CollectionIdOf::::initial_value()) .encode(), ); @@ -441,7 +449,7 @@ fn total_supply_works() { fn create_works() { new_test_ext().execute_with(|| { let owner = ALICE; - let next_collection_id = pallet_nfts::NextCollectionId::::get().unwrap_or_default(); + let next_collection_id = NextCollectionIdOf::::get().unwrap_or_default(); assert_ok!(NonFungibles::create( signed(owner), owner, @@ -474,7 +482,7 @@ fn collection_works() { let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!( NonFungibles::read(Collection(collection)).encode(), - pallet_nfts::Collection::::get(&collection).encode(), + CollectionOf::::get(&collection).encode(), ); }); } @@ -492,7 +500,7 @@ fn balance_of_works() { ); assert_eq!( NonFungibles::read(BalanceOf { collection, owner }).encode(), - AccountBalance::::get(collection, owner).encode() + AccountBalanceOf::::get(collection, owner).encode() ); }); }); @@ -561,7 +569,7 @@ mod nfts { } pub(super) fn next_collection_id() -> u32 { - pallet_nfts::NextCollectionId::::get().unwrap_or_default() + NextCollectionIdOf::::get().unwrap_or_default() } pub(super) fn collection_config_with_all_settings_enabled( diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs deleted file mode 100644 index 6e686389d..000000000 --- a/pallets/api/src/nonfungibles/types.rs +++ /dev/null @@ -1,27 +0,0 @@ -use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; -use frame_system::pallet_prelude::BlockNumberFor; -pub use pallet_nfts::{ - AttributeNamespace, CollectionConfig, CollectionDetails, CollectionSetting, CollectionSettings, - DestroyWitness, ItemDeposit, ItemDetails, ItemSetting, MintSettings, MintType, MintWitness, -}; - -// Type aliases for pallet-nfts. -pub(super) type NftsOf = pallet_nfts::Pallet; -pub(super) type NftsWeightInfoOf = ::WeightInfo; -// Type aliases for pallet-nfts storage items. -pub(super) type AccountIdOf = ::AccountId; -pub(super) type BalanceOf = <>::Currency as Currency< - ::AccountId, ->>::Balance; -pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId; -pub(super) type CollectionIdOf = - as Inspect<::AccountId>>::CollectionId; -pub(super) type ItemIdOf = - as Inspect<::AccountId>>::ItemId; -pub(super) type ItemPriceOf = BalanceOf; -// TODO: Multi-instances. -pub(super) type CollectionDetailsFor = - CollectionDetails, BalanceOf>; -pub(super) type AttributeNamespaceOf = AttributeNamespace>; -pub(super) type CollectionConfigFor = - CollectionConfig, BlockNumberFor, CollectionIdOf>; From 242e53bfd9ba33dfc7b6b74b366297c080232fcd Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:31:33 +0700 Subject: [PATCH 24/76] feat(devnet): pallet nfts instance configuration --- runtime/devnet/src/config/api/mod.rs | 9 ++++--- runtime/devnet/src/config/assets.rs | 8 +++--- runtime/devnet/src/config/proxy.rs | 38 ++++++++++++++-------------- runtime/devnet/src/lib.rs | 2 +- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs index b7c332798..5ea1d9235 100644 --- a/runtime/devnet/src/config/api/mod.rs +++ b/runtime/devnet/src/config/api/mod.rs @@ -11,8 +11,8 @@ use sp_std::vec::Vec; use versioning::*; use crate::{ - config::assets::TrustBackedAssetsInstance, fungibles, nonfungibles, Runtime, RuntimeCall, - RuntimeEvent, + config::assets::{NftsInstance, TrustBackedAssetsInstance}, + fungibles, nonfungibles, Runtime, RuntimeCall, RuntimeEvent, }; mod versioning; @@ -88,7 +88,9 @@ impl fungibles::Config for Runtime { } impl nonfungibles::Config for Runtime { + type NftsInstance = NftsInstance; type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); } #[derive(Default)] @@ -287,8 +289,7 @@ mod tests { #[test] fn filter_allows_nonfungibles_calls() { use pallet_api::nonfungibles::{ - types::{CollectionConfig, CollectionSettings, MintSettings}, - Call::*, + Call::*, CollectionConfig, CollectionSettings, MintSettings, }; use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness}; diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 28a51d521..97c2a9e7d 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -46,7 +46,9 @@ impl Get for KeyLimit { } } -impl pallet_nfts::Config for Runtime { +pub(crate) type NftsInstance = pallet_nfts::Instance1; +pub type NftsCall = pallet_nfts::Call; +impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ApprovalsLimit = ConstU32<20>; type AttributeDepositBase = NftsAttributeDepositBase; @@ -95,8 +97,8 @@ impl pallet_nft_fractionalization::Config for Runtime { type Deposit = AssetDeposit; type NewAssetName = NewAssetName; type NewAssetSymbol = NewAssetSymbol; - type NftCollectionId = ::CollectionId; - type NftId = ::ItemId; + type NftCollectionId = >::CollectionId; + type NftId = >::ItemId; type Nfts = Nfts; type PalletId = NftFractionalizationPalletId; type RuntimeEvent = RuntimeEvent; diff --git a/runtime/devnet/src/config/proxy.rs b/runtime/devnet/src/config/proxy.rs index ff70240e7..161178dc5 100644 --- a/runtime/devnet/src/config/proxy.rs +++ b/runtime/devnet/src/config/proxy.rs @@ -5,7 +5,7 @@ use pop_runtime_common::proxy::{ }; use sp_runtime::traits::BlakeTwo256; -use super::assets::TrustBackedAssetsCall; +use super::assets::{NftsCall, TrustBackedAssetsCall}; use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; impl InstanceFilter for ProxyType { @@ -45,13 +45,13 @@ impl InstanceFilter for ProxyType { RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::transfer_ownership { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_team { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_collection_max_supply { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_collection { .. }) | + RuntimeCall::Nfts(NftsCall::create { .. }) | + RuntimeCall::Nfts(NftsCall::destroy { .. }) | + RuntimeCall::Nfts(NftsCall::redeposit { .. }) | + RuntimeCall::Nfts(NftsCall::transfer_ownership { .. }) | + RuntimeCall::Nfts(NftsCall::set_team { .. }) | + RuntimeCall::Nfts(NftsCall::set_collection_max_supply { .. }) | + RuntimeCall::Nfts(NftsCall::lock_collection { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), @@ -66,17 +66,17 @@ impl InstanceFilter for ProxyType { RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_attributes_pre_signed { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_item_transfer { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::unlock_item_transfer { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_item_properties { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::clear_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_collection_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::clear_collection_metadata { .. }) | + RuntimeCall::Nfts(NftsCall::force_mint { .. }) | + RuntimeCall::Nfts(NftsCall::update_mint_settings { .. }) | + RuntimeCall::Nfts(NftsCall::mint_pre_signed { .. }) | + RuntimeCall::Nfts(NftsCall::set_attributes_pre_signed { .. }) | + RuntimeCall::Nfts(NftsCall::lock_item_transfer { .. }) | + RuntimeCall::Nfts(NftsCall::unlock_item_transfer { .. }) | + RuntimeCall::Nfts(NftsCall::lock_item_properties { .. }) | + RuntimeCall::Nfts(NftsCall::set_metadata { .. }) | + RuntimeCall::Nfts(NftsCall::clear_metadata { .. }) | + RuntimeCall::Nfts(NftsCall::set_collection_metadata { .. }) | + RuntimeCall::Nfts(NftsCall::clear_collection_metadata { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index 1d860f626..839f819dc 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -628,7 +628,7 @@ mod runtime { // Assets #[runtime::pallet_index(50)] - pub type Nfts = pallet_nfts::Pallet; + pub type Nfts = pallet_nfts::Pallet; #[runtime::pallet_index(51)] pub type NftFractionalization = pallet_nft_fractionalization::Pallet; #[runtime::pallet_index(52)] From c69dd85e23f43fa419fa7ecefb9c39bc6f30639b Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Sat, 16 Nov 2024 13:46:04 +0700 Subject: [PATCH 25/76] chore: resolve feedback --- pallets/nfts/Cargo.toml | 5 ++--- pallets/nfts/runtime-api/Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pallets/nfts/Cargo.toml b/pallets/nfts/Cargo.toml index f23b50f00..cf69a164e 100644 --- a/pallets/nfts/Cargo.toml +++ b/pallets/nfts/Cargo.toml @@ -1,6 +1,6 @@ [package] -authors.workspace = true -description = "Fork of FRAME NFTs pallet (polkadot v1.15.0)" +authors = [ "Parity Technologies ", "R0GUE " ] +description = "Fork of FRAME NFTs pallet" edition.workspace = true homepage = "https://substrate.io" license.workspace = true @@ -9,7 +9,6 @@ readme = "README.md" repository.workspace = true version = "31.0.0" - [package.metadata.docs.rs] targets = [ "x86_64-unknown-linux-gnu" ] diff --git a/pallets/nfts/runtime-api/Cargo.toml b/pallets/nfts/runtime-api/Cargo.toml index 17fd68f28..503642ef0 100644 --- a/pallets/nfts/runtime-api/Cargo.toml +++ b/pallets/nfts/runtime-api/Cargo.toml @@ -1,6 +1,6 @@ [package] -authors.workspace = true -description = "Runtime API for the FRAME NFTs pallet. (polkadot v1.15.0)" +authors = [ "Parity Technologies ", "R0GUE " ] +description = "Runtime API for the FRAME NFTs pallet." edition.workspace = true homepage = "https://substrate.io" license = "Apache-2.0" From 5dccecb63e7e4dc3e47268f3549a51038704068a Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Sat, 16 Nov 2024 17:53:09 +0700 Subject: [PATCH 26/76] feat(api/nonfungibles): destroy collection witness data & weights (#383) --- pallets/api/src/nonfungibles/benchmarking.rs | 110 +++ pallets/api/src/nonfungibles/mod.rs | 114 +-- pallets/api/src/nonfungibles/tests.rs | 674 ++++++++++++++---- pallets/api/src/nonfungibles/weights.rs | 217 ++++++ pallets/nfts/src/benchmarking.rs | 62 +- pallets/nfts/src/common_functions.rs | 5 + pallets/nfts/src/features/approvals.rs | 18 + .../src/features/create_delete_collection.rs | 11 +- .../nfts/src/features/create_delete_item.rs | 16 +- pallets/nfts/src/features/transfer.rs | 23 +- pallets/nfts/src/lib.rs | 9 +- pallets/nfts/src/migration.rs | 120 ---- pallets/nfts/src/tests.rs | 50 +- pallets/nfts/src/types.rs | 12 + pallets/nfts/src/weights.rs | 570 ++++++++------- runtime/devnet/src/config/api/mod.rs | 12 +- runtime/devnet/src/config/assets.rs | 10 +- runtime/devnet/src/lib.rs | 1 + 18 files changed, 1442 insertions(+), 592 deletions(-) create mode 100644 pallets/api/src/nonfungibles/benchmarking.rs create mode 100644 pallets/api/src/nonfungibles/weights.rs delete mode 100644 pallets/nfts/src/migration.rs diff --git a/pallets/api/src/nonfungibles/benchmarking.rs b/pallets/api/src/nonfungibles/benchmarking.rs new file mode 100644 index 000000000..45d9d5bd2 --- /dev/null +++ b/pallets/api/src/nonfungibles/benchmarking.rs @@ -0,0 +1,110 @@ +//! Benchmarking setup for pallet_api::nonfungibles + +use frame_benchmarking::{account, v2::*}; +use frame_support::{traits::nonfungibles_v2::Inspect, BoundedVec}; +use sp_runtime::traits::Zero; + +use super::{AttributeNamespace, CollectionIdOf, Config, ItemIdOf, NftsInstanceOf, Pallet, Read}; +use crate::Read as _; + +const SEED: u32 = 1; + +#[benchmarks( + where + > as Inspect<::AccountId>>::ItemId: Zero, + > as Inspect<::AccountId>>::CollectionId: Zero, +)] +mod benchmarks { + use super::*; + + #[benchmark] + // Storage: `Collection` + fn total_supply() { + #[block] + { + Pallet::::read(Read::TotalSupply(CollectionIdOf::::zero())); + } + } + + #[benchmark] + // Storage: `AccountBalance` + fn balance_of() { + #[block] + { + Pallet::::read(Read::BalanceOf { + collection: CollectionIdOf::::zero(), + owner: account("Alice", 0, SEED), + }); + } + } + + #[benchmark] + // Storage: `Allowances`, `Item` + fn allowance() { + #[block] + { + Pallet::::read(Read::Allowance { + collection: CollectionIdOf::::zero(), + owner: account("Alice", 0, SEED), + operator: account("Bob", 0, SEED), + item: Some(ItemIdOf::::zero()), + }); + } + } + + #[benchmark] + // Storage: `Item` + fn owner_of() { + #[block] + { + Pallet::::read(Read::OwnerOf { + collection: CollectionIdOf::::zero(), + item: ItemIdOf::::zero(), + }); + } + } + + #[benchmark] + // Storage: `Attribute` + fn get_attribute() { + #[block] + { + Pallet::::read(Read::GetAttribute { + key: BoundedVec::default(), + collection: CollectionIdOf::::zero(), + item: ItemIdOf::::zero(), + namespace: AttributeNamespace::CollectionOwner, + }); + } + } + + #[benchmark] + // Storage: `Collection` + fn collection() { + #[block] + { + Pallet::::read(Read::Collection(CollectionIdOf::::zero())); + } + } + + #[benchmark] + // Storage: `NextCollectionId` + fn next_collection_id() { + #[block] + { + Pallet::::read(Read::NextCollectionId); + } + } + + #[benchmark] + // Storage: `ItemMetadata` + fn item_metadata() { + #[block] + { + Pallet::::read(Read::ItemMetadata { + collection: CollectionIdOf::::zero(), + item: ItemIdOf::::zero(), + }); + } + } +} diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index b3370a84a..6da7de5f1 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -5,15 +5,20 @@ use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; use frame_system::pallet_prelude::BlockNumberFor; pub use pallet::*; -use pallet_nfts::WeightInfo; +use pallet_nfts::WeightInfo as NftsWeightInfoTrait; pub use pallet_nfts::{ - AttributeNamespace, CollectionConfig, CollectionDetails, CollectionSetting, CollectionSettings, - DestroyWitness, ItemDeposit, ItemDetails, ItemSetting, MintSettings, MintType, MintWitness, + AttributeNamespace, CancelAttributesApprovalWitness, CollectionConfig, CollectionDetails, + CollectionSetting, CollectionSettings, DestroyWitness, ItemDeposit, ItemDetails, ItemMetadata, + ItemSetting, MintSettings, MintType, MintWitness, }; use sp_runtime::traits::StaticLookup; +use weights::WeightInfo; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; #[cfg(test)] mod tests; +pub mod weights; type AccountIdOf = ::AccountId; type NftsOf = pallet_nfts::Pallet>; @@ -31,15 +36,19 @@ type CollectionDetailsFor = CollectionDetails, BalanceOf>; type AttributeNamespaceOf = AttributeNamespace>; type CollectionConfigFor = CollectionConfig, BlockNumberFor, CollectionIdOf>; -// Type aliases for storage items. -pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId>; +// Type aliases for pallet-nfts storage items. pub(super) type AccountBalanceOf = pallet_nfts::AccountBalance>; pub(super) type AttributeOf = pallet_nfts::Attribute>; +pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId>; pub(super) type CollectionOf = pallet_nfts::Collection>; #[frame_support::pallet] pub mod pallet { - use frame_support::{dispatch::DispatchResult, pallet_prelude::*, traits::Incrementable}; + use frame_support::{ + dispatch::{DispatchResult, DispatchResultWithPostInfo, WithPostDispatchInfo}, + pallet_prelude::*, + traits::Incrementable, + }; use frame_system::pallet_prelude::*; use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness, MintWitness}; use sp_runtime::BoundedVec; @@ -59,42 +68,42 @@ pub mod pallet { /// Account balance for a specified collection. #[codec(index = 1)] BalanceOf { - // The collection. + /// The collection. collection: CollectionIdOf, - // The owner of the collection . + /// The owner of the collection . owner: AccountIdOf, }, /// Allowance for an operator approved by an owner, for a specified collection or item. #[codec(index = 2)] Allowance { - // The collection. + /// The collection. collection: CollectionIdOf, - // The collection item. + /// The collection item. item: Option>, - // The owner of the collection item. + /// The owner of the collection item. owner: AccountIdOf, - // The delegated operator of collection item. + /// The delegated operator of collection item. operator: AccountIdOf, }, /// Owner of a specified collection item. #[codec(index = 5)] OwnerOf { - // The collection. + /// The collection. collection: CollectionIdOf, - // The collection item. + /// The collection item. item: ItemIdOf, }, /// Attribute value of a specified collection item. (Error: bounded collection is not /// partial) #[codec(index = 6)] GetAttribute { - // The collection. + /// The collection. collection: CollectionIdOf, - // The collection item. + /// The collection item. item: ItemIdOf, - // The namespace of the attribute. + /// The namespace of the attribute. namespace: AttributeNamespaceOf, - // The key of the attribute. + /// The key of the attribute. key: BoundedVec, }, /// Details of a specified collection. @@ -106,9 +115,9 @@ pub mod pallet { /// Metadata of a specified collection item. #[codec(index = 11)] ItemMetadata { - // The collection. + /// The collection. collection: CollectionIdOf, - // The collection item. + /// The collection item. item: ItemIdOf, }, } @@ -213,8 +222,8 @@ pub mod pallet { /// Transfers the collection item from the caller's account to account `to`. /// /// # Parameters - /// - `collection` - The collection of the item to be transferred. - /// - `item` - The item to be transferred. + /// - `collection` - The collection of the item to transfer. + /// - `item` - The item to transfer. /// - `to` - The recipient account. #[pallet::call_index(3)] #[pallet::weight(NftsWeightInfoOf::::transfer())] @@ -239,38 +248,49 @@ pub mod pallet { /// Approves `operator` to spend the collection item on behalf of the caller. /// /// # Parameters - /// - `collection` - The collection of the item to be approved for delegated transfer. - /// - `item` - The item to be approved for delegated transfer. + /// - `collection` - The collection of the item to approve for a delegated transfer. + /// - `item` - The item to approve for a delegated transfer. /// - `operator` - The account that is allowed to spend the collection item. /// - `approved` - The approval status of the collection item. #[pallet::call_index(4)] - #[pallet::weight(NftsWeightInfoOf::::approve_transfer() + NftsWeightInfoOf::::cancel_approval())] + #[pallet::weight( + NftsWeightInfoOf::::approve_transfer(item.is_some() as u32) + + NftsWeightInfoOf::::cancel_approval(item.is_some() as u32) + )] pub fn approve( origin: OriginFor, collection: CollectionIdOf, item: Option>, operator: AccountIdOf, approved: bool, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { let owner = ensure_signed(origin.clone())?; - if approved { + let weight = if approved { NftsOf::::approve_transfer( origin, collection, item, T::Lookup::unlookup(operator.clone()), None, - )?; + ) + .map_err(|e| { + e.with_weight(NftsWeightInfoOf::::approve_transfer(item.is_some() as u32)) + })?; + NftsWeightInfoOf::::approve_transfer(item.is_some() as u32) } else { NftsOf::::cancel_approval( origin, collection, item, T::Lookup::unlookup(operator.clone()), - )?; - } + ) + .map_err(|e| { + e.with_weight(NftsWeightInfoOf::::cancel_approval(item.is_some() as u32)) + })?; + NftsWeightInfoOf::::cancel_approval(item.is_some() as u32) + }; Self::deposit_event(Event::Approval { collection, item, operator, owner, approved }); - Ok(()) + Ok(Some(weight).into()) } /// Issue a new collection of non-fungible items from a public origin. @@ -286,21 +306,21 @@ pub mod pallet { admin: AccountIdOf, config: CollectionConfigFor, ) -> DispatchResult { + let creator = ensure_signed(origin.clone())?; // TODO: re-evaluate next collection id in nfts pallet. The `Incrementable` trait causes // issues for setting it to xcm's `Location`. This can easily be done differently. let id = NextCollectionIdOf::::get() .or(T::CollectionId::initial_value()) .ok_or(NftsErrorOf::::UnknownCollection)?; - let creator = ensure_signed(origin.clone())?; NftsOf::::create(origin, T::Lookup::unlookup(admin.clone()), config)?; - Self::deposit_event(Event::Created { id, admin, creator }); + Self::deposit_event(Event::Created { id, creator, admin }); Ok(()) } /// Destroy a collection of fungible items. /// /// # Parameters - /// - `collection` - The identifier of the collection to be destroyed. + /// - `collection` - The collection to destroy. /// - `witness` - Information on the items minted in the collection. This must be /// correct. #[pallet::call_index(8)] @@ -308,6 +328,8 @@ pub mod pallet { witness.item_metadatas, witness.item_configs, witness.attributes, + witness.item_holders, + witness.allowances, ))] pub fn destroy( origin: OriginFor, @@ -410,7 +432,7 @@ pub mod pallet { /// All the previously set attributes by the `delegate` will be removed. /// /// # Parameters - /// - `collection` - Collection that the item is contained within. + /// - `collection` - The collection that the item is contained within. /// - `item` - The item that holds attributes. /// - `delegate` - The previously approved account to remove. /// - `witness` - A witness data to cancel attributes approval operation. @@ -450,9 +472,9 @@ pub mod pallet { /// Mint an item of a particular collection. /// /// # Parameters - /// - `collection` - The collection of the item to be minted. + /// - `to` - Account into which the item will be minted. + /// - `collection` - The collection of the item to mint. /// - `item` - An identifier of the new item. - /// - `mint_to` - Account into which the item will be minted. /// - `witness_data` - When the mint type is `HolderOf(collection_id)`, then the owned /// item_id from that collection needs to be provided within the witness data object. If /// the mint price is set, then it should be additionally confirmed in the `witness_data`. @@ -487,8 +509,8 @@ pub mod pallet { /// Destroy a single collection item. /// /// # Parameters - /// - `collection` - The collection of the item to be burned. - /// - `item` - The item to be burned. + /// - `collection` - The collection of the item to burn. + /// - `item` - The item to burn. #[pallet::call_index(20)] #[pallet::weight(NftsWeightInfoOf::::burn())] pub fn burn( @@ -520,8 +542,18 @@ pub mod pallet { /// /// # Parameters /// - `request` - The read request. - fn weight(_request: &Self::Read) -> Weight { - Default::default() + fn weight(request: &Self::Read) -> Weight { + use Read::*; + match request { + TotalSupply(_) => ::WeightInfo::total_supply(), + BalanceOf { .. } => ::WeightInfo::balance_of(), + Allowance { .. } => ::WeightInfo::allowance(), + OwnerOf { .. } => ::WeightInfo::owner_of(), + GetAttribute { .. } => ::WeightInfo::get_attribute(), + Collection(_) => ::WeightInfo::collection(), + ItemMetadata { .. } => ::WeightInfo::item_metadata(), + NextCollectionId => ::WeightInfo::next_collection_id(), + } } /// Performs the requested read and returns the result. diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index 290f49f23..e7866b037 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -2,19 +2,21 @@ use codec::Encode; use frame_support::{ assert_noop, assert_ok, sp_runtime::{BoundedVec, DispatchError::BadOrigin}, - traits::Incrementable, }; +use pallet_nfts::WeightInfo as NftsWeightInfoTrait; use crate::{ mock::*, nonfungibles::{ - AccountBalanceOf, BlockNumberFor, CollectionConfig, CollectionDetails, CollectionIdOf, + AccountBalanceOf, AttributeNamespace, AttributeOf, BlockNumberFor, + CancelAttributesApprovalWitness, CollectionConfig, CollectionDetails, CollectionIdOf, CollectionOf, CollectionSettings, DestroyWitness, ItemIdOf, MintSettings, MintWitness, - NextCollectionIdOf, NftsInstanceOf, Read::*, ReadResult, + NextCollectionIdOf, NftsInstanceOf, NftsWeightInfoOf, Read::*, ReadResult, }, Read, }; +const COLLECTION: u32 = 0; const ITEM: u32 = 1; type NftsError = pallet_nfts::Error>; @@ -71,7 +73,9 @@ mod encoding_read_result { items: 0, item_metadatas: 0, item_configs: 0, + item_holders: 0, attributes: 0, + allowances: 0, }); assert_eq!( ReadResult::Collection::(collection_details.clone()).encode(), @@ -160,9 +164,14 @@ fn burn_works() { new_test_ext().execute_with(|| { let owner = ALICE; + // "UnknownItem" error is returned if collection item is not created. + assert_noop!(NonFungibles::burn(signed(owner), COLLECTION, ITEM), NftsError::UnknownItem); // Successfully burn an existing new collection item. let (collection, item) = nfts::create_collection_mint(owner, ITEM); + let balance_before_burn = AccountBalanceOf::::get(collection, owner); assert_ok!(NonFungibles::burn(signed(owner), collection, ITEM)); + let balance_after_burn = AccountBalanceOf::::get(collection, owner); + assert_eq!(balance_after_burn, balance_before_burn - 1); System::assert_last_event( Event::Transfer { collection, item, from: Some(owner), to: None, price: None }.into(), ); @@ -175,8 +184,12 @@ fn approve_works() { let owner = ALICE; let operator = BOB; let (collection, item) = nfts::create_collection_mint(owner, ITEM); - // Successfully approve `oeprator` to transfer the collection item. - assert_ok!(NonFungibles::approve(signed(owner), collection, Some(item), operator, true)); + // Successfully approve `operator` to transfer the collection item. + assert_eq!( + NonFungibles::approve(signed(owner), collection, Some(item), operator, true), + Ok(Some(NftsWeightInfoOf::::approve_transfer()).into()) + ); + assert_ok!(Nfts::check_allowance(&collection, &Some(item), &owner, &operator)); System::assert_last_event( Event::Approval { collection, item: Some(item), owner, operator, approved: true } .into(), @@ -186,6 +199,26 @@ fn approve_works() { }); } +#[test] +fn approve_collection_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + // Successfully approve `operator` to transfer all items within the collection. + assert_eq!( + NonFungibles::approve(signed(owner), collection, None, operator, true), + Ok(Some(NftsWeightInfoOf::::approve_transfer()).into()) + ); + assert_ok!(Nfts::check_allowance(&collection, &None, &owner, &operator)); + System::assert_last_event( + Event::Approval { collection, item: None, owner, operator, approved: true }.into(), + ); + // Successfully transfer the item by the delegated account `operator`. + assert_ok!(Nfts::transfer(signed(operator), collection, item, operator)); + }); +} + #[test] fn cancel_approval_works() { new_test_ext().execute_with(|| { @@ -193,7 +226,38 @@ fn cancel_approval_works() { let operator = BOB; let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); // Successfully cancel the transfer approval of `operator` by `owner`. - assert_ok!(NonFungibles::approve(signed(owner), collection, Some(item), operator, false)); + assert_eq!( + NonFungibles::approve(signed(owner), collection, Some(item), operator, false), + Ok(Some(NftsWeightInfoOf::::cancel_approval()).into()) + ); + assert_eq!( + Nfts::check_allowance(&collection, &Some(item), &owner, &operator), + Err(NftsError::NoPermission.into()) + ); + // Failed to transfer the item by `operator` without permission. + assert_noop!( + Nfts::transfer(signed(operator), collection, item, operator), + NftsError::NoPermission + ); + }); +} + +#[test] +fn cancel_collection_approval_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + // Successfully cancel the transfer collection approval of `operator` by `owner`. + assert_ok!(Nfts::approve_transfer(signed(owner), collection, None, operator, None)); + assert_eq!( + NonFungibles::approve(signed(owner), collection, None, operator, false), + Ok(Some(NftsWeightInfoOf::::cancel_approval()).into()) + ); + assert_eq!( + Nfts::check_allowance(&collection, &None, &owner, &operator), + Err(NftsError::NoPermission.into()) + ); // Failed to transfer the item by `operator` without permission. assert_noop!( Nfts::transfer(signed(operator), collection, item, operator), @@ -218,60 +282,6 @@ fn set_max_supply_works() { }); } -#[test] -fn owner_of_works() { - new_test_ext().execute_with(|| { - let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); - assert_eq!( - NonFungibles::read(OwnerOf { collection, item }).encode(), - Nfts::owner(collection, item).encode() - ); - }); -} - -#[test] -fn get_attribute_works() { - new_test_ext().execute_with(|| { - let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); - let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); - let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); - let mut result: Option< - BoundedVec>>::ValueLimit>, - > = None; - // No attribute set. - assert_eq!( - NonFungibles::read(GetAttribute { - collection, - item, - namespace: pallet_nfts::AttributeNamespace::CollectionOwner, - key: attribute.clone() - }) - .encode(), - result.encode() - ); - // Successfully get an existing attribute. - result = Some(value.clone()); - assert_ok!(Nfts::set_attribute( - signed(ALICE), - collection, - Some(item), - pallet_nfts::AttributeNamespace::CollectionOwner, - attribute.clone(), - value, - )); - assert_eq!( - NonFungibles::read(GetAttribute { - collection, - item, - namespace: pallet_nfts::AttributeNamespace::CollectionOwner, - key: attribute - }) - .encode(), - result.encode() - ); - }); -} - #[test] fn set_metadata_works() { new_test_ext().execute_with(|| { @@ -316,7 +326,7 @@ fn clear_attribute_works() { signed(ALICE), collection, Some(item), - pallet_nfts::AttributeNamespace::CollectionOwner, + AttributeNamespace::CollectionOwner, attribute.clone(), BoundedVec::truncate_from("some value".as_bytes().to_vec()) )); @@ -325,14 +335,14 @@ fn clear_attribute_works() { signed(ALICE), collection, Some(item), - pallet_nfts::AttributeNamespace::CollectionOwner, + AttributeNamespace::CollectionOwner, attribute.clone(), )); assert_eq!( NonFungibles::read(GetAttribute { collection, item, - namespace: pallet_nfts::AttributeNamespace::CollectionOwner, + namespace: AttributeNamespace::CollectionOwner, key: attribute }) .encode(), @@ -354,7 +364,7 @@ fn approve_item_attribute_works() { signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(BOB), + AttributeNamespace::Account(BOB), attribute.clone(), value.clone() )); @@ -365,7 +375,7 @@ fn approve_item_attribute_works() { NonFungibles::read(GetAttribute { collection, item, - namespace: pallet_nfts::AttributeNamespace::Account(BOB), + namespace: AttributeNamespace::Account(BOB), key: attribute }) .encode(), @@ -387,7 +397,7 @@ fn cancel_item_attribute_approval_works() { signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(BOB), + AttributeNamespace::Account(BOB), attribute.clone(), value.clone() )); @@ -396,14 +406,14 @@ fn cancel_item_attribute_approval_works() { collection, item, BOB, - pallet_nfts::CancelAttributesApprovalWitness { account_attributes: 1 } + CancelAttributesApprovalWitness { account_attributes: 1 } )); assert_noop!( Nfts::set_attribute( signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(BOB), + AttributeNamespace::Account(BOB), attribute.clone(), value.clone() ), @@ -412,78 +422,79 @@ fn cancel_item_attribute_approval_works() { }); } -#[test] -fn next_collection_id_works() { - new_test_ext().execute_with(|| { - let _ = nfts::create_collection_mint(ALICE, ITEM); - assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); - assert_eq!( - NonFungibles::read(NextCollectionId).encode(), - NextCollectionIdOf::::get() - .or(CollectionIdOf::::initial_value()) - .encode(), - ); - }); -} - -#[test] -fn total_supply_works() { - new_test_ext().execute_with(|| { - let owner = ALICE; - let collection = nfts::create_collection(owner); - (0..10).into_iter().for_each(|i| { - assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); - assert_eq!( - NonFungibles::read(TotalSupply(collection)).encode(), - ((i + 1) as u128).encode() - ); - assert_eq!( - NonFungibles::read(TotalSupply(collection)).encode(), - (Nfts::collection_items(collection).unwrap_or_default() as u128).encode() - ); - }); - }); -} - #[test] fn create_works() { new_test_ext().execute_with(|| { - let owner = ALICE; + let creator = ALICE; + let admin = ALICE; let next_collection_id = NextCollectionIdOf::::get().unwrap_or_default(); + for origin in vec![root(), none()] { + assert_noop!( + NonFungibles::create( + origin, + admin, + CollectionConfig { + max_supply: None, + mint_settings: MintSettings::default(), + settings: CollectionSettings::all_enabled() + }, + ), + BadOrigin + ); + } assert_ok!(NonFungibles::create( - signed(owner), - owner, + signed(creator), + admin, CollectionConfig { max_supply: None, mint_settings: MintSettings::default(), settings: CollectionSettings::all_enabled() }, )); - assert_eq!(Nfts::collection_owner(next_collection_id), Some(owner)); + assert_eq!(Nfts::collection_owner(next_collection_id), Some(creator)); + System::assert_last_event(Event::Created { id: next_collection_id, creator, admin }.into()); }); } #[test] fn destroy_works() { new_test_ext().execute_with(|| { - let collection = nfts::create_collection(ALICE); - assert_ok!(NonFungibles::destroy( - signed(ALICE), - collection, - DestroyWitness { item_metadatas: 0, item_configs: 0, attributes: 0 } - )); + let collection = COLLECTION; + let witness = DestroyWitness { + item_metadatas: 0, + item_configs: 0, + item_holders: 0, + attributes: 0, + allowances: 0, + }; + // Check error works for `Nfts::destroy()`. + assert_noop!( + NonFungibles::destroy(signed(ALICE), collection, witness), + NftsError::UnknownCollection + ); + nfts::create_collection(ALICE); + assert_ok!(NonFungibles::destroy(signed(ALICE), collection, witness)); assert_eq!(Nfts::collection_owner(collection), None); }); } #[test] -fn collection_works() { +fn total_supply_works() { new_test_ext().execute_with(|| { - let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); - assert_eq!( - NonFungibles::read(Collection(collection)).encode(), - CollectionOf::::get(&collection).encode(), - ); + let owner = ALICE; + let collection = nfts::create_collection(owner); + assert_eq!(NonFungibles::read(TotalSupply(collection)), ReadResult::TotalSupply(0)); + (0..10).into_iter().for_each(|i| { + assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); + assert_eq!( + NonFungibles::read(TotalSupply(collection)), + ReadResult::TotalSupply((i + 1).into()) + ); + assert_eq!( + NonFungibles::read(TotalSupply(collection)).encode(), + (Nfts::collection_items(collection).unwrap_or_default() as u128).encode() + ); + }); }); } @@ -492,11 +503,15 @@ fn balance_of_works() { new_test_ext().execute_with(|| { let owner = ALICE; let collection = nfts::create_collection(owner); + assert_eq!( + NonFungibles::read(BalanceOf { collection, owner }), + ReadResult::BalanceOf(Default::default()) + ); (0..10).into_iter().for_each(|i| { assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); assert_eq!( - NonFungibles::read(BalanceOf { collection, owner }).encode(), - (i + 1).encode() + NonFungibles::read(BalanceOf { collection, owner }), + ReadResult::BalanceOf(i + 1) ); assert_eq!( NonFungibles::read(BalanceOf { collection, owner }).encode(), @@ -513,9 +528,8 @@ fn allowance_works() { let operator = BOB; let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); assert_eq!( - NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }) - .encode(), - true.encode() + NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }), + ReadResult::Allowance(true) ); assert_eq!( NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }) @@ -527,6 +541,131 @@ fn allowance_works() { }); } +#[test] +fn owner_of_works() { + new_test_ext().execute_with(|| { + assert_eq!( + NonFungibles::read(OwnerOf { collection: COLLECTION, item: ITEM }), + ReadResult::OwnerOf(None) + ); + nfts::create_collection_mint(ALICE, ITEM); + assert_eq!( + NonFungibles::read(OwnerOf { collection: COLLECTION, item: ITEM }), + ReadResult::OwnerOf(Some(ALICE)) + ); + assert_eq!( + NonFungibles::read(OwnerOf { collection: COLLECTION, item: ITEM }).encode(), + Nfts::owner(COLLECTION, ITEM).encode() + ); + }); +} + +#[test] +fn get_attribute_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let raw_value = "some value".as_bytes().to_vec(); + let value = BoundedVec::truncate_from(raw_value.clone()); + let namespace = AttributeNamespace::CollectionOwner; + // No attribute set. + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item, + namespace: namespace.clone(), + key: attribute.clone() + }), + ReadResult::GetAttribute(None) + ); + // Successfully get an existing attribute. + assert_ok!(Nfts::set_attribute( + signed(ALICE), + collection, + Some(item), + namespace.clone(), + attribute.clone(), + value, + )); + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item, + namespace: namespace.clone(), + key: attribute.clone() + }), + ReadResult::GetAttribute(Some(raw_value)) + ); + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item, + namespace: namespace.clone(), + key: attribute.clone() + }) + .encode(), + AttributeOf::::get((collection, Some(item), namespace, attribute)) + .map(|result| result.0) + .encode() + ); + }); +} + +#[test] +fn collection_works() { + new_test_ext().execute_with(|| { + assert_eq!(NonFungibles::read(Collection(COLLECTION)), ReadResult::Collection(None),); + nfts::create_collection_mint(ALICE, ITEM); + assert_eq!( + NonFungibles::read(Collection(COLLECTION)), + ReadResult::Collection(CollectionOf::::get(COLLECTION)), + ); + assert_eq!( + NonFungibles::read(Collection(COLLECTION)).encode(), + CollectionOf::::get(COLLECTION).encode(), + ); + }); +} + +#[test] +fn item_metadata_works() { + new_test_ext().execute_with(|| { + assert_eq!( + NonFungibles::read(ItemMetadata { collection: COLLECTION, item: ITEM }), + ReadResult::ItemMetadata(None) + ); + nfts::create_collection_mint(ALICE, ITEM); + let value = "some metadata".as_bytes().to_vec(); + assert_ok!(NonFungibles::set_metadata( + signed(ALICE), + COLLECTION, + ITEM, + BoundedVec::truncate_from(value.clone()) + )); + assert_eq!( + NonFungibles::read(ItemMetadata { collection: COLLECTION, item: ITEM }), + ReadResult::ItemMetadata(Some(value)) + ); + assert_eq!( + NonFungibles::read(ItemMetadata { collection: COLLECTION, item: ITEM }).encode(), + Nfts::item_metadata(COLLECTION, ITEM).encode() + ); + }); +} + +#[test] +fn next_collection_id_works() { + new_test_ext().execute_with(|| { + assert_eq!(NonFungibles::read(NextCollectionId), ReadResult::NextCollectionId(Some(0))); + nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId), ReadResult::NextCollectionId(Some(1))); + assert_eq!( + NonFungibles::read(NextCollectionId).encode(), + Some(NextCollectionIdOf::::get().unwrap_or_default()).encode(), + ); + }); +} + fn signed(account_id: AccountId) -> RuntimeOrigin { RuntimeOrigin::signed(account_id) } @@ -539,6 +678,7 @@ fn none() -> RuntimeOrigin { RuntimeOrigin::none() } +// Helper functions for interacting with pallet-nfts. mod nfts { use super::*; @@ -559,7 +699,7 @@ mod nfts { } pub(super) fn create_collection(owner: AccountId) -> u32 { - let next_id = next_collection_id(); + let next_id = NextCollectionIdOf::::get().unwrap_or_default(); assert_ok!(Nfts::create( signed(owner), owner, @@ -568,10 +708,6 @@ mod nfts { next_id } - pub(super) fn next_collection_id() -> u32 { - NextCollectionIdOf::::get().unwrap_or_default() - } - pub(super) fn collection_config_with_all_settings_enabled( ) -> CollectionConfig, CollectionIdOf> { CollectionConfig { @@ -581,3 +717,287 @@ mod nfts { } } } + +mod read_weights { + use frame_support::weights::Weight; + + use super::*; + use crate::nonfungibles::{weights::WeightInfo, Config}; + + struct ReadWeightInfo { + total_supply: Weight, + balance_of: Weight, + allowance: Weight, + owner_of: Weight, + get_attribute: Weight, + collection: Weight, + next_collection_id: Weight, + item_metadata: Weight, + } + + impl ReadWeightInfo { + fn new() -> Self { + Self { + total_supply: NonFungibles::weight(&TotalSupply(COLLECTION)), + balance_of: NonFungibles::weight(&BalanceOf { + collection: COLLECTION, + owner: ALICE, + }), + allowance: NonFungibles::weight(&Allowance { + collection: COLLECTION, + item: Some(ITEM), + owner: ALICE, + operator: BOB, + }), + owner_of: NonFungibles::weight(&OwnerOf { collection: COLLECTION, item: ITEM }), + get_attribute: NonFungibles::weight(&GetAttribute { + collection: COLLECTION, + item: ITEM, + namespace: AttributeNamespace::CollectionOwner, + key: BoundedVec::default(), + }), + collection: NonFungibles::weight(&Collection(COLLECTION)), + next_collection_id: NonFungibles::weight(&NextCollectionId), + item_metadata: NonFungibles::weight(&ItemMetadata { + collection: COLLECTION, + item: ITEM, + }), + } + } + } + + #[test] + fn ensure_read_matches_benchmarks() { + let ReadWeightInfo { + allowance, + balance_of, + collection, + get_attribute, + item_metadata, + next_collection_id, + owner_of, + total_supply, + } = ReadWeightInfo::new(); + + assert_eq!(total_supply, ::WeightInfo::total_supply()); + assert_eq!(balance_of, ::WeightInfo::balance_of()); + assert_eq!(allowance, ::WeightInfo::allowance()); + assert_eq!(owner_of, ::WeightInfo::owner_of()); + assert_eq!(get_attribute, ::WeightInfo::get_attribute()); + assert_eq!(collection, ::WeightInfo::collection()); + assert_eq!(next_collection_id, ::WeightInfo::next_collection_id()); + assert_eq!(item_metadata, ::WeightInfo::item_metadata()); + } + + // These types read from the `Collection` storage. + #[test] + fn ensure_collection_variants_match() { + let ReadWeightInfo { total_supply, collection, .. } = ReadWeightInfo::new(); + + assert_eq!(total_supply, collection); + } + + // Proof size is based on `MaxEncodedLen`, not hardware. + // This test ensures that the data structure sizes do not change with upgrades. + #[test] + fn ensure_expected_proof_size_does_not_change() { + let ReadWeightInfo { + allowance, + balance_of, + collection, + get_attribute, + item_metadata, + next_collection_id, + owner_of, + total_supply, + } = ReadWeightInfo::new(); + + // These values come from `weights.rs`. + assert_eq!(total_supply.proof_size(), 3557); + assert_eq!(balance_of.proof_size(), 3529); + assert_eq!(allowance.proof_size(), 4326); + assert_eq!(owner_of.proof_size(), 4326); + assert_eq!(get_attribute.proof_size(), 3944); + assert_eq!(collection.proof_size(), 3557); + assert_eq!(next_collection_id.proof_size(), 1489); + assert_eq!(item_metadata.proof_size(), 3812); + } +} + +mod ensure_codec_indexes { + use super::{Encode, *}; + use crate::{mock::RuntimeCall::NonFungibles, nonfungibles}; + + #[test] + fn ensure_read_variant_indexes() { + [ + (TotalSupply::(Default::default()), 0u8, "TotalSupply"), + ( + BalanceOf:: { collection: Default::default(), owner: Default::default() }, + 1, + "BalanceOf", + ), + ( + Allowance:: { + collection: Default::default(), + item: Default::default(), + owner: Default::default(), + operator: Default::default(), + }, + 2, + "Allowance", + ), + ( + OwnerOf:: { collection: Default::default(), item: Default::default() }, + 5, + "OwnerOf", + ), + ( + GetAttribute:: { + collection: Default::default(), + item: Default::default(), + namespace: AttributeNamespace::CollectionOwner, + key: Default::default(), + }, + 6, + "GetAttribute", + ), + (Collection::(Default::default()), 9, "Collection"), + (NextCollectionId, 10, "NextCollectionId"), + ( + ItemMetadata { collection: Default::default(), item: Default::default() }, + 11, + "ItemMetadata", + ), + ] + .iter() + .for_each(|(variant, expected_index, name)| { + assert_eq!(variant.encode()[0], *expected_index, "{name} variant index changed"); + }) + } + + #[test] + fn ensure_dispatchable_indexes() { + use nonfungibles::Call::*; + + [ + ( + transfer { + collection: Default::default(), + item: Default::default(), + to: Default::default(), + }, + 3u8, + "transfer", + ), + ( + approve { + collection: Default::default(), + item: Default::default(), + operator: Default::default(), + approved: Default::default(), + }, + 4, + "approve", + ), + (create { admin: Default::default(), config: Default::default() }, 7, "create"), + ( + destroy { + collection: Default::default(), + witness: DestroyWitness { + item_metadatas: Default::default(), + item_configs: Default::default(), + item_holders: Default::default(), + attributes: Default::default(), + allowances: Default::default(), + }, + }, + 8, + "destroy", + ), + ( + set_attribute { + collection: Default::default(), + item: Default::default(), + namespace: AttributeNamespace::CollectionOwner, + key: Default::default(), + value: Default::default(), + }, + 12, + "set_attribute", + ), + ( + clear_attribute { + collection: Default::default(), + item: Default::default(), + namespace: AttributeNamespace::CollectionOwner, + key: Default::default(), + }, + 13, + "clear_attribute", + ), + ( + set_metadata { + collection: Default::default(), + item: Default::default(), + data: Default::default(), + }, + 14, + "set_metadata", + ), + ( + clear_metadata { collection: Default::default(), item: Default::default() }, + 15, + "clear_metadata", + ), + ( + approve_item_attributes { + collection: Default::default(), + item: Default::default(), + delegate: Default::default(), + }, + 16, + "approve_item_attributes", + ), + ( + cancel_item_attributes_approval { + collection: Default::default(), + item: Default::default(), + delegate: Default::default(), + witness: CancelAttributesApprovalWitness { + account_attributes: Default::default(), + }, + }, + 17, + "cancel_item_attributes_approval", + ), + ( + set_max_supply { collection: Default::default(), max_supply: Default::default() }, + 18, + "set_max_supply", + ), + ( + mint { + to: Default::default(), + collection: Default::default(), + item: Default::default(), + witness: MintWitness { + owned_item: Default::default(), + mint_price: Default::default(), + }, + }, + 19, + "mint", + ), + (burn { collection: Default::default(), item: Default::default() }, 20, "burn"), + ] + .iter() + .for_each(|(variant, expected_index, name)| { + assert_eq!( + NonFungibles(variant.to_owned()).encode()[1], + *expected_index, + "{name} dispatchable index changed" + ); + }) + } +} diff --git a/pallets/api/src/nonfungibles/weights.rs b/pallets/api/src/nonfungibles/weights.rs new file mode 100644 index 000000000..f0b8fa833 --- /dev/null +++ b/pallets/api/src/nonfungibles/weights.rs @@ -0,0 +1,217 @@ + +//! Autogenerated weights for `nonfungibles` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 40.0.0 +//! DATE: 2024-11-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `R0GUE`, CPU: `` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// ./target/release/pop-node +// benchmark +// pallet +// --chain=dev +// --wasm-execution=compiled +// --pallet=nonfungibles +// --steps=50 +// --repeat=20 +// --json +// --template +// ./scripts/pallet-weights-template.hbs +// --output=./pallets/api/src/nonfungibles/weights.rs +// --extrinsic= + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `nonfungibles`. +pub trait WeightInfo { + fn total_supply() -> Weight; + fn balance_of() -> Weight; + fn allowance() -> Weight; + fn owner_of() -> Weight; + fn get_attribute() -> Weight; + fn collection() -> Weight; + fn next_collection_id() -> Weight; + fn item_metadata() -> Weight; +} + +/// Weights for `nonfungibles` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn total_supply() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + fn balance_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3529` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3529) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Allowances` (r:1 w:0) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn allowance() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(7_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn owner_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + fn get_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3944` + // Minimum execution time: 5_000_000 picoseconds. + Weight::from_parts(5_000_000, 3944) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn collection() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::NextCollectionId` (r:1 w:0) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn next_collection_id() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `1489` + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(1_000_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + fn item_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3812` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3812) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn total_supply() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + fn balance_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3529` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3529) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Allowances` (r:1 w:0) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn allowance() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(7_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn owner_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + fn get_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3944` + // Minimum execution time: 5_000_000 picoseconds. + Weight::from_parts(5_000_000, 3944) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn collection() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::NextCollectionId` (r:1 w:0) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn next_collection_id() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `1489` + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(1_000_000, 1489) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + fn item_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3812` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3812) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } +} + diff --git a/pallets/nfts/src/benchmarking.rs b/pallets/nfts/src/benchmarking.rs index ab66da26d..58209b8bb 100644 --- a/pallets/nfts/src/benchmarking.rs +++ b/pallets/nfts/src/benchmarking.rs @@ -64,6 +64,27 @@ fn add_collection_metadata, I: 'static>() -> (T::AccountId, Account (caller, caller_lookup) } +fn approve_collection, I: 'static>( + index: u32, +) -> (T::AccountId, AccountIdLookupOf) { + let caller = Collection::::get(T::Helper::collection(0)).unwrap().owner; + if caller != whitelisted_caller() { + whitelist_account!(caller); + } + let caller_lookup = T::Lookup::unlookup(caller.clone()); + let delegate: T::AccountId = account("delegate", 0, SEED + index); + let delegate_lookup = T::Lookup::unlookup(delegate.clone()); + let deadline = BlockNumberFor::::max_value(); + assert_ok!(Nfts::::approve_transfer( + SystemOrigin::Signed(caller.clone()).into(), + T::Helper::collection(0), + None, + delegate_lookup.clone(), + Some(deadline), + )); + (caller, caller_lookup) +} + fn mint_item, I: 'static>( index: u16, ) -> (T::ItemId, T::AccountId, AccountIdLookupOf) { @@ -77,7 +98,7 @@ fn mint_item, I: 'static>( let item_exists = Item::::contains_key(&collection, &item); let item_config = ItemConfigOf::::get(&collection, &item); if item_exists { - return (item, caller, caller_lookup) + return (item, caller, caller_lookup); } else if let Some(item_config) = item_config { assert_ok!(Nfts::::force_mint( SystemOrigin::Signed(caller.clone()).into(), @@ -250,6 +271,8 @@ benchmarks_instance_pallet! { let m in 0 .. 1_000; let c in 0 .. 1_000; let a in 0 .. 1_000; + let h in 0 .. 1_000; + let l in 0 .. 1_000; let (collection, caller, _) = create_collection::(); add_collection_metadata::(); @@ -267,6 +290,13 @@ benchmarks_instance_pallet! { for i in 0..a { add_collection_attribute::(i as u16); } + for i in 0..h { + mint_item::(i as u16); + burn_item::(i as u16); + } + for i in 0..l { + approve_collection::(i as u32); + } let witness = Collection::::get(collection).unwrap().destroy_witness(); }: _(SystemOrigin::Signed(caller), collection, witness) verify { @@ -573,27 +603,45 @@ benchmarks_instance_pallet! { } approve_transfer { + let i in 0..1; + let (collection, caller, _) = create_collection::(); let (item, ..) = mint_item::(0); let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); - let deadline = BlockNumberFor::::max_value(); - }: _(SystemOrigin::Signed(caller.clone()), collection, Some(item), delegate_lookup, Some(deadline)) + let maybe_deadline = if i == 0 { + None + } else { + Some(BlockNumberFor::::max_value()) + }; + let maybe_item = if i == 0 { + None + } else { + Some(item) + }; + }: _(SystemOrigin::Signed(caller.clone()), collection, maybe_item, delegate_lookup, maybe_deadline) verify { - assert_last_event::(Event::TransferApproved { collection, item: Some(item), owner: caller, delegate, deadline: Some(deadline) }.into()); + assert_last_event::(Event::TransferApproved { collection, item: maybe_item, owner: caller, delegate, deadline: maybe_deadline }.into()); } cancel_approval { + let i in 0..1; + let (collection, caller, _) = create_collection::(); let (item, ..) = mint_item::(0); let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let origin = SystemOrigin::Signed(caller.clone()).into(); let deadline = BlockNumberFor::::max_value(); - Nfts::::approve_transfer(origin, collection, Some(item), delegate_lookup.clone(), Some(deadline))?; - }: _(SystemOrigin::Signed(caller.clone()), collection, Some(item), delegate_lookup) + let maybe_item = if i == 0 { + None + } else { + Some(item) + }; + Nfts::::approve_transfer(origin, collection, maybe_item, delegate_lookup.clone(), Some(deadline))?; + }: _(SystemOrigin::Signed(caller.clone()), collection, maybe_item, delegate_lookup) verify { - assert_last_event::(Event::ApprovalCancelled { collection, item: Some(item), owner: caller, delegate }.into()); + assert_last_event::(Event::ApprovalCancelled { collection, item: maybe_item, owner: caller, delegate }.into()); } clear_all_transfer_approvals { diff --git a/pallets/nfts/src/common_functions.rs b/pallets/nfts/src/common_functions.rs index 89de1f051..abd8b61d0 100644 --- a/pallets/nfts/src/common_functions.rs +++ b/pallets/nfts/src/common_functions.rs @@ -39,6 +39,11 @@ impl, I: 'static> Pallet { Collection::::get(collection).map(|i| i.items) } + /// Get the allowances to spend items within the collection. + pub fn collection_allowances(collection: T::CollectionId) -> Option { + Collection::::get(collection).map(|i| i.allowances) + } + /// Get the metadata of the collection item. pub fn item_metadata( collection: T::CollectionId, diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index e1e79ef4a..2647492ca 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -195,6 +195,15 @@ impl, I: 'static> Pallet { Allowances::::mutate((&collection, &owner, &delegate), |allowance| { *allowance = true; }); + Collection::::try_mutate( + &collection, + |maybe_collection_details| -> Result<(), DispatchError> { + let collection_details = + maybe_collection_details.as_mut().ok_or(Error::::UnknownCollection)?; + collection_details.allowances.saturating_inc(); + Ok(()) + }, + )?; Self::deposit_event(Event::TransferApproved { collection, @@ -217,6 +226,15 @@ impl, I: 'static> Pallet { ensure!(check_origin == owner, Error::::NoPermission); } Allowances::::remove((&collection, &owner, &delegate)); + Collection::::try_mutate( + &collection, + |maybe_collection_details| -> Result<(), DispatchError> { + let collection_details = + maybe_collection_details.as_mut().ok_or(Error::::UnknownCollection)?; + collection_details.allowances.saturating_dec(); + Ok(()) + }, + )?; Self::deposit_event(Event::ApprovalCancelled { collection, owner, item: None, delegate }); diff --git a/pallets/nfts/src/features/create_delete_collection.rs b/pallets/nfts/src/features/create_delete_collection.rs index b7efd03ac..1d08cd1b6 100644 --- a/pallets/nfts/src/features/create_delete_collection.rs +++ b/pallets/nfts/src/features/create_delete_collection.rs @@ -54,7 +54,9 @@ impl, I: 'static> Pallet { items: 0, item_metadatas: 0, item_configs: 0, + item_holders: 0, attributes: 0, + allowances: 0, }, ); CollectionRoleOf::::insert( @@ -119,6 +121,11 @@ impl, I: 'static> Pallet { collection_details.item_configs == witness.item_configs, Error::::BadWitness ); + ensure!( + collection_details.item_holders == witness.item_holders, + Error::::BadWitness + ); + ensure!(collection_details.allowances == witness.allowances, Error::::BadWitness); for (_, metadata) in ItemMetadataOf::::drain_prefix(&collection) { if let Some(depositor) = metadata.deposit.account { @@ -137,8 +144,6 @@ impl, I: 'static> Pallet { } } - // TODO: Do we need another storage item to keep track of number of holders of a - // collection let _ = AccountBalance::::clear_prefix(collection, collection_details.items, None); let _ = Allowances::::clear_prefix((collection,), collection_details.items, None); @@ -152,7 +157,9 @@ impl, I: 'static> Pallet { Ok(DestroyWitness { item_metadatas: collection_details.item_metadatas, item_configs: collection_details.item_configs, + item_holders: collection_details.item_holders, attributes: collection_details.attributes, + allowances: collection_details.allowances, }) }) } diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index cc29f8dab..a7b7ddf38 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -69,9 +69,15 @@ impl, I: 'static> Pallet { } collection_details.items.saturating_inc(); - AccountBalance::::mutate(collection, &mint_to, |balance| { - balance.saturating_inc(); - }); + + let account_balance = + AccountBalance::::mutate(collection, &mint_to, |balance| -> u32 { + balance.saturating_inc(); + balance.clone() + }); + if account_balance == 1 { + collection_details.item_holders.saturating_inc(); + } let collection_config = Self::get_collection_config(&collection)?; let deposit_amount = match collection_config @@ -257,6 +263,10 @@ impl, I: 'static> Pallet { } } + if AccountBalance::::get(collection, &details.owner) == 1 { + collection_details.item_holders.saturating_dec(); + } + Ok(details.owner) }, )?; diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index 3b25b0145..dbe6f3b09 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -54,7 +54,7 @@ impl, I: 'static> Pallet { ) -> DispatchResult, ) -> DispatchResult { // Retrieve collection details. - let collection_details = + let mut collection_details = Collection::::get(&collection).ok_or(Error::::UnknownCollection)?; // Ensure the item is not locked. @@ -87,13 +87,23 @@ impl, I: 'static> Pallet { // Perform the transfer with custom details using the provided closure. with_details(&collection_details, &mut details)?; - // Update account balances. - AccountBalance::::mutate(collection, &details.owner, |balance| { - balance.saturating_dec(); - }); - AccountBalance::::mutate(collection, &dest, |balance| { + // Update account balance of the owner. + let owner_balance = + AccountBalance::::mutate(collection, &details.owner, |balance| -> u32 { + balance.saturating_dec(); + balance.clone() + }); + if owner_balance == 0 { + collection_details.item_holders.saturating_dec(); + } + // Update account balance of the destination account. + let dest_balance = AccountBalance::::mutate(collection, &dest, |balance| -> u32 { balance.saturating_inc(); + balance.clone() }); + if dest_balance == 1 { + collection_details.item_holders.saturating_inc(); + } // Update account ownership information. Account::::remove((&details.owner, &collection, &item)); @@ -108,6 +118,7 @@ impl, I: 'static> Pallet { // Update item details. Item::::insert(&collection, &item, &details); + Collection::::insert(&collection, &collection_details); ItemPriceOf::::remove(&collection, &item); PendingSwapOf::::remove(&collection, &item); diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index bc8b67b61..37e8b29cc 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -30,7 +30,6 @@ #[cfg(feature = "runtime-benchmarks")] mod benchmarking; -pub mod migration; #[cfg(test)] pub mod mock; #[cfg(test)] @@ -832,6 +831,8 @@ pub mod pallet { witness.item_metadatas, witness.item_configs, witness.attributes, + witness.item_holders, + witness.allowances, ))] pub fn destroy( origin: OriginFor, @@ -847,6 +848,8 @@ pub mod pallet { details.item_metadatas, details.item_configs, details.attributes, + details.item_holders, + details.allowances, )) .into()) } @@ -1311,7 +1314,7 @@ pub mod pallet { /// /// Weight: `O(1)` #[pallet::call_index(15)] - #[pallet::weight(T::WeightInfo::approve_transfer())] + #[pallet::weight(T::WeightInfo::approve_transfer(maybe_item.is_some() as u32))] pub fn approve_transfer( origin: OriginFor, collection: T::CollectionId, @@ -1350,7 +1353,7 @@ pub mod pallet { /// /// Weight: `O(1)` #[pallet::call_index(16)] - #[pallet::weight(T::WeightInfo::cancel_approval())] + #[pallet::weight(T::WeightInfo::cancel_approval(maybe_item.is_some() as u32))] pub fn cancel_approval( origin: OriginFor, collection: T::CollectionId, diff --git a/pallets/nfts/src/migration.rs b/pallets/nfts/src/migration.rs deleted file mode 100644 index af611bf16..000000000 --- a/pallets/nfts/src/migration.rs +++ /dev/null @@ -1,120 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use frame_support::traits::OnRuntimeUpgrade; -use log; -#[cfg(feature = "try-runtime")] -use sp_runtime::TryRuntimeError; - -use super::*; - -pub mod v1 { - use frame_support::{pallet_prelude::*, weights::Weight}; - - use super::*; - - #[derive(Decode)] - pub struct OldCollectionDetails { - pub owner: AccountId, - pub owner_deposit: DepositBalance, - pub items: u32, - pub item_metadatas: u32, - pub attributes: u32, - } - - impl OldCollectionDetails { - /// Migrates the old collection details to the new v1 format. - fn migrate_to_v1(self, item_configs: u32) -> CollectionDetails { - CollectionDetails { - owner: self.owner, - owner_deposit: self.owner_deposit, - items: self.items, - item_metadatas: self.item_metadatas, - item_configs, - attributes: self.attributes, - } - } - } - - /// A migration utility to update the storage version from v0 to v1 for the pallet. - pub struct MigrateToV1(core::marker::PhantomData); - impl OnRuntimeUpgrade for MigrateToV1 { - fn on_runtime_upgrade() -> Weight { - let in_code_version = Pallet::::in_code_storage_version(); - let on_chain_version = Pallet::::on_chain_storage_version(); - - log::info!( - target: LOG_TARGET, - "Running migration with in-code storage version {:?} / onchain {:?}", - in_code_version, - on_chain_version - ); - - if on_chain_version == 0 && in_code_version == 1 { - let mut translated = 0u64; - let mut configs_iterated = 0u64; - Collection::::translate::< - OldCollectionDetails>, - _, - >(|key, old_value| { - let item_configs = ItemConfigOf::::iter_prefix(&key).count() as u32; - configs_iterated += item_configs as u64; - translated.saturating_inc(); - Some(old_value.migrate_to_v1(item_configs)) - }); - - in_code_version.put::>(); - - log::info!( - target: LOG_TARGET, - "Upgraded {} records, storage to version {:?}", - translated, - in_code_version - ); - T::DbWeight::get().reads_writes(translated + configs_iterated + 1, translated + 1) - } else { - log::info!( - target: LOG_TARGET, - "Migration did not execute. This probably should be removed" - ); - T::DbWeight::get().reads(1) - } - } - - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - let prev_count = Collection::::iter().count(); - Ok((prev_count as u32).encode()) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(prev_count: Vec) -> Result<(), TryRuntimeError> { - let prev_count: u32 = Decode::decode(&mut prev_count.as_slice()).expect( - "the state parameter should be something that was generated by pre_upgrade", - ); - let post_count = Collection::::iter().count() as u32; - ensure!( - prev_count == post_count, - "the records count before and after the migration should be the same" - ); - - ensure!(Pallet::::on_chain_storage_version() >= 1, "wrong storage version"); - - Ok(()) - } - } -} diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 4d0f08c93..6d0c894aa 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -165,6 +165,7 @@ fn basic_minting_should_work() { assert_eq!(collections(), vec![(account(1), 0)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); assert_eq!(AccountBalance::::get(0, account(1)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(items(), vec![(account(1), 0, 42)]); assert_ok!(Nfts::force_create( @@ -175,10 +176,37 @@ fn basic_minting_should_work() { assert_eq!(collections(), vec![(account(1), 0), (account(2), 1)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(2)), 1, 69, account(1), None)); assert_eq!(AccountBalance::::get(1, account(1)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(items(), vec![(account(1), 0, 42), (account(1), 1, 69)]); }); } +#[test] +fn collection_item_holders_should_works() { + new_test_ext().execute_with(|| { + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_eq!(collections(), vec![(account(1), 0)]); + let total = 5; + for i in 0..total { + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, i, account(1), None)); + } + assert_eq!(AccountBalance::::get(0, account(1)), total); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); + + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, total, account(2), None)); + assert_eq!(AccountBalance::::get(0, account(2)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 2); + + assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(2)), 0, total)); + assert_eq!(AccountBalance::::get(0, account(2)), 0); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); + }); +} + #[test] fn lifecycle_should_work() { new_test_ext().execute_with(|| { @@ -223,6 +251,7 @@ fn lifecycle_should_work() { assert_eq!(Collection::::get(0).unwrap().items, 3); assert_eq!(Collection::::get(0).unwrap().item_metadatas, 0); assert_eq!(Collection::::get(0).unwrap().item_configs, 3); + assert_eq!(Collection::::get(0).unwrap().item_holders, 3); assert_eq!(Balances::reserved_balance(&account(1)), 8); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 70, account(2))); @@ -317,6 +346,7 @@ fn destroy_should_work() { assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(2), None)); assert_eq!(AccountBalance::::get(0, account(2)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(1)), 0, @@ -360,6 +390,7 @@ fn mint_should_work() { assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); assert_eq!(AccountBalance::::get(0, account(1)), 1); assert_eq!(Nfts::owner(0, 42).unwrap(), account(1)); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(collections(), vec![(account(1), 0)]); assert_eq!(items(), vec![(account(1), 0, 42)]); @@ -425,6 +456,7 @@ fn mint_should_work() { Some(MintWitness { mint_price: Some(1), ..Default::default() }) )); assert_eq!(AccountBalance::::get(0, account(2)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 2); assert_eq!(Balances::total_balance(&account(2)), 99); // validate types @@ -464,6 +496,7 @@ fn mint_should_work() { Some(MintWitness { owned_item: Some(43), ..Default::default() }) )); assert_eq!(AccountBalance::::get(1, account(2)), 1); + assert_eq!(Collection::::get(1).unwrap().item_holders, 1); assert!(events().contains(&Event::::PalletAttributeSet { collection: 0, item: Some(43), @@ -500,10 +533,11 @@ fn transfer_should_work() { account(2), default_item_config() )); - + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); assert_eq!(AccountBalance::::get(0, account(2)), 0); assert_eq!(AccountBalance::::get(0, account(3)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(items(), vec![(account(3), 0, 42)]); assert_noop!( Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4)), @@ -521,6 +555,7 @@ fn transfer_should_work() { assert_eq!(AccountBalance::::get(0, account(2)), 0); assert_eq!(AccountBalance::::get(0, account(3)), 0); assert_eq!(AccountBalance::::get(0, account(4)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); // validate we can't transfer non-transferable items let collection_id = 1; assert_ok!(Nfts::force_create( @@ -1775,6 +1810,7 @@ fn burn_works() { default_item_config() )); assert_eq!(AccountBalance::::get(0, account(5)), 2); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(Balances::reserved_balance(account(1)), 2); assert_noop!( @@ -1783,8 +1819,10 @@ fn burn_works() { ); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 42)); assert_eq!(AccountBalance::::get(0, account(5)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 69)); assert_eq!(AccountBalance::::get(0, account(5)), 0); + assert_eq!(Collection::::get(0).unwrap().item_holders, 0); assert_eq!(Balances::reserved_balance(account(1)), 0); }); } @@ -2036,6 +2074,7 @@ fn cancel_approval_collection_works_with_admin() { delegate: account(3) })); assert_eq!(Allowances::::get((0, account(2), account(3))), false); + assert_eq!(Nfts::collection_allowances(0).unwrap(), 0); assert_noop!( Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4)), @@ -2192,6 +2231,7 @@ fn approval_collection_works_with_admin() { deadline: None })); assert_eq!(Allowances::::get((0, account(1), account(3))), true); + assert_eq!(Nfts::collection_allowances(0).unwrap(), 1); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4))); }); } @@ -4114,7 +4154,13 @@ fn clear_collection_metadata_works() { assert_ok!(Nfts::destroy( RuntimeOrigin::signed(account(1)), 0, - DestroyWitness { item_configs: 0, item_metadatas: 0, attributes: 0 } + DestroyWitness { + item_configs: 0, + item_metadatas: 0, + attributes: 0, + allowances: 0, + item_holders: 0 + } )); assert_eq!(Collection::::get(0), None); assert_eq!(Balances::reserved_balance(&account(1)), 10); diff --git a/pallets/nfts/src/types.rs b/pallets/nfts/src/types.rs index 941da6cad..46148d63d 100644 --- a/pallets/nfts/src/types.rs +++ b/pallets/nfts/src/types.rs @@ -104,8 +104,12 @@ pub struct CollectionDetails { pub item_metadatas: u32, /// The total number of outstanding item configs of this collection. pub item_configs: u32, + /// The total number of accounts that hold items of the collection. + pub item_holders: u32, /// The total number of attributes for this collection. pub attributes: u32, + /// The total number of allowances to spend all items within collections. + pub allowances: u32, } /// Witness data for the destroy transactions. @@ -117,9 +121,15 @@ pub struct DestroyWitness { /// The total number of outstanding item configs of this collection. #[codec(compact)] pub item_configs: u32, + /// The total number of accounts that hold items of the collection. + #[codec(compact)] + pub item_holders: u32, /// The total number of attributes for this collection. #[codec(compact)] pub attributes: u32, + /// The total number of allowances to spend all items within collections. + #[codec(compact)] + pub allowances: u32, } impl CollectionDetails { @@ -127,7 +137,9 @@ impl CollectionDetails { DestroyWitness { item_metadatas: self.item_metadatas, item_configs: self.item_configs, + item_holders: self.item_holders, attributes: self.attributes, + allowances: self.allowances, } } } diff --git a/pallets/nfts/src/weights.rs b/pallets/nfts/src/weights.rs index c374d6dbc..b33075032 100644 --- a/pallets/nfts/src/weights.rs +++ b/pallets/nfts/src/weights.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `pallet_nfts` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 40.0.0 -//! DATE: 2024-10-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-11-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `R0GUE`, CPU: `` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` @@ -36,7 +36,7 @@ use core::marker::PhantomData; pub trait WeightInfo { fn create() -> Weight; fn force_create() -> Weight; - fn destroy(m: u32, c: u32, a: u32, ) -> Weight; + fn destroy(m: u32, c: u32, a: u32, h: u32, l: u32, ) -> Weight; fn mint() -> Weight; fn force_mint() -> Weight; fn burn() -> Weight; @@ -59,8 +59,8 @@ pub trait WeightInfo { fn clear_metadata() -> Weight; fn set_collection_metadata() -> Weight; fn clear_collection_metadata() -> Weight; - fn approve_transfer() -> Weight; - fn cancel_approval() -> Weight; + fn approve_transfer(i: u32, ) -> Weight; + fn cancel_approval(i: u32, ) -> Weight; fn clear_all_transfer_approvals() -> Weight; fn set_accept_ownership() -> Weight; fn set_collection_max_supply() -> Weight; @@ -81,7 +81,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::NextCollectionId` (r:1 w:1) /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) @@ -91,16 +91,16 @@ impl WeightInfo for SubstrateWeight { fn create() -> Weight { // Proof Size summary in bytes: // Measured: `105` - // Estimated: `3549` - // Minimum execution time: 27_000_000 picoseconds. - Weight::from_parts(27_000_000, 3549) + // Estimated: `3557` + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(29_000_000, 3557) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::NextCollectionId` (r:1 w:1) /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) @@ -110,14 +110,14 @@ impl WeightInfo for SubstrateWeight { fn force_create() -> Weight { // Proof Size summary in bytes: // Measured: `3` - // Estimated: `3549` - // Minimum execution time: 14_000_000 picoseconds. - Weight::from_parts(15_000_000, 3549) + // Estimated: `3557` + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(15_000_000, 3557) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) @@ -126,6 +126,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:0) /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:1 w:0) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) @@ -137,19 +139,17 @@ impl WeightInfo for SubstrateWeight { /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. - fn destroy(m: u32, c: u32, a: u32, ) -> Weight { + /// The range of component `h` is `[0, 1000]`. + /// The range of component `l` is `[0, 1000]`. + fn destroy(_m: u32, _c: u32, a: u32, _h: u32, _l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32216 + a * (366 ±0)` + // Measured: `32875 + a * (366 ±0)` // Estimated: `2523990 + a * (2954 ±0)` // Minimum execution time: 982_000_000 picoseconds. - Weight::from_parts(937_587_516, 2523990) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(34_348, 0).saturating_mul(m.into())) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(23_800, 0).saturating_mul(c.into())) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(5_095_505, 0).saturating_mul(a.into())) - .saturating_add(T::DbWeight::get().reads(1005_u64)) + Weight::from_parts(4_613_129_128, 2523990) + // Standard Error: 125_087 + .saturating_add(Weight::from_parts(5_072_767, 0).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(1006_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(1005_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) @@ -160,7 +160,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) @@ -171,10 +171,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: - // Measured: `382` + // Measured: `390` // Estimated: `4326` - // Minimum execution time: 41_000_000 picoseconds. - Weight::from_parts(42_000_000, 4326) + // Minimum execution time: 40_000_000 picoseconds. + Weight::from_parts(41_000_000, 4326) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -183,7 +183,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) @@ -194,10 +194,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn force_mint() -> Weight { // Proof Size summary in bytes: - // Measured: `382` + // Measured: `390` // Estimated: `4326` // Minimum execution time: 39_000_000 picoseconds. - Weight::from_parts(40_000_000, 4326) + Weight::from_parts(39_000_000, 4326) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -206,7 +206,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) @@ -223,15 +223,15 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: - // Measured: `576` + // Measured: `584` // Estimated: `4326` - // Minimum execution time: 46_000_000 picoseconds. - Weight::from_parts(59_000_000, 4326) + // Minimum execution time: 45_000_000 picoseconds. + Weight::from_parts(46_000_000, 4326) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -250,15 +250,15 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `605` + // Measured: `613` // Estimated: `6068` // Minimum execution time: 38_000_000 picoseconds. - Weight::from_parts(83_000_000, 6068) + Weight::from_parts(38_000_000, 6068) .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:5000 w:5000) @@ -266,12 +266,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `690 + i * (108 ±0)` - // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 3549) - // Standard Error: 20_022 - .saturating_add(Weight::from_parts(16_005_327, 0).saturating_mul(i.into())) + // Measured: `698 + i * (108 ±0)` + // Estimated: `3557 + i * (3336 ±0)` + // Minimum execution time: 10_000_000 picoseconds. + Weight::from_parts(11_000_000, 3557) + // Standard Error: 30_743 + .saturating_add(Weight::from_parts(15_569_470, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -285,7 +285,7 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3534` - // Minimum execution time: 13_000_000 picoseconds. + // Minimum execution time: 14_000_000 picoseconds. Weight::from_parts(14_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) @@ -298,35 +298,35 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3534` - // Minimum execution time: 14_000_000 picoseconds. + // Minimum execution time: 13_000_000 picoseconds. Weight::from_parts(14_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn lock_collection() -> Weight { // Proof Size summary in bytes: - // Measured: `267` - // Estimated: `3549` + // Measured: `275` + // Estimated: `3557` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 3549) + Weight::from_parts(11_000_000, 3557) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionAccount` (r:0 w:2) /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `417` + // Measured: `425` // Estimated: `3593` // Minimum execution time: 18_000_000 picoseconds. Weight::from_parts(19_000_000, 3593) @@ -334,12 +334,12 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:2 w:4) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: - // Measured: `296` + // Measured: `304` // Estimated: `6078` // Minimum execution time: 30_000_000 picoseconds. Weight::from_parts(31_000_000, 6078) @@ -347,28 +347,28 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionAccount` (r:0 w:2) /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: - // Measured: `238` - // Estimated: `3549` + // Measured: `246` + // Estimated: `3557` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(12_000_000, 3549) + Weight::from_parts(12_000_000, 3557) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn force_collection_config() -> Weight { // Proof Size summary in bytes: // Measured: `203` - // Estimated: `3549` + // Estimated: `3557` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(9_000_000, 3549) + Weight::from_parts(9_000_000, 3557) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -386,7 +386,7 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -397,20 +397,20 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `499` + // Measured: `507` // Estimated: `3944` - // Minimum execution time: 37_000_000 picoseconds. - Weight::from_parts(38_000_000, 3944) + // Minimum execution time: 38_000_000 picoseconds. + Weight::from_parts(39_000_000, 3944) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:1) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `271` + // Measured: `279` // Estimated: `3944` // Minimum execution time: 19_000_000 picoseconds. Weight::from_parts(19_000_000, 3944) @@ -424,13 +424,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `943` + // Measured: `951` // Estimated: `3944` // Minimum execution time: 35_000_000 picoseconds. - Weight::from_parts(36_000_000, 3944) + Weight::from_parts(37_000_000, 3944) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -462,8 +462,8 @@ impl WeightInfo for SubstrateWeight { // Estimated: `4466 + n * (2954 ±0)` // Minimum execution time: 18_000_000 picoseconds. Weight::from_parts(19_000_000, 4466) - // Standard Error: 6_379 - .saturating_add(Weight::from_parts(5_018_740, 0).saturating_mul(n.into())) + // Standard Error: 10_431 + .saturating_add(Weight::from_parts(4_776_454, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -473,7 +473,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -482,7 +482,7 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `499` + // Measured: `507` // Estimated: `3812` // Minimum execution time: 30_000_000 picoseconds. Weight::from_parts(31_000_000, 3812) @@ -494,15 +494,15 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `809` + // Measured: `817` // Estimated: `3812` - // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(29_000_000, 3812) + // Minimum execution time: 29_000_000 picoseconds. + Weight::from_parts(30_000_000, 3812) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -511,32 +511,32 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `325` + // Measured: `333` // Estimated: `3759` // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(30_000_000, 3759) + Weight::from_parts(28_000_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `643` + // Measured: `651` // Estimated: `3759` // Minimum execution time: 27_000_000 picoseconds. - Weight::from_parts(29_000_000, 3759) + Weight::from_parts(28_000_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -544,25 +544,37 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - fn approve_transfer() -> Weight { - // Proof Size summary in bytes: - // Measured: `337` - // Estimated: `4326` - // Minimum execution time: 13_000_000 picoseconds. - Weight::from_parts(14_000_000, 4326) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:1 w:1) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 1]`. + fn approve_transfer(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `308 + i * (29 ±0)` + // Estimated: `3574 + i * (2163 ±0)` + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(16_969_387, 3574) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 2163).saturating_mul(i.into())) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - fn cancel_approval() -> Weight { - // Proof Size summary in bytes: - // Measured: `345` - // Estimated: `4326` + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:0 w:1) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 1]`. + fn cancel_approval(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `312 + i * (33 ±0)` + // Estimated: `3557 + i * (2163 ±0)` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(12_000_000, 4326) + Weight::from_parts(14_000_000, 3557) .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 2163).saturating_mul(i.into())) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -582,20 +594,20 @@ impl WeightInfo for SubstrateWeight { // Measured: `3` // Estimated: `3517` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(10_000_000, 3517) + Weight::from_parts(9_000_000, 3517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: - // Measured: `267` - // Estimated: `3549` + // Measured: `275` + // Estimated: `3557` // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 3549) + Weight::from_parts(13_000_000, 3557) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -608,7 +620,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `250` // Estimated: `3538` // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 3538) + Weight::from_parts(12_000_000, 3538) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -624,8 +636,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `478` // Estimated: `4326` - // Minimum execution time: 16_000_000 picoseconds. - Weight::from_parts(17_000_000, 4326) + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(16_000_000, 4326) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -633,8 +645,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:1 w:1) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -649,12 +661,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn buy_item() -> Weight { // Proof Size summary in bytes: - // Measured: `717` + // Measured: `725` // Estimated: `6068` - // Minimum execution time: 42_000_000 picoseconds. - Weight::from_parts(45_000_000, 6068) + // Minimum execution time: 43_000_000 picoseconds. + Weight::from_parts(44_000_000, 6068) .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) } /// The range of component `n` is `[0, 10]`. fn pay_tips(n: u32, ) -> Weight { @@ -662,9 +674,9 @@ impl WeightInfo for SubstrateWeight { // Measured: `0` // Estimated: `0` // Minimum execution time: 1_000_000 picoseconds. - Weight::from_parts(390_532, 0) - // Standard Error: 84_277 - .saturating_add(Weight::from_parts(3_087_492, 0).saturating_mul(n.into())) + Weight::from_parts(2_101_372, 0) + // Standard Error: 5_552 + .saturating_add(Weight::from_parts(1_704_563, 0).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:2 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -674,8 +686,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `421` // Estimated: `7662` - // Minimum execution time: 14_000_000 picoseconds. - Weight::from_parts(15_000_000, 7662) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(14_000_000, 7662) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -687,7 +699,7 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `440` // Estimated: `4326` - // Minimum execution time: 14_000_000 picoseconds. + // Minimum execution time: 13_000_000 picoseconds. Weight::from_parts(14_000_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) @@ -696,8 +708,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:1 w:2) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:2 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -712,12 +724,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn claim_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `907` + // Measured: `915` // Estimated: `7662` - // Minimum execution time: 75_000_000 picoseconds. - Weight::from_parts(77_000_000, 7662) + // Minimum execution time: 78_000_000 picoseconds. + Weight::from_parts(79_000_000, 7662) .saturating_add(T::DbWeight::get().reads(11_u64)) - .saturating_add(T::DbWeight::get().writes(12_u64)) + .saturating_add(T::DbWeight::get().writes(13_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -726,7 +738,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) @@ -742,12 +754,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `485` + // Measured: `493` // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 100_000_000 picoseconds. - Weight::from_parts(107_476_765, 6078) - // Standard Error: 61_259 - .saturating_add(Weight::from_parts(27_610_007, 0).saturating_mul(n.into())) + // Minimum execution time: 101_000_000 picoseconds. + Weight::from_parts(102_689_064, 6078) + // Standard Error: 25_175 + .saturating_add(Weight::from_parts(27_553_304, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(7_u64)) @@ -761,7 +773,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:10 w:10) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -769,12 +781,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `514` + // Measured: `522` // Estimated: `4466 + n * (2954 ±0)` - // Minimum execution time: 51_000_000 picoseconds. - Weight::from_parts(57_358_180, 4466) - // Standard Error: 54_968 - .saturating_add(Weight::from_parts(27_429_606, 0).saturating_mul(n.into())) + // Minimum execution time: 50_000_000 picoseconds. + Weight::from_parts(55_735_551, 4466) + // Standard Error: 34_490 + .saturating_add(Weight::from_parts(26_799_214, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -788,7 +800,7 @@ impl WeightInfo for () { /// Storage: `Nfts::NextCollectionId` (r:1 w:1) /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) @@ -798,16 +810,16 @@ impl WeightInfo for () { fn create() -> Weight { // Proof Size summary in bytes: // Measured: `105` - // Estimated: `3549` - // Minimum execution time: 27_000_000 picoseconds. - Weight::from_parts(27_000_000, 3549) + // Estimated: `3557` + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(29_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::NextCollectionId` (r:1 w:1) /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) @@ -817,14 +829,14 @@ impl WeightInfo for () { fn force_create() -> Weight { // Proof Size summary in bytes: // Measured: `3` - // Estimated: `3549` - // Minimum execution time: 14_000_000 picoseconds. - Weight::from_parts(15_000_000, 3549) + // Estimated: `3557` + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(15_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) @@ -833,6 +845,8 @@ impl WeightInfo for () { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:0) /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:1 w:0) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) @@ -844,19 +858,17 @@ impl WeightInfo for () { /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. - fn destroy(m: u32, c: u32, a: u32, ) -> Weight { + /// The range of component `h` is `[0, 1000]`. + /// The range of component `l` is `[0, 1000]`. + fn destroy(_m: u32, _c: u32, a: u32, _h: u32, _l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32216 + a * (366 ±0)` + // Measured: `32875 + a * (366 ±0)` // Estimated: `2523990 + a * (2954 ±0)` // Minimum execution time: 982_000_000 picoseconds. - Weight::from_parts(937_587_516, 2523990) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(34_348, 0).saturating_mul(m.into())) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(23_800, 0).saturating_mul(c.into())) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(5_095_505, 0).saturating_mul(a.into())) - .saturating_add(RocksDbWeight::get().reads(1005_u64)) + Weight::from_parts(4_613_129_128, 2523990) + // Standard Error: 125_087 + .saturating_add(Weight::from_parts(5_072_767, 0).saturating_mul(a.into())) + .saturating_add(RocksDbWeight::get().reads(1006_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(RocksDbWeight::get().writes(1005_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(a.into()))) @@ -867,7 +879,7 @@ impl WeightInfo for () { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) @@ -878,10 +890,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: - // Measured: `382` + // Measured: `390` // Estimated: `4326` - // Minimum execution time: 41_000_000 picoseconds. - Weight::from_parts(42_000_000, 4326) + // Minimum execution time: 40_000_000 picoseconds. + Weight::from_parts(41_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -890,7 +902,7 @@ impl WeightInfo for () { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) @@ -901,10 +913,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn force_mint() -> Weight { // Proof Size summary in bytes: - // Measured: `382` + // Measured: `390` // Estimated: `4326` // Minimum execution time: 39_000_000 picoseconds. - Weight::from_parts(40_000_000, 4326) + Weight::from_parts(39_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -913,7 +925,7 @@ impl WeightInfo for () { /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) @@ -930,15 +942,15 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: - // Measured: `576` + // Measured: `584` // Estimated: `4326` - // Minimum execution time: 46_000_000 picoseconds. - Weight::from_parts(59_000_000, 4326) + // Minimum execution time: 45_000_000 picoseconds. + Weight::from_parts(46_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -957,15 +969,15 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `605` + // Measured: `613` // Estimated: `6068` // Minimum execution time: 38_000_000 picoseconds. - Weight::from_parts(83_000_000, 6068) + Weight::from_parts(38_000_000, 6068) .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:5000 w:5000) @@ -973,12 +985,12 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `690 + i * (108 ±0)` - // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 3549) - // Standard Error: 20_022 - .saturating_add(Weight::from_parts(16_005_327, 0).saturating_mul(i.into())) + // Measured: `698 + i * (108 ±0)` + // Estimated: `3557 + i * (3336 ±0)` + // Minimum execution time: 10_000_000 picoseconds. + Weight::from_parts(11_000_000, 3557) + // Standard Error: 30_743 + .saturating_add(Weight::from_parts(15_569_470, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -992,7 +1004,7 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3534` - // Minimum execution time: 13_000_000 picoseconds. + // Minimum execution time: 14_000_000 picoseconds. Weight::from_parts(14_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) @@ -1005,35 +1017,35 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3534` - // Minimum execution time: 14_000_000 picoseconds. + // Minimum execution time: 13_000_000 picoseconds. Weight::from_parts(14_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn lock_collection() -> Weight { // Proof Size summary in bytes: - // Measured: `267` - // Estimated: `3549` + // Measured: `275` + // Estimated: `3557` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 3549) + Weight::from_parts(11_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionAccount` (r:0 w:2) /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `417` + // Measured: `425` // Estimated: `3593` // Minimum execution time: 18_000_000 picoseconds. Weight::from_parts(19_000_000, 3593) @@ -1041,12 +1053,12 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:2 w:4) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: - // Measured: `296` + // Measured: `304` // Estimated: `6078` // Minimum execution time: 30_000_000 picoseconds. Weight::from_parts(31_000_000, 6078) @@ -1054,28 +1066,28 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionAccount` (r:0 w:2) /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: - // Measured: `238` - // Estimated: `3549` + // Measured: `246` + // Estimated: `3557` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(12_000_000, 3549) + Weight::from_parts(12_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn force_collection_config() -> Weight { // Proof Size summary in bytes: // Measured: `203` - // Estimated: `3549` + // Estimated: `3557` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(9_000_000, 3549) + Weight::from_parts(9_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1093,7 +1105,7 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -1104,20 +1116,20 @@ impl WeightInfo for () { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `499` + // Measured: `507` // Estimated: `3944` - // Minimum execution time: 37_000_000 picoseconds. - Weight::from_parts(38_000_000, 3944) + // Minimum execution time: 38_000_000 picoseconds. + Weight::from_parts(39_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:1) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `271` + // Measured: `279` // Estimated: `3944` // Minimum execution time: 19_000_000 picoseconds. Weight::from_parts(19_000_000, 3944) @@ -1131,13 +1143,13 @@ impl WeightInfo for () { /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `943` + // Measured: `951` // Estimated: `3944` // Minimum execution time: 35_000_000 picoseconds. - Weight::from_parts(36_000_000, 3944) + Weight::from_parts(37_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1169,8 +1181,8 @@ impl WeightInfo for () { // Estimated: `4466 + n * (2954 ±0)` // Minimum execution time: 18_000_000 picoseconds. Weight::from_parts(19_000_000, 4466) - // Standard Error: 6_379 - .saturating_add(Weight::from_parts(5_018_740, 0).saturating_mul(n.into())) + // Standard Error: 10_431 + .saturating_add(Weight::from_parts(4_776_454, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -1180,7 +1192,7 @@ impl WeightInfo for () { /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -1189,7 +1201,7 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `499` + // Measured: `507` // Estimated: `3812` // Minimum execution time: 30_000_000 picoseconds. Weight::from_parts(31_000_000, 3812) @@ -1201,15 +1213,15 @@ impl WeightInfo for () { /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `809` + // Measured: `817` // Estimated: `3812` - // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(29_000_000, 3812) + // Minimum execution time: 29_000_000 picoseconds. + Weight::from_parts(30_000_000, 3812) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1218,32 +1230,32 @@ impl WeightInfo for () { /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `325` + // Measured: `333` // Estimated: `3759` // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(30_000_000, 3759) + Weight::from_parts(28_000_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `643` + // Measured: `651` // Estimated: `3759` // Minimum execution time: 27_000_000 picoseconds. - Weight::from_parts(29_000_000, 3759) + Weight::from_parts(28_000_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1251,25 +1263,37 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - fn approve_transfer() -> Weight { - // Proof Size summary in bytes: - // Measured: `337` - // Estimated: `4326` - // Minimum execution time: 13_000_000 picoseconds. - Weight::from_parts(14_000_000, 4326) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:1 w:1) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 1]`. + fn approve_transfer(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `308 + i * (29 ±0)` + // Estimated: `3574 + i * (2163 ±0)` + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(16_969_387, 3574) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 2163).saturating_mul(i.into())) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - fn cancel_approval() -> Weight { - // Proof Size summary in bytes: - // Measured: `345` - // Estimated: `4326` + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:0 w:1) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 1]`. + fn cancel_approval(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `312 + i * (33 ±0)` + // Estimated: `3557 + i * (2163 ±0)` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(12_000_000, 4326) + Weight::from_parts(14_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 2163).saturating_mul(i.into())) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -1289,20 +1313,20 @@ impl WeightInfo for () { // Measured: `3` // Estimated: `3517` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(10_000_000, 3517) + Weight::from_parts(9_000_000, 3517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: - // Measured: `267` - // Estimated: `3549` + // Measured: `275` + // Estimated: `3557` // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 3549) + Weight::from_parts(13_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1315,7 +1339,7 @@ impl WeightInfo for () { // Measured: `250` // Estimated: `3538` // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 3538) + Weight::from_parts(12_000_000, 3538) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1331,8 +1355,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `478` // Estimated: `4326` - // Minimum execution time: 16_000_000 picoseconds. - Weight::from_parts(17_000_000, 4326) + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(16_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1340,8 +1364,8 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:1 w:1) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -1356,12 +1380,12 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn buy_item() -> Weight { // Proof Size summary in bytes: - // Measured: `717` + // Measured: `725` // Estimated: `6068` - // Minimum execution time: 42_000_000 picoseconds. - Weight::from_parts(45_000_000, 6068) + // Minimum execution time: 43_000_000 picoseconds. + Weight::from_parts(44_000_000, 6068) .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) } /// The range of component `n` is `[0, 10]`. fn pay_tips(n: u32, ) -> Weight { @@ -1369,9 +1393,9 @@ impl WeightInfo for () { // Measured: `0` // Estimated: `0` // Minimum execution time: 1_000_000 picoseconds. - Weight::from_parts(390_532, 0) - // Standard Error: 84_277 - .saturating_add(Weight::from_parts(3_087_492, 0).saturating_mul(n.into())) + Weight::from_parts(2_101_372, 0) + // Standard Error: 5_552 + .saturating_add(Weight::from_parts(1_704_563, 0).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:2 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -1381,8 +1405,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `421` // Estimated: `7662` - // Minimum execution time: 14_000_000 picoseconds. - Weight::from_parts(15_000_000, 7662) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(14_000_000, 7662) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1394,7 +1418,7 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `440` // Estimated: `4326` - // Minimum execution time: 14_000_000 picoseconds. + // Minimum execution time: 13_000_000 picoseconds. Weight::from_parts(14_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) @@ -1403,8 +1427,8 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:1 w:2) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:2 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -1419,12 +1443,12 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn claim_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `907` + // Measured: `915` // Estimated: `7662` - // Minimum execution time: 75_000_000 picoseconds. - Weight::from_parts(77_000_000, 7662) + // Minimum execution time: 78_000_000 picoseconds. + Weight::from_parts(79_000_000, 7662) .saturating_add(RocksDbWeight::get().reads(11_u64)) - .saturating_add(RocksDbWeight::get().writes(12_u64)) + .saturating_add(RocksDbWeight::get().writes(13_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -1433,7 +1457,7 @@ impl WeightInfo for () { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) @@ -1449,12 +1473,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `485` + // Measured: `493` // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 100_000_000 picoseconds. - Weight::from_parts(107_476_765, 6078) - // Standard Error: 61_259 - .saturating_add(Weight::from_parts(27_610_007, 0).saturating_mul(n.into())) + // Minimum execution time: 101_000_000 picoseconds. + Weight::from_parts(102_689_064, 6078) + // Standard Error: 25_175 + .saturating_add(Weight::from_parts(27_553_304, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(7_u64)) @@ -1468,7 +1492,7 @@ impl WeightInfo for () { /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:10 w:10) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -1476,16 +1500,16 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `514` + // Measured: `522` // Estimated: `4466 + n * (2954 ±0)` - // Minimum execution time: 51_000_000 picoseconds. - Weight::from_parts(57_358_180, 4466) - // Standard Error: 54_968 - .saturating_add(Weight::from_parts(27_429_606, 0).saturating_mul(n.into())) + // Minimum execution time: 50_000_000 picoseconds. + Weight::from_parts(55_735_551, 4466) + // Standard Error: 34_490 + .saturating_add(Weight::from_parts(26_799_214, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } -} \ No newline at end of file +} diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs index 5ea1d9235..d96fd85bd 100644 --- a/runtime/devnet/src/config/api/mod.rs +++ b/runtime/devnet/src/config/api/mod.rs @@ -11,7 +11,7 @@ use sp_std::vec::Vec; use versioning::*; use crate::{ - config::assets::{NftsInstance, TrustBackedAssetsInstance}, + config::assets::{TrustBackedAssetsInstance, TrustBackedNftsInstance}, fungibles, nonfungibles, Runtime, RuntimeCall, RuntimeEvent, }; @@ -88,7 +88,7 @@ impl fungibles::Config for Runtime { } impl nonfungibles::Config for Runtime { - type NftsInstance = NftsInstance; + type NftsInstance = TrustBackedNftsInstance; type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } @@ -311,7 +311,13 @@ mod tests { }), NonFungibles(destroy { collection: 0, - witness: DestroyWitness { attributes: 0, item_configs: 0, item_metadatas: 0 }, + witness: DestroyWitness { + attributes: 0, + item_configs: 0, + item_metadatas: 0, + item_holders: 0, + allowances: 0, + }, }), NonFungibles(set_attribute { collection: 0, diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 97c2a9e7d..43f889904 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -46,9 +46,9 @@ impl Get for KeyLimit { } } -pub(crate) type NftsInstance = pallet_nfts::Instance1; -pub type NftsCall = pallet_nfts::Call; -impl pallet_nfts::Config for Runtime { +pub(crate) type TrustBackedNftsInstance = pallet_nfts::Instance1; +pub type NftsCall = pallet_nfts::Call; +impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ApprovalsLimit = ConstU32<20>; type AttributeDepositBase = NftsAttributeDepositBase; @@ -97,8 +97,8 @@ impl pallet_nft_fractionalization::Config for Runtime { type Deposit = AssetDeposit; type NewAssetName = NewAssetName; type NewAssetSymbol = NewAssetSymbol; - type NftCollectionId = >::CollectionId; - type NftId = >::ItemId; + type NftCollectionId = >::CollectionId; + type NftId = >::ItemId; type Nfts = Nfts; type PalletId = NftFractionalizationPalletId; type RuntimeEvent = RuntimeEvent; diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index 839f819dc..736f0be73 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -646,6 +646,7 @@ mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] [fungibles, Fungibles] + [nonfungibles, NonFungibles] [pallet_balances, Balances] [pallet_session, SessionBench::] [pallet_timestamp, Timestamp] From 488be7575d47ee5006394f7746ce0c83f37da7db Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Sat, 16 Nov 2024 23:00:22 +0700 Subject: [PATCH 27/76] chore: rename nfts instance --- Cargo.lock | 20 +++++++-------- runtime/devnet/src/config/assets.rs | 2 +- runtime/devnet/src/config/proxy.rs | 38 ++++++++++++++--------------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 71903ca0c..48f7b34c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7366,7 +7366,7 @@ dependencies = [ "log", "pallet-assets", "pallet-balances", - "pallet-nfts 0.1.0", + "pallet-nfts 31.0.0", "parity-scale-codec", "pop-chain-extension", "scale-info", @@ -8240,39 +8240,39 @@ dependencies = [ [[package]] name = "pallet-nfts" -version = "0.1.0" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e1cd476809de3840e19091a083d5a79178af1f108ad489706e1f9e04c8836a4" dependencies = [ "enumflags2", "frame-benchmarking", "frame-support", "frame-system", "log", - "pallet-balances", "parity-scale-codec", "scale-info", "sp-core", "sp-io", - "sp-keystore", "sp-runtime", + "sp-std", ] [[package]] name = "pallet-nfts" -version = "30.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e1cd476809de3840e19091a083d5a79178af1f108ad489706e1f9e04c8836a4" +version = "31.0.0" dependencies = [ "enumflags2", "frame-benchmarking", "frame-support", "frame-system", "log", + "pallet-balances", "parity-scale-codec", "scale-info", "sp-core", "sp-io", + "sp-keystore", "sp-runtime", - "sp-std", ] [[package]] @@ -10857,7 +10857,7 @@ dependencies = [ "pallet-message-queue", "pallet-multisig", "pallet-nft-fractionalization", - "pallet-nfts 0.1.0", + "pallet-nfts 31.0.0", "pallet-nfts-runtime-api", "pallet-preimage", "pallet-proxy", @@ -11002,7 +11002,7 @@ dependencies = [ "pallet-message-queue", "pallet-multisig", "pallet-nft-fractionalization", - "pallet-nfts 0.1.0", + "pallet-nfts 31.0.0", "pallet-nfts-runtime-api", "pallet-preimage", "pallet-proxy", diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 43f889904..65405ea46 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -47,7 +47,7 @@ impl Get for KeyLimit { } pub(crate) type TrustBackedNftsInstance = pallet_nfts::Instance1; -pub type NftsCall = pallet_nfts::Call; +pub type TrustBackedNftsCall = pallet_nfts::Call; impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ApprovalsLimit = ConstU32<20>; diff --git a/runtime/devnet/src/config/proxy.rs b/runtime/devnet/src/config/proxy.rs index 161178dc5..486530276 100644 --- a/runtime/devnet/src/config/proxy.rs +++ b/runtime/devnet/src/config/proxy.rs @@ -5,7 +5,7 @@ use pop_runtime_common::proxy::{ }; use sp_runtime::traits::BlakeTwo256; -use super::assets::{NftsCall, TrustBackedAssetsCall}; +use super::assets::{TrustBackedAssetsCall, TrustBackedNftsCall}; use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; impl InstanceFilter for ProxyType { @@ -45,13 +45,13 @@ impl InstanceFilter for ProxyType { RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) | - RuntimeCall::Nfts(NftsCall::create { .. }) | - RuntimeCall::Nfts(NftsCall::destroy { .. }) | - RuntimeCall::Nfts(NftsCall::redeposit { .. }) | - RuntimeCall::Nfts(NftsCall::transfer_ownership { .. }) | - RuntimeCall::Nfts(NftsCall::set_team { .. }) | - RuntimeCall::Nfts(NftsCall::set_collection_max_supply { .. }) | - RuntimeCall::Nfts(NftsCall::lock_collection { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::create { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::destroy { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::redeposit { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::transfer_ownership { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_team { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_collection_max_supply { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_collection { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), @@ -66,17 +66,17 @@ impl InstanceFilter for ProxyType { RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) | - RuntimeCall::Nfts(NftsCall::force_mint { .. }) | - RuntimeCall::Nfts(NftsCall::update_mint_settings { .. }) | - RuntimeCall::Nfts(NftsCall::mint_pre_signed { .. }) | - RuntimeCall::Nfts(NftsCall::set_attributes_pre_signed { .. }) | - RuntimeCall::Nfts(NftsCall::lock_item_transfer { .. }) | - RuntimeCall::Nfts(NftsCall::unlock_item_transfer { .. }) | - RuntimeCall::Nfts(NftsCall::lock_item_properties { .. }) | - RuntimeCall::Nfts(NftsCall::set_metadata { .. }) | - RuntimeCall::Nfts(NftsCall::clear_metadata { .. }) | - RuntimeCall::Nfts(NftsCall::set_collection_metadata { .. }) | - RuntimeCall::Nfts(NftsCall::clear_collection_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::force_mint { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::update_mint_settings { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::mint_pre_signed { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_attributes_pre_signed { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_item_transfer { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::unlock_item_transfer { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_item_properties { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::clear_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_collection_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::clear_collection_metadata { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), From 5dbc1b701fafeabe24cbbe6228a29c600f160a06 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Sat, 16 Nov 2024 17:53:09 +0700 Subject: [PATCH 28/76] feat(api/nonfungibles): destroy collection witness data & weights (#383) chore: rename nfts instance feat(api/nonfungibles): destroy collection witness data & weights (#383) chore: rename nfts instance fix(api/nonfungibles): pallet weight testing --- Cargo.lock | 20 +- pallets/api/src/nonfungibles/benchmarking.rs | 110 +++ pallets/api/src/nonfungibles/mod.rs | 114 +-- pallets/api/src/nonfungibles/tests.rs | 674 ++++++++++++++---- pallets/api/src/nonfungibles/weights.rs | 217 ++++++ pallets/nfts/src/benchmarking.rs | 62 +- pallets/nfts/src/common_functions.rs | 5 + pallets/nfts/src/features/approvals.rs | 18 + .../src/features/create_delete_collection.rs | 11 +- .../nfts/src/features/create_delete_item.rs | 16 +- pallets/nfts/src/features/transfer.rs | 23 +- pallets/nfts/src/lib.rs | 9 +- pallets/nfts/src/migration.rs | 120 ---- pallets/nfts/src/tests.rs | 50 +- pallets/nfts/src/types.rs | 12 + pallets/nfts/src/weights.rs | 570 ++++++++------- runtime/devnet/src/config/api/mod.rs | 12 +- runtime/devnet/src/config/assets.rs | 10 +- runtime/devnet/src/config/proxy.rs | 38 +- runtime/devnet/src/lib.rs | 1 + 20 files changed, 1471 insertions(+), 621 deletions(-) create mode 100644 pallets/api/src/nonfungibles/benchmarking.rs create mode 100644 pallets/api/src/nonfungibles/weights.rs delete mode 100644 pallets/nfts/src/migration.rs diff --git a/Cargo.lock b/Cargo.lock index 71903ca0c..48f7b34c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7366,7 +7366,7 @@ dependencies = [ "log", "pallet-assets", "pallet-balances", - "pallet-nfts 0.1.0", + "pallet-nfts 31.0.0", "parity-scale-codec", "pop-chain-extension", "scale-info", @@ -8240,39 +8240,39 @@ dependencies = [ [[package]] name = "pallet-nfts" -version = "0.1.0" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e1cd476809de3840e19091a083d5a79178af1f108ad489706e1f9e04c8836a4" dependencies = [ "enumflags2", "frame-benchmarking", "frame-support", "frame-system", "log", - "pallet-balances", "parity-scale-codec", "scale-info", "sp-core", "sp-io", - "sp-keystore", "sp-runtime", + "sp-std", ] [[package]] name = "pallet-nfts" -version = "30.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e1cd476809de3840e19091a083d5a79178af1f108ad489706e1f9e04c8836a4" +version = "31.0.0" dependencies = [ "enumflags2", "frame-benchmarking", "frame-support", "frame-system", "log", + "pallet-balances", "parity-scale-codec", "scale-info", "sp-core", "sp-io", + "sp-keystore", "sp-runtime", - "sp-std", ] [[package]] @@ -10857,7 +10857,7 @@ dependencies = [ "pallet-message-queue", "pallet-multisig", "pallet-nft-fractionalization", - "pallet-nfts 0.1.0", + "pallet-nfts 31.0.0", "pallet-nfts-runtime-api", "pallet-preimage", "pallet-proxy", @@ -11002,7 +11002,7 @@ dependencies = [ "pallet-message-queue", "pallet-multisig", "pallet-nft-fractionalization", - "pallet-nfts 0.1.0", + "pallet-nfts 31.0.0", "pallet-nfts-runtime-api", "pallet-preimage", "pallet-proxy", diff --git a/pallets/api/src/nonfungibles/benchmarking.rs b/pallets/api/src/nonfungibles/benchmarking.rs new file mode 100644 index 000000000..45d9d5bd2 --- /dev/null +++ b/pallets/api/src/nonfungibles/benchmarking.rs @@ -0,0 +1,110 @@ +//! Benchmarking setup for pallet_api::nonfungibles + +use frame_benchmarking::{account, v2::*}; +use frame_support::{traits::nonfungibles_v2::Inspect, BoundedVec}; +use sp_runtime::traits::Zero; + +use super::{AttributeNamespace, CollectionIdOf, Config, ItemIdOf, NftsInstanceOf, Pallet, Read}; +use crate::Read as _; + +const SEED: u32 = 1; + +#[benchmarks( + where + > as Inspect<::AccountId>>::ItemId: Zero, + > as Inspect<::AccountId>>::CollectionId: Zero, +)] +mod benchmarks { + use super::*; + + #[benchmark] + // Storage: `Collection` + fn total_supply() { + #[block] + { + Pallet::::read(Read::TotalSupply(CollectionIdOf::::zero())); + } + } + + #[benchmark] + // Storage: `AccountBalance` + fn balance_of() { + #[block] + { + Pallet::::read(Read::BalanceOf { + collection: CollectionIdOf::::zero(), + owner: account("Alice", 0, SEED), + }); + } + } + + #[benchmark] + // Storage: `Allowances`, `Item` + fn allowance() { + #[block] + { + Pallet::::read(Read::Allowance { + collection: CollectionIdOf::::zero(), + owner: account("Alice", 0, SEED), + operator: account("Bob", 0, SEED), + item: Some(ItemIdOf::::zero()), + }); + } + } + + #[benchmark] + // Storage: `Item` + fn owner_of() { + #[block] + { + Pallet::::read(Read::OwnerOf { + collection: CollectionIdOf::::zero(), + item: ItemIdOf::::zero(), + }); + } + } + + #[benchmark] + // Storage: `Attribute` + fn get_attribute() { + #[block] + { + Pallet::::read(Read::GetAttribute { + key: BoundedVec::default(), + collection: CollectionIdOf::::zero(), + item: ItemIdOf::::zero(), + namespace: AttributeNamespace::CollectionOwner, + }); + } + } + + #[benchmark] + // Storage: `Collection` + fn collection() { + #[block] + { + Pallet::::read(Read::Collection(CollectionIdOf::::zero())); + } + } + + #[benchmark] + // Storage: `NextCollectionId` + fn next_collection_id() { + #[block] + { + Pallet::::read(Read::NextCollectionId); + } + } + + #[benchmark] + // Storage: `ItemMetadata` + fn item_metadata() { + #[block] + { + Pallet::::read(Read::ItemMetadata { + collection: CollectionIdOf::::zero(), + item: ItemIdOf::::zero(), + }); + } + } +} diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index b3370a84a..6da7de5f1 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -5,15 +5,20 @@ use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; use frame_system::pallet_prelude::BlockNumberFor; pub use pallet::*; -use pallet_nfts::WeightInfo; +use pallet_nfts::WeightInfo as NftsWeightInfoTrait; pub use pallet_nfts::{ - AttributeNamespace, CollectionConfig, CollectionDetails, CollectionSetting, CollectionSettings, - DestroyWitness, ItemDeposit, ItemDetails, ItemSetting, MintSettings, MintType, MintWitness, + AttributeNamespace, CancelAttributesApprovalWitness, CollectionConfig, CollectionDetails, + CollectionSetting, CollectionSettings, DestroyWitness, ItemDeposit, ItemDetails, ItemMetadata, + ItemSetting, MintSettings, MintType, MintWitness, }; use sp_runtime::traits::StaticLookup; +use weights::WeightInfo; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; #[cfg(test)] mod tests; +pub mod weights; type AccountIdOf = ::AccountId; type NftsOf = pallet_nfts::Pallet>; @@ -31,15 +36,19 @@ type CollectionDetailsFor = CollectionDetails, BalanceOf>; type AttributeNamespaceOf = AttributeNamespace>; type CollectionConfigFor = CollectionConfig, BlockNumberFor, CollectionIdOf>; -// Type aliases for storage items. -pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId>; +// Type aliases for pallet-nfts storage items. pub(super) type AccountBalanceOf = pallet_nfts::AccountBalance>; pub(super) type AttributeOf = pallet_nfts::Attribute>; +pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId>; pub(super) type CollectionOf = pallet_nfts::Collection>; #[frame_support::pallet] pub mod pallet { - use frame_support::{dispatch::DispatchResult, pallet_prelude::*, traits::Incrementable}; + use frame_support::{ + dispatch::{DispatchResult, DispatchResultWithPostInfo, WithPostDispatchInfo}, + pallet_prelude::*, + traits::Incrementable, + }; use frame_system::pallet_prelude::*; use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness, MintWitness}; use sp_runtime::BoundedVec; @@ -59,42 +68,42 @@ pub mod pallet { /// Account balance for a specified collection. #[codec(index = 1)] BalanceOf { - // The collection. + /// The collection. collection: CollectionIdOf, - // The owner of the collection . + /// The owner of the collection . owner: AccountIdOf, }, /// Allowance for an operator approved by an owner, for a specified collection or item. #[codec(index = 2)] Allowance { - // The collection. + /// The collection. collection: CollectionIdOf, - // The collection item. + /// The collection item. item: Option>, - // The owner of the collection item. + /// The owner of the collection item. owner: AccountIdOf, - // The delegated operator of collection item. + /// The delegated operator of collection item. operator: AccountIdOf, }, /// Owner of a specified collection item. #[codec(index = 5)] OwnerOf { - // The collection. + /// The collection. collection: CollectionIdOf, - // The collection item. + /// The collection item. item: ItemIdOf, }, /// Attribute value of a specified collection item. (Error: bounded collection is not /// partial) #[codec(index = 6)] GetAttribute { - // The collection. + /// The collection. collection: CollectionIdOf, - // The collection item. + /// The collection item. item: ItemIdOf, - // The namespace of the attribute. + /// The namespace of the attribute. namespace: AttributeNamespaceOf, - // The key of the attribute. + /// The key of the attribute. key: BoundedVec, }, /// Details of a specified collection. @@ -106,9 +115,9 @@ pub mod pallet { /// Metadata of a specified collection item. #[codec(index = 11)] ItemMetadata { - // The collection. + /// The collection. collection: CollectionIdOf, - // The collection item. + /// The collection item. item: ItemIdOf, }, } @@ -213,8 +222,8 @@ pub mod pallet { /// Transfers the collection item from the caller's account to account `to`. /// /// # Parameters - /// - `collection` - The collection of the item to be transferred. - /// - `item` - The item to be transferred. + /// - `collection` - The collection of the item to transfer. + /// - `item` - The item to transfer. /// - `to` - The recipient account. #[pallet::call_index(3)] #[pallet::weight(NftsWeightInfoOf::::transfer())] @@ -239,38 +248,49 @@ pub mod pallet { /// Approves `operator` to spend the collection item on behalf of the caller. /// /// # Parameters - /// - `collection` - The collection of the item to be approved for delegated transfer. - /// - `item` - The item to be approved for delegated transfer. + /// - `collection` - The collection of the item to approve for a delegated transfer. + /// - `item` - The item to approve for a delegated transfer. /// - `operator` - The account that is allowed to spend the collection item. /// - `approved` - The approval status of the collection item. #[pallet::call_index(4)] - #[pallet::weight(NftsWeightInfoOf::::approve_transfer() + NftsWeightInfoOf::::cancel_approval())] + #[pallet::weight( + NftsWeightInfoOf::::approve_transfer(item.is_some() as u32) + + NftsWeightInfoOf::::cancel_approval(item.is_some() as u32) + )] pub fn approve( origin: OriginFor, collection: CollectionIdOf, item: Option>, operator: AccountIdOf, approved: bool, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { let owner = ensure_signed(origin.clone())?; - if approved { + let weight = if approved { NftsOf::::approve_transfer( origin, collection, item, T::Lookup::unlookup(operator.clone()), None, - )?; + ) + .map_err(|e| { + e.with_weight(NftsWeightInfoOf::::approve_transfer(item.is_some() as u32)) + })?; + NftsWeightInfoOf::::approve_transfer(item.is_some() as u32) } else { NftsOf::::cancel_approval( origin, collection, item, T::Lookup::unlookup(operator.clone()), - )?; - } + ) + .map_err(|e| { + e.with_weight(NftsWeightInfoOf::::cancel_approval(item.is_some() as u32)) + })?; + NftsWeightInfoOf::::cancel_approval(item.is_some() as u32) + }; Self::deposit_event(Event::Approval { collection, item, operator, owner, approved }); - Ok(()) + Ok(Some(weight).into()) } /// Issue a new collection of non-fungible items from a public origin. @@ -286,21 +306,21 @@ pub mod pallet { admin: AccountIdOf, config: CollectionConfigFor, ) -> DispatchResult { + let creator = ensure_signed(origin.clone())?; // TODO: re-evaluate next collection id in nfts pallet. The `Incrementable` trait causes // issues for setting it to xcm's `Location`. This can easily be done differently. let id = NextCollectionIdOf::::get() .or(T::CollectionId::initial_value()) .ok_or(NftsErrorOf::::UnknownCollection)?; - let creator = ensure_signed(origin.clone())?; NftsOf::::create(origin, T::Lookup::unlookup(admin.clone()), config)?; - Self::deposit_event(Event::Created { id, admin, creator }); + Self::deposit_event(Event::Created { id, creator, admin }); Ok(()) } /// Destroy a collection of fungible items. /// /// # Parameters - /// - `collection` - The identifier of the collection to be destroyed. + /// - `collection` - The collection to destroy. /// - `witness` - Information on the items minted in the collection. This must be /// correct. #[pallet::call_index(8)] @@ -308,6 +328,8 @@ pub mod pallet { witness.item_metadatas, witness.item_configs, witness.attributes, + witness.item_holders, + witness.allowances, ))] pub fn destroy( origin: OriginFor, @@ -410,7 +432,7 @@ pub mod pallet { /// All the previously set attributes by the `delegate` will be removed. /// /// # Parameters - /// - `collection` - Collection that the item is contained within. + /// - `collection` - The collection that the item is contained within. /// - `item` - The item that holds attributes. /// - `delegate` - The previously approved account to remove. /// - `witness` - A witness data to cancel attributes approval operation. @@ -450,9 +472,9 @@ pub mod pallet { /// Mint an item of a particular collection. /// /// # Parameters - /// - `collection` - The collection of the item to be minted. + /// - `to` - Account into which the item will be minted. + /// - `collection` - The collection of the item to mint. /// - `item` - An identifier of the new item. - /// - `mint_to` - Account into which the item will be minted. /// - `witness_data` - When the mint type is `HolderOf(collection_id)`, then the owned /// item_id from that collection needs to be provided within the witness data object. If /// the mint price is set, then it should be additionally confirmed in the `witness_data`. @@ -487,8 +509,8 @@ pub mod pallet { /// Destroy a single collection item. /// /// # Parameters - /// - `collection` - The collection of the item to be burned. - /// - `item` - The item to be burned. + /// - `collection` - The collection of the item to burn. + /// - `item` - The item to burn. #[pallet::call_index(20)] #[pallet::weight(NftsWeightInfoOf::::burn())] pub fn burn( @@ -520,8 +542,18 @@ pub mod pallet { /// /// # Parameters /// - `request` - The read request. - fn weight(_request: &Self::Read) -> Weight { - Default::default() + fn weight(request: &Self::Read) -> Weight { + use Read::*; + match request { + TotalSupply(_) => ::WeightInfo::total_supply(), + BalanceOf { .. } => ::WeightInfo::balance_of(), + Allowance { .. } => ::WeightInfo::allowance(), + OwnerOf { .. } => ::WeightInfo::owner_of(), + GetAttribute { .. } => ::WeightInfo::get_attribute(), + Collection(_) => ::WeightInfo::collection(), + ItemMetadata { .. } => ::WeightInfo::item_metadata(), + NextCollectionId => ::WeightInfo::next_collection_id(), + } } /// Performs the requested read and returns the result. diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index 290f49f23..68260ab23 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -2,19 +2,21 @@ use codec::Encode; use frame_support::{ assert_noop, assert_ok, sp_runtime::{BoundedVec, DispatchError::BadOrigin}, - traits::Incrementable, }; +use pallet_nfts::WeightInfo as NftsWeightInfoTrait; use crate::{ mock::*, nonfungibles::{ - AccountBalanceOf, BlockNumberFor, CollectionConfig, CollectionDetails, CollectionIdOf, + AccountBalanceOf, AttributeNamespace, AttributeOf, BlockNumberFor, + CancelAttributesApprovalWitness, CollectionConfig, CollectionDetails, CollectionIdOf, CollectionOf, CollectionSettings, DestroyWitness, ItemIdOf, MintSettings, MintWitness, - NextCollectionIdOf, NftsInstanceOf, Read::*, ReadResult, + NextCollectionIdOf, NftsInstanceOf, NftsWeightInfoOf, Read::*, ReadResult, }, Read, }; +const COLLECTION: u32 = 0; const ITEM: u32 = 1; type NftsError = pallet_nfts::Error>; @@ -71,7 +73,9 @@ mod encoding_read_result { items: 0, item_metadatas: 0, item_configs: 0, + item_holders: 0, attributes: 0, + allowances: 0, }); assert_eq!( ReadResult::Collection::(collection_details.clone()).encode(), @@ -160,9 +164,14 @@ fn burn_works() { new_test_ext().execute_with(|| { let owner = ALICE; + // "UnknownItem" error is returned if collection item is not created. + assert_noop!(NonFungibles::burn(signed(owner), COLLECTION, ITEM), NftsError::UnknownItem); // Successfully burn an existing new collection item. let (collection, item) = nfts::create_collection_mint(owner, ITEM); + let balance_before_burn = AccountBalanceOf::::get(collection, owner); assert_ok!(NonFungibles::burn(signed(owner), collection, ITEM)); + let balance_after_burn = AccountBalanceOf::::get(collection, owner); + assert_eq!(balance_after_burn, balance_before_burn - 1); System::assert_last_event( Event::Transfer { collection, item, from: Some(owner), to: None, price: None }.into(), ); @@ -175,8 +184,12 @@ fn approve_works() { let owner = ALICE; let operator = BOB; let (collection, item) = nfts::create_collection_mint(owner, ITEM); - // Successfully approve `oeprator` to transfer the collection item. - assert_ok!(NonFungibles::approve(signed(owner), collection, Some(item), operator, true)); + // Successfully approve `operator` to transfer the collection item. + assert_eq!( + NonFungibles::approve(signed(owner), collection, Some(item), operator, true), + Ok(Some(NftsWeightInfoOf::::approve_transfer(1)).into()) + ); + assert_ok!(Nfts::check_allowance(&collection, &Some(item), &owner, &operator)); System::assert_last_event( Event::Approval { collection, item: Some(item), owner, operator, approved: true } .into(), @@ -186,6 +199,26 @@ fn approve_works() { }); } +#[test] +fn approve_collection_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + // Successfully approve `operator` to transfer all items within the collection. + assert_eq!( + NonFungibles::approve(signed(owner), collection, None, operator, true), + Ok(Some(NftsWeightInfoOf::::approve_transfer(0)).into()) + ); + assert_ok!(Nfts::check_allowance(&collection, &None, &owner, &operator)); + System::assert_last_event( + Event::Approval { collection, item: None, owner, operator, approved: true }.into(), + ); + // Successfully transfer the item by the delegated account `operator`. + assert_ok!(Nfts::transfer(signed(operator), collection, item, operator)); + }); +} + #[test] fn cancel_approval_works() { new_test_ext().execute_with(|| { @@ -193,7 +226,38 @@ fn cancel_approval_works() { let operator = BOB; let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); // Successfully cancel the transfer approval of `operator` by `owner`. - assert_ok!(NonFungibles::approve(signed(owner), collection, Some(item), operator, false)); + assert_eq!( + NonFungibles::approve(signed(owner), collection, Some(item), operator, false), + Ok(Some(NftsWeightInfoOf::::cancel_approval(1)).into()) + ); + assert_eq!( + Nfts::check_allowance(&collection, &Some(item), &owner, &operator), + Err(NftsError::NoPermission.into()) + ); + // Failed to transfer the item by `operator` without permission. + assert_noop!( + Nfts::transfer(signed(operator), collection, item, operator), + NftsError::NoPermission + ); + }); +} + +#[test] +fn cancel_collection_approval_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + // Successfully cancel the transfer collection approval of `operator` by `owner`. + assert_ok!(Nfts::approve_transfer(signed(owner), collection, None, operator, None)); + assert_eq!( + NonFungibles::approve(signed(owner), collection, None, operator, false), + Ok(Some(NftsWeightInfoOf::::cancel_approval(0)).into()) + ); + assert_eq!( + Nfts::check_allowance(&collection, &None, &owner, &operator), + Err(NftsError::NoPermission.into()) + ); // Failed to transfer the item by `operator` without permission. assert_noop!( Nfts::transfer(signed(operator), collection, item, operator), @@ -218,60 +282,6 @@ fn set_max_supply_works() { }); } -#[test] -fn owner_of_works() { - new_test_ext().execute_with(|| { - let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); - assert_eq!( - NonFungibles::read(OwnerOf { collection, item }).encode(), - Nfts::owner(collection, item).encode() - ); - }); -} - -#[test] -fn get_attribute_works() { - new_test_ext().execute_with(|| { - let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); - let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); - let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); - let mut result: Option< - BoundedVec>>::ValueLimit>, - > = None; - // No attribute set. - assert_eq!( - NonFungibles::read(GetAttribute { - collection, - item, - namespace: pallet_nfts::AttributeNamespace::CollectionOwner, - key: attribute.clone() - }) - .encode(), - result.encode() - ); - // Successfully get an existing attribute. - result = Some(value.clone()); - assert_ok!(Nfts::set_attribute( - signed(ALICE), - collection, - Some(item), - pallet_nfts::AttributeNamespace::CollectionOwner, - attribute.clone(), - value, - )); - assert_eq!( - NonFungibles::read(GetAttribute { - collection, - item, - namespace: pallet_nfts::AttributeNamespace::CollectionOwner, - key: attribute - }) - .encode(), - result.encode() - ); - }); -} - #[test] fn set_metadata_works() { new_test_ext().execute_with(|| { @@ -316,7 +326,7 @@ fn clear_attribute_works() { signed(ALICE), collection, Some(item), - pallet_nfts::AttributeNamespace::CollectionOwner, + AttributeNamespace::CollectionOwner, attribute.clone(), BoundedVec::truncate_from("some value".as_bytes().to_vec()) )); @@ -325,14 +335,14 @@ fn clear_attribute_works() { signed(ALICE), collection, Some(item), - pallet_nfts::AttributeNamespace::CollectionOwner, + AttributeNamespace::CollectionOwner, attribute.clone(), )); assert_eq!( NonFungibles::read(GetAttribute { collection, item, - namespace: pallet_nfts::AttributeNamespace::CollectionOwner, + namespace: AttributeNamespace::CollectionOwner, key: attribute }) .encode(), @@ -354,7 +364,7 @@ fn approve_item_attribute_works() { signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(BOB), + AttributeNamespace::Account(BOB), attribute.clone(), value.clone() )); @@ -365,7 +375,7 @@ fn approve_item_attribute_works() { NonFungibles::read(GetAttribute { collection, item, - namespace: pallet_nfts::AttributeNamespace::Account(BOB), + namespace: AttributeNamespace::Account(BOB), key: attribute }) .encode(), @@ -387,7 +397,7 @@ fn cancel_item_attribute_approval_works() { signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(BOB), + AttributeNamespace::Account(BOB), attribute.clone(), value.clone() )); @@ -396,14 +406,14 @@ fn cancel_item_attribute_approval_works() { collection, item, BOB, - pallet_nfts::CancelAttributesApprovalWitness { account_attributes: 1 } + CancelAttributesApprovalWitness { account_attributes: 1 } )); assert_noop!( Nfts::set_attribute( signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(BOB), + AttributeNamespace::Account(BOB), attribute.clone(), value.clone() ), @@ -412,78 +422,79 @@ fn cancel_item_attribute_approval_works() { }); } -#[test] -fn next_collection_id_works() { - new_test_ext().execute_with(|| { - let _ = nfts::create_collection_mint(ALICE, ITEM); - assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); - assert_eq!( - NonFungibles::read(NextCollectionId).encode(), - NextCollectionIdOf::::get() - .or(CollectionIdOf::::initial_value()) - .encode(), - ); - }); -} - -#[test] -fn total_supply_works() { - new_test_ext().execute_with(|| { - let owner = ALICE; - let collection = nfts::create_collection(owner); - (0..10).into_iter().for_each(|i| { - assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); - assert_eq!( - NonFungibles::read(TotalSupply(collection)).encode(), - ((i + 1) as u128).encode() - ); - assert_eq!( - NonFungibles::read(TotalSupply(collection)).encode(), - (Nfts::collection_items(collection).unwrap_or_default() as u128).encode() - ); - }); - }); -} - #[test] fn create_works() { new_test_ext().execute_with(|| { - let owner = ALICE; + let creator = ALICE; + let admin = ALICE; let next_collection_id = NextCollectionIdOf::::get().unwrap_or_default(); + for origin in vec![root(), none()] { + assert_noop!( + NonFungibles::create( + origin, + admin, + CollectionConfig { + max_supply: None, + mint_settings: MintSettings::default(), + settings: CollectionSettings::all_enabled() + }, + ), + BadOrigin + ); + } assert_ok!(NonFungibles::create( - signed(owner), - owner, + signed(creator), + admin, CollectionConfig { max_supply: None, mint_settings: MintSettings::default(), settings: CollectionSettings::all_enabled() }, )); - assert_eq!(Nfts::collection_owner(next_collection_id), Some(owner)); + assert_eq!(Nfts::collection_owner(next_collection_id), Some(creator)); + System::assert_last_event(Event::Created { id: next_collection_id, creator, admin }.into()); }); } #[test] fn destroy_works() { new_test_ext().execute_with(|| { - let collection = nfts::create_collection(ALICE); - assert_ok!(NonFungibles::destroy( - signed(ALICE), - collection, - DestroyWitness { item_metadatas: 0, item_configs: 0, attributes: 0 } - )); + let collection = COLLECTION; + let witness = DestroyWitness { + item_metadatas: 0, + item_configs: 0, + item_holders: 0, + attributes: 0, + allowances: 0, + }; + // Check error works for `Nfts::destroy()`. + assert_noop!( + NonFungibles::destroy(signed(ALICE), collection, witness), + NftsError::UnknownCollection + ); + nfts::create_collection(ALICE); + assert_ok!(NonFungibles::destroy(signed(ALICE), collection, witness)); assert_eq!(Nfts::collection_owner(collection), None); }); } #[test] -fn collection_works() { +fn total_supply_works() { new_test_ext().execute_with(|| { - let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); - assert_eq!( - NonFungibles::read(Collection(collection)).encode(), - CollectionOf::::get(&collection).encode(), - ); + let owner = ALICE; + let collection = nfts::create_collection(owner); + assert_eq!(NonFungibles::read(TotalSupply(collection)), ReadResult::TotalSupply(0)); + (0..10).into_iter().for_each(|i| { + assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); + assert_eq!( + NonFungibles::read(TotalSupply(collection)), + ReadResult::TotalSupply((i + 1).into()) + ); + assert_eq!( + NonFungibles::read(TotalSupply(collection)).encode(), + (Nfts::collection_items(collection).unwrap_or_default() as u128).encode() + ); + }); }); } @@ -492,11 +503,15 @@ fn balance_of_works() { new_test_ext().execute_with(|| { let owner = ALICE; let collection = nfts::create_collection(owner); + assert_eq!( + NonFungibles::read(BalanceOf { collection, owner }), + ReadResult::BalanceOf(Default::default()) + ); (0..10).into_iter().for_each(|i| { assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); assert_eq!( - NonFungibles::read(BalanceOf { collection, owner }).encode(), - (i + 1).encode() + NonFungibles::read(BalanceOf { collection, owner }), + ReadResult::BalanceOf(i + 1) ); assert_eq!( NonFungibles::read(BalanceOf { collection, owner }).encode(), @@ -513,9 +528,8 @@ fn allowance_works() { let operator = BOB; let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); assert_eq!( - NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }) - .encode(), - true.encode() + NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }), + ReadResult::Allowance(true) ); assert_eq!( NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }) @@ -527,6 +541,131 @@ fn allowance_works() { }); } +#[test] +fn owner_of_works() { + new_test_ext().execute_with(|| { + assert_eq!( + NonFungibles::read(OwnerOf { collection: COLLECTION, item: ITEM }), + ReadResult::OwnerOf(None) + ); + nfts::create_collection_mint(ALICE, ITEM); + assert_eq!( + NonFungibles::read(OwnerOf { collection: COLLECTION, item: ITEM }), + ReadResult::OwnerOf(Some(ALICE)) + ); + assert_eq!( + NonFungibles::read(OwnerOf { collection: COLLECTION, item: ITEM }).encode(), + Nfts::owner(COLLECTION, ITEM).encode() + ); + }); +} + +#[test] +fn get_attribute_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let raw_value = "some value".as_bytes().to_vec(); + let value = BoundedVec::truncate_from(raw_value.clone()); + let namespace = AttributeNamespace::CollectionOwner; + // No attribute set. + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item, + namespace: namespace.clone(), + key: attribute.clone() + }), + ReadResult::GetAttribute(None) + ); + // Successfully get an existing attribute. + assert_ok!(Nfts::set_attribute( + signed(ALICE), + collection, + Some(item), + namespace.clone(), + attribute.clone(), + value, + )); + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item, + namespace: namespace.clone(), + key: attribute.clone() + }), + ReadResult::GetAttribute(Some(raw_value)) + ); + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item, + namespace: namespace.clone(), + key: attribute.clone() + }) + .encode(), + AttributeOf::::get((collection, Some(item), namespace, attribute)) + .map(|result| result.0) + .encode() + ); + }); +} + +#[test] +fn collection_works() { + new_test_ext().execute_with(|| { + assert_eq!(NonFungibles::read(Collection(COLLECTION)), ReadResult::Collection(None),); + nfts::create_collection_mint(ALICE, ITEM); + assert_eq!( + NonFungibles::read(Collection(COLLECTION)), + ReadResult::Collection(CollectionOf::::get(COLLECTION)), + ); + assert_eq!( + NonFungibles::read(Collection(COLLECTION)).encode(), + CollectionOf::::get(COLLECTION).encode(), + ); + }); +} + +#[test] +fn item_metadata_works() { + new_test_ext().execute_with(|| { + assert_eq!( + NonFungibles::read(ItemMetadata { collection: COLLECTION, item: ITEM }), + ReadResult::ItemMetadata(None) + ); + nfts::create_collection_mint(ALICE, ITEM); + let value = "some metadata".as_bytes().to_vec(); + assert_ok!(NonFungibles::set_metadata( + signed(ALICE), + COLLECTION, + ITEM, + BoundedVec::truncate_from(value.clone()) + )); + assert_eq!( + NonFungibles::read(ItemMetadata { collection: COLLECTION, item: ITEM }), + ReadResult::ItemMetadata(Some(value)) + ); + assert_eq!( + NonFungibles::read(ItemMetadata { collection: COLLECTION, item: ITEM }).encode(), + Nfts::item_metadata(COLLECTION, ITEM).encode() + ); + }); +} + +#[test] +fn next_collection_id_works() { + new_test_ext().execute_with(|| { + assert_eq!(NonFungibles::read(NextCollectionId), ReadResult::NextCollectionId(Some(0))); + nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId), ReadResult::NextCollectionId(Some(1))); + assert_eq!( + NonFungibles::read(NextCollectionId).encode(), + Some(NextCollectionIdOf::::get().unwrap_or_default()).encode(), + ); + }); +} + fn signed(account_id: AccountId) -> RuntimeOrigin { RuntimeOrigin::signed(account_id) } @@ -539,6 +678,7 @@ fn none() -> RuntimeOrigin { RuntimeOrigin::none() } +// Helper functions for interacting with pallet-nfts. mod nfts { use super::*; @@ -559,7 +699,7 @@ mod nfts { } pub(super) fn create_collection(owner: AccountId) -> u32 { - let next_id = next_collection_id(); + let next_id = NextCollectionIdOf::::get().unwrap_or_default(); assert_ok!(Nfts::create( signed(owner), owner, @@ -568,10 +708,6 @@ mod nfts { next_id } - pub(super) fn next_collection_id() -> u32 { - NextCollectionIdOf::::get().unwrap_or_default() - } - pub(super) fn collection_config_with_all_settings_enabled( ) -> CollectionConfig, CollectionIdOf> { CollectionConfig { @@ -581,3 +717,287 @@ mod nfts { } } } + +mod read_weights { + use frame_support::weights::Weight; + + use super::*; + use crate::nonfungibles::{weights::WeightInfo, Config}; + + struct ReadWeightInfo { + total_supply: Weight, + balance_of: Weight, + allowance: Weight, + owner_of: Weight, + get_attribute: Weight, + collection: Weight, + next_collection_id: Weight, + item_metadata: Weight, + } + + impl ReadWeightInfo { + fn new() -> Self { + Self { + total_supply: NonFungibles::weight(&TotalSupply(COLLECTION)), + balance_of: NonFungibles::weight(&BalanceOf { + collection: COLLECTION, + owner: ALICE, + }), + allowance: NonFungibles::weight(&Allowance { + collection: COLLECTION, + item: Some(ITEM), + owner: ALICE, + operator: BOB, + }), + owner_of: NonFungibles::weight(&OwnerOf { collection: COLLECTION, item: ITEM }), + get_attribute: NonFungibles::weight(&GetAttribute { + collection: COLLECTION, + item: ITEM, + namespace: AttributeNamespace::CollectionOwner, + key: BoundedVec::default(), + }), + collection: NonFungibles::weight(&Collection(COLLECTION)), + next_collection_id: NonFungibles::weight(&NextCollectionId), + item_metadata: NonFungibles::weight(&ItemMetadata { + collection: COLLECTION, + item: ITEM, + }), + } + } + } + + #[test] + fn ensure_read_matches_benchmarks() { + let ReadWeightInfo { + allowance, + balance_of, + collection, + get_attribute, + item_metadata, + next_collection_id, + owner_of, + total_supply, + } = ReadWeightInfo::new(); + + assert_eq!(total_supply, ::WeightInfo::total_supply()); + assert_eq!(balance_of, ::WeightInfo::balance_of()); + assert_eq!(allowance, ::WeightInfo::allowance()); + assert_eq!(owner_of, ::WeightInfo::owner_of()); + assert_eq!(get_attribute, ::WeightInfo::get_attribute()); + assert_eq!(collection, ::WeightInfo::collection()); + assert_eq!(next_collection_id, ::WeightInfo::next_collection_id()); + assert_eq!(item_metadata, ::WeightInfo::item_metadata()); + } + + // These types read from the `Collection` storage. + #[test] + fn ensure_collection_variants_match() { + let ReadWeightInfo { total_supply, collection, .. } = ReadWeightInfo::new(); + + assert_eq!(total_supply, collection); + } + + // Proof size is based on `MaxEncodedLen`, not hardware. + // This test ensures that the data structure sizes do not change with upgrades. + #[test] + fn ensure_expected_proof_size_does_not_change() { + let ReadWeightInfo { + allowance, + balance_of, + collection, + get_attribute, + item_metadata, + next_collection_id, + owner_of, + total_supply, + } = ReadWeightInfo::new(); + + // These values come from `weights.rs`. + assert_eq!(total_supply.proof_size(), 3557); + assert_eq!(balance_of.proof_size(), 3529); + assert_eq!(allowance.proof_size(), 4326); + assert_eq!(owner_of.proof_size(), 4326); + assert_eq!(get_attribute.proof_size(), 3944); + assert_eq!(collection.proof_size(), 3557); + assert_eq!(next_collection_id.proof_size(), 1489); + assert_eq!(item_metadata.proof_size(), 3812); + } +} + +mod ensure_codec_indexes { + use super::{Encode, *}; + use crate::{mock::RuntimeCall::NonFungibles, nonfungibles}; + + #[test] + fn ensure_read_variant_indexes() { + [ + (TotalSupply::(Default::default()), 0u8, "TotalSupply"), + ( + BalanceOf:: { collection: Default::default(), owner: Default::default() }, + 1, + "BalanceOf", + ), + ( + Allowance:: { + collection: Default::default(), + item: Default::default(), + owner: Default::default(), + operator: Default::default(), + }, + 2, + "Allowance", + ), + ( + OwnerOf:: { collection: Default::default(), item: Default::default() }, + 5, + "OwnerOf", + ), + ( + GetAttribute:: { + collection: Default::default(), + item: Default::default(), + namespace: AttributeNamespace::CollectionOwner, + key: Default::default(), + }, + 6, + "GetAttribute", + ), + (Collection::(Default::default()), 9, "Collection"), + (NextCollectionId, 10, "NextCollectionId"), + ( + ItemMetadata { collection: Default::default(), item: Default::default() }, + 11, + "ItemMetadata", + ), + ] + .iter() + .for_each(|(variant, expected_index, name)| { + assert_eq!(variant.encode()[0], *expected_index, "{name} variant index changed"); + }) + } + + #[test] + fn ensure_dispatchable_indexes() { + use nonfungibles::Call::*; + + [ + ( + transfer { + collection: Default::default(), + item: Default::default(), + to: Default::default(), + }, + 3u8, + "transfer", + ), + ( + approve { + collection: Default::default(), + item: Default::default(), + operator: Default::default(), + approved: Default::default(), + }, + 4, + "approve", + ), + (create { admin: Default::default(), config: Default::default() }, 7, "create"), + ( + destroy { + collection: Default::default(), + witness: DestroyWitness { + item_metadatas: Default::default(), + item_configs: Default::default(), + item_holders: Default::default(), + attributes: Default::default(), + allowances: Default::default(), + }, + }, + 8, + "destroy", + ), + ( + set_attribute { + collection: Default::default(), + item: Default::default(), + namespace: AttributeNamespace::CollectionOwner, + key: Default::default(), + value: Default::default(), + }, + 12, + "set_attribute", + ), + ( + clear_attribute { + collection: Default::default(), + item: Default::default(), + namespace: AttributeNamespace::CollectionOwner, + key: Default::default(), + }, + 13, + "clear_attribute", + ), + ( + set_metadata { + collection: Default::default(), + item: Default::default(), + data: Default::default(), + }, + 14, + "set_metadata", + ), + ( + clear_metadata { collection: Default::default(), item: Default::default() }, + 15, + "clear_metadata", + ), + ( + approve_item_attributes { + collection: Default::default(), + item: Default::default(), + delegate: Default::default(), + }, + 16, + "approve_item_attributes", + ), + ( + cancel_item_attributes_approval { + collection: Default::default(), + item: Default::default(), + delegate: Default::default(), + witness: CancelAttributesApprovalWitness { + account_attributes: Default::default(), + }, + }, + 17, + "cancel_item_attributes_approval", + ), + ( + set_max_supply { collection: Default::default(), max_supply: Default::default() }, + 18, + "set_max_supply", + ), + ( + mint { + to: Default::default(), + collection: Default::default(), + item: Default::default(), + witness: MintWitness { + owned_item: Default::default(), + mint_price: Default::default(), + }, + }, + 19, + "mint", + ), + (burn { collection: Default::default(), item: Default::default() }, 20, "burn"), + ] + .iter() + .for_each(|(variant, expected_index, name)| { + assert_eq!( + NonFungibles(variant.to_owned()).encode()[1], + *expected_index, + "{name} dispatchable index changed" + ); + }) + } +} diff --git a/pallets/api/src/nonfungibles/weights.rs b/pallets/api/src/nonfungibles/weights.rs new file mode 100644 index 000000000..f0b8fa833 --- /dev/null +++ b/pallets/api/src/nonfungibles/weights.rs @@ -0,0 +1,217 @@ + +//! Autogenerated weights for `nonfungibles` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 40.0.0 +//! DATE: 2024-11-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `R0GUE`, CPU: `` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// ./target/release/pop-node +// benchmark +// pallet +// --chain=dev +// --wasm-execution=compiled +// --pallet=nonfungibles +// --steps=50 +// --repeat=20 +// --json +// --template +// ./scripts/pallet-weights-template.hbs +// --output=./pallets/api/src/nonfungibles/weights.rs +// --extrinsic= + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `nonfungibles`. +pub trait WeightInfo { + fn total_supply() -> Weight; + fn balance_of() -> Weight; + fn allowance() -> Weight; + fn owner_of() -> Weight; + fn get_attribute() -> Weight; + fn collection() -> Weight; + fn next_collection_id() -> Weight; + fn item_metadata() -> Weight; +} + +/// Weights for `nonfungibles` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn total_supply() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + fn balance_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3529` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3529) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Allowances` (r:1 w:0) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn allowance() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(7_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn owner_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + fn get_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3944` + // Minimum execution time: 5_000_000 picoseconds. + Weight::from_parts(5_000_000, 3944) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn collection() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::NextCollectionId` (r:1 w:0) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn next_collection_id() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `1489` + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(1_000_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + fn item_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3812` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3812) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn total_supply() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + fn balance_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3529` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3529) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Allowances` (r:1 w:0) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn allowance() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(7_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn owner_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + fn get_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3944` + // Minimum execution time: 5_000_000 picoseconds. + Weight::from_parts(5_000_000, 3944) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn collection() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::NextCollectionId` (r:1 w:0) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn next_collection_id() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `1489` + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(1_000_000, 1489) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + fn item_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3812` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3812) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } +} + diff --git a/pallets/nfts/src/benchmarking.rs b/pallets/nfts/src/benchmarking.rs index ab66da26d..58209b8bb 100644 --- a/pallets/nfts/src/benchmarking.rs +++ b/pallets/nfts/src/benchmarking.rs @@ -64,6 +64,27 @@ fn add_collection_metadata, I: 'static>() -> (T::AccountId, Account (caller, caller_lookup) } +fn approve_collection, I: 'static>( + index: u32, +) -> (T::AccountId, AccountIdLookupOf) { + let caller = Collection::::get(T::Helper::collection(0)).unwrap().owner; + if caller != whitelisted_caller() { + whitelist_account!(caller); + } + let caller_lookup = T::Lookup::unlookup(caller.clone()); + let delegate: T::AccountId = account("delegate", 0, SEED + index); + let delegate_lookup = T::Lookup::unlookup(delegate.clone()); + let deadline = BlockNumberFor::::max_value(); + assert_ok!(Nfts::::approve_transfer( + SystemOrigin::Signed(caller.clone()).into(), + T::Helper::collection(0), + None, + delegate_lookup.clone(), + Some(deadline), + )); + (caller, caller_lookup) +} + fn mint_item, I: 'static>( index: u16, ) -> (T::ItemId, T::AccountId, AccountIdLookupOf) { @@ -77,7 +98,7 @@ fn mint_item, I: 'static>( let item_exists = Item::::contains_key(&collection, &item); let item_config = ItemConfigOf::::get(&collection, &item); if item_exists { - return (item, caller, caller_lookup) + return (item, caller, caller_lookup); } else if let Some(item_config) = item_config { assert_ok!(Nfts::::force_mint( SystemOrigin::Signed(caller.clone()).into(), @@ -250,6 +271,8 @@ benchmarks_instance_pallet! { let m in 0 .. 1_000; let c in 0 .. 1_000; let a in 0 .. 1_000; + let h in 0 .. 1_000; + let l in 0 .. 1_000; let (collection, caller, _) = create_collection::(); add_collection_metadata::(); @@ -267,6 +290,13 @@ benchmarks_instance_pallet! { for i in 0..a { add_collection_attribute::(i as u16); } + for i in 0..h { + mint_item::(i as u16); + burn_item::(i as u16); + } + for i in 0..l { + approve_collection::(i as u32); + } let witness = Collection::::get(collection).unwrap().destroy_witness(); }: _(SystemOrigin::Signed(caller), collection, witness) verify { @@ -573,27 +603,45 @@ benchmarks_instance_pallet! { } approve_transfer { + let i in 0..1; + let (collection, caller, _) = create_collection::(); let (item, ..) = mint_item::(0); let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); - let deadline = BlockNumberFor::::max_value(); - }: _(SystemOrigin::Signed(caller.clone()), collection, Some(item), delegate_lookup, Some(deadline)) + let maybe_deadline = if i == 0 { + None + } else { + Some(BlockNumberFor::::max_value()) + }; + let maybe_item = if i == 0 { + None + } else { + Some(item) + }; + }: _(SystemOrigin::Signed(caller.clone()), collection, maybe_item, delegate_lookup, maybe_deadline) verify { - assert_last_event::(Event::TransferApproved { collection, item: Some(item), owner: caller, delegate, deadline: Some(deadline) }.into()); + assert_last_event::(Event::TransferApproved { collection, item: maybe_item, owner: caller, delegate, deadline: maybe_deadline }.into()); } cancel_approval { + let i in 0..1; + let (collection, caller, _) = create_collection::(); let (item, ..) = mint_item::(0); let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let origin = SystemOrigin::Signed(caller.clone()).into(); let deadline = BlockNumberFor::::max_value(); - Nfts::::approve_transfer(origin, collection, Some(item), delegate_lookup.clone(), Some(deadline))?; - }: _(SystemOrigin::Signed(caller.clone()), collection, Some(item), delegate_lookup) + let maybe_item = if i == 0 { + None + } else { + Some(item) + }; + Nfts::::approve_transfer(origin, collection, maybe_item, delegate_lookup.clone(), Some(deadline))?; + }: _(SystemOrigin::Signed(caller.clone()), collection, maybe_item, delegate_lookup) verify { - assert_last_event::(Event::ApprovalCancelled { collection, item: Some(item), owner: caller, delegate }.into()); + assert_last_event::(Event::ApprovalCancelled { collection, item: maybe_item, owner: caller, delegate }.into()); } clear_all_transfer_approvals { diff --git a/pallets/nfts/src/common_functions.rs b/pallets/nfts/src/common_functions.rs index 89de1f051..abd8b61d0 100644 --- a/pallets/nfts/src/common_functions.rs +++ b/pallets/nfts/src/common_functions.rs @@ -39,6 +39,11 @@ impl, I: 'static> Pallet { Collection::::get(collection).map(|i| i.items) } + /// Get the allowances to spend items within the collection. + pub fn collection_allowances(collection: T::CollectionId) -> Option { + Collection::::get(collection).map(|i| i.allowances) + } + /// Get the metadata of the collection item. pub fn item_metadata( collection: T::CollectionId, diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index e1e79ef4a..2647492ca 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -195,6 +195,15 @@ impl, I: 'static> Pallet { Allowances::::mutate((&collection, &owner, &delegate), |allowance| { *allowance = true; }); + Collection::::try_mutate( + &collection, + |maybe_collection_details| -> Result<(), DispatchError> { + let collection_details = + maybe_collection_details.as_mut().ok_or(Error::::UnknownCollection)?; + collection_details.allowances.saturating_inc(); + Ok(()) + }, + )?; Self::deposit_event(Event::TransferApproved { collection, @@ -217,6 +226,15 @@ impl, I: 'static> Pallet { ensure!(check_origin == owner, Error::::NoPermission); } Allowances::::remove((&collection, &owner, &delegate)); + Collection::::try_mutate( + &collection, + |maybe_collection_details| -> Result<(), DispatchError> { + let collection_details = + maybe_collection_details.as_mut().ok_or(Error::::UnknownCollection)?; + collection_details.allowances.saturating_dec(); + Ok(()) + }, + )?; Self::deposit_event(Event::ApprovalCancelled { collection, owner, item: None, delegate }); diff --git a/pallets/nfts/src/features/create_delete_collection.rs b/pallets/nfts/src/features/create_delete_collection.rs index b7efd03ac..1d08cd1b6 100644 --- a/pallets/nfts/src/features/create_delete_collection.rs +++ b/pallets/nfts/src/features/create_delete_collection.rs @@ -54,7 +54,9 @@ impl, I: 'static> Pallet { items: 0, item_metadatas: 0, item_configs: 0, + item_holders: 0, attributes: 0, + allowances: 0, }, ); CollectionRoleOf::::insert( @@ -119,6 +121,11 @@ impl, I: 'static> Pallet { collection_details.item_configs == witness.item_configs, Error::::BadWitness ); + ensure!( + collection_details.item_holders == witness.item_holders, + Error::::BadWitness + ); + ensure!(collection_details.allowances == witness.allowances, Error::::BadWitness); for (_, metadata) in ItemMetadataOf::::drain_prefix(&collection) { if let Some(depositor) = metadata.deposit.account { @@ -137,8 +144,6 @@ impl, I: 'static> Pallet { } } - // TODO: Do we need another storage item to keep track of number of holders of a - // collection let _ = AccountBalance::::clear_prefix(collection, collection_details.items, None); let _ = Allowances::::clear_prefix((collection,), collection_details.items, None); @@ -152,7 +157,9 @@ impl, I: 'static> Pallet { Ok(DestroyWitness { item_metadatas: collection_details.item_metadatas, item_configs: collection_details.item_configs, + item_holders: collection_details.item_holders, attributes: collection_details.attributes, + allowances: collection_details.allowances, }) }) } diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index cc29f8dab..a7b7ddf38 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -69,9 +69,15 @@ impl, I: 'static> Pallet { } collection_details.items.saturating_inc(); - AccountBalance::::mutate(collection, &mint_to, |balance| { - balance.saturating_inc(); - }); + + let account_balance = + AccountBalance::::mutate(collection, &mint_to, |balance| -> u32 { + balance.saturating_inc(); + balance.clone() + }); + if account_balance == 1 { + collection_details.item_holders.saturating_inc(); + } let collection_config = Self::get_collection_config(&collection)?; let deposit_amount = match collection_config @@ -257,6 +263,10 @@ impl, I: 'static> Pallet { } } + if AccountBalance::::get(collection, &details.owner) == 1 { + collection_details.item_holders.saturating_dec(); + } + Ok(details.owner) }, )?; diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index 3b25b0145..dbe6f3b09 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -54,7 +54,7 @@ impl, I: 'static> Pallet { ) -> DispatchResult, ) -> DispatchResult { // Retrieve collection details. - let collection_details = + let mut collection_details = Collection::::get(&collection).ok_or(Error::::UnknownCollection)?; // Ensure the item is not locked. @@ -87,13 +87,23 @@ impl, I: 'static> Pallet { // Perform the transfer with custom details using the provided closure. with_details(&collection_details, &mut details)?; - // Update account balances. - AccountBalance::::mutate(collection, &details.owner, |balance| { - balance.saturating_dec(); - }); - AccountBalance::::mutate(collection, &dest, |balance| { + // Update account balance of the owner. + let owner_balance = + AccountBalance::::mutate(collection, &details.owner, |balance| -> u32 { + balance.saturating_dec(); + balance.clone() + }); + if owner_balance == 0 { + collection_details.item_holders.saturating_dec(); + } + // Update account balance of the destination account. + let dest_balance = AccountBalance::::mutate(collection, &dest, |balance| -> u32 { balance.saturating_inc(); + balance.clone() }); + if dest_balance == 1 { + collection_details.item_holders.saturating_inc(); + } // Update account ownership information. Account::::remove((&details.owner, &collection, &item)); @@ -108,6 +118,7 @@ impl, I: 'static> Pallet { // Update item details. Item::::insert(&collection, &item, &details); + Collection::::insert(&collection, &collection_details); ItemPriceOf::::remove(&collection, &item); PendingSwapOf::::remove(&collection, &item); diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index bc8b67b61..37e8b29cc 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -30,7 +30,6 @@ #[cfg(feature = "runtime-benchmarks")] mod benchmarking; -pub mod migration; #[cfg(test)] pub mod mock; #[cfg(test)] @@ -832,6 +831,8 @@ pub mod pallet { witness.item_metadatas, witness.item_configs, witness.attributes, + witness.item_holders, + witness.allowances, ))] pub fn destroy( origin: OriginFor, @@ -847,6 +848,8 @@ pub mod pallet { details.item_metadatas, details.item_configs, details.attributes, + details.item_holders, + details.allowances, )) .into()) } @@ -1311,7 +1314,7 @@ pub mod pallet { /// /// Weight: `O(1)` #[pallet::call_index(15)] - #[pallet::weight(T::WeightInfo::approve_transfer())] + #[pallet::weight(T::WeightInfo::approve_transfer(maybe_item.is_some() as u32))] pub fn approve_transfer( origin: OriginFor, collection: T::CollectionId, @@ -1350,7 +1353,7 @@ pub mod pallet { /// /// Weight: `O(1)` #[pallet::call_index(16)] - #[pallet::weight(T::WeightInfo::cancel_approval())] + #[pallet::weight(T::WeightInfo::cancel_approval(maybe_item.is_some() as u32))] pub fn cancel_approval( origin: OriginFor, collection: T::CollectionId, diff --git a/pallets/nfts/src/migration.rs b/pallets/nfts/src/migration.rs deleted file mode 100644 index af611bf16..000000000 --- a/pallets/nfts/src/migration.rs +++ /dev/null @@ -1,120 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use frame_support::traits::OnRuntimeUpgrade; -use log; -#[cfg(feature = "try-runtime")] -use sp_runtime::TryRuntimeError; - -use super::*; - -pub mod v1 { - use frame_support::{pallet_prelude::*, weights::Weight}; - - use super::*; - - #[derive(Decode)] - pub struct OldCollectionDetails { - pub owner: AccountId, - pub owner_deposit: DepositBalance, - pub items: u32, - pub item_metadatas: u32, - pub attributes: u32, - } - - impl OldCollectionDetails { - /// Migrates the old collection details to the new v1 format. - fn migrate_to_v1(self, item_configs: u32) -> CollectionDetails { - CollectionDetails { - owner: self.owner, - owner_deposit: self.owner_deposit, - items: self.items, - item_metadatas: self.item_metadatas, - item_configs, - attributes: self.attributes, - } - } - } - - /// A migration utility to update the storage version from v0 to v1 for the pallet. - pub struct MigrateToV1(core::marker::PhantomData); - impl OnRuntimeUpgrade for MigrateToV1 { - fn on_runtime_upgrade() -> Weight { - let in_code_version = Pallet::::in_code_storage_version(); - let on_chain_version = Pallet::::on_chain_storage_version(); - - log::info!( - target: LOG_TARGET, - "Running migration with in-code storage version {:?} / onchain {:?}", - in_code_version, - on_chain_version - ); - - if on_chain_version == 0 && in_code_version == 1 { - let mut translated = 0u64; - let mut configs_iterated = 0u64; - Collection::::translate::< - OldCollectionDetails>, - _, - >(|key, old_value| { - let item_configs = ItemConfigOf::::iter_prefix(&key).count() as u32; - configs_iterated += item_configs as u64; - translated.saturating_inc(); - Some(old_value.migrate_to_v1(item_configs)) - }); - - in_code_version.put::>(); - - log::info!( - target: LOG_TARGET, - "Upgraded {} records, storage to version {:?}", - translated, - in_code_version - ); - T::DbWeight::get().reads_writes(translated + configs_iterated + 1, translated + 1) - } else { - log::info!( - target: LOG_TARGET, - "Migration did not execute. This probably should be removed" - ); - T::DbWeight::get().reads(1) - } - } - - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - let prev_count = Collection::::iter().count(); - Ok((prev_count as u32).encode()) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(prev_count: Vec) -> Result<(), TryRuntimeError> { - let prev_count: u32 = Decode::decode(&mut prev_count.as_slice()).expect( - "the state parameter should be something that was generated by pre_upgrade", - ); - let post_count = Collection::::iter().count() as u32; - ensure!( - prev_count == post_count, - "the records count before and after the migration should be the same" - ); - - ensure!(Pallet::::on_chain_storage_version() >= 1, "wrong storage version"); - - Ok(()) - } - } -} diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 4d0f08c93..6d0c894aa 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -165,6 +165,7 @@ fn basic_minting_should_work() { assert_eq!(collections(), vec![(account(1), 0)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); assert_eq!(AccountBalance::::get(0, account(1)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(items(), vec![(account(1), 0, 42)]); assert_ok!(Nfts::force_create( @@ -175,10 +176,37 @@ fn basic_minting_should_work() { assert_eq!(collections(), vec![(account(1), 0), (account(2), 1)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(2)), 1, 69, account(1), None)); assert_eq!(AccountBalance::::get(1, account(1)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(items(), vec![(account(1), 0, 42), (account(1), 1, 69)]); }); } +#[test] +fn collection_item_holders_should_works() { + new_test_ext().execute_with(|| { + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_eq!(collections(), vec![(account(1), 0)]); + let total = 5; + for i in 0..total { + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, i, account(1), None)); + } + assert_eq!(AccountBalance::::get(0, account(1)), total); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); + + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, total, account(2), None)); + assert_eq!(AccountBalance::::get(0, account(2)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 2); + + assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(2)), 0, total)); + assert_eq!(AccountBalance::::get(0, account(2)), 0); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); + }); +} + #[test] fn lifecycle_should_work() { new_test_ext().execute_with(|| { @@ -223,6 +251,7 @@ fn lifecycle_should_work() { assert_eq!(Collection::::get(0).unwrap().items, 3); assert_eq!(Collection::::get(0).unwrap().item_metadatas, 0); assert_eq!(Collection::::get(0).unwrap().item_configs, 3); + assert_eq!(Collection::::get(0).unwrap().item_holders, 3); assert_eq!(Balances::reserved_balance(&account(1)), 8); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 70, account(2))); @@ -317,6 +346,7 @@ fn destroy_should_work() { assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(2), None)); assert_eq!(AccountBalance::::get(0, account(2)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(1)), 0, @@ -360,6 +390,7 @@ fn mint_should_work() { assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); assert_eq!(AccountBalance::::get(0, account(1)), 1); assert_eq!(Nfts::owner(0, 42).unwrap(), account(1)); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(collections(), vec![(account(1), 0)]); assert_eq!(items(), vec![(account(1), 0, 42)]); @@ -425,6 +456,7 @@ fn mint_should_work() { Some(MintWitness { mint_price: Some(1), ..Default::default() }) )); assert_eq!(AccountBalance::::get(0, account(2)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 2); assert_eq!(Balances::total_balance(&account(2)), 99); // validate types @@ -464,6 +496,7 @@ fn mint_should_work() { Some(MintWitness { owned_item: Some(43), ..Default::default() }) )); assert_eq!(AccountBalance::::get(1, account(2)), 1); + assert_eq!(Collection::::get(1).unwrap().item_holders, 1); assert!(events().contains(&Event::::PalletAttributeSet { collection: 0, item: Some(43), @@ -500,10 +533,11 @@ fn transfer_should_work() { account(2), default_item_config() )); - + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); assert_eq!(AccountBalance::::get(0, account(2)), 0); assert_eq!(AccountBalance::::get(0, account(3)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(items(), vec![(account(3), 0, 42)]); assert_noop!( Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4)), @@ -521,6 +555,7 @@ fn transfer_should_work() { assert_eq!(AccountBalance::::get(0, account(2)), 0); assert_eq!(AccountBalance::::get(0, account(3)), 0); assert_eq!(AccountBalance::::get(0, account(4)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); // validate we can't transfer non-transferable items let collection_id = 1; assert_ok!(Nfts::force_create( @@ -1775,6 +1810,7 @@ fn burn_works() { default_item_config() )); assert_eq!(AccountBalance::::get(0, account(5)), 2); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(Balances::reserved_balance(account(1)), 2); assert_noop!( @@ -1783,8 +1819,10 @@ fn burn_works() { ); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 42)); assert_eq!(AccountBalance::::get(0, account(5)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 69)); assert_eq!(AccountBalance::::get(0, account(5)), 0); + assert_eq!(Collection::::get(0).unwrap().item_holders, 0); assert_eq!(Balances::reserved_balance(account(1)), 0); }); } @@ -2036,6 +2074,7 @@ fn cancel_approval_collection_works_with_admin() { delegate: account(3) })); assert_eq!(Allowances::::get((0, account(2), account(3))), false); + assert_eq!(Nfts::collection_allowances(0).unwrap(), 0); assert_noop!( Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4)), @@ -2192,6 +2231,7 @@ fn approval_collection_works_with_admin() { deadline: None })); assert_eq!(Allowances::::get((0, account(1), account(3))), true); + assert_eq!(Nfts::collection_allowances(0).unwrap(), 1); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4))); }); } @@ -4114,7 +4154,13 @@ fn clear_collection_metadata_works() { assert_ok!(Nfts::destroy( RuntimeOrigin::signed(account(1)), 0, - DestroyWitness { item_configs: 0, item_metadatas: 0, attributes: 0 } + DestroyWitness { + item_configs: 0, + item_metadatas: 0, + attributes: 0, + allowances: 0, + item_holders: 0 + } )); assert_eq!(Collection::::get(0), None); assert_eq!(Balances::reserved_balance(&account(1)), 10); diff --git a/pallets/nfts/src/types.rs b/pallets/nfts/src/types.rs index 941da6cad..46148d63d 100644 --- a/pallets/nfts/src/types.rs +++ b/pallets/nfts/src/types.rs @@ -104,8 +104,12 @@ pub struct CollectionDetails { pub item_metadatas: u32, /// The total number of outstanding item configs of this collection. pub item_configs: u32, + /// The total number of accounts that hold items of the collection. + pub item_holders: u32, /// The total number of attributes for this collection. pub attributes: u32, + /// The total number of allowances to spend all items within collections. + pub allowances: u32, } /// Witness data for the destroy transactions. @@ -117,9 +121,15 @@ pub struct DestroyWitness { /// The total number of outstanding item configs of this collection. #[codec(compact)] pub item_configs: u32, + /// The total number of accounts that hold items of the collection. + #[codec(compact)] + pub item_holders: u32, /// The total number of attributes for this collection. #[codec(compact)] pub attributes: u32, + /// The total number of allowances to spend all items within collections. + #[codec(compact)] + pub allowances: u32, } impl CollectionDetails { @@ -127,7 +137,9 @@ impl CollectionDetails { DestroyWitness { item_metadatas: self.item_metadatas, item_configs: self.item_configs, + item_holders: self.item_holders, attributes: self.attributes, + allowances: self.allowances, } } } diff --git a/pallets/nfts/src/weights.rs b/pallets/nfts/src/weights.rs index c374d6dbc..b33075032 100644 --- a/pallets/nfts/src/weights.rs +++ b/pallets/nfts/src/weights.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `pallet_nfts` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 40.0.0 -//! DATE: 2024-10-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-11-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `R0GUE`, CPU: `` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` @@ -36,7 +36,7 @@ use core::marker::PhantomData; pub trait WeightInfo { fn create() -> Weight; fn force_create() -> Weight; - fn destroy(m: u32, c: u32, a: u32, ) -> Weight; + fn destroy(m: u32, c: u32, a: u32, h: u32, l: u32, ) -> Weight; fn mint() -> Weight; fn force_mint() -> Weight; fn burn() -> Weight; @@ -59,8 +59,8 @@ pub trait WeightInfo { fn clear_metadata() -> Weight; fn set_collection_metadata() -> Weight; fn clear_collection_metadata() -> Weight; - fn approve_transfer() -> Weight; - fn cancel_approval() -> Weight; + fn approve_transfer(i: u32, ) -> Weight; + fn cancel_approval(i: u32, ) -> Weight; fn clear_all_transfer_approvals() -> Weight; fn set_accept_ownership() -> Weight; fn set_collection_max_supply() -> Weight; @@ -81,7 +81,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::NextCollectionId` (r:1 w:1) /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) @@ -91,16 +91,16 @@ impl WeightInfo for SubstrateWeight { fn create() -> Weight { // Proof Size summary in bytes: // Measured: `105` - // Estimated: `3549` - // Minimum execution time: 27_000_000 picoseconds. - Weight::from_parts(27_000_000, 3549) + // Estimated: `3557` + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(29_000_000, 3557) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::NextCollectionId` (r:1 w:1) /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) @@ -110,14 +110,14 @@ impl WeightInfo for SubstrateWeight { fn force_create() -> Weight { // Proof Size summary in bytes: // Measured: `3` - // Estimated: `3549` - // Minimum execution time: 14_000_000 picoseconds. - Weight::from_parts(15_000_000, 3549) + // Estimated: `3557` + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(15_000_000, 3557) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) @@ -126,6 +126,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:0) /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:1 w:0) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) @@ -137,19 +139,17 @@ impl WeightInfo for SubstrateWeight { /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. - fn destroy(m: u32, c: u32, a: u32, ) -> Weight { + /// The range of component `h` is `[0, 1000]`. + /// The range of component `l` is `[0, 1000]`. + fn destroy(_m: u32, _c: u32, a: u32, _h: u32, _l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32216 + a * (366 ±0)` + // Measured: `32875 + a * (366 ±0)` // Estimated: `2523990 + a * (2954 ±0)` // Minimum execution time: 982_000_000 picoseconds. - Weight::from_parts(937_587_516, 2523990) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(34_348, 0).saturating_mul(m.into())) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(23_800, 0).saturating_mul(c.into())) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(5_095_505, 0).saturating_mul(a.into())) - .saturating_add(T::DbWeight::get().reads(1005_u64)) + Weight::from_parts(4_613_129_128, 2523990) + // Standard Error: 125_087 + .saturating_add(Weight::from_parts(5_072_767, 0).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(1006_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(1005_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) @@ -160,7 +160,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) @@ -171,10 +171,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: - // Measured: `382` + // Measured: `390` // Estimated: `4326` - // Minimum execution time: 41_000_000 picoseconds. - Weight::from_parts(42_000_000, 4326) + // Minimum execution time: 40_000_000 picoseconds. + Weight::from_parts(41_000_000, 4326) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -183,7 +183,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) @@ -194,10 +194,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn force_mint() -> Weight { // Proof Size summary in bytes: - // Measured: `382` + // Measured: `390` // Estimated: `4326` // Minimum execution time: 39_000_000 picoseconds. - Weight::from_parts(40_000_000, 4326) + Weight::from_parts(39_000_000, 4326) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -206,7 +206,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) @@ -223,15 +223,15 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: - // Measured: `576` + // Measured: `584` // Estimated: `4326` - // Minimum execution time: 46_000_000 picoseconds. - Weight::from_parts(59_000_000, 4326) + // Minimum execution time: 45_000_000 picoseconds. + Weight::from_parts(46_000_000, 4326) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -250,15 +250,15 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `605` + // Measured: `613` // Estimated: `6068` // Minimum execution time: 38_000_000 picoseconds. - Weight::from_parts(83_000_000, 6068) + Weight::from_parts(38_000_000, 6068) .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:5000 w:5000) @@ -266,12 +266,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `690 + i * (108 ±0)` - // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 3549) - // Standard Error: 20_022 - .saturating_add(Weight::from_parts(16_005_327, 0).saturating_mul(i.into())) + // Measured: `698 + i * (108 ±0)` + // Estimated: `3557 + i * (3336 ±0)` + // Minimum execution time: 10_000_000 picoseconds. + Weight::from_parts(11_000_000, 3557) + // Standard Error: 30_743 + .saturating_add(Weight::from_parts(15_569_470, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -285,7 +285,7 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3534` - // Minimum execution time: 13_000_000 picoseconds. + // Minimum execution time: 14_000_000 picoseconds. Weight::from_parts(14_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) @@ -298,35 +298,35 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3534` - // Minimum execution time: 14_000_000 picoseconds. + // Minimum execution time: 13_000_000 picoseconds. Weight::from_parts(14_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn lock_collection() -> Weight { // Proof Size summary in bytes: - // Measured: `267` - // Estimated: `3549` + // Measured: `275` + // Estimated: `3557` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 3549) + Weight::from_parts(11_000_000, 3557) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionAccount` (r:0 w:2) /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `417` + // Measured: `425` // Estimated: `3593` // Minimum execution time: 18_000_000 picoseconds. Weight::from_parts(19_000_000, 3593) @@ -334,12 +334,12 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:2 w:4) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: - // Measured: `296` + // Measured: `304` // Estimated: `6078` // Minimum execution time: 30_000_000 picoseconds. Weight::from_parts(31_000_000, 6078) @@ -347,28 +347,28 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionAccount` (r:0 w:2) /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: - // Measured: `238` - // Estimated: `3549` + // Measured: `246` + // Estimated: `3557` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(12_000_000, 3549) + Weight::from_parts(12_000_000, 3557) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn force_collection_config() -> Weight { // Proof Size summary in bytes: // Measured: `203` - // Estimated: `3549` + // Estimated: `3557` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(9_000_000, 3549) + Weight::from_parts(9_000_000, 3557) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -386,7 +386,7 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -397,20 +397,20 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `499` + // Measured: `507` // Estimated: `3944` - // Minimum execution time: 37_000_000 picoseconds. - Weight::from_parts(38_000_000, 3944) + // Minimum execution time: 38_000_000 picoseconds. + Weight::from_parts(39_000_000, 3944) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:1) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `271` + // Measured: `279` // Estimated: `3944` // Minimum execution time: 19_000_000 picoseconds. Weight::from_parts(19_000_000, 3944) @@ -424,13 +424,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `943` + // Measured: `951` // Estimated: `3944` // Minimum execution time: 35_000_000 picoseconds. - Weight::from_parts(36_000_000, 3944) + Weight::from_parts(37_000_000, 3944) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -462,8 +462,8 @@ impl WeightInfo for SubstrateWeight { // Estimated: `4466 + n * (2954 ±0)` // Minimum execution time: 18_000_000 picoseconds. Weight::from_parts(19_000_000, 4466) - // Standard Error: 6_379 - .saturating_add(Weight::from_parts(5_018_740, 0).saturating_mul(n.into())) + // Standard Error: 10_431 + .saturating_add(Weight::from_parts(4_776_454, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -473,7 +473,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -482,7 +482,7 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `499` + // Measured: `507` // Estimated: `3812` // Minimum execution time: 30_000_000 picoseconds. Weight::from_parts(31_000_000, 3812) @@ -494,15 +494,15 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `809` + // Measured: `817` // Estimated: `3812` - // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(29_000_000, 3812) + // Minimum execution time: 29_000_000 picoseconds. + Weight::from_parts(30_000_000, 3812) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -511,32 +511,32 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `325` + // Measured: `333` // Estimated: `3759` // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(30_000_000, 3759) + Weight::from_parts(28_000_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `643` + // Measured: `651` // Estimated: `3759` // Minimum execution time: 27_000_000 picoseconds. - Weight::from_parts(29_000_000, 3759) + Weight::from_parts(28_000_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -544,25 +544,37 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - fn approve_transfer() -> Weight { - // Proof Size summary in bytes: - // Measured: `337` - // Estimated: `4326` - // Minimum execution time: 13_000_000 picoseconds. - Weight::from_parts(14_000_000, 4326) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:1 w:1) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 1]`. + fn approve_transfer(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `308 + i * (29 ±0)` + // Estimated: `3574 + i * (2163 ±0)` + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(16_969_387, 3574) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 2163).saturating_mul(i.into())) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - fn cancel_approval() -> Weight { - // Proof Size summary in bytes: - // Measured: `345` - // Estimated: `4326` + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:0 w:1) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 1]`. + fn cancel_approval(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `312 + i * (33 ±0)` + // Estimated: `3557 + i * (2163 ±0)` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(12_000_000, 4326) + Weight::from_parts(14_000_000, 3557) .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 2163).saturating_mul(i.into())) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -582,20 +594,20 @@ impl WeightInfo for SubstrateWeight { // Measured: `3` // Estimated: `3517` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(10_000_000, 3517) + Weight::from_parts(9_000_000, 3517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: - // Measured: `267` - // Estimated: `3549` + // Measured: `275` + // Estimated: `3557` // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 3549) + Weight::from_parts(13_000_000, 3557) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -608,7 +620,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `250` // Estimated: `3538` // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 3538) + Weight::from_parts(12_000_000, 3538) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -624,8 +636,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `478` // Estimated: `4326` - // Minimum execution time: 16_000_000 picoseconds. - Weight::from_parts(17_000_000, 4326) + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(16_000_000, 4326) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -633,8 +645,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:1 w:1) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -649,12 +661,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn buy_item() -> Weight { // Proof Size summary in bytes: - // Measured: `717` + // Measured: `725` // Estimated: `6068` - // Minimum execution time: 42_000_000 picoseconds. - Weight::from_parts(45_000_000, 6068) + // Minimum execution time: 43_000_000 picoseconds. + Weight::from_parts(44_000_000, 6068) .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) } /// The range of component `n` is `[0, 10]`. fn pay_tips(n: u32, ) -> Weight { @@ -662,9 +674,9 @@ impl WeightInfo for SubstrateWeight { // Measured: `0` // Estimated: `0` // Minimum execution time: 1_000_000 picoseconds. - Weight::from_parts(390_532, 0) - // Standard Error: 84_277 - .saturating_add(Weight::from_parts(3_087_492, 0).saturating_mul(n.into())) + Weight::from_parts(2_101_372, 0) + // Standard Error: 5_552 + .saturating_add(Weight::from_parts(1_704_563, 0).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:2 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -674,8 +686,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `421` // Estimated: `7662` - // Minimum execution time: 14_000_000 picoseconds. - Weight::from_parts(15_000_000, 7662) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(14_000_000, 7662) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -687,7 +699,7 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `440` // Estimated: `4326` - // Minimum execution time: 14_000_000 picoseconds. + // Minimum execution time: 13_000_000 picoseconds. Weight::from_parts(14_000_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) @@ -696,8 +708,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:1 w:2) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:2 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -712,12 +724,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn claim_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `907` + // Measured: `915` // Estimated: `7662` - // Minimum execution time: 75_000_000 picoseconds. - Weight::from_parts(77_000_000, 7662) + // Minimum execution time: 78_000_000 picoseconds. + Weight::from_parts(79_000_000, 7662) .saturating_add(T::DbWeight::get().reads(11_u64)) - .saturating_add(T::DbWeight::get().writes(12_u64)) + .saturating_add(T::DbWeight::get().writes(13_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -726,7 +738,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) @@ -742,12 +754,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `485` + // Measured: `493` // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 100_000_000 picoseconds. - Weight::from_parts(107_476_765, 6078) - // Standard Error: 61_259 - .saturating_add(Weight::from_parts(27_610_007, 0).saturating_mul(n.into())) + // Minimum execution time: 101_000_000 picoseconds. + Weight::from_parts(102_689_064, 6078) + // Standard Error: 25_175 + .saturating_add(Weight::from_parts(27_553_304, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(7_u64)) @@ -761,7 +773,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:10 w:10) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -769,12 +781,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `514` + // Measured: `522` // Estimated: `4466 + n * (2954 ±0)` - // Minimum execution time: 51_000_000 picoseconds. - Weight::from_parts(57_358_180, 4466) - // Standard Error: 54_968 - .saturating_add(Weight::from_parts(27_429_606, 0).saturating_mul(n.into())) + // Minimum execution time: 50_000_000 picoseconds. + Weight::from_parts(55_735_551, 4466) + // Standard Error: 34_490 + .saturating_add(Weight::from_parts(26_799_214, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -788,7 +800,7 @@ impl WeightInfo for () { /// Storage: `Nfts::NextCollectionId` (r:1 w:1) /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) @@ -798,16 +810,16 @@ impl WeightInfo for () { fn create() -> Weight { // Proof Size summary in bytes: // Measured: `105` - // Estimated: `3549` - // Minimum execution time: 27_000_000 picoseconds. - Weight::from_parts(27_000_000, 3549) + // Estimated: `3557` + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(29_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::NextCollectionId` (r:1 w:1) /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) @@ -817,14 +829,14 @@ impl WeightInfo for () { fn force_create() -> Weight { // Proof Size summary in bytes: // Measured: `3` - // Estimated: `3549` - // Minimum execution time: 14_000_000 picoseconds. - Weight::from_parts(15_000_000, 3549) + // Estimated: `3557` + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(15_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) @@ -833,6 +845,8 @@ impl WeightInfo for () { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:0) /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:1 w:0) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) @@ -844,19 +858,17 @@ impl WeightInfo for () { /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. - fn destroy(m: u32, c: u32, a: u32, ) -> Weight { + /// The range of component `h` is `[0, 1000]`. + /// The range of component `l` is `[0, 1000]`. + fn destroy(_m: u32, _c: u32, a: u32, _h: u32, _l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32216 + a * (366 ±0)` + // Measured: `32875 + a * (366 ±0)` // Estimated: `2523990 + a * (2954 ±0)` // Minimum execution time: 982_000_000 picoseconds. - Weight::from_parts(937_587_516, 2523990) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(34_348, 0).saturating_mul(m.into())) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(23_800, 0).saturating_mul(c.into())) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(5_095_505, 0).saturating_mul(a.into())) - .saturating_add(RocksDbWeight::get().reads(1005_u64)) + Weight::from_parts(4_613_129_128, 2523990) + // Standard Error: 125_087 + .saturating_add(Weight::from_parts(5_072_767, 0).saturating_mul(a.into())) + .saturating_add(RocksDbWeight::get().reads(1006_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(RocksDbWeight::get().writes(1005_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(a.into()))) @@ -867,7 +879,7 @@ impl WeightInfo for () { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) @@ -878,10 +890,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: - // Measured: `382` + // Measured: `390` // Estimated: `4326` - // Minimum execution time: 41_000_000 picoseconds. - Weight::from_parts(42_000_000, 4326) + // Minimum execution time: 40_000_000 picoseconds. + Weight::from_parts(41_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -890,7 +902,7 @@ impl WeightInfo for () { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) @@ -901,10 +913,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn force_mint() -> Weight { // Proof Size summary in bytes: - // Measured: `382` + // Measured: `390` // Estimated: `4326` // Minimum execution time: 39_000_000 picoseconds. - Weight::from_parts(40_000_000, 4326) + Weight::from_parts(39_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -913,7 +925,7 @@ impl WeightInfo for () { /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) @@ -930,15 +942,15 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: - // Measured: `576` + // Measured: `584` // Estimated: `4326` - // Minimum execution time: 46_000_000 picoseconds. - Weight::from_parts(59_000_000, 4326) + // Minimum execution time: 45_000_000 picoseconds. + Weight::from_parts(46_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -957,15 +969,15 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `605` + // Measured: `613` // Estimated: `6068` // Minimum execution time: 38_000_000 picoseconds. - Weight::from_parts(83_000_000, 6068) + Weight::from_parts(38_000_000, 6068) .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:5000 w:5000) @@ -973,12 +985,12 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `690 + i * (108 ±0)` - // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 3549) - // Standard Error: 20_022 - .saturating_add(Weight::from_parts(16_005_327, 0).saturating_mul(i.into())) + // Measured: `698 + i * (108 ±0)` + // Estimated: `3557 + i * (3336 ±0)` + // Minimum execution time: 10_000_000 picoseconds. + Weight::from_parts(11_000_000, 3557) + // Standard Error: 30_743 + .saturating_add(Weight::from_parts(15_569_470, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -992,7 +1004,7 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3534` - // Minimum execution time: 13_000_000 picoseconds. + // Minimum execution time: 14_000_000 picoseconds. Weight::from_parts(14_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) @@ -1005,35 +1017,35 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3534` - // Minimum execution time: 14_000_000 picoseconds. + // Minimum execution time: 13_000_000 picoseconds. Weight::from_parts(14_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn lock_collection() -> Weight { // Proof Size summary in bytes: - // Measured: `267` - // Estimated: `3549` + // Measured: `275` + // Estimated: `3557` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 3549) + Weight::from_parts(11_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionAccount` (r:0 w:2) /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `417` + // Measured: `425` // Estimated: `3593` // Minimum execution time: 18_000_000 picoseconds. Weight::from_parts(19_000_000, 3593) @@ -1041,12 +1053,12 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:2 w:4) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: - // Measured: `296` + // Measured: `304` // Estimated: `6078` // Minimum execution time: 30_000_000 picoseconds. Weight::from_parts(31_000_000, 6078) @@ -1054,28 +1066,28 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionAccount` (r:0 w:2) /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: - // Measured: `238` - // Estimated: `3549` + // Measured: `246` + // Estimated: `3557` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(12_000_000, 3549) + Weight::from_parts(12_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn force_collection_config() -> Weight { // Proof Size summary in bytes: // Measured: `203` - // Estimated: `3549` + // Estimated: `3557` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(9_000_000, 3549) + Weight::from_parts(9_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1093,7 +1105,7 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -1104,20 +1116,20 @@ impl WeightInfo for () { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `499` + // Measured: `507` // Estimated: `3944` - // Minimum execution time: 37_000_000 picoseconds. - Weight::from_parts(38_000_000, 3944) + // Minimum execution time: 38_000_000 picoseconds. + Weight::from_parts(39_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:1) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `271` + // Measured: `279` // Estimated: `3944` // Minimum execution time: 19_000_000 picoseconds. Weight::from_parts(19_000_000, 3944) @@ -1131,13 +1143,13 @@ impl WeightInfo for () { /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `943` + // Measured: `951` // Estimated: `3944` // Minimum execution time: 35_000_000 picoseconds. - Weight::from_parts(36_000_000, 3944) + Weight::from_parts(37_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1169,8 +1181,8 @@ impl WeightInfo for () { // Estimated: `4466 + n * (2954 ±0)` // Minimum execution time: 18_000_000 picoseconds. Weight::from_parts(19_000_000, 4466) - // Standard Error: 6_379 - .saturating_add(Weight::from_parts(5_018_740, 0).saturating_mul(n.into())) + // Standard Error: 10_431 + .saturating_add(Weight::from_parts(4_776_454, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -1180,7 +1192,7 @@ impl WeightInfo for () { /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -1189,7 +1201,7 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `499` + // Measured: `507` // Estimated: `3812` // Minimum execution time: 30_000_000 picoseconds. Weight::from_parts(31_000_000, 3812) @@ -1201,15 +1213,15 @@ impl WeightInfo for () { /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `809` + // Measured: `817` // Estimated: `3812` - // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(29_000_000, 3812) + // Minimum execution time: 29_000_000 picoseconds. + Weight::from_parts(30_000_000, 3812) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1218,32 +1230,32 @@ impl WeightInfo for () { /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `325` + // Measured: `333` // Estimated: `3759` // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(30_000_000, 3759) + Weight::from_parts(28_000_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `643` + // Measured: `651` // Estimated: `3759` // Minimum execution time: 27_000_000 picoseconds. - Weight::from_parts(29_000_000, 3759) + Weight::from_parts(28_000_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1251,25 +1263,37 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - fn approve_transfer() -> Weight { - // Proof Size summary in bytes: - // Measured: `337` - // Estimated: `4326` - // Minimum execution time: 13_000_000 picoseconds. - Weight::from_parts(14_000_000, 4326) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:1 w:1) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 1]`. + fn approve_transfer(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `308 + i * (29 ±0)` + // Estimated: `3574 + i * (2163 ±0)` + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(16_969_387, 3574) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 2163).saturating_mul(i.into())) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - fn cancel_approval() -> Weight { - // Proof Size summary in bytes: - // Measured: `345` - // Estimated: `4326` + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:0 w:1) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 1]`. + fn cancel_approval(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `312 + i * (33 ±0)` + // Estimated: `3557 + i * (2163 ±0)` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(12_000_000, 4326) + Weight::from_parts(14_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 2163).saturating_mul(i.into())) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -1289,20 +1313,20 @@ impl WeightInfo for () { // Measured: `3` // Estimated: `3517` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(10_000_000, 3517) + Weight::from_parts(9_000_000, 3517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: - // Measured: `267` - // Estimated: `3549` + // Measured: `275` + // Estimated: `3557` // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 3549) + Weight::from_parts(13_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1315,7 +1339,7 @@ impl WeightInfo for () { // Measured: `250` // Estimated: `3538` // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 3538) + Weight::from_parts(12_000_000, 3538) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1331,8 +1355,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `478` // Estimated: `4326` - // Minimum execution time: 16_000_000 picoseconds. - Weight::from_parts(17_000_000, 4326) + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(16_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1340,8 +1364,8 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:1 w:1) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -1356,12 +1380,12 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn buy_item() -> Weight { // Proof Size summary in bytes: - // Measured: `717` + // Measured: `725` // Estimated: `6068` - // Minimum execution time: 42_000_000 picoseconds. - Weight::from_parts(45_000_000, 6068) + // Minimum execution time: 43_000_000 picoseconds. + Weight::from_parts(44_000_000, 6068) .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) } /// The range of component `n` is `[0, 10]`. fn pay_tips(n: u32, ) -> Weight { @@ -1369,9 +1393,9 @@ impl WeightInfo for () { // Measured: `0` // Estimated: `0` // Minimum execution time: 1_000_000 picoseconds. - Weight::from_parts(390_532, 0) - // Standard Error: 84_277 - .saturating_add(Weight::from_parts(3_087_492, 0).saturating_mul(n.into())) + Weight::from_parts(2_101_372, 0) + // Standard Error: 5_552 + .saturating_add(Weight::from_parts(1_704_563, 0).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:2 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -1381,8 +1405,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `421` // Estimated: `7662` - // Minimum execution time: 14_000_000 picoseconds. - Weight::from_parts(15_000_000, 7662) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(14_000_000, 7662) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1394,7 +1418,7 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `440` // Estimated: `4326` - // Minimum execution time: 14_000_000 picoseconds. + // Minimum execution time: 13_000_000 picoseconds. Weight::from_parts(14_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) @@ -1403,8 +1427,8 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:1 w:2) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:2 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -1419,12 +1443,12 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn claim_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `907` + // Measured: `915` // Estimated: `7662` - // Minimum execution time: 75_000_000 picoseconds. - Weight::from_parts(77_000_000, 7662) + // Minimum execution time: 78_000_000 picoseconds. + Weight::from_parts(79_000_000, 7662) .saturating_add(RocksDbWeight::get().reads(11_u64)) - .saturating_add(RocksDbWeight::get().writes(12_u64)) + .saturating_add(RocksDbWeight::get().writes(13_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -1433,7 +1457,7 @@ impl WeightInfo for () { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) @@ -1449,12 +1473,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `485` + // Measured: `493` // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 100_000_000 picoseconds. - Weight::from_parts(107_476_765, 6078) - // Standard Error: 61_259 - .saturating_add(Weight::from_parts(27_610_007, 0).saturating_mul(n.into())) + // Minimum execution time: 101_000_000 picoseconds. + Weight::from_parts(102_689_064, 6078) + // Standard Error: 25_175 + .saturating_add(Weight::from_parts(27_553_304, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(7_u64)) @@ -1468,7 +1492,7 @@ impl WeightInfo for () { /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:10 w:10) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -1476,16 +1500,16 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `514` + // Measured: `522` // Estimated: `4466 + n * (2954 ±0)` - // Minimum execution time: 51_000_000 picoseconds. - Weight::from_parts(57_358_180, 4466) - // Standard Error: 54_968 - .saturating_add(Weight::from_parts(27_429_606, 0).saturating_mul(n.into())) + // Minimum execution time: 50_000_000 picoseconds. + Weight::from_parts(55_735_551, 4466) + // Standard Error: 34_490 + .saturating_add(Weight::from_parts(26_799_214, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } -} \ No newline at end of file +} diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs index 5ea1d9235..d96fd85bd 100644 --- a/runtime/devnet/src/config/api/mod.rs +++ b/runtime/devnet/src/config/api/mod.rs @@ -11,7 +11,7 @@ use sp_std::vec::Vec; use versioning::*; use crate::{ - config::assets::{NftsInstance, TrustBackedAssetsInstance}, + config::assets::{TrustBackedAssetsInstance, TrustBackedNftsInstance}, fungibles, nonfungibles, Runtime, RuntimeCall, RuntimeEvent, }; @@ -88,7 +88,7 @@ impl fungibles::Config for Runtime { } impl nonfungibles::Config for Runtime { - type NftsInstance = NftsInstance; + type NftsInstance = TrustBackedNftsInstance; type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } @@ -311,7 +311,13 @@ mod tests { }), NonFungibles(destroy { collection: 0, - witness: DestroyWitness { attributes: 0, item_configs: 0, item_metadatas: 0 }, + witness: DestroyWitness { + attributes: 0, + item_configs: 0, + item_metadatas: 0, + item_holders: 0, + allowances: 0, + }, }), NonFungibles(set_attribute { collection: 0, diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 97c2a9e7d..65405ea46 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -46,9 +46,9 @@ impl Get for KeyLimit { } } -pub(crate) type NftsInstance = pallet_nfts::Instance1; -pub type NftsCall = pallet_nfts::Call; -impl pallet_nfts::Config for Runtime { +pub(crate) type TrustBackedNftsInstance = pallet_nfts::Instance1; +pub type TrustBackedNftsCall = pallet_nfts::Call; +impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ApprovalsLimit = ConstU32<20>; type AttributeDepositBase = NftsAttributeDepositBase; @@ -97,8 +97,8 @@ impl pallet_nft_fractionalization::Config for Runtime { type Deposit = AssetDeposit; type NewAssetName = NewAssetName; type NewAssetSymbol = NewAssetSymbol; - type NftCollectionId = >::CollectionId; - type NftId = >::ItemId; + type NftCollectionId = >::CollectionId; + type NftId = >::ItemId; type Nfts = Nfts; type PalletId = NftFractionalizationPalletId; type RuntimeEvent = RuntimeEvent; diff --git a/runtime/devnet/src/config/proxy.rs b/runtime/devnet/src/config/proxy.rs index 161178dc5..486530276 100644 --- a/runtime/devnet/src/config/proxy.rs +++ b/runtime/devnet/src/config/proxy.rs @@ -5,7 +5,7 @@ use pop_runtime_common::proxy::{ }; use sp_runtime::traits::BlakeTwo256; -use super::assets::{NftsCall, TrustBackedAssetsCall}; +use super::assets::{TrustBackedAssetsCall, TrustBackedNftsCall}; use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; impl InstanceFilter for ProxyType { @@ -45,13 +45,13 @@ impl InstanceFilter for ProxyType { RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) | - RuntimeCall::Nfts(NftsCall::create { .. }) | - RuntimeCall::Nfts(NftsCall::destroy { .. }) | - RuntimeCall::Nfts(NftsCall::redeposit { .. }) | - RuntimeCall::Nfts(NftsCall::transfer_ownership { .. }) | - RuntimeCall::Nfts(NftsCall::set_team { .. }) | - RuntimeCall::Nfts(NftsCall::set_collection_max_supply { .. }) | - RuntimeCall::Nfts(NftsCall::lock_collection { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::create { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::destroy { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::redeposit { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::transfer_ownership { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_team { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_collection_max_supply { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_collection { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), @@ -66,17 +66,17 @@ impl InstanceFilter for ProxyType { RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) | - RuntimeCall::Nfts(NftsCall::force_mint { .. }) | - RuntimeCall::Nfts(NftsCall::update_mint_settings { .. }) | - RuntimeCall::Nfts(NftsCall::mint_pre_signed { .. }) | - RuntimeCall::Nfts(NftsCall::set_attributes_pre_signed { .. }) | - RuntimeCall::Nfts(NftsCall::lock_item_transfer { .. }) | - RuntimeCall::Nfts(NftsCall::unlock_item_transfer { .. }) | - RuntimeCall::Nfts(NftsCall::lock_item_properties { .. }) | - RuntimeCall::Nfts(NftsCall::set_metadata { .. }) | - RuntimeCall::Nfts(NftsCall::clear_metadata { .. }) | - RuntimeCall::Nfts(NftsCall::set_collection_metadata { .. }) | - RuntimeCall::Nfts(NftsCall::clear_collection_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::force_mint { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::update_mint_settings { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::mint_pre_signed { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_attributes_pre_signed { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_item_transfer { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::unlock_item_transfer { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_item_properties { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::clear_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_collection_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::clear_collection_metadata { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index 839f819dc..736f0be73 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -646,6 +646,7 @@ mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] [fungibles, Fungibles] + [nonfungibles, NonFungibles] [pallet_balances, Balances] [pallet_session, SessionBench::] [pallet_timestamp, Timestamp] From c5532616dbbfa1cb5d7d5a10800eb2ea87ee0a7a Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 18 Nov 2024 12:14:46 +0700 Subject: [PATCH 29/76] chore: clippy --- pallets/nfts/src/benchmarking.rs | 2 +- pallets/nfts/src/features/create_delete_item.rs | 2 +- pallets/nfts/src/features/transfer.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pallets/nfts/src/benchmarking.rs b/pallets/nfts/src/benchmarking.rs index 58209b8bb..d8876d521 100644 --- a/pallets/nfts/src/benchmarking.rs +++ b/pallets/nfts/src/benchmarking.rs @@ -295,7 +295,7 @@ benchmarks_instance_pallet! { burn_item::(i as u16); } for i in 0..l { - approve_collection::(i as u32); + approve_collection::(i); } let witness = Collection::::get(collection).unwrap().destroy_witness(); }: _(SystemOrigin::Signed(caller), collection, witness) diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index a7b7ddf38..08cf5f951 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -73,7 +73,7 @@ impl, I: 'static> Pallet { let account_balance = AccountBalance::::mutate(collection, &mint_to, |balance| -> u32 { balance.saturating_inc(); - balance.clone() + *balance }); if account_balance == 1 { collection_details.item_holders.saturating_inc(); diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index dbe6f3b09..3f2dae3b9 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -91,7 +91,7 @@ impl, I: 'static> Pallet { let owner_balance = AccountBalance::::mutate(collection, &details.owner, |balance| -> u32 { balance.saturating_dec(); - balance.clone() + *balance }); if owner_balance == 0 { collection_details.item_holders.saturating_dec(); @@ -99,7 +99,7 @@ impl, I: 'static> Pallet { // Update account balance of the destination account. let dest_balance = AccountBalance::::mutate(collection, &dest, |balance| -> u32 { balance.saturating_inc(); - balance.clone() + *balance }); if dest_balance == 1 { collection_details.item_holders.saturating_inc(); From c5ecbd8ebd4724d22f32921eb97a5e594312f533 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:23:51 +0700 Subject: [PATCH 30/76] chore: forked pallet nfts --- pallets/nfts/src/migration.rs | 120 ++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 pallets/nfts/src/migration.rs diff --git a/pallets/nfts/src/migration.rs b/pallets/nfts/src/migration.rs new file mode 100644 index 000000000..8f82e0922 --- /dev/null +++ b/pallets/nfts/src/migration.rs @@ -0,0 +1,120 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::*; +use frame_support::traits::OnRuntimeUpgrade; +use log; + +#[cfg(feature = "try-runtime")] +use sp_runtime::TryRuntimeError; + +pub mod v1 { + use frame_support::{pallet_prelude::*, weights::Weight}; + + use super::*; + + #[derive(Decode)] + pub struct OldCollectionDetails { + pub owner: AccountId, + pub owner_deposit: DepositBalance, + pub items: u32, + pub item_metadatas: u32, + pub attributes: u32, + } + + impl OldCollectionDetails { + /// Migrates the old collection details to the new v1 format. + fn migrate_to_v1(self, item_configs: u32) -> CollectionDetails { + CollectionDetails { + owner: self.owner, + owner_deposit: self.owner_deposit, + items: self.items, + item_metadatas: self.item_metadatas, + item_configs, + attributes: self.attributes, + } + } + } + + /// A migration utility to update the storage version from v0 to v1 for the pallet. + pub struct MigrateToV1(core::marker::PhantomData); + impl OnRuntimeUpgrade for MigrateToV1 { + fn on_runtime_upgrade() -> Weight { + let in_code_version = Pallet::::in_code_storage_version(); + let on_chain_version = Pallet::::on_chain_storage_version(); + + log::info!( + target: LOG_TARGET, + "Running migration with in-code storage version {:?} / onchain {:?}", + in_code_version, + on_chain_version + ); + + if on_chain_version == 0 && in_code_version == 1 { + let mut translated = 0u64; + let mut configs_iterated = 0u64; + Collection::::translate::< + OldCollectionDetails>, + _, + >(|key, old_value| { + let item_configs = ItemConfigOf::::iter_prefix(&key).count() as u32; + configs_iterated += item_configs as u64; + translated.saturating_inc(); + Some(old_value.migrate_to_v1(item_configs)) + }); + + in_code_version.put::>(); + + log::info!( + target: LOG_TARGET, + "Upgraded {} records, storage to version {:?}", + translated, + in_code_version + ); + T::DbWeight::get().reads_writes(translated + configs_iterated + 1, translated + 1) + } else { + log::info!( + target: LOG_TARGET, + "Migration did not execute. This probably should be removed" + ); + T::DbWeight::get().reads(1) + } + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, TryRuntimeError> { + let prev_count = Collection::::iter().count(); + Ok((prev_count as u32).encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(prev_count: Vec) -> Result<(), TryRuntimeError> { + let prev_count: u32 = Decode::decode(&mut prev_count.as_slice()).expect( + "the state parameter should be something that was generated by pre_upgrade", + ); + let post_count = Collection::::iter().count() as u32; + ensure!( + prev_count == post_count, + "the records count before and after the migration should be the same" + ); + + ensure!(Pallet::::on_chain_storage_version() >= 1, "wrong storage version"); + + Ok(()) + } + } +} From 9fd921a1cd3bbe5b8e1838d5f57c3f4a7d1b449a Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 13 Nov 2024 09:36:36 +0700 Subject: [PATCH 31/76] feat: add nonfungibles api + integration tests --- pop-api/Cargo.toml | 3 + pop-api/integration-tests/Cargo.toml | 3 + .../contracts/nonfungibles/Cargo.toml | 21 + .../contracts/nonfungibles/lib.rs | 244 +++++++++++ .../integration-tests/src/fungibles/utils.rs | 33 -- pop-api/integration-tests/src/lib.rs | 9 +- .../integration-tests/src/nonfungibles/mod.rs | 409 ++++++++++++++++++ .../src/nonfungibles/utils.rs | 328 ++++++++++++++ pop-api/integration-tests/src/utils.rs | 34 ++ pop-api/src/lib.rs | 3 + pop-api/src/macros.rs | 53 +++ pop-api/src/primitives.rs | 3 +- pop-api/src/v0/mod.rs | 3 + pop-api/src/v0/nonfungibles/errors.rs | 35 ++ pop-api/src/v0/nonfungibles/events.rs | 50 +++ pop-api/src/v0/nonfungibles/mod.rs | 300 +++++++++++++ pop-api/src/v0/nonfungibles/traits.rs | 85 ++++ pop-api/src/v0/nonfungibles/types.rs | 192 ++++++++ 18 files changed, 1771 insertions(+), 37 deletions(-) create mode 100644 pop-api/integration-tests/contracts/nonfungibles/Cargo.toml create mode 100644 pop-api/integration-tests/contracts/nonfungibles/lib.rs create mode 100644 pop-api/integration-tests/src/nonfungibles/mod.rs create mode 100644 pop-api/integration-tests/src/nonfungibles/utils.rs create mode 100644 pop-api/integration-tests/src/utils.rs create mode 100644 pop-api/src/macros.rs create mode 100644 pop-api/src/v0/nonfungibles/errors.rs create mode 100644 pop-api/src/v0/nonfungibles/events.rs create mode 100644 pop-api/src/v0/nonfungibles/mod.rs create mode 100644 pop-api/src/v0/nonfungibles/traits.rs create mode 100644 pop-api/src/v0/nonfungibles/types.rs diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index 4caf8eaad..c9d0c4f59 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -6,6 +6,8 @@ name = "pop-api" version = "0.0.0" [dependencies] +bitflags = { version = "1.3.2" } +enumflags2 = "0.7.9" ink = { version = "5.0.0", default-features = false } pop-primitives = { path = "../primitives", default-features = false } sp-io = { version = "37.0.0", default-features = false, features = [ @@ -22,4 +24,5 @@ path = "src/lib.rs" [features] default = [ "std" ] fungibles = [ ] +nonfungibles = [ ] std = [ "ink/std", "pop-primitives/std", "sp-io/std" ] diff --git a/pop-api/integration-tests/Cargo.toml b/pop-api/integration-tests/Cargo.toml index 482a214f7..f87cdddb8 100644 --- a/pop-api/integration-tests/Cargo.toml +++ b/pop-api/integration-tests/Cargo.toml @@ -16,8 +16,10 @@ log = "0.4.22" pallet-assets = { version = "37.0.0", default-features = false } pallet-balances = { version = "37.0.0", default-features = false } pallet-contracts = { version = "35.0.0", default-features = false } +pallet-nfts = { path = "../../pallets/nfts", default-features = false } pop-api = { path = "../../pop-api", default-features = false, features = [ "fungibles", + "nonfungibles", ] } pop-primitives = { path = "../../primitives", default-features = false } pop-runtime-devnet = { path = "../../runtime/devnet", default-features = false } @@ -39,6 +41,7 @@ std = [ "pallet-assets/std", "pallet-balances/std", "pallet-contracts/std", + "pallet-nfts/std", "pop-api/std", "pop-primitives/std", "pop-runtime-devnet/std", diff --git a/pop-api/integration-tests/contracts/nonfungibles/Cargo.toml b/pop-api/integration-tests/contracts/nonfungibles/Cargo.toml new file mode 100644 index 000000000..9c8bda797 --- /dev/null +++ b/pop-api/integration-tests/contracts/nonfungibles/Cargo.toml @@ -0,0 +1,21 @@ +[package] +authors = [ "R0GUE " ] +edition = "2021" +name = "nonfungibles" +version = "0.1.0" + +[dependencies] +ink = { version = "5.0.0", default-features = false } +pop-api = { path = "../../../../pop-api", default-features = false, features = [ "nonfungibles" ] } + +[lib] +path = "lib.rs" + +[features] +default = [ "std" ] +e2e-tests = [ ] +ink-as-dependency = [ ] +std = [ + "ink/std", + "pop-api/std", +] diff --git a/pop-api/integration-tests/contracts/nonfungibles/lib.rs b/pop-api/integration-tests/contracts/nonfungibles/lib.rs new file mode 100644 index 000000000..134467914 --- /dev/null +++ b/pop-api/integration-tests/contracts/nonfungibles/lib.rs @@ -0,0 +1,244 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +/// 1. PSP-34 +/// 2. PSP-34 Metadata +/// 3. Management +/// 4. PSP-34 Mintable & Burnable +use ink::prelude::vec::Vec; +use pop_api::{ + nonfungibles::{ + self as api, + events::{Approval, AttributeSet, Transfer}, + AttributeNamespace, CancelAttributesApprovalWitness, CollectionConfig, CollectionDetails, + CollectionId, DestroyWitness, ItemId, MintWitness, + }, + StatusCode, +}; + +pub type Result = core::result::Result; + +#[ink::contract] +mod nonfungibles { + use super::*; + + #[ink(storage)] + #[derive(Default)] + pub struct NonFungibles; + + impl NonFungibles { + #[ink(constructor, payable)] + pub fn new() -> Self { + ink::env::debug_println!("PopApiNonFungiblesExample::new"); + Default::default() + } + + /// 1. PSP-34 Interface: + /// - total_supply + /// - balance_of + /// - allowance + /// - transfer + /// - approve + /// - owner_of + + #[ink(message)] + pub fn total_supply(&self, collection: CollectionId) -> Result { + api::total_supply(collection) + } + + #[ink(message)] + pub fn balance_of(&self, collection: CollectionId, owner: AccountId) -> Result { + api::balance_of(collection, owner) + } + + #[ink(message)] + pub fn allowance( + &self, + collection: CollectionId, + owner: AccountId, + operator: AccountId, + item: Option, + ) -> Result { + api::allowance(collection, owner, operator, item) + } + + #[ink(message)] + pub fn transfer( + &mut self, + collection: CollectionId, + item: ItemId, + to: AccountId, + ) -> Result<()> { + api::transfer(collection, item, to)?; + self.env().emit_event(Transfer { + from: Some(self.env().account_id()), + to: Some(to), + item, + }); + Ok(()) + } + + #[ink(message)] + pub fn approve( + &mut self, + collection: CollectionId, + item: Option, + operator: AccountId, + approved: bool, + ) -> Result<()> { + api::approve(collection, item, operator, approved)?; + self.env().emit_event(Approval { + owner: self.env().account_id(), + operator, + item, + approved, + }); + Ok(()) + } + + #[ink(message)] + pub fn owner_of( + &self, + collection: CollectionId, + item: ItemId, + ) -> Result> { + api::owner_of(collection, item) + } + + /// 2. PSP-34 Metadata Interface: + /// - get_attribute + + #[ink(message)] + pub fn get_attribute( + &self, + collection: CollectionId, + item: ItemId, + namespace: AttributeNamespace, + key: Vec, + ) -> Result>> { + api::get_attribute(collection, item, namespace, key) + } + + /// 3. Asset Management: + /// - create + /// - destroy + /// - collection + /// - set_attribute + /// - clear_attribute + /// - set_metadata + /// - clear_metadata + /// - approve_item_attributes + /// - cancel_item_attributes_approval + /// - set_max_supply + /// - item_metadata + + #[ink(message)] + pub fn create(&mut self, admin: AccountId, config: CollectionConfig) -> Result<()> { + api::create(admin, config) + } + + #[ink(message)] + pub fn destroy(&mut self, collection: CollectionId, witness: DestroyWitness) -> Result<()> { + api::destroy(collection, witness) + } + + #[ink(message)] + pub fn collection(&self, collection: CollectionId) -> Result> { + api::collection(collection) + } + + #[ink(message)] + pub fn set_attribute( + &mut self, + collection: CollectionId, + item: ItemId, + namespace: AttributeNamespace, + key: Vec, + value: Vec, + ) -> Result<()> { + api::set_attribute(collection, item, namespace, key.clone(), value.clone())?; + self.env().emit_event(AttributeSet { item, key, data: value }); + Ok(()) + } + + #[ink(message)] + pub fn clear_attribute( + &mut self, + collection: CollectionId, + item: ItemId, + namespace: AttributeNamespace, + key: Vec, + ) -> Result<()> { + api::clear_attribute(collection, item, namespace, key) + } + + #[ink(message)] + pub fn set_metadata( + &mut self, + collection: CollectionId, + item: ItemId, + data: Vec, + ) -> Result<()> { + api::set_metadata(collection, item, data) + } + + #[ink(message)] + pub fn clear_metadata(&mut self, collection: CollectionId, item: ItemId) -> Result<()> { + api::clear_metadata(collection, item) + } + + #[ink(message)] + pub fn approve_item_attributes( + &mut self, + collection: CollectionId, + item: ItemId, + delegate: AccountId, + ) -> Result<()> { + api::approve_item_attributes(collection, item, delegate) + } + + #[ink(message)] + pub fn cancel_item_attributes_approval( + &mut self, + collection: CollectionId, + item: ItemId, + delegate: AccountId, + witness: CancelAttributesApprovalWitness, + ) -> Result<()> { + api::cancel_item_attributes_approval(collection, item, delegate, witness) + } + + #[ink(message)] + pub fn set_max_supply(&mut self, collection: CollectionId, max_supply: u32) -> Result<()> { + api::set_max_supply(collection, max_supply) + } + + #[ink(message)] + pub fn item_metadata( + &mut self, + collection: CollectionId, + item: ItemId, + ) -> Result>> { + api::item_metadata(collection, item) + } + + /// 4. PSP-22 Mintable & Burnable Interface: + /// - mint + /// - burn + + #[ink(message)] + pub fn mint( + &mut self, + to: AccountId, + collection: CollectionId, + item: ItemId, + witness: MintWitness, + ) -> Result<()> { + api::mint(to, collection, item, witness) + } + + #[ink(message)] + pub fn burn(&mut self, collection: CollectionId, item: ItemId) -> Result<()> { + api::burn(collection, item) + } + } +} diff --git a/pop-api/integration-tests/src/fungibles/utils.rs b/pop-api/integration-tests/src/fungibles/utils.rs index 07be866e5..018c6cfc4 100644 --- a/pop-api/integration-tests/src/fungibles/utils.rs +++ b/pop-api/integration-tests/src/fungibles/utils.rs @@ -1,16 +1,5 @@ use super::*; -fn do_bare_call(function: &str, addr: &AccountId32, params: Vec) -> ExecReturnValue { - let function = function_selector(function); - let params = [function, params].concat(); - bare_call(addr.clone(), params, 0).expect("should work") -} - -// TODO - issue #263 - why result.data[1..] -pub(super) fn decoded(result: ExecReturnValue) -> Result { - ::decode(&mut &result.data[1..]).map_err(|_| result) -} - pub(super) fn total_supply(addr: &AccountId32, token_id: TokenId) -> Result { let result = do_bare_call("total_supply", addr, token_id.encode()); decoded::>(result.clone()) @@ -340,25 +329,3 @@ pub(super) fn instantiate_and_create_fungible( .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) .map(|_| address) } - -/// Get the last event from pallet contracts. -pub(super) fn last_contract_event() -> Vec { - let events = System::read_events_for_pallet::>(); - let contract_events = events - .iter() - .filter_map(|event| match event { - pallet_contracts::Event::::ContractEmitted { data, .. } => - Some(data.as_slice()), - _ => None, - }) - .collect::>(); - contract_events.last().unwrap().to_vec() -} - -/// Decodes a byte slice into an `AccountId` as defined in `primitives`. -/// -/// This is used to resolve type mismatches between the `AccountId` in the integration tests and the -/// contract environment. -pub fn account_id_from_slice(s: &[u8; 32]) -> pop_api::primitives::AccountId { - pop_api::primitives::AccountId::decode(&mut &s[..]).expect("Should be decoded to AccountId") -} diff --git a/pop-api/integration-tests/src/lib.rs b/pop-api/integration-tests/src/lib.rs index 586418894..4738d010a 100644 --- a/pop-api/integration-tests/src/lib.rs +++ b/pop-api/integration-tests/src/lib.rs @@ -9,13 +9,16 @@ use frame_support::{ }; use pallet_contracts::{Code, CollectEvents, Determinism, ExecReturnValue}; #[cfg(feature = "devnet")] -use pop_runtime_devnet::{Assets, Contracts, Runtime, RuntimeOrigin, System, UNIT}; +use pop_runtime_devnet::{Assets, Contracts, Nfts, Runtime, RuntimeOrigin, System, UNIT}; #[cfg(feature = "testnet")] -use pop_runtime_testnet::{Assets, Contracts, Runtime, RuntimeOrigin, System, UNIT}; +use pop_runtime_testnet::{Assets, Contracts, Nfts, Runtime, RuntimeOrigin, System, UNIT}; use scale::{Decode, Encode}; use sp_runtime::{AccountId32, BuildStorage, DispatchError}; +use utils::*; mod fungibles; +mod nonfungibles; +mod utils; type Balance = u128; @@ -23,7 +26,7 @@ const ALICE: AccountId32 = AccountId32::new([1_u8; 32]); const BOB: AccountId32 = AccountId32::new([2_u8; 32]); const DEBUG_OUTPUT: pallet_contracts::DebugInfo = pallet_contracts::DebugInfo::UnsafeDebug; const FERDIE: AccountId32 = AccountId32::new([3_u8; 32]); -const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024); +const GAS_LIMIT: Weight = Weight::from_parts(500_000_000_000, 3 * 1024 * 1024); const INIT_AMOUNT: Balance = 100_000_000 * UNIT; const INIT_VALUE: Balance = 100 * UNIT; diff --git a/pop-api/integration-tests/src/nonfungibles/mod.rs b/pop-api/integration-tests/src/nonfungibles/mod.rs new file mode 100644 index 000000000..c92652c08 --- /dev/null +++ b/pop-api/integration-tests/src/nonfungibles/mod.rs @@ -0,0 +1,409 @@ +use frame_support::BoundedVec; +use pop_api::{ + nonfungibles::{ + events::{Approval, AttributeSet, Transfer}, + types::*, + }, + primitives::BlockNumber, +}; +use pop_primitives::{ArithmeticError::*, Error, Error::*, TokenError::*}; +use utils::*; + +use super::*; + +mod utils; + +const COLLECTION_ID: CollectionId = 0; +const ITEM_ID: ItemId = 1; +const CONTRACT: &str = "contracts/nonfungibles/target/ink/nonfungibles.wasm"; + +#[test] +fn total_supply_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + // No tokens in circulation. + assert_eq!( + total_supply(&addr, COLLECTION_ID), + Ok(Nfts::collection_items(COLLECTION_ID).unwrap_or_default() as u128) + ); + assert_eq!(total_supply(&addr, COLLECTION_ID), Ok(0)); + + // Tokens in circulation. + nfts::create_collection_and_mint_to(&addr, &addr, &ALICE, ITEM_ID); + assert_eq!( + total_supply(&addr, COLLECTION_ID), + Ok(Nfts::collection_items(COLLECTION_ID).unwrap_or_default() as u128) + ); + assert_eq!(total_supply(&addr, COLLECTION_ID), Ok(1)); + }); +} + +#[test] +fn balance_of_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + // No tokens in circulation. + assert_eq!( + balance_of(&addr, COLLECTION_ID, ALICE), + Ok(nfts::balance_of(COLLECTION_ID, ALICE)), + ); + assert_eq!(total_supply(&addr, COLLECTION_ID), Ok(0)); + + // Tokens in circulation. + nfts::create_collection_and_mint_to(&addr, &addr, &ALICE, ITEM_ID); + assert_eq!( + balance_of(&addr, COLLECTION_ID, ALICE), + Ok(nfts::balance_of(COLLECTION_ID, ALICE)), + ); + assert_eq!(total_supply(&addr, COLLECTION_ID), Ok(1)); + }); +} + +#[test] +fn allowance_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + // No tokens in circulation. + assert_eq!( + allowance(&addr.clone(), COLLECTION_ID, addr.clone(), ALICE, None), + Ok(!Nfts::check_allowance(&COLLECTION_ID, &None, &addr, &ALICE).is_err()), + ); + assert_eq!(allowance(&addr.clone(), COLLECTION_ID, addr.clone(), ALICE, None), Ok(false)); + + let (_, item) = + nfts::create_collection_mint_and_approve(&addr, &addr, ITEM_ID, &addr, &ALICE); + assert_eq!( + allowance(&addr.clone(), COLLECTION_ID, addr.clone(), ALICE, Some(item)), + Ok(Nfts::check_allowance(&COLLECTION_ID, &Some(item), &addr.clone(), &ALICE).is_ok()), + ); + assert_eq!( + allowance(&addr.clone(), COLLECTION_ID, addr.clone(), ALICE, Some(item)), + Ok(true) + ); + }); +} + +#[test] +fn transfer_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + let before_transfer_balance = nfts::balance_of(COLLECTION_ID, ALICE); + assert_ok!(transfer(&addr, collection, item, ALICE)); + let after_transfer_balance = nfts::balance_of(COLLECTION_ID, ALICE); + assert_eq!(after_transfer_balance - before_transfer_balance, 1); + }); +} + +#[test] +fn approve_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + assert_ok!(approve(&addr, collection, Some(item), ALICE, true)); + assert!(Nfts::check_allowance(&collection, &Some(item), &addr.clone(), &ALICE).is_ok(),); + + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(ALICE), collection, item, BOB.into())); + }); +} + +#[test] +fn owner_of_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &ALICE, ITEM_ID); + assert_eq!(owner_of(&addr, collection, item), Ok(ALICE)); + }); +} + +#[test] +fn get_attribute_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + + assert_ok!(Nfts::set_attribute( + RuntimeOrigin::signed(addr.clone()), + collection, + Some(item), + pallet_nfts::AttributeNamespace::CollectionOwner, + BoundedVec::truncate_from("some attribute".as_bytes().to_vec()), + BoundedVec::truncate_from("some value".as_bytes().to_vec()), + )); + assert_eq!( + get_attribute( + &addr.clone(), + collection, + item, + AttributeNamespace::CollectionOwner, + "some attribute".as_bytes().to_vec(), + ), + Ok(Some("some value".as_bytes().to_vec())) + ); + }); +} + +#[test] +fn set_attribute_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + + assert_ok!(set_attribute( + &addr.clone(), + collection, + item, + AttributeNamespace::CollectionOwner, + "some attribute".as_bytes().to_vec(), + "some value".as_bytes().to_vec(), + )); + + assert_eq!( + pallet_nfts::Attribute::::get(( + collection, + Some(item), + pallet_nfts::AttributeNamespace::CollectionOwner, + AttributeKey::truncate_from("some attribute".as_bytes().to_vec()), + )) + .map(|attribute| attribute.0), + Some(AttributeValue::truncate_from("some value".as_bytes().to_vec())) + ); + }); +} + +#[test] +fn clear_attribute_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + assert_ok!(Nfts::set_attribute( + RuntimeOrigin::signed(addr.clone()), + collection, + Some(item), + pallet_nfts::AttributeNamespace::CollectionOwner, + BoundedVec::truncate_from("some attribute".as_bytes().to_vec()), + BoundedVec::truncate_from("some value".as_bytes().to_vec()), + )); + assert_ok!(clear_attribute( + &addr.clone(), + collection, + item, + AttributeNamespace::CollectionOwner, + "some attribute".as_bytes().to_vec() + )); + assert_eq!( + pallet_nfts::Attribute::::get(( + collection, + Some(item), + pallet_nfts::AttributeNamespace::CollectionOwner, + AttributeKey::truncate_from("some attribute".as_bytes().to_vec()), + )) + .map(|attribute| attribute.0), + None + ); + }); +} + +#[test] +fn approve_item_attributes_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + assert_ok!(approve_item_attributes(&addr.clone(), collection, item, ALICE)); + assert_ok!(Nfts::set_attribute( + RuntimeOrigin::signed(ALICE), + collection, + Some(item), + pallet_nfts::AttributeNamespace::Account(ALICE), + BoundedVec::truncate_from("some attribute".as_bytes().to_vec()), + BoundedVec::truncate_from("some value".as_bytes().to_vec()), + )); + assert_eq!( + pallet_nfts::Attribute::::get(( + collection, + Some(item), + pallet_nfts::AttributeNamespace::Account(ALICE), + AttributeKey::truncate_from("some attribute".as_bytes().to_vec()), + )) + .map(|attribute| attribute.0), + Some(AttributeValue::truncate_from("some value".as_bytes().to_vec())) + ); + }); +} + +#[test] +fn cancel_item_attributes_approval_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + assert_ok!(Nfts::approve_item_attributes( + RuntimeOrigin::signed(addr.clone()), + collection, + item, + ALICE.into() + )); + assert_ok!(Nfts::set_attribute( + RuntimeOrigin::signed(ALICE), + collection, + Some(item), + pallet_nfts::AttributeNamespace::Account(ALICE), + BoundedVec::truncate_from("some attribute".as_bytes().to_vec()), + BoundedVec::truncate_from("some value".as_bytes().to_vec()), + )); + assert_ok!(cancel_item_attributes_approval( + &addr.clone(), + collection, + item, + ALICE, + CancelAttributesApprovalWitness { account_attributes: 1 } + )); + assert!(Nfts::set_attribute( + RuntimeOrigin::signed(ALICE), + collection, + Some(item), + pallet_nfts::AttributeNamespace::Account(ALICE), + BoundedVec::truncate_from("some attribute".as_bytes().to_vec()), + BoundedVec::truncate_from("some value".as_bytes().to_vec()), + ) + .is_err()); + }); +} + +#[test] +fn set_metadata_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + assert_ok!(set_metadata(&addr.clone(), collection, item, vec![])); + assert_eq!(Nfts::item_metadata(collection, item), Some(MetadataData::default())); + }); +} + +#[test] +fn clear_metadata_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + assert_ok!(Nfts::set_metadata( + RuntimeOrigin::signed(addr.clone()), + collection, + item, + MetadataData::default() + )); + assert_ok!(clear_metadata(&addr.clone(), collection, item)); + assert_eq!(Nfts::item_metadata(collection, item), None); + }); +} + +#[test] +fn create_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + let collection = nfts::next_collection_id(); + assert_ok!(create( + &addr.clone(), + addr.clone(), + CollectionConfig { + max_supply: Some(100), + mint_settings: MintSettings::default(), + settings: CollectionSettings::all_enabled(), + } + )); + assert_eq!( + pallet_nfts::Collection::::get(collection), + Some(pallet_nfts::CollectionDetails { + owner: addr.clone(), + owner_deposit: 100000000000, + items: 0, + item_metadatas: 0, + item_configs: 0, + attributes: 0, + }) + ); + }); +} + +#[test] +fn destroy_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + let collection = nfts::create_collection(&addr, &addr); + assert_ok!(destroy( + &addr.clone(), + collection, + DestroyWitness { item_metadatas: 0, item_configs: 0, attributes: 0 } + )); + assert_eq!(pallet_nfts::Collection::::get(collection), None); + }); +} + +#[test] +fn set_max_supply_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + let value = 10; + + let collection = nfts::create_collection(&addr, &addr); + assert_ok!(set_max_supply(&addr.clone(), collection, value)); + + (0..value).into_iter().for_each(|i| { + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(addr.clone()), + collection, + i, + ALICE.into(), + None + )); + }); + assert!(Nfts::mint( + RuntimeOrigin::signed(addr.clone()), + collection, + value + 1, + ALICE.into(), + None + ) + .is_err()); + }); +} + +#[test] +fn mint_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + let value = 10; + + let collection = nfts::create_collection(&addr, &addr); + assert_ok!(mint( + &addr.clone(), + ALICE, + collection, + ITEM_ID, + MintWitness { mint_price: None, owned_item: None } + )); + assert_eq!(nfts::balance_of(COLLECTION_ID, ALICE), 1); + }); +} + +#[test] +fn burn_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + assert_ok!(burn(&addr.clone(), collection, ITEM_ID,)); + assert_eq!(nfts::balance_of(COLLECTION_ID, addr), 0); + }); +} diff --git a/pop-api/integration-tests/src/nonfungibles/utils.rs b/pop-api/integration-tests/src/nonfungibles/utils.rs new file mode 100644 index 000000000..0c1c3c19b --- /dev/null +++ b/pop-api/integration-tests/src/nonfungibles/utils.rs @@ -0,0 +1,328 @@ +use super::*; + +pub(super) type AttributeKey = BoundedVec::KeyLimit>; +pub(super) type AttributeValue = BoundedVec::ValueLimit>; +pub(super) type MetadataData = BoundedVec::StringLimit>; + +pub(super) fn total_supply(addr: &AccountId32, collection: CollectionId) -> Result { + let result = do_bare_call("total_supply", addr, collection.encode()); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn balance_of( + addr: &AccountId32, + collection: CollectionId, + owner: AccountId32, +) -> Result { + let params = [collection.encode(), owner.encode()].concat(); + let result = do_bare_call("balance_of", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn allowance( + addr: &AccountId32, + collection: CollectionId, + owner: AccountId32, + operator: AccountId32, + item: Option, +) -> Result { + let params = [collection.encode(), owner.encode(), operator.encode(), item.encode()].concat(); + let result = do_bare_call("allowance", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn transfer( + addr: &AccountId32, + collection: CollectionId, + item: ItemId, + to: AccountId32, +) -> Result<(), Error> { + let params = [collection.encode(), item.encode(), to.encode()].concat(); + let result = do_bare_call("transfer", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn approve( + addr: &AccountId32, + collection: CollectionId, + item: Option, + operator: AccountId32, + approved: bool, +) -> Result<(), Error> { + let params = + [collection.encode(), item.encode(), operator.encode(), approved.encode()].concat(); + let result = do_bare_call("approve", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn owner_of( + addr: &AccountId32, + collection: CollectionId, + item: ItemId, +) -> Result { + let params = [collection.encode(), item.encode()].concat(); + let result = do_bare_call("owner_of", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn get_attribute( + addr: &AccountId32, + collection: CollectionId, + item: ItemId, + namespace: AttributeNamespace, + key: Vec, +) -> Result>, Error> { + let params = [ + collection.encode(), + item.encode(), + namespace.encode(), + AttributeKey::truncate_from(key).encode(), + ] + .concat(); + let result = do_bare_call("get_attribute", &addr, params); + decoded::, Error>>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) + .map(|value| value.map(|v| v.to_vec())) +} + +pub(super) fn create( + addr: &AccountId32, + admin: AccountId32, + config: CollectionConfig, +) -> Result<(), Error> { + let params = [admin.encode(), config.encode()].concat(); + let result = do_bare_call("create", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn destroy( + addr: &AccountId32, + collection: CollectionId, + witness: DestroyWitness, +) -> Result<(), Error> { + let params = [collection.encode(), witness.encode()].concat(); + let result = do_bare_call("destroy", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn collection( + addr: &AccountId32, + collection: CollectionId, +) -> Result, Error> { + let result = do_bare_call("collection", &addr, collection.encode()); + decoded::, Error>>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn set_attribute( + addr: &AccountId32, + collection: CollectionId, + item: ItemId, + namespace: AttributeNamespace, + key: Vec, + value: Vec, +) -> Result<(), Error> { + let params = [ + collection.encode(), + item.encode(), + namespace.encode(), + AttributeKey::truncate_from(key).encode(), + AttributeValue::truncate_from(value).encode(), + ] + .concat(); + let result = do_bare_call("set_attribute", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn clear_attribute( + addr: &AccountId32, + collection: CollectionId, + item: ItemId, + namespace: AttributeNamespace, + key: Vec, +) -> Result<(), Error> { + let params = [collection.encode(), item.encode(), namespace.encode(), key.encode()].concat(); + let result = do_bare_call("clear_attribute", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn set_metadata( + addr: &AccountId32, + collection: CollectionId, + item: ItemId, + data: Vec, +) -> Result<(), Error> { + let params = [collection.encode(), item.encode(), data.encode()].concat(); + let result = do_bare_call("set_metadata", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn clear_metadata( + addr: &AccountId32, + collection: CollectionId, + item: ItemId, +) -> Result<(), Error> { + let params = [collection.encode(), item.encode()].concat(); + let result = do_bare_call("clear_metadata", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn approve_item_attributes( + addr: &AccountId32, + collection: CollectionId, + item: ItemId, + delegate: AccountId32, +) -> Result<(), Error> { + let params = [collection.encode(), item.encode(), delegate.encode()].concat(); + let result = do_bare_call("approve_item_attributes", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn cancel_item_attributes_approval( + addr: &AccountId32, + collection: CollectionId, + item: ItemId, + delegate: AccountId32, + witness: CancelAttributesApprovalWitness, +) -> Result<(), Error> { + let params = [collection.encode(), item.encode(), delegate.encode(), witness.encode()].concat(); + let result = do_bare_call("cancel_item_attributes_approval", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn set_max_supply( + addr: &AccountId32, + collection: CollectionId, + max_supply: u32, +) -> Result<(), Error> { + let params = [collection.encode(), max_supply.encode()].concat(); + let result = do_bare_call("set_max_supply", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn item_metadata( + addr: &AccountId32, + collection: CollectionId, + item: ItemId, +) -> Result>, Error> { + let params = [collection.encode(), item.encode()].concat(); + let result = do_bare_call("item_metadata", &addr, params); + decoded::>, Error>>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) + .map(|value| value.map(|v| v.to_vec())) +} + +pub(super) fn mint( + addr: &AccountId32, + to: AccountId32, + collection: CollectionId, + item: ItemId, + witness: MintWitness, +) -> Result<(), Error> { + let params = [to.encode(), collection.encode(), item.encode(), witness.encode()].concat(); + let result = do_bare_call("mint", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) fn burn( + addr: &AccountId32, + collection: CollectionId, + item: ItemId, +) -> Result<(), Error> { + let params = [collection.encode(), item.encode()].concat(); + let result = do_bare_call("burn", &addr, params); + decoded::>(result.clone()) + .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) +} + +pub(super) mod nfts { + use super::*; + + pub(crate) fn create_collection_and_mint_to( + owner: &AccountId32, + admin: &AccountId32, + to: &AccountId32, + item: ItemId, + ) -> (CollectionId, ItemId) { + let collection = create_collection(owner, admin); + mint(collection, item, owner, to); + (collection, item) + } + + pub(crate) fn create_collection_mint_and_approve( + owner: &AccountId32, + admin: &AccountId32, + item: ItemId, + to: &AccountId32, + operator: &AccountId32, + ) -> (u32, u32) { + let (collection, item) = create_collection_and_mint_to(&owner.clone(), admin, to, item); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(to.clone()), + collection, + Some(item), + operator.clone().into(), + None + )); + (collection, item) + } + + pub(crate) fn create_collection(owner: &AccountId32, admin: &AccountId32) -> CollectionId { + let next_id = next_collection_id(); + assert_ok!(Nfts::create( + RuntimeOrigin::signed(owner.clone()), + admin.clone().into(), + collection_config_with_all_settings_enabled() + )); + next_id + } + + pub(crate) fn next_collection_id() -> u32 { + pallet_nfts::NextCollectionId::::get().unwrap_or_default() + } + + pub(crate) fn mint( + collection: CollectionId, + item: ItemId, + owner: &AccountId32, + to: &AccountId32, + ) -> ItemId { + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(owner.clone()), + collection, + item, + to.clone().into(), + None + )); + item + } + + pub(crate) fn balance_of(collection: CollectionId, owner: AccountId32) -> u32 { + pallet_nfts::AccountBalance::::get(collection, owner) + } + + pub(super) fn collection_config_with_all_settings_enabled( + ) -> pallet_nfts::CollectionConfig { + pallet_nfts::CollectionConfig { + settings: pallet_nfts::CollectionSettings::all_enabled(), + max_supply: None, + mint_settings: pallet_nfts::MintSettings::default(), + } + } +} diff --git a/pop-api/integration-tests/src/utils.rs b/pop-api/integration-tests/src/utils.rs new file mode 100644 index 000000000..9b2131fd1 --- /dev/null +++ b/pop-api/integration-tests/src/utils.rs @@ -0,0 +1,34 @@ +use super::*; + +/// Get the last event from pallet contracts. +pub(super) fn last_contract_event() -> Vec { + let events = System::read_events_for_pallet::>(); + let contract_events = events + .iter() + .filter_map(|event| match event { + pallet_contracts::Event::::ContractEmitted { data, .. } => + Some(data.as_slice()), + _ => None, + }) + .collect::>(); + contract_events.last().unwrap().to_vec() +} + +/// Decodes a byte slice into an `AccountId` as defined in `primitives`. +/// +/// This is used to resolve type mismatches between the `AccountId` in the integration tests and the +/// contract environment. +pub(super) fn account_id_from_slice(s: &[u8; 32]) -> pop_api::primitives::AccountId { + pop_api::primitives::AccountId::decode(&mut &s[..]).expect("Should be decoded to AccountId") +} + +pub(super) fn do_bare_call(function: &str, addr: &AccountId32, params: Vec) -> ExecReturnValue { + let function = function_selector(function); + let params = [function, params].concat(); + bare_call(addr.clone(), params, 0).expect("should work") +} + +// TODO - issue #263 - why result.data[1..] +pub(super) fn decoded(result: ExecReturnValue) -> Result { + ::decode(&mut &result.data[1..]).map_err(|_| result) +} diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index b9dbf6342..9a4172f86 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -12,6 +12,8 @@ use constants::DECODING_FAILED; use ink::env::chain_extension::{ChainExtensionMethod, FromStatusCode}; pub use v0::*; +/// Module providing macros. +pub mod macros; /// Module providing primitives types. pub mod primitives; /// The first version of the API. @@ -73,6 +75,7 @@ mod constants { pub(crate) const ASSETS: u8 = 52; pub(crate) const BALANCES: u8 = 10; pub(crate) const FUNGIBLES: u8 = 150; + pub(crate) const NONFUNGIBLES: u8 = 151; } // Helper method to build a dispatch call or a call to read state. diff --git a/pop-api/src/macros.rs b/pop-api/src/macros.rs new file mode 100644 index 000000000..7a9fd34db --- /dev/null +++ b/pop-api/src/macros.rs @@ -0,0 +1,53 @@ +/// Implements encoding and decoding traits for a wrapper type that represents +/// bitflags. The wrapper type should contain a field of type `$size`, where +/// `$size` is an integer type (e.g., u8, u16, u32) that can represent the bitflags. +/// The `$bitflag_enum` type is the enumeration type that defines the individual bitflags. +/// +/// This macro provides implementations for the following traits: +/// - `MaxEncodedLen`: Calculates the maximum encoded length for the wrapper type. +/// - `Encode`: Encodes the wrapper type using the provided encoding function. +/// - `EncodeLike`: Trait indicating the type can be encoded as is. +/// - `Decode`: Decodes the wrapper type from the input. +/// - `TypeInfo`: Provides type information for the wrapper type. +macro_rules! impl_codec_bitflags { + ($wrapper:ty, $size:ty, $bitflag_enum:ty) => { + impl ink::scale::MaxEncodedLen for $wrapper { + fn max_encoded_len() -> usize { + <$size>::max_encoded_len() + } + } + impl ink::scale::Encode for $wrapper { + fn using_encoded R>(&self, f: F) -> R { + self.0.bits().using_encoded(f) + } + } + impl ink::scale::EncodeLike for $wrapper {} + impl ink::scale::Decode for $wrapper { + fn decode( + input: &mut I, + ) -> ::core::result::Result { + let field = <$size>::decode(input)?; + Ok(Self(BitFlags::from_bits(field as $size).map_err(|_| "invalid value")?)) + } + } + + #[cfg(feature = "std")] + impl ink::scale_info::TypeInfo for $wrapper { + type Identity = Self; + + fn type_info() -> ink::scale_info::Type { + ink::scale_info::Type::builder() + .path(ink::scale_info::Path::new("BitFlags", module_path!())) + .type_params(vec![ink::scale_info::TypeParameter::new( + "T", + Some(ink::scale_info::meta_type::<$bitflag_enum>()), + )]) + .composite( + ink::scale_info::build::Fields::unnamed() + .field(|f| f.ty::<$size>().type_name(stringify!($bitflag_enum))), + ) + } + } + }; +} +pub(crate) use impl_codec_bitflags; diff --git a/pop-api/src/primitives.rs b/pop-api/src/primitives.rs index 2fcb8a952..ce396fc88 100644 --- a/pop-api/src/primitives.rs +++ b/pop-api/src/primitives.rs @@ -3,4 +3,5 @@ pub use pop_primitives::*; // Public due to integration tests crate. pub type AccountId = ::AccountId; -pub(crate) type Balance = ::Balance; +pub type Balance = ::Balance; +pub type BlockNumber = ::BlockNumber; diff --git a/pop-api/src/v0/mod.rs b/pop-api/src/v0/mod.rs index c61538923..2f12f5f44 100644 --- a/pop-api/src/v0/mod.rs +++ b/pop-api/src/v0/mod.rs @@ -8,6 +8,9 @@ use crate::{ /// APIs for fungible tokens. #[cfg(feature = "fungibles")] pub mod fungibles; +/// APIs for nonfungible tokens. +#[cfg(feature = "nonfungibles")] +pub mod nonfungibles; pub(crate) const V0: u8 = 0; diff --git a/pop-api/src/v0/nonfungibles/errors.rs b/pop-api/src/v0/nonfungibles/errors.rs new file mode 100644 index 000000000..c955bf608 --- /dev/null +++ b/pop-api/src/v0/nonfungibles/errors.rs @@ -0,0 +1,35 @@ +//! A set of errors for use in smart contracts that interact with the nonfungibles api. This +//! includes errors compliant to standards. + +use ink::prelude::string::{String, ToString}; + +use super::*; + +/// The PSP34 error. +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub enum Psp34Error { + /// Custom error type for cases if writer of traits added own restrictions + Custom(String), + /// Returned if owner approves self + SelfApprove, + /// Returned if the caller doesn't have allowance for transferring. + NotApproved, + /// Returned if the owner already own the token. + TokenExists, + /// Returned if the token doesn't exist + TokenNotExists, + /// Returned if safe transfer check fails + SafeTransferCheckFailed(String), +} + +impl From for Psp34Error { + /// Converts a `StatusCode` to a `PSP22Error`. + fn from(value: StatusCode) -> Self { + let encoded = value.0.to_le_bytes(); + match encoded { + // TODO: Handle conversion. + _ => Psp34Error::Custom(value.0.to_string()), + } + } +} diff --git a/pop-api/src/v0/nonfungibles/events.rs b/pop-api/src/v0/nonfungibles/events.rs new file mode 100644 index 000000000..3c4098685 --- /dev/null +++ b/pop-api/src/v0/nonfungibles/events.rs @@ -0,0 +1,50 @@ +//! A set of events for use in smart contracts interacting with the nonfungibles API. +//! +//! The `Transfer` and `Approval` events conform to the PSP-34 standard. +//! +//! These events are not emitted by the API itself but can be used in your contracts to +//! track token operations. Be mindful of the costs associated with emitting events. +//! +//! For more details, refer to [ink! events](https://use.ink/basics/events). + +use super::*; + +/// Event emitted when a token transfer occurs. +#[ink::event] +pub struct Transfer { + /// The source of the transfer. `None` when minting. + #[ink(topic)] + pub from: Option, + /// The recipient of the transfer. `None` when burning. + #[ink(topic)] + pub to: Option, + /// The item transferred (or minted/burned). + pub item: ItemId, +} + +/// Event emitted when a token approve occurs. +#[ink::event] +pub struct Approval { + /// The owner providing the allowance. + #[ink(topic)] + pub owner: AccountId, + /// The beneficiary of the allowance. + #[ink(topic)] + pub operator: AccountId, + /// The item which is (dis)approved. `None` for all owner's items. + pub item: Option, + /// Whether allowance is set or removed. + pub approved: bool, +} + +/// Event emitted when an attribute is set for a token. +#[ink::event] +pub struct AttributeSet { + /// The item which attribute is set. + #[ink(topic)] + pub item: ItemId, + /// The key for the attribute. + pub key: Vec, + /// The data for the attribute. + pub data: Vec, +} diff --git a/pop-api/src/v0/nonfungibles/mod.rs b/pop-api/src/v0/nonfungibles/mod.rs new file mode 100644 index 000000000..7b2bd187e --- /dev/null +++ b/pop-api/src/v0/nonfungibles/mod.rs @@ -0,0 +1,300 @@ +//! The `nonfungibles` module provides an API for interacting and managing nonfungible tokens. +//! +//! The API includes the following interfaces: +//! 1. PSP-34 +//! 2. PSP-34 Metadata +//! 3. PSP-22 Mintable & Burnable + +use constants::*; +pub use errors::*; +pub use events::*; +use ink::prelude::vec::Vec; +pub use traits::*; +pub use types::*; + +use crate::{ + constants::NONFUNGIBLES, + primitives::{AccountId, BlockNumber}, + ChainExtensionMethodApi, Result, StatusCode, +}; + +pub mod errors; +pub mod events; +pub mod traits; +pub mod types; + +#[inline] +pub fn total_supply(collection: CollectionId) -> Result { + build_read_state(TOTAL_SUPPLY) + .input::() + .output::, true>() + .handle_error_code::() + .call(&(collection)) +} + +#[inline] +pub fn balance_of(collection: CollectionId, owner: AccountId) -> Result { + build_read_state(BALANCE_OF) + .input::<(CollectionId, AccountId)>() + .output::, true>() + .handle_error_code::() + .call(&(collection, owner)) +} + +#[inline] +pub fn allowance( + collection: CollectionId, + owner: AccountId, + operator: AccountId, + item: Option, +) -> Result { + build_read_state(ALLOWANCE) + .input::<(CollectionId, AccountId, AccountId, Option)>() + .output::, true>() + .handle_error_code::() + .call(&(collection, owner, operator, item)) +} + +#[inline] +pub fn transfer(collection: CollectionId, item: ItemId, to: AccountId) -> Result<()> { + build_dispatch(TRANSFER) + .input::<(CollectionId, ItemId, AccountId)>() + .output::, true>() + .handle_error_code::() + .call(&(collection, item, to)) +} + +#[inline] +pub fn approve( + collection: CollectionId, + item: Option, + operator: AccountId, + approved: bool, +) -> Result<()> { + build_dispatch(APPROVE) + .input::<(CollectionId, Option, AccountId, bool)>() + .output::, true>() + .handle_error_code::() + .call(&(collection, item, operator, approved)) +} + +#[inline] +pub fn owner_of(collection: CollectionId, item: ItemId) -> Result> { + build_read_state(OWNER_OF) + .input::<(CollectionId, ItemId)>() + .output::>, true>() + .handle_error_code::() + .call(&(collection, item)) +} + +#[inline] +pub fn get_attribute( + collection: CollectionId, + item: ItemId, + namespace: AttributeNamespace, + key: Vec, +) -> Result>> { + build_read_state(GET_ATTRIBUTE) + .input::<(CollectionId, ItemId, AttributeNamespace, Vec)>() + .output::>>, true>() + .handle_error_code::() + .call(&(collection, item, namespace, key)) +} + +#[inline] +pub fn create(admin: AccountId, config: CollectionConfig) -> Result<()> { + build_dispatch(CREATE) + .input::<(AccountId, CollectionConfig)>() + .output::, true>() + .handle_error_code::() + .call(&(admin, config))?; + Ok(()) +} + +#[inline] +pub fn destroy(collection: CollectionId, witness: DestroyWitness) -> Result<()> { + build_dispatch(DESTROY) + .input::<(CollectionId, DestroyWitness)>() + .output::, true>() + .handle_error_code::() + .call(&(collection, witness)) +} + +#[inline] +pub fn collection(collection: CollectionId) -> Result> { + build_read_state(COLLECTION) + .input::() + .output::>, true>() + .handle_error_code::() + .call(&(collection)) +} + +#[inline] +pub fn item_metadata(collection: CollectionId, item: ItemId) -> Result>> { + build_read_state(ITEM_METADATA) + .input::<(CollectionId, ItemId)>() + .output::>>, true>() + .handle_error_code::() + .call(&(collection, item)) +} + +#[inline] +pub fn set_attribute( + collection: CollectionId, + item: ItemId, + namespace: AttributeNamespace, + key: Vec, + value: Vec, +) -> Result<()> { + build_dispatch(SET_ATTRIBUTE) + .input::<(CollectionId, Option, AttributeNamespace, Vec, Vec)>() + .output::, true>() + .handle_error_code::() + .call(&(collection, Some(item), namespace, key, value)) +} + +#[inline] +pub fn clear_attribute( + collection: CollectionId, + item: ItemId, + namespace: AttributeNamespace, + key: Vec, +) -> Result<()> { + build_dispatch(CLEAR_ATTRIBUTE) + .input::<(CollectionId, Option, AttributeNamespace, Vec)>() + .output::, true>() + .handle_error_code::() + .call(&(collection, Some(item), namespace, key)) +} + +#[inline] +pub fn set_metadata(collection: CollectionId, item: ItemId, data: Vec) -> Result<()> { + build_dispatch(SET_METADATA) + .input::<(CollectionId, ItemId, Vec)>() + .output::, true>() + .handle_error_code::() + .call(&(collection, item, data)) +} + +#[inline] +pub fn clear_metadata(collection: CollectionId, item: ItemId) -> Result<()> { + build_dispatch(CLEAR_METADATA) + .input::<(CollectionId, ItemId)>() + .output::, true>() + .handle_error_code::() + .call(&(collection, item)) +} + +#[inline] +pub fn approve_item_attributes( + collection: CollectionId, + item: ItemId, + delegate: AccountId, +) -> Result<()> { + build_dispatch(APPROVE_ITEM_ATTRIBUTES) + .input::<(CollectionId, ItemId, AccountId)>() + .output::, true>() + .handle_error_code::() + .call(&(collection, item, delegate)) +} + +#[inline] +pub fn cancel_item_attributes_approval( + collection: CollectionId, + item: ItemId, + delegate: AccountId, + witness: CancelAttributesApprovalWitness, +) -> Result<()> { + build_dispatch(CANCEL_ITEM_ATTRIBUTES_APPROVAL) + .input::<(CollectionId, ItemId, AccountId, CancelAttributesApprovalWitness)>() + .output::, true>() + .handle_error_code::() + .call(&(collection, item, delegate, witness)) +} + +#[inline] +pub fn set_max_supply(collection: CollectionId, max_supply: u32) -> Result<()> { + build_dispatch(SET_MAX_SUPPLY) + .input::<(CollectionId, u32)>() + .output::, true>() + .handle_error_code::() + .call(&(collection, max_supply)) +} + +#[inline] +pub fn mint( + to: AccountId, + collection: CollectionId, + item: ItemId, + witness: MintWitness, +) -> Result<()> { + build_dispatch(MINT) + .input::<(AccountId, CollectionId, ItemId, MintWitness)>() + .output::, true>() + .handle_error_code::() + .call(&(to, collection, item, witness)) +} + +#[inline] +pub fn burn(collection: CollectionId, item: ItemId) -> Result<()> { + build_dispatch(BURN) + .input::<(CollectionId, ItemId)>() + .output::, true>() + .handle_error_code::() + .call(&(collection, item)) +} + +#[inline] +pub fn next_collection_id() -> Result { + build_read_state(NEXT_COLLECTION_ID) + .output::, true>() + .handle_error_code::() + .call(&()) +} + +mod constants { + /// 1. PSP-34 + pub(super) const TOTAL_SUPPLY: u8 = 0; + pub(super) const BALANCE_OF: u8 = 1; + pub(super) const ALLOWANCE: u8 = 2; + pub(super) const TRANSFER: u8 = 3; + pub(super) const APPROVE: u8 = 4; + pub(super) const OWNER_OF: u8 = 5; + + /// 2. PSP-34 Metadata + pub(super) const GET_ATTRIBUTE: u8 = 6; + + /// 3. Management + pub(super) const CREATE: u8 = 7; + pub(super) const DESTROY: u8 = 8; + pub(super) const COLLECTION: u8 = 9; + pub(super) const NEXT_COLLECTION_ID: u8 = 10; + pub(super) const ITEM_METADATA: u8 = 11; + pub(super) const SET_ATTRIBUTE: u8 = 12; + pub(super) const CLEAR_ATTRIBUTE: u8 = 13; + pub(super) const SET_METADATA: u8 = 14; + pub(super) const CLEAR_METADATA: u8 = 15; + pub(super) const APPROVE_ITEM_ATTRIBUTES: u8 = 16; + pub(super) const CANCEL_ITEM_ATTRIBUTES_APPROVAL: u8 = 17; + pub(super) const SET_MAX_SUPPLY: u8 = 18; + + /// 4. PSP-34 Mintable & Burnable + pub(super) const MINT: u8 = 19; + pub(super) const BURN: u8 = 20; +} + +// Helper method to build a dispatch call. +// +// Parameters: +// - 'dispatchable': The index of the dispatchable function within the module. +fn build_dispatch(dispatchable: u8) -> ChainExtensionMethodApi { + crate::v0::build_dispatch(NONFUNGIBLES, dispatchable) +} + +// Helper method to build a call to read state. +// +// Parameters: +// - 'state_query': The index of the runtime state query. +fn build_read_state(state_query: u8) -> ChainExtensionMethodApi { + crate::v0::build_read_state(NONFUNGIBLES, state_query) +} diff --git a/pop-api/src/v0/nonfungibles/traits.rs b/pop-api/src/v0/nonfungibles/traits.rs new file mode 100644 index 000000000..c9e3ad041 --- /dev/null +++ b/pop-api/src/v0/nonfungibles/traits.rs @@ -0,0 +1,85 @@ +//! Traits that can be used by contracts. Including standard compliant traits. + +use core::result::Result; + +use super::*; + +#[ink::trait_definition] +pub trait Psp34 { + /// Returns the collection `Id`. + #[ink(message, selector = 0xffa27a5f)] + fn collection_id(&self) -> ItemId; + + // Returns the current total supply of the NFT. + #[ink(message, selector = 0x628413fe)] + fn total_supply(&self) -> u128; + + /// Returns the amount of items the owner has within a collection. + /// + /// # Parameters + /// - `owner` - The account whose balance is being queried. + #[ink(message, selector = 0xcde7e55f)] + fn balance_of(&self, owner: AccountId) -> u32; + + /// Returns whether the operator is approved by the owner to withdraw `item`. If `item` is + /// `None`, it returns whether the operator is approved to withdraw all owner's items for the + /// given collection. + /// + /// # Parameters + /// * `owner` - The account that owns the item(s). + /// * `operator` - the account that is allowed to withdraw the item(s). + /// * `item` - The item. If `None`, it is regarding all owner's items in collection. + #[ink(message, selector = 0x4790f55a)] + fn allowance(&self, owner: AccountId, operator: AccountId, id: Option) -> bool; + + /// Transfers an owned or approved item to the specified recipient. + /// + /// # Parameters + /// * `to` - The recipient account. + /// * `item` - The item. + /// - `data` - Additional data in unspecified format. + #[ink(message, selector = 0x3128d61b)] + fn transfer(&mut self, to: AccountId, id: ItemId, data: Vec) -> Result<(), Psp34Error>; + + /// Approves operator to withdraw item(s) from the contract's account. + /// + /// # Parameters + /// * `operator` - The account that is allowed to withdraw the item. + /// * `item` - Optional item. `None` means all items owned in the specified collection. + /// * `approved` - Whether the operator is given or removed the right to withdraw the item(s). + #[ink(message, selector = 0x1932a8b0)] + fn approve( + &mut self, + operator: AccountId, + id: Option, + approved: bool, + ) -> Result<(), Psp34Error>; + + /// Returns the owner of an item within a specified collection, if any. + /// + /// # Parameters + /// * `item` - The item. + #[ink(message, selector = 0x1168624d)] + fn owner_of(&self, id: ItemId) -> Option; +} + +#[ink::trait_definition] +pub trait Psp34Metadata { + /// Returns the attribute of `item` for the given `key`. + /// + /// # Parameters + /// * `item` - The item. If `None` the attributes for the collection are queried. + /// * `namespace` - The attribute's namespace. + /// * `key` - The key of the attribute. + #[ink(message, selector = 0xf19d48d1)] + fn get_attribute(&self, id: ItemId, key: Vec) -> Option>; +} + +#[ink::trait_definition] +pub trait Psp34Enumerable { + #[ink(message, selector = 0x3bcfb511)] + fn owners_token_by_index(&self, owner: AccountId, index: u128) -> Result; + + #[ink(message, selector = 0xcd0340d0)] + fn token_by_index(&self, index: u128) -> Result; +} diff --git a/pop-api/src/v0/nonfungibles/types.rs b/pop-api/src/v0/nonfungibles/types.rs new file mode 100644 index 000000000..c630f04b9 --- /dev/null +++ b/pop-api/src/v0/nonfungibles/types.rs @@ -0,0 +1,192 @@ +use enumflags2::{bitflags, BitFlags}; + +use super::*; +use crate::{macros::impl_codec_bitflags, primitives::AccountId}; + +pub type ItemId = u32; +pub type CollectionId = u32; +pub(super) type Balance = u32; + +/// Information about a collection. +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub struct CollectionDetails { + /// Collection's owner. + pub owner: AccountId, + /// The total balance deposited by the owner for all the storage data associated with this + /// collection. Used by `destroy`. + pub owner_deposit: Balance, + /// The total number of outstanding items of this collection. + pub items: u32, + /// The total number of outstanding item metadata of this collection. + pub item_metadatas: u32, + /// The total number of outstanding item configs of this collection. + pub item_configs: u32, + /// The total number of attributes for this collection. + pub attributes: u32, +} + +/// Attribute namespaces for non-fungible tokens. +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub enum AttributeNamespace { + /// An attribute set by collection's owner. + #[codec(index = 1)] + CollectionOwner, + /// An attribute set by item's owner. + #[codec(index = 2)] + ItemOwner, + /// An attribute set by a pre-approved account. + #[codec(index = 3)] + Account(AccountId), +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub enum MintType { + /// Only an `Issuer` could mint items. + Issuer, + /// Anyone could mint items. + Public, + /// Only holders of items in specified collection could mint new items. + HolderOf(CollectionId), +} + +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub struct CancelAttributesApprovalWitness { + /// An amount of attributes previously created by account. + pub account_attributes: u32, +} + +/// Witness data for the destroy transactions. +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub struct DestroyWitness { + /// The total number of items in this collection that have outstanding item metadata. + #[codec(compact)] + pub item_metadatas: u32, + /// The total number of outstanding item configs of this collection. + #[codec(compact)] + pub item_configs: u32, + /// The total number of attributes for this collection. + #[codec(compact)] + pub attributes: u32, +} + +/// Witness data for items mint transactions. +#[derive(Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub struct MintWitness { + /// Provide the id of the item in a required collection. + pub owned_item: Option, + /// The price specified in mint settings. + pub mint_price: Option, +} + +/// Collection's configuration. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub struct CollectionConfig { + /// Collection's settings. + pub settings: CollectionSettings, + /// Collection's max supply. + pub max_supply: Option, + /// Default settings each item will get during the mint. + pub mint_settings: MintSettings, +} + +/// Support for up to 64 user-enabled features on a collection. +#[bitflags] +#[repr(u64)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub enum CollectionSetting { + /// Items in this collection are transferable. + TransferableItems, + /// The metadata of this collection can be modified. + UnlockedMetadata, + /// Attributes of this collection can be modified. + UnlockedAttributes, + /// The supply of this collection can be modified. + UnlockedMaxSupply, + /// When this isn't set then the deposit is required to hold the items of this collection. + DepositRequired, +} + +/// Wrapper type for `BitFlags` that implements `Codec`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CollectionSettings(pub BitFlags); + +impl CollectionSettings { + pub fn from_disabled(settings: BitFlags) -> Self { + Self(settings) + } + + #[cfg(feature = "std")] + pub fn all_enabled() -> Self { + Self(BitFlags::EMPTY) + } +} + +impl_codec_bitflags!(CollectionSettings, u64, CollectionSetting); + +/// Support for up to 64 user-enabled features on an item. +#[bitflags] +#[repr(u64)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub enum ItemSetting { + /// This item is transferable. + Transferable, + /// The metadata of this item can be modified. + UnlockedMetadata, + /// Attributes of this item can be modified. + UnlockedAttributes, +} + +/// Wrapper type for `BitFlags` that implements `Codec`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct ItemSettings(pub BitFlags); + +impl ItemSettings { + pub fn all_enabled() -> Self { + Self(BitFlags::EMPTY) + } + + #[cfg(feature = "std")] + pub fn from_disabled(settings: BitFlags) -> Self { + Self(settings) + } +} + +impl_codec_bitflags!(ItemSettings, u64, ItemSetting); + +/// Holds the information about minting. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[ink::scale_derive(Encode, Decode, TypeInfo)] +pub struct MintSettings { + /// Whether anyone can mint or if minters are restricted to some subset. + pub mint_type: MintType, + /// An optional price per mint. + pub price: Option, + /// When the mint starts. + pub start_block: Option, + /// When the mint ends. + pub end_block: Option, + /// Default settings each item will get during the mint. + pub default_item_settings: ItemSettings, +} + +#[cfg(feature = "std")] +impl Default for MintSettings { + fn default() -> Self { + Self { + mint_type: MintType::Issuer, + price: None, + start_block: None, + end_block: None, + default_item_settings: ItemSettings::all_enabled(), + } + } +} From 325e8d31f7b4f39e7f0386d98b00b7560e9126d4 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 18 Nov 2024 12:26:45 +0700 Subject: [PATCH 32/76] chore: delete migration.rs --- pallets/nfts/src/migration.rs | 120 ---------------------------------- 1 file changed, 120 deletions(-) delete mode 100644 pallets/nfts/src/migration.rs diff --git a/pallets/nfts/src/migration.rs b/pallets/nfts/src/migration.rs deleted file mode 100644 index 8f82e0922..000000000 --- a/pallets/nfts/src/migration.rs +++ /dev/null @@ -1,120 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use super::*; -use frame_support::traits::OnRuntimeUpgrade; -use log; - -#[cfg(feature = "try-runtime")] -use sp_runtime::TryRuntimeError; - -pub mod v1 { - use frame_support::{pallet_prelude::*, weights::Weight}; - - use super::*; - - #[derive(Decode)] - pub struct OldCollectionDetails { - pub owner: AccountId, - pub owner_deposit: DepositBalance, - pub items: u32, - pub item_metadatas: u32, - pub attributes: u32, - } - - impl OldCollectionDetails { - /// Migrates the old collection details to the new v1 format. - fn migrate_to_v1(self, item_configs: u32) -> CollectionDetails { - CollectionDetails { - owner: self.owner, - owner_deposit: self.owner_deposit, - items: self.items, - item_metadatas: self.item_metadatas, - item_configs, - attributes: self.attributes, - } - } - } - - /// A migration utility to update the storage version from v0 to v1 for the pallet. - pub struct MigrateToV1(core::marker::PhantomData); - impl OnRuntimeUpgrade for MigrateToV1 { - fn on_runtime_upgrade() -> Weight { - let in_code_version = Pallet::::in_code_storage_version(); - let on_chain_version = Pallet::::on_chain_storage_version(); - - log::info!( - target: LOG_TARGET, - "Running migration with in-code storage version {:?} / onchain {:?}", - in_code_version, - on_chain_version - ); - - if on_chain_version == 0 && in_code_version == 1 { - let mut translated = 0u64; - let mut configs_iterated = 0u64; - Collection::::translate::< - OldCollectionDetails>, - _, - >(|key, old_value| { - let item_configs = ItemConfigOf::::iter_prefix(&key).count() as u32; - configs_iterated += item_configs as u64; - translated.saturating_inc(); - Some(old_value.migrate_to_v1(item_configs)) - }); - - in_code_version.put::>(); - - log::info!( - target: LOG_TARGET, - "Upgraded {} records, storage to version {:?}", - translated, - in_code_version - ); - T::DbWeight::get().reads_writes(translated + configs_iterated + 1, translated + 1) - } else { - log::info!( - target: LOG_TARGET, - "Migration did not execute. This probably should be removed" - ); - T::DbWeight::get().reads(1) - } - } - - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - let prev_count = Collection::::iter().count(); - Ok((prev_count as u32).encode()) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(prev_count: Vec) -> Result<(), TryRuntimeError> { - let prev_count: u32 = Decode::decode(&mut prev_count.as_slice()).expect( - "the state parameter should be something that was generated by pre_upgrade", - ); - let post_count = Collection::::iter().count() as u32; - ensure!( - prev_count == post_count, - "the records count before and after the migration should be the same" - ); - - ensure!(Pallet::::on_chain_storage_version() >= 1, "wrong storage version"); - - Ok(()) - } - } -} From f205909f6a752ac48a2489516805d404d5fcbcee Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:36:59 +0700 Subject: [PATCH 33/76] chore: fork pallet nfts --- pallets/nfts/Cargo.toml | 8 ++++---- pallets/nfts/runtime-api/Cargo.toml | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pallets/nfts/Cargo.toml b/pallets/nfts/Cargo.toml index bef584b85..791db0a73 100644 --- a/pallets/nfts/Cargo.toml +++ b/pallets/nfts/Cargo.toml @@ -1,5 +1,5 @@ [package] -authors = [ "Parity Technologies ", "R0GUE " ] +authors = ["Parity Technologies ", "R0GUE "] description = "Fork of FRAME NFTs pallet" edition.workspace = true homepage = "https://substrate.io" @@ -10,13 +10,13 @@ repository.workspace = true version = "31.0.0" [package.metadata.docs.rs] -targets = [ "x86_64-unknown-linux-gnu" ] +targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { workspace = true } enumflags2 = { workspace = true } log = { workspace = true } -scale-info = { features = [ "derive" ], workspace = true } +scale-info = { features = ["derive"], workspace = true } # Substrate frame-benchmarking = { optional = true, workspace = true } @@ -31,7 +31,7 @@ pallet-balances.workspace = true sp-keystore.workspace = true [features] -default = [ "std" ] +default = ["std"] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", diff --git a/pallets/nfts/runtime-api/Cargo.toml b/pallets/nfts/runtime-api/Cargo.toml index 503642ef0..d9a748d6c 100644 --- a/pallets/nfts/runtime-api/Cargo.toml +++ b/pallets/nfts/runtime-api/Cargo.toml @@ -1,5 +1,5 @@ [package] -authors = [ "Parity Technologies ", "R0GUE " ] +authors = ["Parity Technologies ", "R0GUE "] description = "Runtime API for the FRAME NFTs pallet." edition.workspace = true homepage = "https://substrate.io" @@ -13,13 +13,13 @@ version = "23.0.0" workspace = true [package.metadata.docs.rs] -targets = [ "x86_64-unknown-linux-gnu" ] +targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { features = [ "derive" ], workspace = true } +codec = { features = ["derive"], workspace = true } pallet-nfts.workspace = true sp-api.workspace = true [features] -default = [ "std" ] -std = [ "codec/std", "pallet-nfts/std", "sp-api/std" ] +default = ["std"] +std = ["codec/std", "pallet-nfts/std", "sp-api/std"] From 9cc20fe147fb1a2ba5d560f363dea3f168c546e9 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:23:51 +0700 Subject: [PATCH 34/76] chore: forked pallet nfts --- pallets/nfts/src/benchmarking.rs | 2 +- pallets/nfts/src/common_functions.rs | 4 +- pallets/nfts/src/features/approvals.rs | 3 +- pallets/nfts/src/features/atomic_swap.rs | 4 +- pallets/nfts/src/features/attributes.rs | 3 +- pallets/nfts/src/features/buy_sell.rs | 3 +- .../src/features/create_delete_collection.rs | 3 +- .../nfts/src/features/create_delete_item.rs | 3 +- pallets/nfts/src/features/lock.rs | 4 +- pallets/nfts/src/features/metadata.rs | 4 +- pallets/nfts/src/features/roles.rs | 4 +- pallets/nfts/src/features/settings.rs | 3 +- pallets/nfts/src/features/transfer.rs | 4 +- pallets/nfts/src/impl_nonfungibles.rs | 9 ++-- pallets/nfts/src/lib.rs | 10 ++-- pallets/nfts/src/migration.rs | 4 +- pallets/nfts/src/mock.rs | 48 +++++++++---------- pallets/nfts/src/tests.rs | 3 +- pallets/nfts/src/types.rs | 24 +--------- 19 files changed, 49 insertions(+), 93 deletions(-) diff --git a/pallets/nfts/src/benchmarking.rs b/pallets/nfts/src/benchmarking.rs index 8fa87557c..bc81096b4 100644 --- a/pallets/nfts/src/benchmarking.rs +++ b/pallets/nfts/src/benchmarking.rs @@ -19,6 +19,7 @@ #![cfg(feature = "runtime-benchmarks")] +use super::*; use enumflags2::{BitFlag, BitFlags}; use frame_benchmarking::v1::{ account, benchmarks_instance_pallet, whitelist_account, whitelisted_caller, BenchmarkError, @@ -31,7 +32,6 @@ use frame_support::{ use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin as SystemOrigin}; use sp_runtime::traits::{Bounded, One}; -use super::*; use crate::Pallet as Nfts; const SEED: u32 = 0; diff --git a/pallets/nfts/src/common_functions.rs b/pallets/nfts/src/common_functions.rs index f51de1922..2c4778c14 100644 --- a/pallets/nfts/src/common_functions.rs +++ b/pallets/nfts/src/common_functions.rs @@ -17,12 +17,10 @@ //! Various pieces of common functionality. +use crate::*; use alloc::vec::Vec; - use frame_support::pallet_prelude::*; -use crate::*; - impl, I: 'static> Pallet { /// Get the owner of the item, if the item exists. pub fn owner(collection: T::CollectionId, item: T::ItemId) -> Option { diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index ad5d93c2e..053fa6716 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -19,9 +19,8 @@ //! The bitflag [`PalletFeature::Approvals`] needs to be set in [`Config::Features`] for NFTs //! to have the functionality defined in this module. -use frame_support::pallet_prelude::*; - use crate::*; +use frame_support::pallet_prelude::*; impl, I: 'static> Pallet { /// Approves the transfer of an item to a delegate. diff --git a/pallets/nfts/src/features/atomic_swap.rs b/pallets/nfts/src/features/atomic_swap.rs index 31c93fba8..830283b73 100644 --- a/pallets/nfts/src/features/atomic_swap.rs +++ b/pallets/nfts/src/features/atomic_swap.rs @@ -20,13 +20,12 @@ //! The bitflag [`PalletFeature::Swaps`] needs to be set in [`Config::Features`] for NFTs //! to have the functionality defined in this module. +use crate::*; use frame_support::{ pallet_prelude::*, traits::{Currency, ExistenceRequirement::KeepAlive}, }; -use crate::*; - impl, I: 'static> Pallet { /// Creates a new swap offer for the specified item. /// @@ -102,7 +101,6 @@ impl, I: 'static> Pallet { Ok(()) } - /// Cancels the specified swap offer. /// /// This function is used to cancel the specified swap offer created by the `caller` account. If diff --git a/pallets/nfts/src/features/attributes.rs b/pallets/nfts/src/features/attributes.rs index ab0cdc68b..28f7bd2c5 100644 --- a/pallets/nfts/src/features/attributes.rs +++ b/pallets/nfts/src/features/attributes.rs @@ -20,9 +20,8 @@ //! The bitflag [`PalletFeature::Attributes`] needs to be set in [`Config::Features`] for NFTs //! to have the functionality defined in this module. -use frame_support::pallet_prelude::*; - use crate::*; +use frame_support::pallet_prelude::*; impl, I: 'static> Pallet { /// Sets the attribute of an item or a collection. diff --git a/pallets/nfts/src/features/buy_sell.rs b/pallets/nfts/src/features/buy_sell.rs index 8cf86f79a..d6ec6f50d 100644 --- a/pallets/nfts/src/features/buy_sell.rs +++ b/pallets/nfts/src/features/buy_sell.rs @@ -20,13 +20,12 @@ //! The bitflag [`PalletFeature::Trading`] needs to be set in the [`Config::Features`] for NFTs //! to have the functionality defined in this module. +use crate::*; use frame_support::{ pallet_prelude::*, traits::{Currency, ExistenceRequirement, ExistenceRequirement::KeepAlive}, }; -use crate::*; - impl, I: 'static> Pallet { /// Pays the specified tips to the corresponding receivers. /// diff --git a/pallets/nfts/src/features/create_delete_collection.rs b/pallets/nfts/src/features/create_delete_collection.rs index 348ec6b92..f03df7fdd 100644 --- a/pallets/nfts/src/features/create_delete_collection.rs +++ b/pallets/nfts/src/features/create_delete_collection.rs @@ -18,9 +18,8 @@ //! This module contains helper methods to perform functionality associated with creating and //! destroying collections for the NFTs pallet. -use frame_support::pallet_prelude::*; - use crate::*; +use frame_support::pallet_prelude::*; impl, I: 'static> Pallet { /// Create a new collection with the given `collection`, `owner`, `admin`, `config`, `deposit`, diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index e9843b2e7..37f64ae1b 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -18,9 +18,8 @@ //! This module contains helper methods to perform functionality associated with minting and burning //! items for the NFTs pallet. -use frame_support::{pallet_prelude::*, traits::ExistenceRequirement}; - use crate::*; +use frame_support::{pallet_prelude::*, traits::ExistenceRequirement}; impl, I: 'static> Pallet { /// Mint a new unique item with the given `collection`, `item`, and other minting configuration diff --git a/pallets/nfts/src/features/lock.rs b/pallets/nfts/src/features/lock.rs index 4649f4a01..1c3c9c867 100644 --- a/pallets/nfts/src/features/lock.rs +++ b/pallets/nfts/src/features/lock.rs @@ -18,9 +18,8 @@ //! This module contains helper methods to configure locks on collections and items for the NFTs //! pallet. -use frame_support::pallet_prelude::*; - use crate::*; +use frame_support::pallet_prelude::*; impl, I: 'static> Pallet { /// Locks a collection with specified settings. @@ -30,6 +29,7 @@ impl, I: 'static> Pallet { /// /// Note: it's possible only to lock the setting, but not to unlock it after. + /// /// - `origin`: The origin of the transaction, representing the account attempting to lock the /// collection. /// - `collection`: The identifier of the collection to be locked. diff --git a/pallets/nfts/src/features/metadata.rs b/pallets/nfts/src/features/metadata.rs index b3d16b12c..260061603 100644 --- a/pallets/nfts/src/features/metadata.rs +++ b/pallets/nfts/src/features/metadata.rs @@ -17,12 +17,10 @@ //! This module contains helper methods to configure the metadata of collections and items. +use crate::*; use alloc::vec::Vec; - use frame_support::pallet_prelude::*; -use crate::*; - impl, I: 'static> Pallet { /// Sets the metadata for a specific item within a collection. /// diff --git a/pallets/nfts/src/features/roles.rs b/pallets/nfts/src/features/roles.rs index 053eaf0b0..aa6394f70 100644 --- a/pallets/nfts/src/features/roles.rs +++ b/pallets/nfts/src/features/roles.rs @@ -17,12 +17,10 @@ //! This module contains helper methods to configure account roles for existing collections. +use crate::*; use alloc::{collections::btree_map::BTreeMap, vec::Vec}; - use frame_support::pallet_prelude::*; -use crate::*; - impl, I: 'static> Pallet { /// Set the team roles for a specific collection. /// diff --git a/pallets/nfts/src/features/settings.rs b/pallets/nfts/src/features/settings.rs index 9c7ac7ca2..d4f7533ff 100644 --- a/pallets/nfts/src/features/settings.rs +++ b/pallets/nfts/src/features/settings.rs @@ -17,9 +17,8 @@ //! This module provides helper methods to configure collection settings for the NFTs pallet. -use frame_support::pallet_prelude::*; - use crate::*; +use frame_support::pallet_prelude::*; impl, I: 'static> Pallet { /// Forcefully change the configuration of a collection. diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index b7223a7c3..bba834483 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -18,9 +18,8 @@ //! This module contains helper methods to perform the transfer functionalities //! of the NFTs pallet. -use frame_support::pallet_prelude::*; - use crate::*; +use frame_support::pallet_prelude::*; impl, I: 'static> Pallet { /// Transfer an NFT to the specified destination account. @@ -161,7 +160,6 @@ impl, I: 'static> Pallet { Ok(()) }) } - /// Set or unset the ownership acceptance for an account regarding a specific collection. /// /// - `who`: The account for which to set or unset the ownership acceptance. diff --git a/pallets/nfts/src/impl_nonfungibles.rs b/pallets/nfts/src/impl_nonfungibles.rs index 362cccd93..c90655aad 100644 --- a/pallets/nfts/src/impl_nonfungibles.rs +++ b/pallets/nfts/src/impl_nonfungibles.rs @@ -17,6 +17,7 @@ //! Implementations for `nonfungibles` traits. +use super::*; use frame_support::{ ensure, storage::KeyPrefixIterator, @@ -25,11 +26,9 @@ use frame_support::{ }; use sp_runtime::{DispatchError, DispatchResult}; -use super::*; - impl, I: 'static> Inspect<::AccountId> for Pallet { - type CollectionId = T::CollectionId; type ItemId = T::ItemId; + type CollectionId = T::CollectionId; fn owner( collection: &Self::CollectionId, @@ -141,11 +140,9 @@ impl, I: 'static> InspectRole<::AccountId> for P fn is_issuer(collection: &Self::CollectionId, who: &::AccountId) -> bool { Self::has_role(collection, who, CollectionRole::Issuer) } - fn is_admin(collection: &Self::CollectionId, who: &::AccountId) -> bool { Self::has_role(collection, who, CollectionRole::Admin) } - fn is_freezer(collection: &Self::CollectionId, who: &::AccountId) -> bool { Self::has_role(collection, who, CollectionRole::Freezer) } @@ -472,9 +469,9 @@ impl, I: 'static> Trading> for Pallet impl, I: 'static> InspectEnumerable for Pallet { type CollectionsIterator = KeyPrefixIterator<>::CollectionId>; type ItemsIterator = KeyPrefixIterator<>::ItemId>; - type OwnedInCollectionIterator = KeyPrefixIterator<>::ItemId>; type OwnedIterator = KeyPrefixIterator<(>::CollectionId, >::ItemId)>; + type OwnedInCollectionIterator = KeyPrefixIterator<>::ItemId>; /// Returns an iterator of the collections in existence. /// diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index 89bfb9637..4e5493a3c 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -51,18 +51,18 @@ pub mod weights; extern crate alloc; use alloc::{boxed::Box, vec, vec::Vec}; - use codec::{Decode, Encode}; use frame_support::traits::{ tokens::Locker, BalanceStatus::Reserved, Currency, EnsureOriginWithArg, Incrementable, ReservableCurrency, }; use frame_system::Config as SystemConfig; -pub use pallet::*; use sp_runtime::{ traits::{IdentifyAccount, Saturating, StaticLookup, Verify, Zero}, RuntimeDebug, }; + +pub use pallet::*; pub use types::*; pub use weights::WeightInfo; @@ -74,11 +74,10 @@ type AccountIdLookupOf = <::Lookup as StaticLookup>::Sourc #[frame_support::pallet] pub mod pallet { + use super::*; use frame_support::{pallet_prelude::*, traits::ExistenceRequirement}; use frame_system::pallet_prelude::*; - use super::*; - /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); @@ -109,17 +108,14 @@ pub mod pallet { fn collection(i: u16) -> CollectionId { i.into() } - fn item(i: u16) -> ItemId { i.into() } - fn signer() -> (sp_runtime::MultiSigner, sp_runtime::AccountId32) { let public = sp_io::crypto::sr25519_generate(0.into(), None); let account = sp_runtime::MultiSigner::Sr25519(public).into_account(); (public.into(), account) } - fn sign(signer: &sp_runtime::MultiSigner, message: &[u8]) -> sp_runtime::MultiSignature { sp_runtime::MultiSignature::Sr25519( sp_io::crypto::sr25519_sign(0.into(), &signer.clone().try_into().unwrap(), message) diff --git a/pallets/nfts/src/migration.rs b/pallets/nfts/src/migration.rs index af611bf16..8f82e0922 100644 --- a/pallets/nfts/src/migration.rs +++ b/pallets/nfts/src/migration.rs @@ -15,13 +15,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +use super::*; use frame_support::traits::OnRuntimeUpgrade; use log; + #[cfg(feature = "try-runtime")] use sp_runtime::TryRuntimeError; -use super::*; - pub mod v1 { use frame_support::{pallet_prelude::*, weights::Weight}; diff --git a/pallets/nfts/src/mock.rs b/pallets/nfts/src/mock.rs index 5532be8f4..5b589f591 100644 --- a/pallets/nfts/src/mock.rs +++ b/pallets/nfts/src/mock.rs @@ -17,6 +17,9 @@ //! Test environment for Nfts pallet. +use super::*; +use crate as pallet_nfts; + use frame_support::{ construct_runtime, derive_impl, parameter_types, traits::{AsEnsureOriginWithArg, ConstU32, ConstU64}, @@ -27,9 +30,6 @@ use sp_runtime::{ BuildStorage, MultiSignature, }; -use super::*; -use crate as pallet_nfts; - type Block = frame_system::mocking::MockBlock; construct_runtime!( @@ -47,10 +47,10 @@ pub type AccountId = ::AccountId; #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { - type AccountData = pallet_balances::AccountData; type AccountId = AccountId; - type Block = Block; type Lookup = IdentityLookup; + type Block = Block; + type AccountData = pallet_balances::AccountData; } #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] @@ -63,35 +63,35 @@ parameter_types! { } impl Config for Test { - type ApprovalsLimit = ConstU32<10>; - type AttributeDepositBase = ConstU64<1>; - type CollectionDeposit = ConstU64<2>; + type RuntimeEvent = RuntimeEvent; type CollectionId = u32; - type CreateOrigin = AsEnsureOriginWithArg>; + type ItemId = u32; type Currency = Balances; - type DepositPerByte = ConstU64<1>; - type Features = Features; + type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = frame_system::EnsureRoot; - #[cfg(feature = "runtime-benchmarks")] - type Helper = (); - type ItemAttributesApprovalsLimit = ConstU32<2>; + type Locker = (); + type CollectionDeposit = ConstU64<2>; type ItemDeposit = ConstU64<1>; - type ItemId = u32; + type MetadataDepositBase = ConstU64<1>; + type AttributeDepositBase = ConstU64<1>; + type DepositPerByte = ConstU64<1>; + type StringLimit = ConstU32<50>; type KeyLimit = ConstU32<50>; - type Locker = (); - type MaxAttributesPerCall = ConstU32<2>; - type MaxDeadlineDuration = ConstU64<10000>; + type ValueLimit = ConstU32<50>; + type ApprovalsLimit = ConstU32<10>; + type ItemAttributesApprovalsLimit = ConstU32<2>; type MaxTips = ConstU32<10>; - type MetadataDepositBase = ConstU64<1>; - /// Using `AccountPublic` here makes it trivial to convert to `AccountId` via `into_account()`. - type OffchainPublic = AccountPublic; + type MaxDeadlineDuration = ConstU64<10000>; + type MaxAttributesPerCall = ConstU32<2>; + type Features = Features; /// Off-chain = signature On-chain - therefore no conversion needed. /// It needs to be From for benchmarking. type OffchainSignature = Signature; - type RuntimeEvent = RuntimeEvent; - type StringLimit = ConstU32<50>; - type ValueLimit = ConstU32<50>; + /// Using `AccountPublic` here makes it trivial to convert to `AccountId` via `into_account()`. + type OffchainPublic = AccountPublic; type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); } pub(crate) fn new_test_ext() -> sp_io::TestExternalities { diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 44f2f32ae..e1b598ca4 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -17,6 +17,7 @@ //! Tests for Nfts pallet. +use crate::{mock::*, Event, SystemConfig, *}; use enumflags2::BitFlags; use frame_support::{ assert_noop, assert_ok, @@ -32,8 +33,6 @@ use sp_runtime::{ MultiSignature, MultiSigner, }; -use crate::{mock::*, Event, SystemConfig, *}; - type AccountIdOf = ::AccountId; fn account(id: u8) -> AccountIdOf { diff --git a/pallets/nfts/src/types.rs b/pallets/nfts/src/types.rs index f08f1d097..1687a0352 100644 --- a/pallets/nfts/src/types.rs +++ b/pallets/nfts/src/types.rs @@ -17,8 +17,9 @@ //! This module contains various basic types and data structures used in the NFTs pallet. +use super::*; +use crate::macros::*; use alloc::{vec, vec::Vec}; - use codec::EncodeLike; use enumflags2::{bitflags, BitFlags}; use frame_support::{ @@ -29,9 +30,6 @@ use frame_support::{ use frame_system::pallet_prelude::BlockNumberFor; use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter}; -use super::*; -use crate::macros::*; - /// A type alias for handling balance deposits. pub(super) type DepositBalanceOf = <>::Currency as Currency<::AccountId>>::Balance; @@ -278,15 +276,12 @@ impl CollectionSettings { pub fn all_enabled() -> Self { Self(BitFlags::EMPTY) } - pub fn get_disabled(&self) -> BitFlags { self.0 } - pub fn is_disabled(&self, setting: CollectionSetting) -> bool { self.0.contains(setting) } - pub fn from_disabled(settings: BitFlags) -> Self { Self(settings) } @@ -382,15 +377,12 @@ impl CollectionConfig bool { !self.settings.is_disabled(setting) } - pub fn has_disabled_setting(&self, setting: CollectionSetting) -> bool { self.settings.is_disabled(setting) } - pub fn enable_setting(&mut self, setting: CollectionSetting) { self.settings.0.remove(setting); } - pub fn disable_setting(&mut self, setting: CollectionSetting) { self.settings.0.insert(setting); } @@ -417,15 +409,12 @@ impl ItemSettings { pub fn all_enabled() -> Self { Self(BitFlags::EMPTY) } - pub fn get_disabled(&self) -> BitFlags { self.0 } - pub fn is_disabled(&self, setting: ItemSetting) -> bool { self.0.contains(setting) } - pub fn from_disabled(settings: BitFlags) -> Self { Self(settings) } @@ -446,19 +435,15 @@ impl ItemConfig { pub fn is_setting_enabled(&self, setting: ItemSetting) -> bool { !self.settings.is_disabled(setting) } - pub fn has_disabled_setting(&self, setting: ItemSetting) -> bool { self.settings.is_disabled(setting) } - pub fn has_disabled_settings(&self) -> bool { !self.settings.get_disabled().is_empty() } - pub fn enable_setting(&mut self, setting: ItemSetting) { self.settings.0.remove(setting); } - pub fn disable_setting(&mut self, setting: ItemSetting) { self.settings.0.insert(setting); } @@ -487,11 +472,9 @@ impl PalletFeatures { pub fn all_enabled() -> Self { Self(BitFlags::EMPTY) } - pub fn from_disabled(features: BitFlags) -> Self { Self(features) } - pub fn is_enabled(&self, feature: PalletFeature) -> bool { !self.0.contains(feature) } @@ -519,15 +502,12 @@ impl CollectionRoles { pub fn none() -> Self { Self(BitFlags::EMPTY) } - pub fn has_role(&self, role: CollectionRole) -> bool { self.0.contains(role) } - pub fn add_role(&mut self, role: CollectionRole) { self.0.insert(role); } - pub fn max_roles() -> u8 { let all: BitFlags = BitFlags::all(); all.len() as u8 From 707bd809d32356c56dc83d53e91d555199c15519 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:24:10 +0700 Subject: [PATCH 35/76] fix: formatting --- pallets/nfts/src/benchmarking.rs | 2 +- pallets/nfts/src/common_functions.rs | 4 +- pallets/nfts/src/features/approvals.rs | 3 +- pallets/nfts/src/features/atomic_swap.rs | 4 +- pallets/nfts/src/features/attributes.rs | 3 +- pallets/nfts/src/features/buy_sell.rs | 3 +- .../src/features/create_delete_collection.rs | 3 +- .../nfts/src/features/create_delete_item.rs | 3 +- pallets/nfts/src/features/lock.rs | 4 +- pallets/nfts/src/features/metadata.rs | 4 +- pallets/nfts/src/features/roles.rs | 4 +- pallets/nfts/src/features/settings.rs | 3 +- pallets/nfts/src/features/transfer.rs | 4 +- pallets/nfts/src/impl_nonfungibles.rs | 9 ++-- pallets/nfts/src/lib.rs | 10 ++-- pallets/nfts/src/migration.rs | 4 +- pallets/nfts/src/mock.rs | 48 +++++++++---------- pallets/nfts/src/tests.rs | 3 +- pallets/nfts/src/types.rs | 24 +++++++++- 19 files changed, 93 insertions(+), 49 deletions(-) diff --git a/pallets/nfts/src/benchmarking.rs b/pallets/nfts/src/benchmarking.rs index bc81096b4..8fa87557c 100644 --- a/pallets/nfts/src/benchmarking.rs +++ b/pallets/nfts/src/benchmarking.rs @@ -19,7 +19,6 @@ #![cfg(feature = "runtime-benchmarks")] -use super::*; use enumflags2::{BitFlag, BitFlags}; use frame_benchmarking::v1::{ account, benchmarks_instance_pallet, whitelist_account, whitelisted_caller, BenchmarkError, @@ -32,6 +31,7 @@ use frame_support::{ use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin as SystemOrigin}; use sp_runtime::traits::{Bounded, One}; +use super::*; use crate::Pallet as Nfts; const SEED: u32 = 0; diff --git a/pallets/nfts/src/common_functions.rs b/pallets/nfts/src/common_functions.rs index 2c4778c14..f51de1922 100644 --- a/pallets/nfts/src/common_functions.rs +++ b/pallets/nfts/src/common_functions.rs @@ -17,10 +17,12 @@ //! Various pieces of common functionality. -use crate::*; use alloc::vec::Vec; + use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Get the owner of the item, if the item exists. pub fn owner(collection: T::CollectionId, item: T::ItemId) -> Option { diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index 053fa6716..ad5d93c2e 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -19,9 +19,10 @@ //! The bitflag [`PalletFeature::Approvals`] needs to be set in [`Config::Features`] for NFTs //! to have the functionality defined in this module. -use crate::*; use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Approves the transfer of an item to a delegate. /// diff --git a/pallets/nfts/src/features/atomic_swap.rs b/pallets/nfts/src/features/atomic_swap.rs index 830283b73..31c93fba8 100644 --- a/pallets/nfts/src/features/atomic_swap.rs +++ b/pallets/nfts/src/features/atomic_swap.rs @@ -20,12 +20,13 @@ //! The bitflag [`PalletFeature::Swaps`] needs to be set in [`Config::Features`] for NFTs //! to have the functionality defined in this module. -use crate::*; use frame_support::{ pallet_prelude::*, traits::{Currency, ExistenceRequirement::KeepAlive}, }; +use crate::*; + impl, I: 'static> Pallet { /// Creates a new swap offer for the specified item. /// @@ -101,6 +102,7 @@ impl, I: 'static> Pallet { Ok(()) } + /// Cancels the specified swap offer. /// /// This function is used to cancel the specified swap offer created by the `caller` account. If diff --git a/pallets/nfts/src/features/attributes.rs b/pallets/nfts/src/features/attributes.rs index 28f7bd2c5..ab0cdc68b 100644 --- a/pallets/nfts/src/features/attributes.rs +++ b/pallets/nfts/src/features/attributes.rs @@ -20,9 +20,10 @@ //! The bitflag [`PalletFeature::Attributes`] needs to be set in [`Config::Features`] for NFTs //! to have the functionality defined in this module. -use crate::*; use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Sets the attribute of an item or a collection. /// diff --git a/pallets/nfts/src/features/buy_sell.rs b/pallets/nfts/src/features/buy_sell.rs index d6ec6f50d..8cf86f79a 100644 --- a/pallets/nfts/src/features/buy_sell.rs +++ b/pallets/nfts/src/features/buy_sell.rs @@ -20,12 +20,13 @@ //! The bitflag [`PalletFeature::Trading`] needs to be set in the [`Config::Features`] for NFTs //! to have the functionality defined in this module. -use crate::*; use frame_support::{ pallet_prelude::*, traits::{Currency, ExistenceRequirement, ExistenceRequirement::KeepAlive}, }; +use crate::*; + impl, I: 'static> Pallet { /// Pays the specified tips to the corresponding receivers. /// diff --git a/pallets/nfts/src/features/create_delete_collection.rs b/pallets/nfts/src/features/create_delete_collection.rs index f03df7fdd..348ec6b92 100644 --- a/pallets/nfts/src/features/create_delete_collection.rs +++ b/pallets/nfts/src/features/create_delete_collection.rs @@ -18,9 +18,10 @@ //! This module contains helper methods to perform functionality associated with creating and //! destroying collections for the NFTs pallet. -use crate::*; use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Create a new collection with the given `collection`, `owner`, `admin`, `config`, `deposit`, /// and `event`. diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index 37f64ae1b..e9843b2e7 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -18,9 +18,10 @@ //! This module contains helper methods to perform functionality associated with minting and burning //! items for the NFTs pallet. -use crate::*; use frame_support::{pallet_prelude::*, traits::ExistenceRequirement}; +use crate::*; + impl, I: 'static> Pallet { /// Mint a new unique item with the given `collection`, `item`, and other minting configuration /// details. diff --git a/pallets/nfts/src/features/lock.rs b/pallets/nfts/src/features/lock.rs index 1c3c9c867..4649f4a01 100644 --- a/pallets/nfts/src/features/lock.rs +++ b/pallets/nfts/src/features/lock.rs @@ -18,9 +18,10 @@ //! This module contains helper methods to configure locks on collections and items for the NFTs //! pallet. -use crate::*; use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Locks a collection with specified settings. /// @@ -29,7 +30,6 @@ impl, I: 'static> Pallet { /// /// Note: it's possible only to lock the setting, but not to unlock it after. - /// /// - `origin`: The origin of the transaction, representing the account attempting to lock the /// collection. /// - `collection`: The identifier of the collection to be locked. diff --git a/pallets/nfts/src/features/metadata.rs b/pallets/nfts/src/features/metadata.rs index 260061603..b3d16b12c 100644 --- a/pallets/nfts/src/features/metadata.rs +++ b/pallets/nfts/src/features/metadata.rs @@ -17,10 +17,12 @@ //! This module contains helper methods to configure the metadata of collections and items. -use crate::*; use alloc::vec::Vec; + use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Sets the metadata for a specific item within a collection. /// diff --git a/pallets/nfts/src/features/roles.rs b/pallets/nfts/src/features/roles.rs index aa6394f70..053eaf0b0 100644 --- a/pallets/nfts/src/features/roles.rs +++ b/pallets/nfts/src/features/roles.rs @@ -17,10 +17,12 @@ //! This module contains helper methods to configure account roles for existing collections. -use crate::*; use alloc::{collections::btree_map::BTreeMap, vec::Vec}; + use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Set the team roles for a specific collection. /// diff --git a/pallets/nfts/src/features/settings.rs b/pallets/nfts/src/features/settings.rs index d4f7533ff..9c7ac7ca2 100644 --- a/pallets/nfts/src/features/settings.rs +++ b/pallets/nfts/src/features/settings.rs @@ -17,9 +17,10 @@ //! This module provides helper methods to configure collection settings for the NFTs pallet. -use crate::*; use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Forcefully change the configuration of a collection. /// diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index bba834483..b7223a7c3 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -18,9 +18,10 @@ //! This module contains helper methods to perform the transfer functionalities //! of the NFTs pallet. -use crate::*; use frame_support::pallet_prelude::*; +use crate::*; + impl, I: 'static> Pallet { /// Transfer an NFT to the specified destination account. /// @@ -160,6 +161,7 @@ impl, I: 'static> Pallet { Ok(()) }) } + /// Set or unset the ownership acceptance for an account regarding a specific collection. /// /// - `who`: The account for which to set or unset the ownership acceptance. diff --git a/pallets/nfts/src/impl_nonfungibles.rs b/pallets/nfts/src/impl_nonfungibles.rs index c90655aad..362cccd93 100644 --- a/pallets/nfts/src/impl_nonfungibles.rs +++ b/pallets/nfts/src/impl_nonfungibles.rs @@ -17,7 +17,6 @@ //! Implementations for `nonfungibles` traits. -use super::*; use frame_support::{ ensure, storage::KeyPrefixIterator, @@ -26,9 +25,11 @@ use frame_support::{ }; use sp_runtime::{DispatchError, DispatchResult}; +use super::*; + impl, I: 'static> Inspect<::AccountId> for Pallet { - type ItemId = T::ItemId; type CollectionId = T::CollectionId; + type ItemId = T::ItemId; fn owner( collection: &Self::CollectionId, @@ -140,9 +141,11 @@ impl, I: 'static> InspectRole<::AccountId> for P fn is_issuer(collection: &Self::CollectionId, who: &::AccountId) -> bool { Self::has_role(collection, who, CollectionRole::Issuer) } + fn is_admin(collection: &Self::CollectionId, who: &::AccountId) -> bool { Self::has_role(collection, who, CollectionRole::Admin) } + fn is_freezer(collection: &Self::CollectionId, who: &::AccountId) -> bool { Self::has_role(collection, who, CollectionRole::Freezer) } @@ -469,9 +472,9 @@ impl, I: 'static> Trading> for Pallet impl, I: 'static> InspectEnumerable for Pallet { type CollectionsIterator = KeyPrefixIterator<>::CollectionId>; type ItemsIterator = KeyPrefixIterator<>::ItemId>; + type OwnedInCollectionIterator = KeyPrefixIterator<>::ItemId>; type OwnedIterator = KeyPrefixIterator<(>::CollectionId, >::ItemId)>; - type OwnedInCollectionIterator = KeyPrefixIterator<>::ItemId>; /// Returns an iterator of the collections in existence. /// diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index 4e5493a3c..89bfb9637 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -51,18 +51,18 @@ pub mod weights; extern crate alloc; use alloc::{boxed::Box, vec, vec::Vec}; + use codec::{Decode, Encode}; use frame_support::traits::{ tokens::Locker, BalanceStatus::Reserved, Currency, EnsureOriginWithArg, Incrementable, ReservableCurrency, }; use frame_system::Config as SystemConfig; +pub use pallet::*; use sp_runtime::{ traits::{IdentifyAccount, Saturating, StaticLookup, Verify, Zero}, RuntimeDebug, }; - -pub use pallet::*; pub use types::*; pub use weights::WeightInfo; @@ -74,10 +74,11 @@ type AccountIdLookupOf = <::Lookup as StaticLookup>::Sourc #[frame_support::pallet] pub mod pallet { - use super::*; use frame_support::{pallet_prelude::*, traits::ExistenceRequirement}; use frame_system::pallet_prelude::*; + use super::*; + /// The in-code storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); @@ -108,14 +109,17 @@ pub mod pallet { fn collection(i: u16) -> CollectionId { i.into() } + fn item(i: u16) -> ItemId { i.into() } + fn signer() -> (sp_runtime::MultiSigner, sp_runtime::AccountId32) { let public = sp_io::crypto::sr25519_generate(0.into(), None); let account = sp_runtime::MultiSigner::Sr25519(public).into_account(); (public.into(), account) } + fn sign(signer: &sp_runtime::MultiSigner, message: &[u8]) -> sp_runtime::MultiSignature { sp_runtime::MultiSignature::Sr25519( sp_io::crypto::sr25519_sign(0.into(), &signer.clone().try_into().unwrap(), message) diff --git a/pallets/nfts/src/migration.rs b/pallets/nfts/src/migration.rs index 8f82e0922..af611bf16 100644 --- a/pallets/nfts/src/migration.rs +++ b/pallets/nfts/src/migration.rs @@ -15,13 +15,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::*; use frame_support::traits::OnRuntimeUpgrade; use log; - #[cfg(feature = "try-runtime")] use sp_runtime::TryRuntimeError; +use super::*; + pub mod v1 { use frame_support::{pallet_prelude::*, weights::Weight}; diff --git a/pallets/nfts/src/mock.rs b/pallets/nfts/src/mock.rs index 5b589f591..5532be8f4 100644 --- a/pallets/nfts/src/mock.rs +++ b/pallets/nfts/src/mock.rs @@ -17,9 +17,6 @@ //! Test environment for Nfts pallet. -use super::*; -use crate as pallet_nfts; - use frame_support::{ construct_runtime, derive_impl, parameter_types, traits::{AsEnsureOriginWithArg, ConstU32, ConstU64}, @@ -30,6 +27,9 @@ use sp_runtime::{ BuildStorage, MultiSignature, }; +use super::*; +use crate as pallet_nfts; + type Block = frame_system::mocking::MockBlock; construct_runtime!( @@ -47,10 +47,10 @@ pub type AccountId = ::AccountId; #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Test { + type AccountData = pallet_balances::AccountData; type AccountId = AccountId; - type Lookup = IdentityLookup; type Block = Block; - type AccountData = pallet_balances::AccountData; + type Lookup = IdentityLookup; } #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] @@ -63,35 +63,35 @@ parameter_types! { } impl Config for Test { - type RuntimeEvent = RuntimeEvent; + type ApprovalsLimit = ConstU32<10>; + type AttributeDepositBase = ConstU64<1>; + type CollectionDeposit = ConstU64<2>; type CollectionId = u32; - type ItemId = u32; - type Currency = Balances; type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type DepositPerByte = ConstU64<1>; + type Features = Features; type ForceOrigin = frame_system::EnsureRoot; - type Locker = (); - type CollectionDeposit = ConstU64<2>; + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); + type ItemAttributesApprovalsLimit = ConstU32<2>; type ItemDeposit = ConstU64<1>; - type MetadataDepositBase = ConstU64<1>; - type AttributeDepositBase = ConstU64<1>; - type DepositPerByte = ConstU64<1>; - type StringLimit = ConstU32<50>; + type ItemId = u32; type KeyLimit = ConstU32<50>; - type ValueLimit = ConstU32<50>; - type ApprovalsLimit = ConstU32<10>; - type ItemAttributesApprovalsLimit = ConstU32<2>; - type MaxTips = ConstU32<10>; - type MaxDeadlineDuration = ConstU64<10000>; + type Locker = (); type MaxAttributesPerCall = ConstU32<2>; - type Features = Features; + type MaxDeadlineDuration = ConstU64<10000>; + type MaxTips = ConstU32<10>; + type MetadataDepositBase = ConstU64<1>; + /// Using `AccountPublic` here makes it trivial to convert to `AccountId` via `into_account()`. + type OffchainPublic = AccountPublic; /// Off-chain = signature On-chain - therefore no conversion needed. /// It needs to be From for benchmarking. type OffchainSignature = Signature; - /// Using `AccountPublic` here makes it trivial to convert to `AccountId` via `into_account()`. - type OffchainPublic = AccountPublic; + type RuntimeEvent = RuntimeEvent; + type StringLimit = ConstU32<50>; + type ValueLimit = ConstU32<50>; type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type Helper = (); } pub(crate) fn new_test_ext() -> sp_io::TestExternalities { diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index e1b598ca4..44f2f32ae 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -17,7 +17,6 @@ //! Tests for Nfts pallet. -use crate::{mock::*, Event, SystemConfig, *}; use enumflags2::BitFlags; use frame_support::{ assert_noop, assert_ok, @@ -33,6 +32,8 @@ use sp_runtime::{ MultiSignature, MultiSigner, }; +use crate::{mock::*, Event, SystemConfig, *}; + type AccountIdOf = ::AccountId; fn account(id: u8) -> AccountIdOf { diff --git a/pallets/nfts/src/types.rs b/pallets/nfts/src/types.rs index 1687a0352..f08f1d097 100644 --- a/pallets/nfts/src/types.rs +++ b/pallets/nfts/src/types.rs @@ -17,9 +17,8 @@ //! This module contains various basic types and data structures used in the NFTs pallet. -use super::*; -use crate::macros::*; use alloc::{vec, vec::Vec}; + use codec::EncodeLike; use enumflags2::{bitflags, BitFlags}; use frame_support::{ @@ -30,6 +29,9 @@ use frame_support::{ use frame_system::pallet_prelude::BlockNumberFor; use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter}; +use super::*; +use crate::macros::*; + /// A type alias for handling balance deposits. pub(super) type DepositBalanceOf = <>::Currency as Currency<::AccountId>>::Balance; @@ -276,12 +278,15 @@ impl CollectionSettings { pub fn all_enabled() -> Self { Self(BitFlags::EMPTY) } + pub fn get_disabled(&self) -> BitFlags { self.0 } + pub fn is_disabled(&self, setting: CollectionSetting) -> bool { self.0.contains(setting) } + pub fn from_disabled(settings: BitFlags) -> Self { Self(settings) } @@ -377,12 +382,15 @@ impl CollectionConfig bool { !self.settings.is_disabled(setting) } + pub fn has_disabled_setting(&self, setting: CollectionSetting) -> bool { self.settings.is_disabled(setting) } + pub fn enable_setting(&mut self, setting: CollectionSetting) { self.settings.0.remove(setting); } + pub fn disable_setting(&mut self, setting: CollectionSetting) { self.settings.0.insert(setting); } @@ -409,12 +417,15 @@ impl ItemSettings { pub fn all_enabled() -> Self { Self(BitFlags::EMPTY) } + pub fn get_disabled(&self) -> BitFlags { self.0 } + pub fn is_disabled(&self, setting: ItemSetting) -> bool { self.0.contains(setting) } + pub fn from_disabled(settings: BitFlags) -> Self { Self(settings) } @@ -435,15 +446,19 @@ impl ItemConfig { pub fn is_setting_enabled(&self, setting: ItemSetting) -> bool { !self.settings.is_disabled(setting) } + pub fn has_disabled_setting(&self, setting: ItemSetting) -> bool { self.settings.is_disabled(setting) } + pub fn has_disabled_settings(&self) -> bool { !self.settings.get_disabled().is_empty() } + pub fn enable_setting(&mut self, setting: ItemSetting) { self.settings.0.remove(setting); } + pub fn disable_setting(&mut self, setting: ItemSetting) { self.settings.0.insert(setting); } @@ -472,9 +487,11 @@ impl PalletFeatures { pub fn all_enabled() -> Self { Self(BitFlags::EMPTY) } + pub fn from_disabled(features: BitFlags) -> Self { Self(features) } + pub fn is_enabled(&self, feature: PalletFeature) -> bool { !self.0.contains(feature) } @@ -502,12 +519,15 @@ impl CollectionRoles { pub fn none() -> Self { Self(BitFlags::EMPTY) } + pub fn has_role(&self, role: CollectionRole) -> bool { self.0.contains(role) } + pub fn add_role(&mut self, role: CollectionRole) { self.0.insert(role); } + pub fn max_roles() -> u8 { let all: BitFlags = BitFlags::all(); all.len() as u8 From 7f5cec544415f9e42a9f9e77adbc49fff62c799f Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:47:40 +0700 Subject: [PATCH 36/76] feat: add nonfungibles implementation --- Cargo.lock | 1 + pallets/api/Cargo.toml | 3 + pallets/api/src/fungibles/tests.rs | 286 ++++++++++++++++---------- pallets/api/src/lib.rs | 1 + pallets/api/src/mock.rs | 74 ++++++- pallets/api/src/nonfungibles/mod.rs | 260 +++++++++++++++++++++++ pallets/api/src/nonfungibles/tests.rs | 183 ++++++++++++++++ pallets/api/src/nonfungibles/types.rs | 61 ++++++ 8 files changed, 750 insertions(+), 119 deletions(-) create mode 100644 pallets/api/src/nonfungibles/mod.rs create mode 100644 pallets/api/src/nonfungibles/tests.rs create mode 100644 pallets/api/src/nonfungibles/types.rs diff --git a/Cargo.lock b/Cargo.lock index d2bf2acec..6f98f910e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7366,6 +7366,7 @@ dependencies = [ "log", "pallet-assets", "pallet-balances", + "pallet-nfts", "parity-scale-codec", "pop-chain-extension", "scale-info", diff --git a/pallets/api/Cargo.toml b/pallets/api/Cargo.toml index 55a007895..5d3987244 100644 --- a/pallets/api/Cargo.toml +++ b/pallets/api/Cargo.toml @@ -22,6 +22,7 @@ frame-benchmarking.workspace = true frame-support.workspace = true frame-system.workspace = true pallet-assets.workspace = true +pallet-nfts.workspace = true sp-runtime.workspace = true sp-std.workspace = true @@ -37,6 +38,7 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-assets/runtime-benchmarks", + "pallet-nfts/runtime-benchmarks", "pop-chain-extension/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] @@ -47,6 +49,7 @@ std = [ "frame-system/std", "pallet-assets/std", "pallet-balances/std", + "pallet-nfts/std", "pop-chain-extension/std", "scale-info/std", "sp-core/std", diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index f5c560bb7..6e181a6f7 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -83,17 +83,21 @@ fn transfer_works() { let to = BOB; for origin in vec![root(), none()] { - assert_noop!(Fungibles::transfer(origin, token, to, value), BadOrigin); + assert_noop!(Fungibles::transfer(origin, token, account(to), value), BadOrigin); } // Check error works for `Assets::transfer_keep_alive()`. - assert_noop!(Fungibles::transfer(signed(from), token, to, value), AssetsError::Unknown); + assert_noop!( + Fungibles::transfer(signed(from), token, account(to), value), + AssetsError::Unknown + ); assets::create_and_mint_to(from, token, from, value * 2); - let balance_before_transfer = Assets::balance(token, &to); - assert_ok!(Fungibles::transfer(signed(from), token, to, value)); - let balance_after_transfer = Assets::balance(token, &to); + let balance_before_transfer = Assets::balance(token, &account(to)); + assert_ok!(Fungibles::transfer(signed(from), token, account(to), value)); + let balance_after_transfer = Assets::balance(token, &account(to)); assert_eq!(balance_after_transfer, balance_before_transfer + value); System::assert_last_event( - Event::Transfer { token, from: Some(from), to: Some(to), value }.into(), + Event::Transfer { token, from: Some(account(from)), to: Some(account(to)), value } + .into(), ); }); } @@ -108,26 +112,36 @@ fn transfer_from_works() { let spender = CHARLIE; for origin in vec![root(), none()] { - assert_noop!(Fungibles::transfer_from(origin, token, from, to, value), BadOrigin); + assert_noop!( + Fungibles::transfer_from(origin, token, account(from), account(to), value), + BadOrigin + ); } // Check error works for `Assets::transfer_approved()`. assert_noop!( - Fungibles::transfer_from(signed(spender), token, from, to, value), + Fungibles::transfer_from(signed(spender), token, account(from), account(to), value), AssetsError::Unknown ); // Approve `spender` to transfer up to `value`. assets::create_mint_and_approve(spender, token, from, value * 2, spender, value); // Successfully call transfer from. - let from_balance_before_transfer = Assets::balance(token, &from); - let to_balance_before_transfer = Assets::balance(token, &to); - assert_ok!(Fungibles::transfer_from(signed(spender), token, from, to, value)); - let from_balance_after_transfer = Assets::balance(token, &from); - let to_balance_after_transfer = Assets::balance(token, &to); + let from_balance_before_transfer = Assets::balance(token, &account(from)); + let to_balance_before_transfer = Assets::balance(token, &account(to)); + assert_ok!(Fungibles::transfer_from( + signed(spender), + token, + account(from), + account(to), + value + )); + let from_balance_after_transfer = Assets::balance(token, &account(from)); + let to_balance_after_transfer = Assets::balance(token, &account(to)); // Check that `to` has received the `value` tokens from `from`. assert_eq!(to_balance_after_transfer, to_balance_before_transfer + value); assert_eq!(from_balance_after_transfer, from_balance_before_transfer - value); System::assert_last_event( - Event::Transfer { token, from: Some(from), to: Some(to), value }.into(), + Event::Transfer { token, from: Some(account(from)), to: Some(account(to)), value } + .into(), ); }); } @@ -144,7 +158,7 @@ mod approve { for origin in vec![root(), none()] { assert_noop!( - Fungibles::approve(origin, token, spender, value), + Fungibles::approve(origin, token, account(spender), value), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } @@ -161,20 +175,20 @@ mod approve { for origin in vec![root(), none()] { assert_noop!( - Fungibles::approve(origin, token, spender, value), + Fungibles::approve(origin, token, account(spender), value), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } // Check error works for `Assets::approve_transfer()` in `Greater` match arm. assert_noop!( - Fungibles::approve(signed(owner), token, spender, value), + Fungibles::approve(signed(owner), token, account(spender), value), AssetsError::Unknown.with_weight(WeightInfo::approve(1, 0)) ); assets::create_mint_and_approve(owner, token, owner, value, spender, value); // Check error works for `Assets::cancel_approval()` in `Less` match arm. assert_ok!(Assets::freeze_asset(signed(owner), token)); assert_noop!( - Fungibles::approve(signed(owner), token, spender, value / 2), + Fungibles::approve(signed(owner), token, account(spender), value / 2), AssetsError::AssetNotLive.with_weight(WeightInfo::approve(0, 1)) ); assert_ok!(Assets::thaw_asset(signed(owner), token)); @@ -193,38 +207,61 @@ mod approve { // Approves a value to spend that is higher than the current allowance. assets::create_and_mint_to(owner, token, owner, value); - assert_eq!(Assets::allowance(token, &owner, &spender), 0); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), 0); assert_eq!( - Fungibles::approve(signed(owner), token, spender, value), + Fungibles::approve(signed(owner), token, account(spender), value), Ok(Some(WeightInfo::approve(1, 0)).into()) ); - assert_eq!(Assets::allowance(token, &owner, &spender), value); - System::assert_last_event(Event::Approval { token, owner, spender, value }.into()); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); + System::assert_last_event( + Event::Approval { token, owner: account(owner), spender: account(spender), value } + .into(), + ); // Approves a value to spend that is lower than the current allowance. assert_eq!( - Fungibles::approve(signed(owner), token, spender, value / 2), + Fungibles::approve(signed(owner), token, account(spender), value / 2), Ok(Some(WeightInfo::approve(1, 1)).into()) ); - assert_eq!(Assets::allowance(token, &owner, &spender), value / 2); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value / 2); System::assert_last_event( - Event::Approval { token, owner, spender, value: value / 2 }.into(), + Event::Approval { + token, + owner: account(owner), + spender: account(spender), + value: value / 2, + } + .into(), ); // Approves a value to spend that is equal to the current allowance. assert_eq!( - Fungibles::approve(signed(owner), token, spender, value / 2), + Fungibles::approve(signed(owner), token, account(spender), value / 2), Ok(Some(WeightInfo::approve(0, 0)).into()) ); - assert_eq!(Assets::allowance(token, &owner, &spender), value / 2); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value / 2); System::assert_last_event( - Event::Approval { token, owner, spender, value: value / 2 }.into(), + Event::Approval { + token, + owner: account(owner), + spender: account(spender), + value: value / 2, + } + .into(), ); // Sets allowance to zero. assert_eq!( - Fungibles::approve(signed(owner), token, spender, 0), + Fungibles::approve(signed(owner), token, account(spender), 0), Ok(Some(WeightInfo::approve(0, 1)).into()) ); - assert_eq!(Assets::allowance(token, &owner, &spender), 0); - System::assert_last_event(Event::Approval { token, owner, spender, value: 0 }.into()); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), 0); + System::assert_last_event( + Event::Approval { + token, + owner: account(owner), + spender: account(spender), + value: 0, + } + .into(), + ); }); } } @@ -239,25 +276,34 @@ fn increase_allowance_works() { for origin in vec![root(), none()] { assert_noop!( - Fungibles::increase_allowance(origin, token, spender, value), + Fungibles::increase_allowance(origin, token, account(spender), value), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } // Check error works for `Assets::approve_transfer()`. assert_noop!( - Fungibles::increase_allowance(signed(owner), token, spender, value), + Fungibles::increase_allowance(signed(owner), token, account(spender), value), AssetsError::Unknown.with_weight(AssetsWeightInfo::approve_transfer()) ); assets::create_and_mint_to(owner, token, owner, value); - assert_eq!(0, Assets::allowance(token, &owner, &spender)); - assert_ok!(Fungibles::increase_allowance(signed(owner), token, spender, value)); - assert_eq!(Assets::allowance(token, &owner, &spender), value); - System::assert_last_event(Event::Approval { token, owner, spender, value }.into()); + assert_eq!(0, Assets::allowance(token, &account(owner), &account(spender))); + assert_ok!(Fungibles::increase_allowance(signed(owner), token, account(spender), value)); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); + System::assert_last_event( + Event::Approval { token, owner: account(owner), spender: account(spender), value } + .into(), + ); // Additive. - assert_ok!(Fungibles::increase_allowance(signed(owner), token, spender, value)); - assert_eq!(Assets::allowance(token, &owner, &spender), value * 2); + assert_ok!(Fungibles::increase_allowance(signed(owner), token, account(spender), value)); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value * 2); System::assert_last_event( - Event::Approval { token, owner, spender, value: value * 2 }.into(), + Event::Approval { + token, + owner: account(owner), + spender: account(spender), + value: value * 2, + } + .into(), ); }); } @@ -272,40 +318,46 @@ fn decrease_allowance_works() { for origin in vec![root(), none()] { assert_noop!( - Fungibles::decrease_allowance(origin, token, spender, 0), + Fungibles::decrease_allowance(origin, token, account(spender), 0), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } assets::create_mint_and_approve(owner, token, owner, value, spender, value); - assert_eq!(Assets::allowance(token, &owner, &spender), value); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); // Check error works for `Assets::cancel_approval()`. No error test for `approve_transfer` // because it is not possible. assert_ok!(Assets::freeze_asset(signed(owner), token)); assert_noop!( - Fungibles::decrease_allowance(signed(owner), token, spender, value / 2), + Fungibles::decrease_allowance(signed(owner), token, account(spender), value / 2), AssetsError::AssetNotLive.with_weight(WeightInfo::approve(0, 1)) ); assert_ok!(Assets::thaw_asset(signed(owner), token)); // Owner balance is not changed if decreased by zero. assert_eq!( - Fungibles::decrease_allowance(signed(owner), token, spender, 0), + Fungibles::decrease_allowance(signed(owner), token, account(spender), 0), Ok(Some(WeightInfo::approve(0, 0)).into()) ); - assert_eq!(Assets::allowance(token, &owner, &spender), value); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); // "Unapproved" error is returned if the current allowance is less than amount to decrease // with. assert_noop!( - Fungibles::decrease_allowance(signed(owner), token, spender, value * 2), + Fungibles::decrease_allowance(signed(owner), token, account(spender), value * 2), AssetsError::Unapproved ); // Decrease allowance successfully. assert_eq!( - Fungibles::decrease_allowance(signed(owner), token, spender, value / 2), + Fungibles::decrease_allowance(signed(owner), token, account(spender), value / 2), Ok(Some(WeightInfo::approve(1, 1)).into()) ); - assert_eq!(Assets::allowance(token, &owner, &spender), value / 2); + assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value / 2); System::assert_last_event( - Event::Approval { token, owner, spender, value: value / 2 }.into(), + Event::Approval { + token, + owner: account(owner), + spender: account(spender), + value: value / 2, + } + .into(), ); }); } @@ -318,14 +370,19 @@ fn create_works() { let admin = ALICE; for origin in vec![root(), none()] { - assert_noop!(Fungibles::create(origin, id, admin, 100), BadOrigin); + assert_noop!(Fungibles::create(origin, id, account(admin), 100), BadOrigin); } assert!(!Assets::asset_exists(id)); - assert_ok!(Fungibles::create(signed(creator), id, admin, 100)); + assert_ok!(Fungibles::create(signed(creator), id, account(admin), 100)); assert!(Assets::asset_exists(id)); - System::assert_last_event(Event::Created { id, creator, admin }.into()); + System::assert_last_event( + Event::Created { id, creator: account(creator), admin: account(admin) }.into(), + ); // Check error works for `Assets::create()`. - assert_noop!(Fungibles::create(signed(creator), id, admin, 100), AssetsError::InUse); + assert_noop!( + Fungibles::create(signed(creator), id, account(admin), 100), + AssetsError::InUse + ); }); } @@ -336,11 +393,11 @@ fn start_destroy_works() { // Check error works for `Assets::start_destroy()`. assert_noop!(Fungibles::start_destroy(signed(ALICE), token), AssetsError::Unknown); - assert_ok!(Assets::create(signed(ALICE), token, ALICE, 1)); + assert_ok!(Assets::create(signed(ALICE), token, account(ALICE), 1)); assert_ok!(Fungibles::start_destroy(signed(ALICE), token)); // Check that the token is not live after starting the destroy process. assert_noop!( - Assets::mint(signed(ALICE), token, ALICE, 10 * UNIT), + Assets::mint(signed(ALICE), token, account(ALICE), 10 * UNIT), AssetsError::AssetNotLive ); }); @@ -359,7 +416,7 @@ fn set_metadata_works() { Fungibles::set_metadata(signed(ALICE), token, name.clone(), symbol.clone(), decimals), AssetsError::Unknown ); - assert_ok!(Assets::create(signed(ALICE), token, ALICE, 1)); + assert_ok!(Assets::create(signed(ALICE), token, account(ALICE), 1)); assert_ok!(Fungibles::set_metadata( signed(ALICE), token, @@ -398,16 +455,16 @@ fn mint_works() { // Check error works for `Assets::mint()`. assert_noop!( - Fungibles::mint(signed(from), token, to, value), + Fungibles::mint(signed(from), token, account(to), value), sp_runtime::TokenError::UnknownAsset ); - assert_ok!(Assets::create(signed(from), token, from, 1)); - let balance_before_mint = Assets::balance(token, &to); - assert_ok!(Fungibles::mint(signed(from), token, to, value)); - let balance_after_mint = Assets::balance(token, &to); + assert_ok!(Assets::create(signed(from), token, account(from), 1)); + let balance_before_mint = Assets::balance(token, &account(to)); + assert_ok!(Fungibles::mint(signed(from), token, account(to), value)); + let balance_after_mint = Assets::balance(token, &account(to)); assert_eq!(balance_after_mint, balance_before_mint + value); System::assert_last_event( - Event::Transfer { token, from: None, to: Some(to), value }.into(), + Event::Transfer { token, from: None, to: Some(account(to)), value }.into(), ); }); } @@ -423,27 +480,30 @@ fn burn_works() { // "BalanceLow" error is returned if token is not created. assert_noop!( - Fungibles::burn(signed(owner), token, from, value), + Fungibles::burn(signed(owner), token, account(from), value), AssetsError::BalanceLow.with_weight(WeightInfo::balance_of()) ); assets::create_and_mint_to(owner, token, from, total_supply); assert_eq!(Assets::total_supply(TOKEN), total_supply); // Check error works for `Assets::burn()`. assert_ok!(Assets::freeze_asset(signed(owner), token)); - assert_noop!(Fungibles::burn(signed(owner), token, from, value), AssetsError::AssetNotLive); + assert_noop!( + Fungibles::burn(signed(owner), token, account(from), value), + AssetsError::AssetNotLive + ); assert_ok!(Assets::thaw_asset(signed(owner), token)); // "BalanceLow" error is returned if the balance is less than amount to burn. assert_noop!( - Fungibles::burn(signed(owner), token, from, total_supply * 2), + Fungibles::burn(signed(owner), token, account(from), total_supply * 2), AssetsError::BalanceLow.with_weight(WeightInfo::balance_of()) ); - let balance_before_burn = Assets::balance(token, &from); - assert_ok!(Fungibles::burn(signed(owner), token, from, value)); + let balance_before_burn = Assets::balance(token, &account(from)); + assert_ok!(Fungibles::burn(signed(owner), token, account(from), value)); assert_eq!(Assets::total_supply(TOKEN), total_supply - value); - let balance_after_burn = Assets::balance(token, &from); + let balance_after_burn = Assets::balance(token, &account(from)); assert_eq!(balance_after_burn, balance_before_burn - value); System::assert_last_event( - Event::Transfer { token, from: Some(from), to: None, value }.into(), + Event::Transfer { token, from: Some(account(from)), to: None, value }.into(), ); }); } @@ -470,17 +530,17 @@ fn balance_of_works() { new_test_ext().execute_with(|| { let value = 1_000 * UNIT; assert_eq!( - Fungibles::read(BalanceOf { token: TOKEN, owner: ALICE }), + Fungibles::read(BalanceOf { token: TOKEN, owner: account(ALICE) }), ReadResult::BalanceOf(Default::default()) ); assets::create_and_mint_to(ALICE, TOKEN, ALICE, value); assert_eq!( - Fungibles::read(BalanceOf { token: TOKEN, owner: ALICE }), + Fungibles::read(BalanceOf { token: TOKEN, owner: account(ALICE) }), ReadResult::BalanceOf(value) ); assert_eq!( - Fungibles::read(BalanceOf { token: TOKEN, owner: ALICE }).encode(), - Assets::balance(TOKEN, ALICE).encode(), + Fungibles::read(BalanceOf { token: TOKEN, owner: account(ALICE) }).encode(), + Assets::balance(TOKEN, account(ALICE)).encode(), ); }); } @@ -490,17 +550,30 @@ fn allowance_works() { new_test_ext().execute_with(|| { let value = 1_000 * UNIT; assert_eq!( - Fungibles::read(Allowance { token: TOKEN, owner: ALICE, spender: BOB }), + Fungibles::read(Allowance { + token: TOKEN, + owner: account(ALICE), + spender: account(BOB) + }), ReadResult::Allowance(Default::default()) ); assets::create_mint_and_approve(ALICE, TOKEN, ALICE, value * 2, BOB, value); assert_eq!( - Fungibles::read(Allowance { token: TOKEN, owner: ALICE, spender: BOB }), + Fungibles::read(Allowance { + token: TOKEN, + owner: account(ALICE), + spender: account(BOB) + }), ReadResult::Allowance(value) ); assert_eq!( - Fungibles::read(Allowance { token: TOKEN, owner: ALICE, spender: BOB }).encode(), - Assets::allowance(TOKEN, &ALICE, &BOB).encode(), + Fungibles::read(Allowance { + token: TOKEN, + owner: account(ALICE), + spender: account(BOB) + }) + .encode(), + Assets::allowance(TOKEN, &account(ALICE), &account(BOB)).encode(), ); }); } @@ -534,7 +607,7 @@ fn token_metadata_works() { fn token_exists_works() { new_test_ext().execute_with(|| { assert_eq!(Fungibles::read(TokenExists(TOKEN)), ReadResult::TokenExists(false)); - assert_ok!(Assets::create(signed(ALICE), TOKEN, ALICE, 1)); + assert_ok!(Assets::create(signed(ALICE), TOKEN, account(ALICE), 1)); assert_eq!(Fungibles::read(TokenExists(TOKEN)), ReadResult::TokenExists(true)); assert_eq!( Fungibles::read(TokenExists(TOKEN)).encode(), @@ -543,8 +616,8 @@ fn token_exists_works() { }); } -fn signed(account: AccountId) -> RuntimeOrigin { - RuntimeOrigin::signed(account) +fn signed(account_id: u8) -> RuntimeOrigin { + RuntimeOrigin::signed(account(account_id)) } fn root() -> RuntimeOrigin { @@ -559,36 +632,31 @@ fn none() -> RuntimeOrigin { mod assets { use super::*; - pub(super) fn create_and_mint_to( - owner: AccountId, - token: TokenId, - to: AccountId, - value: Balance, - ) { - assert_ok!(Assets::create(signed(owner), token, owner, 1)); - assert_ok!(Assets::mint(signed(owner), token, to, value)); + pub(super) fn create_and_mint_to(owner: u8, token: TokenId, to: u8, value: Balance) { + assert_ok!(Assets::create(signed(owner), token, account(owner), 1)); + assert_ok!(Assets::mint(signed(owner), token, account(to), value)); } pub(super) fn create_mint_and_approve( - owner: AccountId, + owner: u8, token: TokenId, - to: AccountId, + to: u8, mint: Balance, - spender: AccountId, + spender: u8, approve: Balance, ) { create_and_mint_to(owner, token, to, mint); - assert_ok!(Assets::approve_transfer(signed(to), token, spender, approve,)); + assert_ok!(Assets::approve_transfer(signed(to), token, account(spender), approve,)); } pub(super) fn create_and_set_metadata( - owner: AccountId, + owner: u8, token: TokenId, name: Vec, symbol: Vec, decimals: u8, ) { - assert_ok!(Assets::create(signed(owner), token, owner, 1)); + assert_ok!(Assets::create(signed(owner), token, account(owner), 1)); assert_ok!(Assets::set_metadata(signed(owner), token, name, symbol, decimals)); } } @@ -613,11 +681,11 @@ mod read_weights { fn new() -> Self { Self { total_supply: Fungibles::weight(&TotalSupply(TOKEN)), - balance_of: Fungibles::weight(&BalanceOf { token: TOKEN, owner: ALICE }), + balance_of: Fungibles::weight(&BalanceOf { token: TOKEN, owner: account(ALICE) }), allowance: Fungibles::weight(&Allowance { token: TOKEN, - owner: ALICE, - spender: BOB, + owner: account(ALICE), + spender: account(BOB), }), token_name: Fungibles::weight(&TokenName(TOKEN)), token_symbol: Fungibles::weight(&TokenSymbol(TOKEN)), @@ -699,15 +767,15 @@ mod ensure_codec_indexes { [ (TotalSupply::(Default::default()), 0u8, "TotalSupply"), ( - BalanceOf:: { token: Default::default(), owner: Default::default() }, + BalanceOf:: { token: Default::default(), owner: account(Default::default()) }, 1, "BalanceOf", ), ( Allowance:: { token: Default::default(), - owner: Default::default(), - spender: Default::default(), + owner: account(Default::default()), + spender: account(Default::default()), }, 2, "Allowance", @@ -731,7 +799,7 @@ mod ensure_codec_indexes { ( transfer { token: Default::default(), - to: Default::default(), + to: account(Default::default()), value: Default::default(), }, 3u8, @@ -740,8 +808,8 @@ mod ensure_codec_indexes { ( transfer_from { token: Default::default(), - from: Default::default(), - to: Default::default(), + from: account(Default::default()), + to: account(Default::default()), value: Default::default(), }, 4, @@ -750,7 +818,7 @@ mod ensure_codec_indexes { ( approve { token: Default::default(), - spender: Default::default(), + spender: account(Default::default()), value: Default::default(), }, 5, @@ -759,7 +827,7 @@ mod ensure_codec_indexes { ( increase_allowance { token: Default::default(), - spender: Default::default(), + spender: account(Default::default()), value: Default::default(), }, 6, @@ -768,7 +836,7 @@ mod ensure_codec_indexes { ( decrease_allowance { token: Default::default(), - spender: Default::default(), + spender: account(Default::default()), value: Default::default(), }, 7, @@ -777,7 +845,7 @@ mod ensure_codec_indexes { ( create { id: Default::default(), - admin: Default::default(), + admin: account(Default::default()), min_balance: Default::default(), }, 11, @@ -798,7 +866,7 @@ mod ensure_codec_indexes { ( mint { token: Default::default(), - account: Default::default(), + account: account(Default::default()), value: Default::default(), }, 19, @@ -807,7 +875,7 @@ mod ensure_codec_indexes { ( burn { token: Default::default(), - account: Default::default(), + account: account(Default::default()), value: Default::default(), }, 20, diff --git a/pallets/api/src/lib.rs b/pallets/api/src/lib.rs index d94d19788..e3d706e2d 100644 --- a/pallets/api/src/lib.rs +++ b/pallets/api/src/lib.rs @@ -7,6 +7,7 @@ pub mod extension; pub mod fungibles; #[cfg(test)] mod mock; +pub mod nonfungibles; /// Trait for performing reads of runtime state. pub trait Read { diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs index 42c8bf0e2..920d590f9 100644 --- a/pallets/api/src/mock.rs +++ b/pallets/api/src/mock.rs @@ -1,25 +1,28 @@ use frame_support::{ derive_impl, parameter_types, - traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, Everything}, + traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, ConstU64, Everything}, }; use frame_system::{EnsureRoot, EnsureSigned}; +use pallet_nfts::PalletFeatures; use sp_core::H256; use sp_runtime::{ - traits::{BlakeTwo256, IdentityLookup}, - BuildStorage, + traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Verify}, + BuildStorage, MultiSignature, }; -pub(crate) const ALICE: AccountId = 1; -pub(crate) const BOB: AccountId = 2; -pub(crate) const CHARLIE: AccountId = 3; +pub(crate) const ALICE: u8 = 1; +pub(crate) const BOB: u8 = 2; +pub(crate) const CHARLIE: u8 = 3; pub(crate) const INIT_AMOUNT: Balance = 100_000_000 * UNIT; pub(crate) const UNIT: Balance = 10_000_000_000; type Block = frame_system::mocking::MockBlock; -pub(crate) type AccountId = u64; +pub(crate) type AccountId = ::AccountId; pub(crate) type Balance = u128; // For terminology in tests. pub(crate) type TokenId = u32; +type Signature = MultiSignature; +type AccountPublic = ::Signer; // Configure a mock runtime to test the pallet. frame_support::construct_runtime!( @@ -29,6 +32,8 @@ frame_support::construct_runtime!( Assets: pallet_assets::, Balances: pallet_balances, Fungibles: crate::fungibles, + Nfts: pallet_nfts, + NonFungibles: crate::nonfungibles } ); @@ -91,10 +96,10 @@ impl pallet_assets::Config for Test { #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); type CallbackHandle = (); - type CreateOrigin = AsEnsureOriginWithArg>; + type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; type Extra = (); - type ForceOrigin = EnsureRoot; + type ForceOrigin = EnsureRoot; type Freezer = (); type MetadataDepositBase = ConstU128<1>; type MetadataDepositPerByte = ConstU128<1>; @@ -110,13 +115,62 @@ impl crate::fungibles::Config for Test { type WeightInfo = (); } +parameter_types! { + pub storage Features: PalletFeatures = PalletFeatures::all_enabled(); +} + +impl pallet_nfts::Config for Test { + type ApprovalsLimit = ConstU32<10>; + type AttributeDepositBase = ConstU128<1>; + type CollectionDeposit = ConstU128<2>; + type CollectionId = u32; + type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type DepositPerByte = ConstU128<1>; + type Features = Features; + type ForceOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); + type ItemAttributesApprovalsLimit = ConstU32<2>; + type ItemDeposit = ConstU128<1>; + type ItemId = u32; + type KeyLimit = ConstU32<50>; + type Locker = (); + type MaxAttributesPerCall = ConstU32<2>; + type MaxDeadlineDuration = ConstU64<10000>; + type MaxTips = ConstU32<10>; + type MetadataDepositBase = ConstU128<1>; + /// Using `AccountPublic` here makes it trivial to convert to `AccountId` via `into_account()`. + type OffchainPublic = AccountPublic; + /// Off-chain = signature On-chain - therefore no conversion needed. + /// It needs to be From for benchmarking. + type OffchainSignature = Signature; + type RuntimeEvent = RuntimeEvent; + type StringLimit = ConstU32<50>; + type ValueLimit = ConstU32<50>; + type WeightInfo = (); +} + +impl crate::nonfungibles::Config for Test { + type RuntimeEvent = RuntimeEvent; +} + +/// Initialize a new account ID. +pub(crate) fn account(id: u8) -> AccountId { + [id; 32].into() +} + pub(crate) fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::::default() .build_storage() .expect("Frame system builds valid default genesis config"); pallet_balances::GenesisConfig:: { - balances: vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT), (CHARLIE, INIT_AMOUNT)], + balances: vec![ + (account(ALICE), INIT_AMOUNT), + (account(BOB), INIT_AMOUNT), + (account(CHARLIE), INIT_AMOUNT), + ], } .assimilate_storage(&mut t) .expect("Pallet balances storage can be assimilated"); diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs new file mode 100644 index 000000000..cac0cbbab --- /dev/null +++ b/pallets/api/src/nonfungibles/mod.rs @@ -0,0 +1,260 @@ +//! The non-fungibles pallet offers a streamlined interface for interacting with non-fungible +//! assets. The goal is to provide a simplified, consistent API that adheres to standards in the +//! smart contract space. + +use frame_support::traits::nonfungibles_v2::InspectEnumerable; +pub use pallet::*; +use pallet_nfts::WeightInfo; +use sp_runtime::traits::StaticLookup; + +#[cfg(test)] +mod tests; +mod types; + +#[frame_support::pallet] +pub mod pallet { + use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; + use frame_system::pallet_prelude::*; + use sp_std::vec::Vec; + use types::{AccountIdOf, CollectionIdOf, ItemDetails, ItemIdOf, NftsOf, NftsWeightInfoOf}; + + use super::*; + + /// State reads for the fungibles API with required input. + #[derive(Encode, Decode, Debug, MaxEncodedLen)] + #[repr(u8)] + #[allow(clippy::unnecessary_cast)] + pub enum Read { + /// Returns the owner of an item. + #[codec(index = 0)] + OwnerOf { collection: CollectionIdOf, item: ItemIdOf }, + /// Returns the owner of a collection. + #[codec(index = 1)] + CollectionOwner(CollectionIdOf), + /// Number of items existing in a concrete collection. + #[codec(index = 2)] + TotalSupply(CollectionIdOf), + /// Returns the total number of items in the collection owned by the account. + #[codec(index = 3)] + BalanceOf { collection: CollectionIdOf, owner: AccountIdOf }, + /// Returns the details of a collection. + #[codec(index = 4)] + Collection(CollectionIdOf), + /// Returns the details of an item. + #[codec(index = 5)] + Item { collection: CollectionIdOf, item: ItemIdOf }, + /// Whether a spender is allowed to transfer an item or items from owner. + #[codec(index = 6)] + Allowance { spender: AccountIdOf, collection: CollectionIdOf, item: ItemIdOf }, + } + + /// Configure the pallet by specifying the parameters and types on which it depends. + #[pallet::config] + pub trait Config: frame_system::Config + pallet_nfts::Config { + /// Because this pallet emits events, it depends on the runtime's definition of an event. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + } + + #[pallet::pallet] + pub struct Pallet(_); + + /// The events that can be emitted. + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Event emitted when allowance by `owner` to `spender` canceled. + CancelApproval { + /// The collection ID. + collection: CollectionIdOf, + /// the item ID. + item: ItemIdOf, + /// The beneficiary of the allowance. + spender: AccountIdOf, + }, + /// Event emitted when allowance by `owner` to `spender` changes. + Approval { + /// The collection ID. + collection: CollectionIdOf, + /// the item ID. + item: ItemIdOf, + /// The owner providing the allowance. + owner: AccountIdOf, + /// The beneficiary of the allowance. + spender: AccountIdOf, + }, + /// Event emitted when new item is minted to the account. + Mint { + /// The owner of the item. + to: AccountIdOf, + /// The collection ID. + collection: CollectionIdOf, + /// the item ID. + item: ItemIdOf, + }, + /// Event emitted when item is burned. + Burn { + /// The collection ID. + collection: CollectionIdOf, + /// the item ID. + item: ItemIdOf, + }, + /// Event emitted when an item transfer occurs. + Transfer { + /// The collection ID. + collection: CollectionIdOf, + /// the item ID. + item: ItemIdOf, + /// The source of the transfer. + from: AccountIdOf, + /// The recipient of the transfer. + to: AccountIdOf, + }, + } + + #[pallet::call] + impl Pallet { + /// Create a new non-fungible token to the collection. + /// + /// # Parameters + /// - `to` - The owner of the collection item. + /// - `collection` - The collection ID. + /// - `item` - The item ID. + #[pallet::call_index(0)] + #[pallet::weight(NftsWeightInfoOf::::mint())] + pub fn mint( + origin: OriginFor, + to: AccountIdOf, + collection: CollectionIdOf, + item: ItemIdOf, + ) -> DispatchResult { + NftsOf::::mint(origin, collection, item, T::Lookup::unlookup(to.clone()), None)?; + Self::deposit_event(Event::Mint { to, collection, item }); + Ok(()) + } + + /// Destroy a new non-fungible token to the collection. + /// + /// # Parameters + /// - `collection` - The collection ID. + /// - `item` - The item ID. + #[pallet::call_index(1)] + #[pallet::weight(NftsWeightInfoOf::::burn())] + pub fn burn( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + ) -> DispatchResult { + NftsOf::::burn(origin, collection, item)?; + Self::deposit_event(Event::Burn { collection, item }); + Ok(()) + } + + /// Transfer a token from one account to the another account. + /// + /// # Parameters + /// - `collection` - The collection ID. + /// - `item` - The item ID. + /// - `to` - The recipient account. + #[pallet::call_index(2)] + #[pallet::weight(NftsWeightInfoOf::::transfer())] + pub fn transfer( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + to: AccountIdOf, + ) -> DispatchResult { + let from = ensure_signed(origin.clone())?; + NftsOf::::transfer(origin, collection, item, T::Lookup::unlookup(to.clone()))?; + Self::deposit_event(Event::Transfer { from, to, collection, item }); + Ok(()) + } + + /// Delegate a permission to perform actions on the collection item to an account. + /// + /// # Parameters + /// - `collection` - The collection ID. + /// - `item` - The item ID. + /// - `spender` - The account that is allowed to transfer the collection item. + #[pallet::call_index(3)] + #[pallet::weight(NftsWeightInfoOf::::approve_transfer())] + pub fn approve( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + spender: AccountIdOf, + ) -> DispatchResult { + let owner = ensure_signed(origin.clone())?; + NftsOf::::approve_transfer( + origin, + collection, + item, + T::Lookup::unlookup(spender.clone()), + None, + )?; + Self::deposit_event(Event::Approval { collection, item, spender, owner }); + Ok(()) + } + + /// Cancel one of the transfer approvals for a specific item. + /// + /// # Parameters + /// - `collection` - The collection ID. + /// - `item` - The item ID. + /// - `spender` - The account that is revoked permission to transfer the collection item. + #[pallet::call_index(4)] + #[pallet::weight(NftsWeightInfoOf::::cancel_approval())] + pub fn cancel_approval( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + spender: AccountIdOf, + ) -> DispatchResult { + NftsOf::::cancel_approval( + origin, + collection, + item, + T::Lookup::unlookup(spender.clone()), + )?; + Self::deposit_event(Event::CancelApproval { collection, item, spender }); + Ok(()) + } + } + + impl Pallet { + /// Reads fungible asset state based on the provided value. + /// + /// This function matches the value to determine the type of state query and returns the + /// encoded result. + /// + /// # Parameter + /// - `value` - An instance of `Read`, which specifies the type of state query and the + /// associated parameters. + pub fn read_state(value: Read) -> Vec { + use Read::*; + match value { + OwnerOf { collection, item } => NftsOf::::owner(collection, item).encode(), + CollectionOwner(collection) => NftsOf::::collection_owner(collection).encode(), + TotalSupply(collection) => (NftsOf::::items(&collection).count() as u8).encode(), + Collection(collection) => pallet_nfts::Collection::::get(&collection).encode(), + Item { collection, item } => pallet_nfts::Item::::get(collection, item).encode(), + Allowance { collection, item, spender } => + Self::allowance(collection, item, spender).encode(), + BalanceOf { collection, owner } => + (NftsOf::::owned_in_collection(&collection, &owner).count() as u8).encode(), + } + } + + /// Check if the `spender` is approved to transfer the collection item + pub(super) fn allowance( + collection: CollectionIdOf, + item: ItemIdOf, + spender: AccountIdOf, + ) -> bool { + let data = pallet_nfts::Item::::get(collection, item).encode(); + if let Ok(detail) = ItemDetails::::decode(&mut data.as_slice()) { + return detail.approvals.contains_key(&spender); + } + false + } + } +} diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs new file mode 100644 index 000000000..9e9da5c27 --- /dev/null +++ b/pallets/api/src/nonfungibles/tests.rs @@ -0,0 +1,183 @@ +use codec::Encode; +use frame_support::{assert_ok, traits::nonfungibles_v2::InspectEnumerable}; +use frame_system::pallet_prelude::BlockNumberFor; +use pallet_nfts::{CollectionConfig, CollectionSettings, MintSettings}; + +use super::types::*; +use crate::{ + mock::*, + nonfungibles::{Event, Read::*}, +}; + +const ITEM: u32 = 1; + +#[test] +fn mint_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let collection = create_collection(owner.clone()); + // Successfully mint a new collection item. + assert_ok!(NonFungibles::mint(signed(owner.clone()), owner.clone(), collection, ITEM)); + System::assert_last_event(Event::Mint { to: owner, collection, item: ITEM }.into()); + }); +} + +#[test] +fn burn_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let (collection, item) = create_collection_mint(owner.clone(), ITEM); + // Successfully burn an existing new collection item. + assert_ok!(NonFungibles::burn(signed(owner.clone()), collection, ITEM)); + System::assert_last_event(Event::Burn { collection, item }.into()); + }); +} + +#[test] +fn transfer() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let dest = account(BOB); + let (collection, item) = create_collection_mint(owner.clone(), ITEM); + // Successfully burn an existing new collection item. + assert_ok!(NonFungibles::transfer(signed(owner.clone()), collection, ITEM, dest.clone())); + System::assert_last_event( + Event::Transfer { collection, item, from: owner, to: dest }.into(), + ); + }); +} + +#[test] +fn approve_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let spender = account(BOB); + let (collection, item) = create_collection_mint(owner.clone(), ITEM); + // Successfully approve `spender` to transfer the collection item. + assert_ok!(NonFungibles::approve(signed(owner.clone()), collection, item, spender.clone())); + System::assert_last_event( + Event::Approval { collection, item, owner, spender: spender.clone() }.into(), + ); + // Successfully transfer the item by the delegated account `spender`. + assert_ok!(Nfts::transfer(signed(spender.clone()), collection, item, spender)); + }); +} + +#[test] +fn cancel_approval_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let spender = account(BOB); + let (collection, item) = + create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); + // Successfully cancel the transfer approval of `spender` by `owner`. + assert_ok!(NonFungibles::cancel_approval(signed(owner), collection, item, spender.clone())); + // Failed to transfer the item by `spender` without permission. + assert!(Nfts::transfer(signed(spender.clone()), collection, item, spender).is_err()); + }); +} + +#[test] +fn owner_of_works() {} + +#[test] +fn collection_owner_works() { + new_test_ext().execute_with(|| { + let collection = create_collection(account(ALICE)); + assert_eq!( + NonFungibles::read_state(CollectionOwner(collection)), + Nfts::collection_owner(collection).encode() + ); + }); +} + +#[test] +fn total_supply_works() { + new_test_ext().execute_with(|| { + let (collection, _) = create_collection_mint(account(ALICE), ITEM); + assert_eq!( + NonFungibles::read_state(TotalSupply(collection)), + (Nfts::items(&collection).count() as u8).encode() + ); + }); +} + +#[test] +fn collection_works() { + new_test_ext().execute_with(|| { + let (collection, _) = create_collection_mint(account(ALICE), ITEM); + assert_eq!( + NonFungibles::read_state(Collection(collection)), + pallet_nfts::Collection::::get(&collection).encode(), + ); + }); +} + +#[test] +fn balance_of_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let (collection, _) = create_collection_mint(owner.clone(), ITEM); + assert_eq!( + NonFungibles::read_state(BalanceOf { collection, owner: owner.clone() }), + (Nfts::owned_in_collection(&collection, &owner).count() as u8).encode() + ); + }); +} + +#[test] +fn allowance_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let spender = account(BOB); + let (collection, item) = + create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); + assert_eq!( + NonFungibles::read_state(Allowance { spender: spender.clone(), collection, item }), + super::Pallet::::allowance(collection, item, spender).encode() + ); + }); +} + +fn signed(account: AccountId) -> RuntimeOrigin { + RuntimeOrigin::signed(account) +} + +fn create_collection_mint_and_approve( + owner: AccountIdOf, + item: ItemIdOf, + spender: AccountIdOf, +) -> (u32, u32) { + let (collection, item) = create_collection_mint(owner.clone(), item); + assert_ok!(Nfts::approve_transfer(signed(owner), collection, item, spender, None)); + (collection, item) +} + +fn create_collection_mint(owner: AccountIdOf, item: ItemIdOf) -> (u32, u32) { + let collection = create_collection(owner.clone()); + assert_ok!(Nfts::mint(signed(owner.clone()), collection, item, owner, None)); + (collection, item) +} + +fn create_collection(owner: AccountIdOf) -> u32 { + let next_id = next_collection_id(); + assert_ok!(Nfts::create( + signed(owner.clone()), + owner.clone(), + collection_config_with_all_settings_enabled() + )); + next_id +} + +fn next_collection_id() -> u32 { + pallet_nfts::NextCollectionId::::get().unwrap_or_default() +} + +fn collection_config_with_all_settings_enabled( +) -> CollectionConfig, CollectionIdOf> { + CollectionConfig { + settings: CollectionSettings::all_enabled(), + max_supply: None, + mint_settings: MintSettings::default(), + } +} diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs new file mode 100644 index 000000000..0174ef77b --- /dev/null +++ b/pallets/api/src/nonfungibles/types.rs @@ -0,0 +1,61 @@ +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; +use frame_system::pallet_prelude::BlockNumberFor; +use scale_info::TypeInfo; +use sp_runtime::BoundedBTreeMap; + +use super::Config; + +pub(super) type AccountIdOf = ::AccountId; + +pub(super) type NftsOf = pallet_nfts::Pallet; + +/// Weight information for extrinsics in this pallet. +pub(super) type NftsWeightInfoOf = ::WeightInfo; + +/// A type alias for the collection ID. +pub(super) type CollectionIdOf = + as Inspect<::AccountId>>::CollectionId; + +/// A type alias for the collection item ID. +pub(super) type ItemIdOf = + as Inspect<::AccountId>>::ItemId; + +// TODO: Even though this serves the `allowance` method, it creates the maintenance cost. + +/// A type that holds the deposit for a single item. +pub(super) type ItemDepositOf = + ItemDeposit, ::AccountId>; + +/// A type alias for handling balance deposits. +pub(super) type DepositBalanceOf = <::Currency as Currency< + ::AccountId, +>>::Balance; + +/// A type alias for keeping track of approvals used by a single item. +pub(super) type ApprovalsOf = BoundedBTreeMap< + AccountIdOf, + Option>, + ::ApprovalsLimit, +>; + +/// Information concerning the ownership of a single unique item. +#[derive(Clone, Encode, Decode, Eq, PartialEq, TypeInfo, MaxEncodedLen)] +pub(super) struct ItemDetails { + /// The owner of this item. + pub(super) owner: AccountIdOf, + /// The approved transferrer of this item, if one is set. + pub(super) approvals: ApprovalsOf, + /// The amount held in the pallet's default account for this item. Free-hold items will have + /// this as zero. + pub(super) deposit: ItemDepositOf, +} + +/// Information about the reserved item deposit. +#[derive(Clone, Encode, Decode, Eq, PartialEq, TypeInfo, MaxEncodedLen)] +pub struct ItemDeposit { + /// A depositor account. + pub(super) account: AccountId, + /// An amount that gets reserved. + pub(super) amount: DepositBalance, +} From cd84ed81053765a8894cf34be28da52eb07292e8 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:12:39 +0700 Subject: [PATCH 37/76] chore: add nfts pallet --- Cargo.lock | 2 +- pallets/api/src/nonfungibles/mod.rs | 171 +++++++++--- pallets/api/src/nonfungibles/tests.rs | 367 +++++++++++++------------- pallets/api/src/nonfungibles/types.rs | 57 ++-- 4 files changed, 357 insertions(+), 240 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f98f910e..ed534195c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7366,7 +7366,7 @@ dependencies = [ "log", "pallet-assets", "pallet-balances", - "pallet-nfts", + "pallet-nfts 31.0.0", "parity-scale-codec", "pop-chain-extension", "scale-info", diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index cac0cbbab..c5e8cffbe 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -2,10 +2,9 @@ //! assets. The goal is to provide a simplified, consistent API that adheres to standards in the //! smart contract space. -use frame_support::traits::nonfungibles_v2::InspectEnumerable; pub use pallet::*; use pallet_nfts::WeightInfo; -use sp_runtime::traits::StaticLookup; +use sp_runtime::{traits::StaticLookup, RuntimeDebug}; #[cfg(test)] mod tests; @@ -16,12 +15,16 @@ pub mod pallet { use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; use frame_system::pallet_prelude::*; use sp_std::vec::Vec; - use types::{AccountIdOf, CollectionIdOf, ItemDetails, ItemIdOf, NftsOf, NftsWeightInfoOf}; + use types::{ + AccountIdOf, BalanceOf, CollectionDetailsFor, CollectionIdOf, ItemDetailsFor, ItemIdOf, + NftsOf, NftsWeightInfoOf, + }; use super::*; - /// State reads for the fungibles API with required input. + /// State reads for the non-fungibles API with required input. #[derive(Encode, Decode, Debug, MaxEncodedLen)] + #[cfg_attr(feature = "std", derive(PartialEq, Clone))] #[repr(u8)] #[allow(clippy::unnecessary_cast)] pub enum Read { @@ -45,7 +48,41 @@ pub mod pallet { Item { collection: CollectionIdOf, item: ItemIdOf }, /// Whether a spender is allowed to transfer an item or items from owner. #[codec(index = 6)] - Allowance { spender: AccountIdOf, collection: CollectionIdOf, item: ItemIdOf }, + Allowance { + collection: CollectionIdOf, + owner: AccountIdOf, + operator: AccountIdOf, + item: Option>, + }, + } + + /// Results of state reads for the non-fungibles API. + #[derive(Debug)] + #[cfg_attr(feature = "std", derive(PartialEq, Clone))] + pub enum ReadResult { + OwnerOf(Option>), + CollectionOwner(Option>), + TotalSupply(u32), + BalanceOf(BalanceOf), + Collection(Option>), + Item(Option>), + Allowance(bool), + } + + impl ReadResult { + /// Encodes the result. + pub fn encode(&self) -> Vec { + use ReadResult::*; + match self { + OwnerOf(result) => result.encode(), + CollectionOwner(result) => result.encode(), + TotalSupply(result) => result.encode(), + BalanceOf(result) => result.encode(), + Collection(result) => result.encode(), + Item(result) => result.encode(), + Allowance(result) => result.encode(), + } + } } /// Configure the pallet by specifying the parameters and types on which it depends. @@ -55,6 +92,32 @@ pub mod pallet { type RuntimeEvent: From> + IsType<::RuntimeEvent>; } + #[pallet::storage] + type AccountBalance = StorageNMap< + Key = ( + // Collection ID + NMapKey>, + // Collection Owner ID + NMapKey>, + ), + Value = BalanceOf, + QueryKind = ValueQuery, + >; + + #[pallet::storage] + type Allowances = StorageNMap< + Key = ( + // Collection ID + NMapKey>, + // Collection Owner ID + NMapKey>, + // Collection Operator ID + NMapKey>, + ), + Value = bool, + QueryKind = ValueQuery, + >; + #[pallet::pallet] pub struct Pallet(_); @@ -221,40 +284,86 @@ pub mod pallet { } impl Pallet { - /// Reads fungible asset state based on the provided value. - /// - /// This function matches the value to determine the type of state query and returns the - /// encoded result. - /// - /// # Parameter - /// - `value` - An instance of `Read`, which specifies the type of state query and the - /// associated parameters. - pub fn read_state(value: Read) -> Vec { - use Read::*; - match value { - OwnerOf { collection, item } => NftsOf::::owner(collection, item).encode(), - CollectionOwner(collection) => NftsOf::::collection_owner(collection).encode(), - TotalSupply(collection) => (NftsOf::::items(&collection).count() as u8).encode(), - Collection(collection) => pallet_nfts::Collection::::get(&collection).encode(), - Item { collection, item } => pallet_nfts::Item::::get(collection, item).encode(), - Allowance { collection, item, spender } => - Self::allowance(collection, item, spender).encode(), - BalanceOf { collection, owner } => - (NftsOf::::owned_in_collection(&collection, &owner).count() as u8).encode(), - } + /// Check if the `spender` is approved to transfer the collection item. + pub(super) fn allowance( + collection: CollectionIdOf, + owner: AccountIdOf, + operator: AccountIdOf, + maybe_item: Option>, + ) -> bool { + // Check if has a permission to transfer all collection items. + Allowances::::get((collection, owner, operator.clone())) || + maybe_item + .and_then(|item| Some(Self::allowance_item(collection, operator, item))) + .unwrap_or(false) } - /// Check if the `spender` is approved to transfer the collection item - pub(super) fn allowance( + // Check the permission for the single item. + pub(super) fn allowance_item( collection: CollectionIdOf, + operator: AccountIdOf, item: ItemIdOf, - spender: AccountIdOf, ) -> bool { let data = pallet_nfts::Item::::get(collection, item).encode(); - if let Ok(detail) = ItemDetails::::decode(&mut data.as_slice()) { - return detail.approvals.contains_key(&spender); + if let Ok(detail) = ItemDetailsFor::::decode(&mut data.as_slice()) { + return detail.approvals.contains_key(&operator); } false } } + + impl crate::Read for Pallet { + /// The type of read requested. + type Read = Read; + /// The type or result returned. + type Result = ReadResult; + + /// Determines the weight of the requested read, used to charge the appropriate weight + /// before the read is performed. + /// + /// # Parameters + /// - `request` - The read request. + fn weight(_request: &Self::Read) -> Weight { + Default::default() + } + + /// Performs the requested read and returns the result. + /// + /// # Parameters + /// - `request` - The read request. + fn read(value: Self::Read) -> Self::Result { + use Read::*; + match value { + OwnerOf { collection, item } => + ReadResult::OwnerOf(NftsOf::::owner(collection, item)), + CollectionOwner(collection) => + ReadResult::CollectionOwner(NftsOf::::collection_owner(collection)), + TotalSupply(collection) => { + let data = pallet_nfts::Collection::::get(collection).encode(); + ReadResult::TotalSupply( + CollectionDetailsFor::::decode(&mut data.as_slice()) + .map(|detail| detail.items) + .unwrap_or_default(), + ) + }, + Collection(collection) => { + let data = pallet_nfts::Collection::::get(collection).encode(); + ReadResult::Collection( + Option::>::decode(&mut data.as_slice()) + .unwrap_or(None), + ) + }, + Item { collection, item } => { + let data = pallet_nfts::Item::::get(collection, item).encode(); + ReadResult::Item( + Option::>::decode(&mut data.as_slice()).unwrap_or(None), + ) + }, + Allowance { collection, owner, operator, item } => + ReadResult::Allowance(Self::allowance(collection, owner, operator, item)), + BalanceOf { collection, owner } => + ReadResult::BalanceOf(AccountBalance::::get((collection, owner))), + } + } + } } diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index 9e9da5c27..54d855167 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -1,183 +1,184 @@ -use codec::Encode; -use frame_support::{assert_ok, traits::nonfungibles_v2::InspectEnumerable}; -use frame_system::pallet_prelude::BlockNumberFor; -use pallet_nfts::{CollectionConfig, CollectionSettings, MintSettings}; - -use super::types::*; -use crate::{ - mock::*, - nonfungibles::{Event, Read::*}, -}; - -const ITEM: u32 = 1; - -#[test] -fn mint_works() { - new_test_ext().execute_with(|| { - let owner = account(ALICE); - let collection = create_collection(owner.clone()); - // Successfully mint a new collection item. - assert_ok!(NonFungibles::mint(signed(owner.clone()), owner.clone(), collection, ITEM)); - System::assert_last_event(Event::Mint { to: owner, collection, item: ITEM }.into()); - }); -} - -#[test] -fn burn_works() { - new_test_ext().execute_with(|| { - let owner = account(ALICE); - let (collection, item) = create_collection_mint(owner.clone(), ITEM); - // Successfully burn an existing new collection item. - assert_ok!(NonFungibles::burn(signed(owner.clone()), collection, ITEM)); - System::assert_last_event(Event::Burn { collection, item }.into()); - }); -} - -#[test] -fn transfer() { - new_test_ext().execute_with(|| { - let owner = account(ALICE); - let dest = account(BOB); - let (collection, item) = create_collection_mint(owner.clone(), ITEM); - // Successfully burn an existing new collection item. - assert_ok!(NonFungibles::transfer(signed(owner.clone()), collection, ITEM, dest.clone())); - System::assert_last_event( - Event::Transfer { collection, item, from: owner, to: dest }.into(), - ); - }); -} - -#[test] -fn approve_works() { - new_test_ext().execute_with(|| { - let owner = account(ALICE); - let spender = account(BOB); - let (collection, item) = create_collection_mint(owner.clone(), ITEM); - // Successfully approve `spender` to transfer the collection item. - assert_ok!(NonFungibles::approve(signed(owner.clone()), collection, item, spender.clone())); - System::assert_last_event( - Event::Approval { collection, item, owner, spender: spender.clone() }.into(), - ); - // Successfully transfer the item by the delegated account `spender`. - assert_ok!(Nfts::transfer(signed(spender.clone()), collection, item, spender)); - }); -} - -#[test] -fn cancel_approval_works() { - new_test_ext().execute_with(|| { - let owner = account(ALICE); - let spender = account(BOB); - let (collection, item) = - create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); - // Successfully cancel the transfer approval of `spender` by `owner`. - assert_ok!(NonFungibles::cancel_approval(signed(owner), collection, item, spender.clone())); - // Failed to transfer the item by `spender` without permission. - assert!(Nfts::transfer(signed(spender.clone()), collection, item, spender).is_err()); - }); -} - -#[test] -fn owner_of_works() {} - -#[test] -fn collection_owner_works() { - new_test_ext().execute_with(|| { - let collection = create_collection(account(ALICE)); - assert_eq!( - NonFungibles::read_state(CollectionOwner(collection)), - Nfts::collection_owner(collection).encode() - ); - }); -} - -#[test] -fn total_supply_works() { - new_test_ext().execute_with(|| { - let (collection, _) = create_collection_mint(account(ALICE), ITEM); - assert_eq!( - NonFungibles::read_state(TotalSupply(collection)), - (Nfts::items(&collection).count() as u8).encode() - ); - }); -} - -#[test] -fn collection_works() { - new_test_ext().execute_with(|| { - let (collection, _) = create_collection_mint(account(ALICE), ITEM); - assert_eq!( - NonFungibles::read_state(Collection(collection)), - pallet_nfts::Collection::::get(&collection).encode(), - ); - }); -} - -#[test] -fn balance_of_works() { - new_test_ext().execute_with(|| { - let owner = account(ALICE); - let (collection, _) = create_collection_mint(owner.clone(), ITEM); - assert_eq!( - NonFungibles::read_state(BalanceOf { collection, owner: owner.clone() }), - (Nfts::owned_in_collection(&collection, &owner).count() as u8).encode() - ); - }); -} - -#[test] -fn allowance_works() { - new_test_ext().execute_with(|| { - let owner = account(ALICE); - let spender = account(BOB); - let (collection, item) = - create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); - assert_eq!( - NonFungibles::read_state(Allowance { spender: spender.clone(), collection, item }), - super::Pallet::::allowance(collection, item, spender).encode() - ); - }); -} - -fn signed(account: AccountId) -> RuntimeOrigin { - RuntimeOrigin::signed(account) -} - -fn create_collection_mint_and_approve( - owner: AccountIdOf, - item: ItemIdOf, - spender: AccountIdOf, -) -> (u32, u32) { - let (collection, item) = create_collection_mint(owner.clone(), item); - assert_ok!(Nfts::approve_transfer(signed(owner), collection, item, spender, None)); - (collection, item) -} - -fn create_collection_mint(owner: AccountIdOf, item: ItemIdOf) -> (u32, u32) { - let collection = create_collection(owner.clone()); - assert_ok!(Nfts::mint(signed(owner.clone()), collection, item, owner, None)); - (collection, item) -} - -fn create_collection(owner: AccountIdOf) -> u32 { - let next_id = next_collection_id(); - assert_ok!(Nfts::create( - signed(owner.clone()), - owner.clone(), - collection_config_with_all_settings_enabled() - )); - next_id -} - -fn next_collection_id() -> u32 { - pallet_nfts::NextCollectionId::::get().unwrap_or_default() -} - -fn collection_config_with_all_settings_enabled( -) -> CollectionConfig, CollectionIdOf> { - CollectionConfig { - settings: CollectionSettings::all_enabled(), - max_supply: None, - mint_settings: MintSettings::default(), - } -} +// TODO +// use codec::Encode; +// use frame_support::{assert_ok, traits::nonfungibles_v2::InspectEnumerable}; +// use frame_system::pallet_prelude::BlockNumberFor; +// use pallet_nfts::{CollectionConfig, CollectionSettings, MintSettings}; + +// use super::types::*; +// use crate::{ +// mock::*, +// nonfungibles::{Event, Read::*}, +// }; + +// const ITEM: u32 = 1; + +// #[test] +// fn mint_works() { +// new_test_ext().execute_with(|| { +// let owner = account(ALICE); +// let collection = create_collection(owner.clone()); +// // Successfully mint a new collection item. +// assert_ok!(NonFungibles::mint(signed(owner.clone()), owner.clone(), collection, ITEM)); +// System::assert_last_event(Event::Mint { to: owner, collection, item: ITEM }.into()); +// }); +// } + +// #[test] +// fn burn_works() { +// new_test_ext().execute_with(|| { +// let owner = account(ALICE); +// let (collection, item) = create_collection_mint(owner.clone(), ITEM); +// // Successfully burn an existing new collection item. +// assert_ok!(NonFungibles::burn(signed(owner.clone()), collection, ITEM)); +// System::assert_last_event(Event::Burn { collection, item }.into()); +// }); +// } + +// #[test] +// fn transfer() { +// new_test_ext().execute_with(|| { +// let owner = account(ALICE); +// let dest = account(BOB); +// let (collection, item) = create_collection_mint(owner.clone(), ITEM); +// // Successfully burn an existing new collection item. +// assert_ok!(NonFungibles::transfer(signed(owner.clone()), collection, ITEM, dest.clone())); +// System::assert_last_event( +// Event::Transfer { collection, item, from: owner, to: dest }.into(), +// ); +// }); +// } + +// #[test] +// fn approve_works() { +// new_test_ext().execute_with(|| { +// let owner = account(ALICE); +// let spender = account(BOB); +// let (collection, item) = create_collection_mint(owner.clone(), ITEM); +// // Successfully approve `spender` to transfer the collection item. +// assert_ok!(NonFungibles::approve(signed(owner.clone()), collection, item, spender.clone())); +// System::assert_last_event( +// Event::Approval { collection, item, owner, spender: spender.clone() }.into(), +// ); +// // Successfully transfer the item by the delegated account `spender`. +// assert_ok!(Nfts::transfer(signed(spender.clone()), collection, item, spender)); +// }); +// } + +// #[test] +// fn cancel_approval_works() { +// new_test_ext().execute_with(|| { +// let owner = account(ALICE); +// let spender = account(BOB); +// let (collection, item) = +// create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); +// // Successfully cancel the transfer approval of `spender` by `owner`. +// assert_ok!(NonFungibles::cancel_approval(signed(owner), collection, item, spender.clone())); +// // Failed to transfer the item by `spender` without permission. +// assert!(Nfts::transfer(signed(spender.clone()), collection, item, spender).is_err()); +// }); +// } + +// #[test] +// fn owner_of_works() {} + +// #[test] +// fn collection_owner_works() { +// new_test_ext().execute_with(|| { +// let collection = create_collection(account(ALICE)); +// assert_eq!( +// NonFungibles::read_state(CollectionOwner(collection)), +// Nfts::collection_owner(collection).encode() +// ); +// }); +// } + +// #[test] +// fn total_supply_works() { +// new_test_ext().execute_with(|| { +// let (collection, _) = create_collection_mint(account(ALICE), ITEM); +// assert_eq!( +// NonFungibles::read_state(TotalSupply(collection)), +// (Nfts::items(&collection).count() as u8).encode() +// ); +// }); +// } + +// #[test] +// fn collection_works() { +// new_test_ext().execute_with(|| { +// let (collection, _) = create_collection_mint(account(ALICE), ITEM); +// assert_eq!( +// NonFungibles::read_state(Collection(collection)), +// pallet_nfts::Collection::::get(&collection).encode(), +// ); +// }); +// } + +// #[test] +// fn balance_of_works() { +// new_test_ext().execute_with(|| { +// let owner = account(ALICE); +// let (collection, _) = create_collection_mint(owner.clone(), ITEM); +// assert_eq!( +// NonFungibles::read_state(BalanceOf { collection, owner: owner.clone() }), +// (Nfts::owned_in_collection(&collection, &owner).count() as u8).encode() +// ); +// }); +// } + +// #[test] +// fn allowance_works() { +// new_test_ext().execute_with(|| { +// let owner = account(ALICE); +// let spender = account(BOB); +// let (collection, item) = +// create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); +// assert_eq!( +// NonFungibles::read_state(Allowance { spender: spender.clone(), collection, item }), +// super::Pallet::::allowance(collection, item, spender).encode() +// ); +// }); +// } + +// fn signed(account: AccountId) -> RuntimeOrigin { +// RuntimeOrigin::signed(account) +// } + +// fn create_collection_mint_and_approve( +// owner: AccountIdOf, +// item: ItemIdOf, +// spender: AccountIdOf, +// ) -> (u32, u32) { +// let (collection, item) = create_collection_mint(owner.clone(), item); +// assert_ok!(Nfts::approve_transfer(signed(owner), collection, item, spender, None)); +// (collection, item) +// } + +// fn create_collection_mint(owner: AccountIdOf, item: ItemIdOf) -> (u32, u32) { +// let collection = create_collection(owner.clone()); +// assert_ok!(Nfts::mint(signed(owner.clone()), collection, item, owner, None)); +// (collection, item) +// } + +// fn create_collection(owner: AccountIdOf) -> u32 { +// let next_id = next_collection_id(); +// assert_ok!(Nfts::create( +// signed(owner.clone()), +// owner.clone(), +// collection_config_with_all_settings_enabled() +// )); +// next_id +// } + +// fn next_collection_id() -> u32 { +// pallet_nfts::NextCollectionId::::get().unwrap_or_default() +// } + +// fn collection_config_with_all_settings_enabled( +// ) -> CollectionConfig, CollectionIdOf> { +// CollectionConfig { +// settings: CollectionSettings::all_enabled(), +// max_supply: None, +// mint_settings: MintSettings::default(), +// } +// } diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs index 0174ef77b..a55a8ec26 100644 --- a/pallets/api/src/nonfungibles/types.rs +++ b/pallets/api/src/nonfungibles/types.rs @@ -4,34 +4,22 @@ use frame_system::pallet_prelude::BlockNumberFor; use scale_info::TypeInfo; use sp_runtime::BoundedBTreeMap; -use super::Config; +use super::*; pub(super) type AccountIdOf = ::AccountId; - pub(super) type NftsOf = pallet_nfts::Pallet; - /// Weight information for extrinsics in this pallet. pub(super) type NftsWeightInfoOf = ::WeightInfo; - /// A type alias for the collection ID. pub(super) type CollectionIdOf = - as Inspect<::AccountId>>::CollectionId; - + as Inspect<::AccountId>>::CollectionId; /// A type alias for the collection item ID. pub(super) type ItemIdOf = - as Inspect<::AccountId>>::ItemId; - -// TODO: Even though this serves the `allowance` method, it creates the maintenance cost. - -/// A type that holds the deposit for a single item. -pub(super) type ItemDepositOf = - ItemDeposit, ::AccountId>; - + as Inspect<::AccountId>>::ItemId; /// A type alias for handling balance deposits. -pub(super) type DepositBalanceOf = <::Currency as Currency< +pub(super) type BalanceOf = <::Currency as Currency< ::AccountId, >>::Balance; - /// A type alias for keeping track of approvals used by a single item. pub(super) type ApprovalsOf = BoundedBTreeMap< AccountIdOf, @@ -39,23 +27,42 @@ pub(super) type ApprovalsOf = BoundedBTreeMap< ::ApprovalsLimit, >; +pub(super) type ItemDetailsFor = ItemDetails, BalanceOf, ApprovalsOf>; +pub(super) type CollectionDetailsFor = CollectionDetails, BalanceOf>; + /// Information concerning the ownership of a single unique item. -#[derive(Clone, Encode, Decode, Eq, PartialEq, TypeInfo, MaxEncodedLen)] -pub(super) struct ItemDetails { +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct ItemDetails { /// The owner of this item. - pub(super) owner: AccountIdOf, + pub owner: AccountId, /// The approved transferrer of this item, if one is set. - pub(super) approvals: ApprovalsOf, + pub approvals: Approvals, /// The amount held in the pallet's default account for this item. Free-hold items will have /// this as zero. - pub(super) deposit: ItemDepositOf, + pub deposit: Deposit, } - /// Information about the reserved item deposit. -#[derive(Clone, Encode, Decode, Eq, PartialEq, TypeInfo, MaxEncodedLen)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct ItemDeposit { /// A depositor account. - pub(super) account: AccountId, + account: AccountId, /// An amount that gets reserved. - pub(super) amount: DepositBalance, + amount: DepositBalance, +} +/// Information about a collection. +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct CollectionDetails { + /// Collection's owner. + pub owner: AccountId, + /// The total balance deposited by the owner for all the storage data associated with this + /// collection. Used by `destroy`. + pub owner_deposit: DepositBalance, + /// The total number of outstanding items of this collection. + pub items: u32, + /// The total number of outstanding item metadata of this collection. + pub item_metadatas: u32, + /// The total number of outstanding item configs of this collection. + pub item_configs: u32, + /// The total number of attributes for this collection. + pub attributes: u32, } From 3fad99499da309ab2a0729f423270eb845e6ff41 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 15 Oct 2024 21:23:52 +0700 Subject: [PATCH 38/76] feat: add new storage items to pallet-nfts --- pallets/api/src/nonfungibles/mod.rs | 101 +++--------------- pallets/api/src/nonfungibles/types.rs | 68 +++--------- pallets/nfts/src/common_functions.rs | 7 +- pallets/nfts/src/features/approvals.rs | 85 ++++++++++++++- .../src/features/create_delete_collection.rs | 3 + .../nfts/src/features/create_delete_item.rs | 6 ++ pallets/nfts/src/features/transfer.rs | 8 ++ pallets/nfts/src/lib.rs | 88 ++++++++++++++- 8 files changed, 220 insertions(+), 146 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index c5e8cffbe..cf2b14e7e 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -4,7 +4,7 @@ pub use pallet::*; use pallet_nfts::WeightInfo; -use sp_runtime::{traits::StaticLookup, RuntimeDebug}; +use sp_runtime::traits::StaticLookup; #[cfg(test)] mod tests; @@ -16,8 +16,8 @@ pub mod pallet { use frame_system::pallet_prelude::*; use sp_std::vec::Vec; use types::{ - AccountIdOf, BalanceOf, CollectionDetailsFor, CollectionIdOf, ItemDetailsFor, ItemIdOf, - NftsOf, NftsWeightInfoOf, + AccountIdOf, CollectionDetailsFor, CollectionIdOf, ItemDetailsFor, ItemIdOf, NftsOf, + NftsWeightInfoOf, }; use super::*; @@ -63,7 +63,7 @@ pub mod pallet { OwnerOf(Option>), CollectionOwner(Option>), TotalSupply(u32), - BalanceOf(BalanceOf), + BalanceOf(u32), Collection(Option>), Item(Option>), Allowance(bool), @@ -92,32 +92,6 @@ pub mod pallet { type RuntimeEvent: From> + IsType<::RuntimeEvent>; } - #[pallet::storage] - type AccountBalance = StorageNMap< - Key = ( - // Collection ID - NMapKey>, - // Collection Owner ID - NMapKey>, - ), - Value = BalanceOf, - QueryKind = ValueQuery, - >; - - #[pallet::storage] - type Allowances = StorageNMap< - Key = ( - // Collection ID - NMapKey>, - // Collection Owner ID - NMapKey>, - // Collection Operator ID - NMapKey>, - ), - Value = bool, - QueryKind = ValueQuery, - >; - #[pallet::pallet] pub struct Pallet(_); @@ -283,35 +257,6 @@ pub mod pallet { } } - impl Pallet { - /// Check if the `spender` is approved to transfer the collection item. - pub(super) fn allowance( - collection: CollectionIdOf, - owner: AccountIdOf, - operator: AccountIdOf, - maybe_item: Option>, - ) -> bool { - // Check if has a permission to transfer all collection items. - Allowances::::get((collection, owner, operator.clone())) || - maybe_item - .and_then(|item| Some(Self::allowance_item(collection, operator, item))) - .unwrap_or(false) - } - - // Check the permission for the single item. - pub(super) fn allowance_item( - collection: CollectionIdOf, - operator: AccountIdOf, - item: ItemIdOf, - ) -> bool { - let data = pallet_nfts::Item::::get(collection, item).encode(); - if let Ok(detail) = ItemDetailsFor::::decode(&mut data.as_slice()) { - return detail.approvals.contains_key(&operator); - } - false - } - } - impl crate::Read for Pallet { /// The type of read requested. type Read = Read; @@ -338,31 +283,19 @@ pub mod pallet { ReadResult::OwnerOf(NftsOf::::owner(collection, item)), CollectionOwner(collection) => ReadResult::CollectionOwner(NftsOf::::collection_owner(collection)), - TotalSupply(collection) => { - let data = pallet_nfts::Collection::::get(collection).encode(); - ReadResult::TotalSupply( - CollectionDetailsFor::::decode(&mut data.as_slice()) - .map(|detail| detail.items) - .unwrap_or_default(), - ) - }, - Collection(collection) => { - let data = pallet_nfts::Collection::::get(collection).encode(); - ReadResult::Collection( - Option::>::decode(&mut data.as_slice()) - .unwrap_or(None), - ) - }, - Item { collection, item } => { - let data = pallet_nfts::Item::::get(collection, item).encode(); - ReadResult::Item( - Option::>::decode(&mut data.as_slice()).unwrap_or(None), - ) - }, - Allowance { collection, owner, operator, item } => - ReadResult::Allowance(Self::allowance(collection, owner, operator, item)), - BalanceOf { collection, owner } => - ReadResult::BalanceOf(AccountBalance::::get((collection, owner))), + TotalSupply(collection) => ReadResult::TotalSupply( + NftsOf::::collection_items(collection).unwrap_or_default(), + ), + Collection(collection) => + ReadResult::Collection(pallet_nfts::Collection::::get(collection)), + Item { collection, item } => + ReadResult::Item(pallet_nfts::Item::::get(collection, item)), + Allowance { collection, owner, operator, item } => ReadResult::Allowance( + NftsOf::::allowance(collection, item, owner, operator).unwrap_or(false), + ), + BalanceOf { collection, owner } => ReadResult::BalanceOf( + pallet_nfts::AccountBalance::::get((collection, owner)), + ), } } } diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs index a55a8ec26..f81ea5359 100644 --- a/pallets/api/src/nonfungibles/types.rs +++ b/pallets/api/src/nonfungibles/types.rs @@ -1,68 +1,28 @@ -use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; use frame_system::pallet_prelude::BlockNumberFor; -use scale_info::TypeInfo; +use pallet_nfts::{CollectionDetails, ItemDeposit, ItemDetails}; use sp_runtime::BoundedBTreeMap; -use super::*; - -pub(super) type AccountIdOf = ::AccountId; +// Type aliases for pallet-nfts. pub(super) type NftsOf = pallet_nfts::Pallet; -/// Weight information for extrinsics in this pallet. pub(super) type NftsWeightInfoOf = ::WeightInfo; -/// A type alias for the collection ID. +// Type aliases for pallet-nfts storage items. +pub(super) type AccountIdOf = ::AccountId; +pub(super) type BalanceOf = <>::Currency as Currency< + ::AccountId, +>>::Balance; pub(super) type CollectionIdOf = as Inspect<::AccountId>>::CollectionId; -/// A type alias for the collection item ID. pub(super) type ItemIdOf = as Inspect<::AccountId>>::ItemId; -/// A type alias for handling balance deposits. -pub(super) type BalanceOf = <::Currency as Currency< - ::AccountId, ->>::Balance; -/// A type alias for keeping track of approvals used by a single item. -pub(super) type ApprovalsOf = BoundedBTreeMap< +type ApprovalsOf = BoundedBTreeMap< AccountIdOf, Option>, ::ApprovalsLimit, >; - -pub(super) type ItemDetailsFor = ItemDetails, BalanceOf, ApprovalsOf>; -pub(super) type CollectionDetailsFor = CollectionDetails, BalanceOf>; - -/// Information concerning the ownership of a single unique item. -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub struct ItemDetails { - /// The owner of this item. - pub owner: AccountId, - /// The approved transferrer of this item, if one is set. - pub approvals: Approvals, - /// The amount held in the pallet's default account for this item. Free-hold items will have - /// this as zero. - pub deposit: Deposit, -} -/// Information about the reserved item deposit. -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub struct ItemDeposit { - /// A depositor account. - account: AccountId, - /// An amount that gets reserved. - amount: DepositBalance, -} -/// Information about a collection. -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub struct CollectionDetails { - /// Collection's owner. - pub owner: AccountId, - /// The total balance deposited by the owner for all the storage data associated with this - /// collection. Used by `destroy`. - pub owner_deposit: DepositBalance, - /// The total number of outstanding items of this collection. - pub items: u32, - /// The total number of outstanding item metadata of this collection. - pub item_metadatas: u32, - /// The total number of outstanding item configs of this collection. - pub item_configs: u32, - /// The total number of attributes for this collection. - pub attributes: u32, -} +// TODO: Multi-instances. +pub(super) type ItemDepositOf = ItemDeposit, AccountIdOf>; +pub(super) type CollectionDetailsFor = + CollectionDetails, BalanceOf>; +pub(super) type ItemDetailsFor = + ItemDetails, ItemDepositOf, ApprovalsOf>; diff --git a/pallets/nfts/src/common_functions.rs b/pallets/nfts/src/common_functions.rs index f51de1922..6fe483f1a 100644 --- a/pallets/nfts/src/common_functions.rs +++ b/pallets/nfts/src/common_functions.rs @@ -34,6 +34,11 @@ impl, I: 'static> Pallet { Collection::::get(collection).map(|i| i.owner) } + /// Get the total number of items in the collection, if the collection exists. + pub fn collection_items(collection: T::CollectionId) -> Option { + Collection::::get(collection).map(|i| i.items) + } + /// Validates the signature of the given data with the provided signer's account ID. /// /// # Errors @@ -46,7 +51,7 @@ impl, I: 'static> Pallet { signer: &T::AccountId, ) -> DispatchResult { if signature.verify(&**data, &signer) { - return Ok(()) + return Ok(()); } // NOTE: for security reasons modern UIs implicitly wrap the data requested to sign into diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index ad5d93c2e..f626a9fe9 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -65,7 +65,6 @@ impl, I: 'static> Pallet { if let Some(check_origin) = maybe_check_origin { ensure!(check_origin == details.owner, Error::::NoPermission); } - let now = frame_system::Pallet::::block_number(); let deadline = maybe_deadline.map(|d| d.saturating_add(now)); @@ -74,15 +73,13 @@ impl, I: 'static> Pallet { .try_insert(delegate.clone(), deadline) .map_err(|_| Error::::ReachedApprovalLimit)?; Item::::insert(&collection, &item, &details); - Self::deposit_event(Event::TransferApproved { collection, - item, + item: Some(item), owner: details.owner, delegate, deadline, }); - Ok(()) } @@ -129,7 +126,7 @@ impl, I: 'static> Pallet { Self::deposit_event(Event::ApprovalCancelled { collection, - item, + item: Some(item), owner: details.owner, delegate, }); @@ -173,4 +170,82 @@ impl, I: 'static> Pallet { Ok(()) } + + pub(crate) fn do_approve_transfer_collection( + maybe_check_origin: Option, + collection: T::CollectionId, + delegate: T::AccountId, + ) -> DispatchResult { + ensure!( + Self::is_pallet_feature_enabled(PalletFeature::Approvals), + Error::::MethodDisabled + ); + let collection_owner = + Self::collection_owner(collection).ok_or(Error::::UnknownCollection)?; + + let collection_config = Self::get_collection_config(&collection)?; + ensure!( + collection_config.is_setting_enabled(CollectionSetting::TransferableItems), + Error::::ItemsNonTransferable + ); + + if let Some(check_origin) = maybe_check_origin { + ensure!(check_origin == collection_owner, Error::::NoPermission); + } + + Allowances::::mutate((&collection, &collection_owner, &delegate), |allowance| { + *allowance = true; + }); + + Self::deposit_event(Event::TransferApproved { + collection, + item: None, + owner: collection_owner, + delegate, + deadline: None, + }); + Ok(()) + } + + pub(crate) fn do_cancel_approval_collection( + maybe_check_origin: Option, + collection: T::CollectionId, + delegate: T::AccountId, + ) -> DispatchResult { + let collection_owner = + Self::collection_owner(collection).ok_or(Error::::UnknownCollection)?; + + if let Some(check_origin) = maybe_check_origin { + ensure!(check_origin == collection_owner, Error::::NoPermission); + } + + Allowances::::remove((&collection, &collection_owner, &delegate)); + + Self::deposit_event(Event::ApprovalCancelled { + collection, + owner: collection_owner, + item: None, + delegate, + }); + + Ok(()) + } + + pub fn allowance( + collection: T::CollectionId, + item: Option, + owner: T::AccountId, + delegate: T::AccountId, + ) -> Option { + // Check if a `delegate` has a permission to spend the collection. + if Allowances::::get((&collection, &owner, &delegate)) { + return Some(true); + } + // Check if a `delegate` has a permission to spend the collection item. + item.map(|item| { + Item::::get(&collection, &item) + .map(|detail| detail.approvals.contains_key(&delegate)) + }) + .unwrap_or_default() + } } diff --git a/pallets/nfts/src/features/create_delete_collection.rs b/pallets/nfts/src/features/create_delete_collection.rs index 348ec6b92..2ea5cd732 100644 --- a/pallets/nfts/src/features/create_delete_collection.rs +++ b/pallets/nfts/src/features/create_delete_collection.rs @@ -137,6 +137,9 @@ impl, I: 'static> Pallet { } } + let _ = + AccountBalance::::clear_prefix((collection,), collection_details.items, None); + let _ = Allowances::::clear_prefix((collection,), collection_details.items, None); CollectionAccount::::remove(&collection_details.owner, &collection); T::Currency::unreserve(&collection_details.owner, collection_details.owner_deposit); CollectionConfigOf::::remove(&collection); diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index e9843b2e7..036a63b70 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -69,6 +69,9 @@ impl, I: 'static> Pallet { } collection_details.items.saturating_inc(); + AccountBalance::::mutate((collection, &mint_to), |balance| { + balance.saturating_inc(); + }); let collection_config = Self::get_collection_config(&collection)?; let deposit_amount = match collection_config @@ -263,6 +266,9 @@ impl, I: 'static> Pallet { ItemPriceOf::::remove(&collection, &item); PendingSwapOf::::remove(&collection, &item); ItemAttributesApprovalsOf::::remove(&collection, &item); + AccountBalance::::mutate((collection, &owner), |balance| { + balance.saturating_dec(); + }); if remove_config { ItemConfigOf::::remove(&collection, &item); diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index b7223a7c3..0aa83fe8a 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -87,6 +87,14 @@ impl, I: 'static> Pallet { // Perform the transfer with custom details using the provided closure. with_details(&collection_details, &mut details)?; + // Update account balances. + AccountBalance::::mutate((collection, &details.owner), |balance| { + balance.saturating_dec(); + }); + AccountBalance::::mutate((collection, &dest), |balance| { + balance.saturating_dec(); + }); + // Update account ownership information. Account::::remove((&details.owner, &collection, &item)); Account::::insert((&dest, &collection, &item), ()); diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index 89bfb9637..9f4d3aedd 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -402,6 +402,36 @@ pub mod pallet { pub type CollectionConfigOf, I: 'static = ()> = StorageMap<_, Blake2_128Concat, T::CollectionId, CollectionConfigFor, OptionQuery>; + /// Number of collection items that accounts own. + #[pallet::storage] + pub type AccountBalance, I: 'static = ()> = StorageNMap< + _, + ( + // Collection Id. + NMapKey, + // Collection Owner Id. + NMapKey, + ), + u32, + ValueQuery, + >; + + /// Permission for the delegate to transfer all owner's items within a collection. + #[pallet::storage] + pub type Allowances, I: 'static = ()> = StorageNMap< + _, + ( + // Collection ID. + NMapKey, + // Collection Owner Id. + NMapKey, + // Delegate Id. + NMapKey, + ), + bool, + ValueQuery, + >; + /// Config of an item. #[pallet::storage] pub type ItemConfigOf, I: 'static = ()> = StorageDoubleMap< @@ -460,7 +490,7 @@ pub mod pallet { /// a `delegate`. TransferApproved { collection: T::CollectionId, - item: T::ItemId, + item: Option, owner: T::AccountId, delegate: T::AccountId, deadline: Option>, @@ -469,7 +499,7 @@ pub mod pallet { /// `collection` was cancelled by its `owner`. ApprovalCancelled { collection: T::CollectionId, - item: T::ItemId, + item: Option, owner: T::AccountId, delegate: T::AccountId, }, @@ -1931,6 +1961,60 @@ pub mod pallet { Self::validate_signature(&Encode::encode(&data), &signature, &signer)?; Self::do_set_attributes_pre_signed(origin, data, signer) } + + /// Approve an item to be transferred by a delegated third-party account. + /// + /// Origin must be either `ForceOrigin` or Signed and the sender should be the Owner of the + /// `item`. + /// + /// - `collection`: The collection of the item to be approved for delegated transfer. + /// - `item`: The item to be approved for delegated transfer. + /// - `delegate`: The account to delegate permission to transfer the item. + /// + /// Emits `TransferApproved` on success. + /// + /// Weight: `O(1)` + #[pallet::call_index(39)] + #[pallet::weight(T::WeightInfo::approve_transfer())] + pub fn approve_transfer_collection( + origin: OriginFor, + collection: T::CollectionId, + delegate: AccountIdLookupOf, + ) -> DispatchResult { + let maybe_check_origin = T::ForceOrigin::try_origin(origin) + .map(|_| None) + .or_else(|origin| ensure_signed(origin).map(Some).map_err(DispatchError::from))?; + let delegate = T::Lookup::lookup(delegate)?; + Self::do_approve_transfer_collection(maybe_check_origin, collection, delegate) + } + + /// Cancel one of the transfer approvals for a specific item. + /// + /// Origin must be either: + /// - the `Force` origin; + /// - `Signed` with the signer being the Owner of the `item`; + /// + /// Arguments: + /// - `collection`: The collection of the item of whose approval will be cancelled. + /// - `item`: The item of the collection of whose approval will be cancelled. + /// - `delegate`: The account that is going to loose their approval. + /// + /// Emits `ApprovalCancelled` on success. + /// + /// Weight: `O(1)` + #[pallet::call_index(40)] + #[pallet::weight(T::WeightInfo::cancel_approval())] + pub fn cancel_approval_collection( + origin: OriginFor, + collection: T::CollectionId, + delegate: AccountIdLookupOf, + ) -> DispatchResult { + let maybe_check_origin = T::ForceOrigin::try_origin(origin) + .map(|_| None) + .or_else(|origin| ensure_signed(origin).map(Some).map_err(DispatchError::from))?; + let delegate = T::Lookup::lookup(delegate)?; + Self::do_cancel_approval_collection(maybe_check_origin, collection, delegate) + } } } From bc2deee38e6ac4b1751cb1f9dc89aa73f65290b0 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 16 Oct 2024 22:30:14 +0700 Subject: [PATCH 39/76] feat: check allowance --- pallets/api/src/nonfungibles/mod.rs | 102 +++++++------------------ pallets/nfts/src/features/approvals.rs | 28 ++++--- pallets/nfts/src/features/transfer.rs | 6 +- pallets/nfts/src/lib.rs | 94 ++++++----------------- pallets/nfts/src/tests.rs | 93 +++++++++++++--------- 5 files changed, 128 insertions(+), 195 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index cf2b14e7e..bc728ac8c 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -62,7 +62,7 @@ pub mod pallet { pub enum ReadResult { OwnerOf(Option>), CollectionOwner(Option>), - TotalSupply(u32), + TotalSupply(u128), BalanceOf(u32), Collection(Option>), Item(Option>), @@ -99,25 +99,18 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// Event emitted when allowance by `owner` to `spender` canceled. - CancelApproval { - /// The collection ID. - collection: CollectionIdOf, - /// the item ID. - item: ItemIdOf, - /// The beneficiary of the allowance. - spender: AccountIdOf, - }, - /// Event emitted when allowance by `owner` to `spender` changes. + /// Event emitted when allowance by `owner` to `operator` changes. Approval { /// The collection ID. collection: CollectionIdOf, - /// the item ID. - item: ItemIdOf, /// The owner providing the allowance. owner: AccountIdOf, /// The beneficiary of the allowance. - spender: AccountIdOf, + operator: AccountIdOf, + /// The item which is (dis)approved. `None` for all owner's items. + item: Option>, + /// Whether allowance is set or removed. + approved: bool, }, /// Event emitted when new item is minted to the account. Mint { @@ -150,12 +143,6 @@ pub mod pallet { #[pallet::call] impl Pallet { - /// Create a new non-fungible token to the collection. - /// - /// # Parameters - /// - `to` - The owner of the collection item. - /// - `collection` - The collection ID. - /// - `item` - The item ID. #[pallet::call_index(0)] #[pallet::weight(NftsWeightInfoOf::::mint())] pub fn mint( @@ -169,11 +156,6 @@ pub mod pallet { Ok(()) } - /// Destroy a new non-fungible token to the collection. - /// - /// # Parameters - /// - `collection` - The collection ID. - /// - `item` - The item ID. #[pallet::call_index(1)] #[pallet::weight(NftsWeightInfoOf::::burn())] pub fn burn( @@ -186,12 +168,6 @@ pub mod pallet { Ok(()) } - /// Transfer a token from one account to the another account. - /// - /// # Parameters - /// - `collection` - The collection ID. - /// - `item` - The item ID. - /// - `to` - The recipient account. #[pallet::call_index(2)] #[pallet::weight(NftsWeightInfoOf::::transfer())] pub fn transfer( @@ -206,53 +182,33 @@ pub mod pallet { Ok(()) } - /// Delegate a permission to perform actions on the collection item to an account. - /// - /// # Parameters - /// - `collection` - The collection ID. - /// - `item` - The item ID. - /// - `spender` - The account that is allowed to transfer the collection item. #[pallet::call_index(3)] #[pallet::weight(NftsWeightInfoOf::::approve_transfer())] pub fn approve( origin: OriginFor, collection: CollectionIdOf, - item: ItemIdOf, - spender: AccountIdOf, + item: Option>, + operator: AccountIdOf, + approved: bool, ) -> DispatchResult { let owner = ensure_signed(origin.clone())?; - NftsOf::::approve_transfer( - origin, - collection, - item, - T::Lookup::unlookup(spender.clone()), - None, - )?; - Self::deposit_event(Event::Approval { collection, item, spender, owner }); - Ok(()) - } - - /// Cancel one of the transfer approvals for a specific item. - /// - /// # Parameters - /// - `collection` - The collection ID. - /// - `item` - The item ID. - /// - `spender` - The account that is revoked permission to transfer the collection item. - #[pallet::call_index(4)] - #[pallet::weight(NftsWeightInfoOf::::cancel_approval())] - pub fn cancel_approval( - origin: OriginFor, - collection: CollectionIdOf, - item: ItemIdOf, - spender: AccountIdOf, - ) -> DispatchResult { - NftsOf::::cancel_approval( - origin, - collection, - item, - T::Lookup::unlookup(spender.clone()), - )?; - Self::deposit_event(Event::CancelApproval { collection, item, spender }); + if approved { + NftsOf::::approve_transfer( + origin, + collection, + item, + T::Lookup::unlookup(operator.clone()), + None, + )?; + } else { + NftsOf::::cancel_approval( + origin, + collection, + item, + T::Lookup::unlookup(operator.clone()), + )?; + } + Self::deposit_event(Event::Approval { collection, item, operator, owner, approved }); Ok(()) } } @@ -284,14 +240,14 @@ pub mod pallet { CollectionOwner(collection) => ReadResult::CollectionOwner(NftsOf::::collection_owner(collection)), TotalSupply(collection) => ReadResult::TotalSupply( - NftsOf::::collection_items(collection).unwrap_or_default(), + NftsOf::::collection_items(collection).unwrap_or_default().into(), ), Collection(collection) => ReadResult::Collection(pallet_nfts::Collection::::get(collection)), Item { collection, item } => ReadResult::Item(pallet_nfts::Item::::get(collection, item)), Allowance { collection, owner, operator, item } => ReadResult::Allowance( - NftsOf::::allowance(collection, item, owner, operator).unwrap_or(false), + NftsOf::::allowance(&collection, &item, &owner, &operator).is_ok(), ), BalanceOf { collection, owner } => ReadResult::BalanceOf( pallet_nfts::AccountBalance::::get((collection, owner)), diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index f626a9fe9..979035fa6 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -232,20 +232,26 @@ impl, I: 'static> Pallet { } pub fn allowance( - collection: T::CollectionId, - item: Option, - owner: T::AccountId, - delegate: T::AccountId, - ) -> Option { + collection: &T::CollectionId, + item: &Option, + owner: &T::AccountId, + delegate: &T::AccountId, + ) -> Result<(), DispatchError> { // Check if a `delegate` has a permission to spend the collection. if Allowances::::get((&collection, &owner, &delegate)) { - return Some(true); + return Ok(()); } // Check if a `delegate` has a permission to spend the collection item. - item.map(|item| { - Item::::get(&collection, &item) - .map(|detail| detail.approvals.contains_key(&delegate)) - }) - .unwrap_or_default() + if let Some(item) = item { + let details = + Item::::get(&collection, &item).ok_or(Error::::UnknownItem)?; + + let deadline = details.approvals.get(&delegate).ok_or(Error::::NoPermission)?; + if let Some(d) = deadline { + let block_number = frame_system::Pallet::::block_number(); + ensure!(block_number <= *d, Error::::ApprovalExpired); + } + }; + Ok(()) } } diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index 0aa83fe8a..04d9f4fe8 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -92,7 +92,7 @@ impl, I: 'static> Pallet { balance.saturating_dec(); }); AccountBalance::::mutate((collection, &dest), |balance| { - balance.saturating_dec(); + balance.saturating_inc(); }); // Update account ownership information. @@ -145,7 +145,7 @@ impl, I: 'static> Pallet { // Check if the `origin` is the current owner of the collection. ensure!(origin == details.owner, Error::::NoPermission); if details.owner == new_owner { - return Ok(()) + return Ok(()); } // Move the deposit to the new owner. @@ -220,7 +220,7 @@ impl, I: 'static> Pallet { Collection::::try_mutate(collection, |maybe_details| { let details = maybe_details.as_mut().ok_or(Error::::UnknownCollection)?; if details.owner == owner { - return Ok(()) + return Ok(()); } // Move the deposit to the new owner. diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index 9f4d3aedd..146892935 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -1060,12 +1060,7 @@ pub mod pallet { Self::do_transfer(collection, item, dest, |_, details| { if details.owner != origin { - let deadline = - details.approvals.get(&origin).ok_or(Error::::NoPermission)?; - if let Some(d) = deadline { - let block_number = frame_system::Pallet::::block_number(); - ensure!(block_number <= *d, Error::::ApprovalExpired); - } + Self::allowance(&collection, &Some(item), &details.owner, &origin)?; } Ok(()) }) @@ -1120,10 +1115,10 @@ pub mod pallet { if T::Currency::reserve(&details.deposit.account, deposit - old).is_err() { // NOTE: No alterations made to collection_details in this iteration so far, // so this is OK to do. - continue + continue; } } else { - continue + continue; } details.deposit.amount = deposit; Item::::insert(&collection, &item, &details); @@ -1322,7 +1317,7 @@ pub mod pallet { pub fn approve_transfer( origin: OriginFor, collection: T::CollectionId, - item: T::ItemId, + maybe_item: Option, delegate: AccountIdLookupOf, maybe_deadline: Option>, ) -> DispatchResult { @@ -1330,13 +1325,17 @@ pub mod pallet { .map(|_| None) .or_else(|origin| ensure_signed(origin).map(Some).map_err(DispatchError::from))?; let delegate = T::Lookup::lookup(delegate)?; - Self::do_approve_transfer( - maybe_check_origin, - collection, - item, - delegate, - maybe_deadline, - ) + match maybe_item { + Some(item) => Self::do_approve_transfer( + maybe_check_origin, + collection, + item, + delegate, + maybe_deadline, + ), + None => + Self::do_approve_transfer_collection(maybe_check_origin, collection, delegate), + } } /// Cancel one of the transfer approvals for a specific item. @@ -1358,14 +1357,19 @@ pub mod pallet { pub fn cancel_approval( origin: OriginFor, collection: T::CollectionId, - item: T::ItemId, + maybe_item: Option, delegate: AccountIdLookupOf, ) -> DispatchResult { let maybe_check_origin = T::ForceOrigin::try_origin(origin) .map(|_| None) .or_else(|origin| ensure_signed(origin).map(Some).map_err(DispatchError::from))?; let delegate = T::Lookup::lookup(delegate)?; - Self::do_cancel_approval(maybe_check_origin, collection, item, delegate) + match maybe_item { + Some(item) => + Self::do_cancel_approval(maybe_check_origin, collection, item, delegate), + None => + Self::do_cancel_approval_collection(maybe_check_origin, collection, delegate), + } } /// Cancel all the approvals of a specific item. @@ -1961,60 +1965,6 @@ pub mod pallet { Self::validate_signature(&Encode::encode(&data), &signature, &signer)?; Self::do_set_attributes_pre_signed(origin, data, signer) } - - /// Approve an item to be transferred by a delegated third-party account. - /// - /// Origin must be either `ForceOrigin` or Signed and the sender should be the Owner of the - /// `item`. - /// - /// - `collection`: The collection of the item to be approved for delegated transfer. - /// - `item`: The item to be approved for delegated transfer. - /// - `delegate`: The account to delegate permission to transfer the item. - /// - /// Emits `TransferApproved` on success. - /// - /// Weight: `O(1)` - #[pallet::call_index(39)] - #[pallet::weight(T::WeightInfo::approve_transfer())] - pub fn approve_transfer_collection( - origin: OriginFor, - collection: T::CollectionId, - delegate: AccountIdLookupOf, - ) -> DispatchResult { - let maybe_check_origin = T::ForceOrigin::try_origin(origin) - .map(|_| None) - .or_else(|origin| ensure_signed(origin).map(Some).map_err(DispatchError::from))?; - let delegate = T::Lookup::lookup(delegate)?; - Self::do_approve_transfer_collection(maybe_check_origin, collection, delegate) - } - - /// Cancel one of the transfer approvals for a specific item. - /// - /// Origin must be either: - /// - the `Force` origin; - /// - `Signed` with the signer being the Owner of the `item`; - /// - /// Arguments: - /// - `collection`: The collection of the item of whose approval will be cancelled. - /// - `item`: The item of the collection of whose approval will be cancelled. - /// - `delegate`: The account that is going to loose their approval. - /// - /// Emits `ApprovalCancelled` on success. - /// - /// Weight: `O(1)` - #[pallet::call_index(40)] - #[pallet::weight(T::WeightInfo::cancel_approval())] - pub fn cancel_approval_collection( - origin: OriginFor, - collection: T::CollectionId, - delegate: AccountIdLookupOf, - ) -> DispatchResult { - let maybe_check_origin = T::ForceOrigin::try_origin(origin) - .map(|_| None) - .or_else(|origin| ensure_signed(origin).map(Some).map_err(DispatchError::from))?; - let delegate = T::Lookup::lookup(delegate)?; - Self::do_cancel_approval_collection(maybe_check_origin, collection, delegate) - } } } diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 44f2f32ae..4002c48ee 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -487,7 +487,7 @@ fn transfer_should_work() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(3)), 0, - 42, + Some(42), account(2), None )); @@ -1777,7 +1777,7 @@ fn approval_lifecycle_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), None )); @@ -1791,7 +1791,7 @@ fn approval_lifecycle_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(4)), 0, - 42, + Some(42), account(2), None )); @@ -1819,7 +1819,7 @@ fn approval_lifecycle_works() { Nfts::approve_transfer( RuntimeOrigin::signed(account(1)), collection_id, - 1, + Some(1), account(2), None ), @@ -1847,30 +1847,35 @@ fn cancel_approval_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), None )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 1, 42, account(3)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 1, Some(42), account(3)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 43, account(3)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, Some(43), account(3)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(3)), 0, 42, account(3)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(3)), 0, Some(42), account(3)), Error::::NoPermission ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(4)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, Some(42), account(4)), Error::::NotDelegate ); - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); + assert_ok!(Nfts::cancel_approval( + RuntimeOrigin::signed(account(2)), + 0, + Some(42), + account(3) + )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, Some(42), account(3)), Error::::NotDelegate ); @@ -1887,18 +1892,23 @@ fn cancel_approval_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), Some(2) )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(5)), 0, 42, account(3)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(5)), 0, Some(42), account(3)), Error::::NoPermission ); System::set_block_number(current_block + 3); // 5 can cancel the approval since the deadline has passed. - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(5)), 0, 42, account(3))); + assert_ok!(Nfts::cancel_approval( + RuntimeOrigin::signed(account(5)), + 0, + Some(42), + account(3) + )); assert_eq!(approvals(0, 69), vec![]); }); } @@ -1924,21 +1934,21 @@ fn approving_multiple_accounts_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), None )); assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(4), None )); assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(5), Some(2) )); @@ -1979,14 +1989,20 @@ fn approvals_limit_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(i), None )); } // the limit is 10 assert_noop!( - Nfts::approve_transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(14), None), + Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + Some(42), + account(14), + None + ), Error::::ReachedApprovalLimit ); }); @@ -2015,7 +2031,7 @@ fn approval_deadline_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), Some(2) )); @@ -2034,7 +2050,7 @@ fn approval_deadline_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(4)), 0, - 42, + Some(42), account(6), Some(4) )); @@ -2063,26 +2079,31 @@ fn cancel_approval_works_with_admin() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), None )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 1, 42, account(1)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 1, Some(42), account(1)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 43, account(1)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, Some(43), account(1)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(4)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, Some(42), account(4)), Error::::NotDelegate ); - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); + assert_ok!(Nfts::cancel_approval( + RuntimeOrigin::signed(account(2)), + 0, + Some(42), + account(3) + )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(1)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, Some(42), account(1)), Error::::NotDelegate ); }); @@ -2107,26 +2128,26 @@ fn cancel_approval_works_with_force() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), None )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::root(), 1, 42, account(1)), + Nfts::cancel_approval(RuntimeOrigin::root(), 1, Some(42), account(1)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::root(), 0, 43, account(1)), + Nfts::cancel_approval(RuntimeOrigin::root(), 0, Some(43), account(1)), Error::::UnknownItem ); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, account(4)), + Nfts::cancel_approval(RuntimeOrigin::root(), 0, Some(42), account(4)), Error::::NotDelegate ); - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, account(3))); + assert_ok!(Nfts::cancel_approval(RuntimeOrigin::root(), 0, Some(42), account(3))); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, account(1)), + Nfts::cancel_approval(RuntimeOrigin::root(), 0, Some(42), account(1)), Error::::NotDelegate ); }); @@ -2151,14 +2172,14 @@ fn clear_all_transfer_approvals_works() { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(3), None )); assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(2)), 0, - 42, + Some(42), account(4), None )); @@ -3169,7 +3190,7 @@ fn pallet_level_feature_flags_should_work() { Nfts::approve_transfer( RuntimeOrigin::signed(user_id.clone()), collection_id, - item_id, + Some(item_id), account(2), None ), From 1946b15479f55c449220f9272722ac9fd55e34d4 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 00:03:43 +0700 Subject: [PATCH 40/76] test(nfts): check account balance & test total supply --- pallets/nfts/src/tests.rs | 61 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 4002c48ee..f75c25d88 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -164,6 +164,7 @@ fn basic_minting_should_work() { )); assert_eq!(collections(), vec![(account(1), 0)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); + assert_eq!(AccountBalance::::get((0, account(1))), 1); assert_eq!(items(), vec![(account(1), 0, 42)]); assert_ok!(Nfts::force_create( @@ -173,6 +174,7 @@ fn basic_minting_should_work() { )); assert_eq!(collections(), vec![(account(1), 0), (account(2), 1)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(2)), 1, 69, account(1), None)); + assert_eq!(AccountBalance::::get((1, account(1))), 1); assert_eq!(items(), vec![(account(1), 0, 42), (account(1), 1, 69)]); }); } @@ -204,6 +206,7 @@ fn lifecycle_should_work() { account(10), default_item_config() )); + assert_eq!(AccountBalance::::get((0, account(10))), 1); assert_eq!(Balances::reserved_balance(&account(1)), 6); assert_ok!(Nfts::force_mint( RuntimeOrigin::signed(account(1)), @@ -212,8 +215,10 @@ fn lifecycle_should_work() { account(20), default_item_config() )); + assert_eq!(AccountBalance::::get((0, account(20))), 1); assert_eq!(Balances::reserved_balance(&account(1)), 7); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 70, account(1), None)); + assert_eq!(AccountBalance::::get((0, account(1))), 1); assert_eq!(items(), vec![(account(1), 0, 70), (account(10), 0, 42), (account(20), 0, 69)]); assert_eq!(Collection::::get(0).unwrap().items, 3); assert_eq!(Collection::::get(0).unwrap().item_metadatas, 0); @@ -221,6 +226,8 @@ fn lifecycle_should_work() { assert_eq!(Balances::reserved_balance(&account(1)), 8); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 70, account(2))); + assert_eq!(AccountBalance::::get((0, account(1))), 0); + assert_eq!(AccountBalance::::get((0, account(2))), 1); assert_eq!(Balances::reserved_balance(&account(1)), 8); assert_eq!(Balances::reserved_balance(&account(2)), 0); @@ -238,6 +245,7 @@ fn lifecycle_should_work() { Nfts::destroy(RuntimeOrigin::signed(account(1)), 0, w), Error::::CollectionNotEmpty ); + assert_eq!(AccountBalance::::get((0, account(1))), 0); assert_ok!(Nfts::set_attribute( RuntimeOrigin::signed(account(1)), @@ -248,7 +256,9 @@ fn lifecycle_should_work() { bvec![0], )); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(10)), 0, 42)); + assert_eq!(AccountBalance::::get((0, account(10))), 0); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(20)), 0, 69)); + assert_eq!(AccountBalance::::get((0, account(10))), 0); assert_ok!(Nfts::burn(RuntimeOrigin::root(), 0, 70)); let w = Nfts::get_destroy_witness(&0).unwrap(); @@ -256,6 +266,7 @@ fn lifecycle_should_work() { assert_eq!(w.item_metadatas, 0); assert_eq!(w.item_configs, 0); assert_ok!(Nfts::destroy(RuntimeOrigin::signed(account(1)), 0, w)); + assert_eq!(AccountBalance::::get((0, account(1))), 0); assert_eq!(Balances::reserved_balance(&account(1)), 0); assert!(!Collection::::contains_key(0)); @@ -305,6 +316,7 @@ fn destroy_should_work() { )); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(2), None)); + assert_eq!(AccountBalance::::get((0, account(2))), 1); assert_noop!( Nfts::destroy( RuntimeOrigin::signed(account(1)), @@ -323,6 +335,7 @@ fn destroy_should_work() { 0, Nfts::get_destroy_witness(&0).unwrap() )); + assert_eq!(AccountBalance::::get((0, account(1))), 0); assert!(!ItemConfigOf::::contains_key(0, 42)); assert_eq!(ItemConfigOf::::iter_prefix(0).count() as u32, 0); }); @@ -337,6 +350,7 @@ fn mint_should_work() { default_collection_config() )); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); + assert_eq!(AccountBalance::::get((0, account(1))), 1); assert_eq!(Nfts::owner(0, 42).unwrap(), account(1)); assert_eq!(collections(), vec![(account(1), 0)]); assert_eq!(items(), vec![(account(1), 0, 42)]); @@ -402,6 +416,7 @@ fn mint_should_work() { account(2), Some(MintWitness { mint_price: Some(1), ..Default::default() }) )); + assert_eq!(AccountBalance::::get((0, account(2))), 1); assert_eq!(Balances::total_balance(&account(2)), 99); // validate types @@ -440,6 +455,7 @@ fn mint_should_work() { account(2), Some(MintWitness { owned_item: Some(43), ..Default::default() }) )); + assert_eq!(AccountBalance::::get((1, account(2))), 1); assert!(events().contains(&Event::::PalletAttributeSet { collection: 0, item: Some(43), @@ -478,6 +494,8 @@ fn transfer_should_work() { )); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); + assert_eq!(AccountBalance::::get((0, account(2))), 0); + assert_eq!(AccountBalance::::get((0, account(3))), 1); assert_eq!(items(), vec![(account(3), 0, 42)]); assert_noop!( Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4)), @@ -492,7 +510,9 @@ fn transfer_should_work() { None )); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4))); - + assert_eq!(AccountBalance::::get((0, account(2))), 0); + assert_eq!(AccountBalance::::get((0, account(3))), 0); + assert_eq!(AccountBalance::::get((0, account(4))), 1); // validate we can't transfer non-transferable items let collection_id = 1; assert_ok!(Nfts::force_create( @@ -1746,15 +1766,17 @@ fn burn_works() { account(5), default_item_config() )); + assert_eq!(AccountBalance::::get((0, account(5))), 2); assert_eq!(Balances::reserved_balance(account(1)), 2); assert_noop!( Nfts::burn(RuntimeOrigin::signed(account(0)), 0, 42), Error::::NoPermission ); - assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 42)); + assert_eq!(AccountBalance::::get((0, account(5))), 1); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 69)); + assert_eq!(AccountBalance::::get((0, account(5))), 0); assert_eq!(Balances::reserved_balance(account(1)), 0); }); } @@ -2209,6 +2231,36 @@ fn clear_all_transfer_approvals_works() { }); } +#[test] +fn total_supply_should_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let user_id = account(1); + let total_items = 10; + + // no collection. + assert_eq!(Nfts::collection_items(collection_id), None); + + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + user_id.clone(), + default_collection_config() + )); + + // mint items and validate the total supply. + (0..total_items).into_iter().for_each(|i| { + assert_ok!(Nfts::force_mint( + RuntimeOrigin::root(), + collection_id, + i, + user_id.clone(), + ItemConfig::default() + )); + }); + assert_eq!(Nfts::collection_items(collection_id), Some(total_items)); + }); +} + #[test] fn max_supply_should_work() { new_test_ext().execute_with(|| { @@ -2545,6 +2597,7 @@ fn buy_item_should_work() { item_1, price_1 + 1, )); + assert_eq!(AccountBalance::::get((collection_id, user_2.clone())), 1); // validate the new owner & balances let item = Item::::get(collection_id, item_1).unwrap(); @@ -2912,6 +2965,8 @@ fn claim_swap_should_work() { default_item_config(), )); + assert_eq!(AccountBalance::::get((collection_id, user_1.clone())), 2); + assert_eq!(AccountBalance::::get((collection_id, user_2.clone())), 3); assert_ok!(Nfts::create_swap( RuntimeOrigin::signed(user_1.clone()), collection_id, @@ -3002,6 +3057,8 @@ fn claim_swap_should_work() { item_1, Some(price_with_direction.clone()), )); + assert_eq!(AccountBalance::::get((collection_id, user_1.clone())), 2); + assert_eq!(AccountBalance::::get((collection_id, user_2.clone())), 3); // validate the new owner let item = Item::::get(collection_id, item_1).unwrap(); From 684d87058226928029cbf37441f22626414a5022 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 00:39:53 +0700 Subject: [PATCH 41/76] test(nfts): allowance works --- pallets/api/src/nonfungibles/mod.rs | 2 +- pallets/nfts/src/features/approvals.rs | 8 +++- pallets/nfts/src/lib.rs | 2 +- pallets/nfts/src/tests.rs | 57 ++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index bc728ac8c..4b6558e90 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -247,7 +247,7 @@ pub mod pallet { Item { collection, item } => ReadResult::Item(pallet_nfts::Item::::get(collection, item)), Allowance { collection, owner, operator, item } => ReadResult::Allowance( - NftsOf::::allowance(&collection, &item, &owner, &operator).is_ok(), + NftsOf::::check_allowance(&collection, &item, &owner, &operator).is_ok(), ), BalanceOf { collection, owner } => ReadResult::BalanceOf( pallet_nfts::AccountBalance::::get((collection, owner)), diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index 979035fa6..89b8fc6a1 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -231,7 +231,7 @@ impl, I: 'static> Pallet { Ok(()) } - pub fn allowance( + pub fn check_allowance( collection: &T::CollectionId, item: &Option, owner: &T::AccountId, @@ -239,6 +239,9 @@ impl, I: 'static> Pallet { ) -> Result<(), DispatchError> { // Check if a `delegate` has a permission to spend the collection. if Allowances::::get((&collection, &owner, &delegate)) { + if let Some(item) = item { + Item::::get(&collection, &item).ok_or(Error::::UnknownItem)?; + }; return Ok(()); } // Check if a `delegate` has a permission to spend the collection item. @@ -251,7 +254,8 @@ impl, I: 'static> Pallet { let block_number = frame_system::Pallet::::block_number(); ensure!(block_number <= *d, Error::::ApprovalExpired); } + return Ok(()); }; - Ok(()) + Err(Error::::NoPermission.into()) } } diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index 146892935..c7d826b54 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -1060,7 +1060,7 @@ pub mod pallet { Self::do_transfer(collection, item, dest, |_, details| { if details.owner != origin { - Self::allowance(&collection, &Some(item), &details.owner, &origin)?; + Self::check_allowance(&collection, &Some(item), &details.owner, &origin)?; } Ok(()) }) diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index f75c25d88..5ad13e6ed 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -1850,6 +1850,63 @@ fn approval_lifecycle_works() { }); } +#[test] +fn allowance_works() { + new_test_ext().execute_with(|| { + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); + + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(1)), + 0, + None, + account(2), + None + )); + + // collection transfer approved. + assert_noop!( + Nfts::check_allowance(&0, &Some(43), &account(1), &account(2)), + Error::::UnknownItem + ); + assert_noop!( + Nfts::check_allowance(&0, &Some(42), &account(1), &account(3)), + Error::::NoPermission + ); + assert_ok!(Nfts::check_allowance(&0, &None, &account(1), &account(2))); + assert_ok!(Nfts::check_allowance(&0, &Some(42), &account(1), &account(2))); + + // collection item transfer approved. + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + Some(42), + account(3), + None + )); + + assert_noop!( + Nfts::check_allowance(&0, &Some(43), &account(2), &account(3)), + Error::::UnknownItem + ); + assert_noop!( + Nfts::check_allowance(&0, &Some(42), &account(2), &account(4)), + Error::::NoPermission + ); + assert_ok!(Nfts::check_allowance(&0, &Some(42), &account(2), &account(3))); + }); +} + #[test] fn cancel_approval_works() { new_test_ext().execute_with(|| { From 90ab45e90b809690072ea184644a941f68aa1c12 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 00:40:34 +0700 Subject: [PATCH 42/76] refactor(test): check_allowance_works --- pallets/nfts/src/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 5ad13e6ed..9c3cce0d4 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -1851,7 +1851,7 @@ fn approval_lifecycle_works() { } #[test] -fn allowance_works() { +fn check_allowance_works() { new_test_ext().execute_with(|| { assert_ok!(Nfts::force_create( RuntimeOrigin::root(), From f862516ef68744c132dccab94fb265c27bb24c55 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 10:18:49 +0700 Subject: [PATCH 43/76] fix(nfts): cancel / approve collection transfer --- pallets/nfts/src/features/approvals.rs | 27 ++++------ pallets/nfts/src/tests.rs | 72 ++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 20 deletions(-) diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index 89b8fc6a1..05696fee5 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -180,27 +180,24 @@ impl, I: 'static> Pallet { Self::is_pallet_feature_enabled(PalletFeature::Approvals), Error::::MethodDisabled ); - let collection_owner = - Self::collection_owner(collection).ok_or(Error::::UnknownCollection)?; - + if !Collection::::contains_key(collection) { + return Err(Error::::UnknownCollection.into()); + } let collection_config = Self::get_collection_config(&collection)?; ensure!( collection_config.is_setting_enabled(CollectionSetting::TransferableItems), Error::::ItemsNonTransferable ); - if let Some(check_origin) = maybe_check_origin { - ensure!(check_origin == collection_owner, Error::::NoPermission); - } - - Allowances::::mutate((&collection, &collection_owner, &delegate), |allowance| { + let origin = maybe_check_origin.ok_or(Error::::WrongOrigin)?; + Allowances::::mutate((&collection, &origin, &delegate), |allowance| { *allowance = true; }); Self::deposit_event(Event::TransferApproved { collection, item: None, - owner: collection_owner, + owner: origin, delegate, deadline: None, }); @@ -212,18 +209,16 @@ impl, I: 'static> Pallet { collection: T::CollectionId, delegate: T::AccountId, ) -> DispatchResult { - let collection_owner = - Self::collection_owner(collection).ok_or(Error::::UnknownCollection)?; - - if let Some(check_origin) = maybe_check_origin { - ensure!(check_origin == collection_owner, Error::::NoPermission); + if !Collection::::contains_key(collection) { + return Err(Error::::UnknownCollection.into()); } - Allowances::::remove((&collection, &collection_owner, &delegate)); + let origin = maybe_check_origin.ok_or(Error::::WrongOrigin)?; + Allowances::::remove((&collection, &origin, &delegate)); Self::deposit_event(Event::ApprovalCancelled { collection, - owner: collection_owner, + owner: origin, item: None, delegate, }); diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 9c3cce0d4..07f2a74de 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -1876,12 +1876,12 @@ fn check_allowance_works() { // collection transfer approved. assert_noop!( - Nfts::check_allowance(&0, &Some(43), &account(1), &account(2)), - Error::::UnknownItem + Nfts::check_allowance(&1, &None, &account(1), &account(2)), + Error::::NoPermission ); assert_noop!( - Nfts::check_allowance(&0, &Some(42), &account(1), &account(3)), - Error::::NoPermission + Nfts::check_allowance(&1, &Some(43), &account(1), &account(2)), + Error::::UnknownItem ); assert_ok!(Nfts::check_allowance(&0, &None, &account(1), &account(2))); assert_ok!(Nfts::check_allowance(&0, &Some(42), &account(1), &account(2))); @@ -1992,6 +1992,43 @@ fn cancel_approval_works() { }); } +#[test] +fn cancel_approval_collection_works() { + new_test_ext().execute_with(|| { + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); + + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + None, + account(3), + None + )); + assert_noop!( + Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 1, None, account(3)), + Error::::UnknownCollection + ); + + assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, None, account(3))); + + assert_noop!( + Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4)), + Error::::NoPermission + ); + }); +} + #[test] fn approving_multiple_accounts_works() { new_test_ext().execute_with(|| { @@ -2087,6 +2124,33 @@ fn approvals_limit_works() { }); } +#[test] +fn approval_collection_works() { + new_test_ext().execute_with(|| { + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + 0, + 42, + account(2), + default_item_config() + )); + + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(1)), + 0, + None, + account(3), + None + )); + assert_eq!(Allowances::::get((0, account(1), account(3))), true); + }); +} + #[test] fn approval_deadline_works() { new_test_ext().execute_with(|| { From 7e55eb14fdbe30653590b1f2879ca53028f96a3f Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:17:38 +0700 Subject: [PATCH 44/76] test(nfts): cancel approval collection --- pallets/nfts/src/tests.rs | 49 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 07f2a74de..4fbec4de9 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -2021,6 +2021,13 @@ fn cancel_approval_collection_works() { ); assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, None, account(3))); + assert!(events().contains(&Event::::ApprovalCancelled { + collection: 0, + item: None, + owner: account(2), + delegate: account(3) + })); + assert_eq!(Allowances::::get((0, account(2), account(3))), false); assert_noop!( Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4)), @@ -2127,6 +2134,11 @@ fn approvals_limit_works() { #[test] fn approval_collection_works() { new_test_ext().execute_with(|| { + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), account(1), @@ -2140,14 +2152,47 @@ fn approval_collection_works() { default_item_config() )); - assert_ok!(Nfts::approve_transfer( + // Error::ItemsNonTransferable. + assert_ok!(Nfts::lock_collection( RuntimeOrigin::signed(account(1)), + 1, + CollectionSettings::from_disabled(CollectionSetting::TransferableItems.into()) + )); + assert_noop!( + Nfts::approve_transfer(RuntimeOrigin::signed(account(1)), 1, None, account(2), None), + Error::::ItemsNonTransferable + ); + + // Error::MethodDisabled. + Features::set(&PalletFeatures::from_disabled(PalletFeature::Approvals.into())); + assert_noop!( + Nfts::approve_transfer(RuntimeOrigin::signed(account(1)), 1, None, account(2), None), + Error::::MethodDisabled + ); + Features::set(&PalletFeatures::all_enabled()); + + // Error::UnknownCollection. + assert_noop!( + Nfts::approve_transfer(RuntimeOrigin::signed(account(2)), 2, None, account(3), None), + Error::::UnknownCollection + ); + + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), 0, None, account(3), None )); - assert_eq!(Allowances::::get((0, account(1), account(3))), true); + assert!(events().contains(&Event::::TransferApproved { + collection: 0, + item: None, + owner: account(2), + delegate: account(3), + deadline: None + })); + assert_eq!(Allowances::::get((0, account(2), account(3))), true); + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4))); }); } From af87aafd549885b21160cd52ecc5feea9df2c400 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:23:23 +0700 Subject: [PATCH 45/76] test(nfts): update approval test cases --- pallets/nfts/src/tests.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 4fbec4de9..10c95bd6c 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -1993,7 +1993,7 @@ fn cancel_approval_works() { } #[test] -fn cancel_approval_collection_works() { +fn cancel_approval_collection_works_with_admin() { new_test_ext().execute_with(|| { assert_ok!(Nfts::force_create( RuntimeOrigin::root(), @@ -2132,7 +2132,7 @@ fn approvals_limit_works() { } #[test] -fn approval_collection_works() { +fn approval_collection_works_with_admin() { new_test_ext().execute_with(|| { assert_ok!(Nfts::force_create( RuntimeOrigin::root(), @@ -2163,14 +2163,6 @@ fn approval_collection_works() { Error::::ItemsNonTransferable ); - // Error::MethodDisabled. - Features::set(&PalletFeatures::from_disabled(PalletFeature::Approvals.into())); - assert_noop!( - Nfts::approve_transfer(RuntimeOrigin::signed(account(1)), 1, None, account(2), None), - Error::::MethodDisabled - ); - Features::set(&PalletFeatures::all_enabled()); - // Error::UnknownCollection. assert_noop!( Nfts::approve_transfer(RuntimeOrigin::signed(account(2)), 2, None, account(3), None), From 06c0db92101888ca29f5df4bd069f6007f97bbcc Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 17:18:20 +0700 Subject: [PATCH 46/76] feat(nfts): get attribute read method --- pallets/api/src/nonfungibles/mod.rs | 105 ++++++++++++++++++-------- pallets/api/src/nonfungibles/types.rs | 6 +- 2 files changed, 78 insertions(+), 33 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index 4b6558e90..83d23585a 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -14,10 +14,11 @@ mod types; pub mod pallet { use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; use frame_system::pallet_prelude::*; + use pallet_nfts::MintWitness; use sp_std::vec::Vec; use types::{ - AccountIdOf, CollectionDetailsFor, CollectionIdOf, ItemDetailsFor, ItemIdOf, NftsOf, - NftsWeightInfoOf, + AccountIdOf, AttributeNamespaceOf, BalanceOf, CollectionDetailsFor, CollectionIdOf, + ItemDetailsFor, ItemIdOf, ItemPriceOf, NftsOf, NftsWeightInfoOf, }; use super::*; @@ -54,6 +55,14 @@ pub mod pallet { operator: AccountIdOf, item: Option>, }, + /// Returns the attribute of `item` for the given `key`. + #[codec(index = 6)] + GetAttribute { + collection: CollectionIdOf, + item: Option>, + namespace: AttributeNamespaceOf, + key: BoundedVec, + }, } /// Results of state reads for the non-fungibles API. @@ -67,6 +76,7 @@ pub mod pallet { Collection(Option>), Item(Option>), Allowance(bool), + GetAttribute(Option>), } impl ReadResult { @@ -81,6 +91,7 @@ pub mod pallet { Collection(result) => result.encode(), Item(result) => result.encode(), Allowance(result) => result.encode(), + GetAttribute(result) => result.encode(), } } } @@ -103,46 +114,46 @@ pub mod pallet { Approval { /// The collection ID. collection: CollectionIdOf, + /// The item which is (dis)approved. `None` for all owner's items. + item: Option>, /// The owner providing the allowance. owner: AccountIdOf, /// The beneficiary of the allowance. operator: AccountIdOf, - /// The item which is (dis)approved. `None` for all owner's items. - item: Option>, /// Whether allowance is set or removed. approved: bool, }, - /// Event emitted when new item is minted to the account. - Mint { - /// The owner of the item. - to: AccountIdOf, - /// The collection ID. - collection: CollectionIdOf, - /// the item ID. - item: ItemIdOf, - }, - /// Event emitted when item is burned. - Burn { - /// The collection ID. - collection: CollectionIdOf, - /// the item ID. - item: ItemIdOf, - }, - /// Event emitted when an item transfer occurs. + /// Event emitted when a token transfer occurs. + // Differing style: event name abides by the PSP22 standard. Transfer { /// The collection ID. collection: CollectionIdOf, - /// the item ID. + /// The collection item ID. item: ItemIdOf, - /// The source of the transfer. - from: AccountIdOf, - /// The recipient of the transfer. - to: AccountIdOf, + /// The source of the transfer. `None` when minting. + from: Option>, + /// The recipient of the transfer. `None` when burning. + to: Option>, + /// The amount minted. + value: Option>, }, } #[pallet::call] impl Pallet { + #[pallet::call_index(20)] + #[pallet::weight(NftsWeightInfoOf::::create())] + pub fn create(_origin: OriginFor) -> DispatchResult { + Ok(()) + } + + // TODO: Fix weight + #[pallet::call_index(21)] + #[pallet::weight(NftsWeightInfoOf::::create())] + pub fn destroy(_origin: OriginFor) -> DispatchResult { + Ok(()) + } + #[pallet::call_index(0)] #[pallet::weight(NftsWeightInfoOf::::mint())] pub fn mint( @@ -150,9 +161,24 @@ pub mod pallet { to: AccountIdOf, collection: CollectionIdOf, item: ItemIdOf, + mint_price: Option>, ) -> DispatchResult { - NftsOf::::mint(origin, collection, item, T::Lookup::unlookup(to.clone()), None)?; - Self::deposit_event(Event::Mint { to, collection, item }); + let account = ensure_signed(origin.clone())?; + let witness_data = MintWitness { mint_price, owned_item: Some(item) }; + NftsOf::::mint( + origin, + collection, + item, + T::Lookup::unlookup(to.clone()), + Some(witness_data), + )?; + Self::deposit_event(Event::Transfer { + collection, + item, + from: None, + to: Some(account), + value: mint_price, + }); Ok(()) } @@ -163,8 +189,15 @@ pub mod pallet { collection: CollectionIdOf, item: ItemIdOf, ) -> DispatchResult { + let account = ensure_signed(origin.clone())?; NftsOf::::burn(origin, collection, item)?; - Self::deposit_event(Event::Burn { collection, item }); + Self::deposit_event(Event::Transfer { + collection, + item, + from: Some(account), + to: None, + value: None, + }); Ok(()) } @@ -178,12 +211,18 @@ pub mod pallet { ) -> DispatchResult { let from = ensure_signed(origin.clone())?; NftsOf::::transfer(origin, collection, item, T::Lookup::unlookup(to.clone()))?; - Self::deposit_event(Event::Transfer { from, to, collection, item }); + Self::deposit_event(Event::Transfer { + collection, + item, + from: Some(from), + to: Some(to), + value: None, + }); Ok(()) } #[pallet::call_index(3)] - #[pallet::weight(NftsWeightInfoOf::::approve_transfer())] + #[pallet::weight(NftsWeightInfoOf::::approve_transfer() + NftsWeightInfoOf::::cancel_approval())] pub fn approve( origin: OriginFor, collection: CollectionIdOf, @@ -252,6 +291,10 @@ pub mod pallet { BalanceOf { collection, owner } => ReadResult::BalanceOf( pallet_nfts::AccountBalance::::get((collection, owner)), ), + GetAttribute { collection, item, namespace, key } => ReadResult::GetAttribute( + pallet_nfts::Attribute::::get((collection, item, namespace, key)) + .map(|attribute| attribute.0), + ), } } } diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs index f81ea5359..da9491715 100644 --- a/pallets/api/src/nonfungibles/types.rs +++ b/pallets/api/src/nonfungibles/types.rs @@ -1,6 +1,6 @@ use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; use frame_system::pallet_prelude::BlockNumberFor; -use pallet_nfts::{CollectionDetails, ItemDeposit, ItemDetails}; +use pallet_nfts::{AttributeNamespace, CollectionDetails, ItemDeposit, ItemDetails}; use sp_runtime::BoundedBTreeMap; // Type aliases for pallet-nfts. @@ -15,14 +15,16 @@ pub(super) type CollectionIdOf = as Inspect<::AccountId>>::CollectionId; pub(super) type ItemIdOf = as Inspect<::AccountId>>::ItemId; -type ApprovalsOf = BoundedBTreeMap< +pub(super) type ApprovalsOf = BoundedBTreeMap< AccountIdOf, Option>, ::ApprovalsLimit, >; +pub(super) type ItemPriceOf = BalanceOf; // TODO: Multi-instances. pub(super) type ItemDepositOf = ItemDeposit, AccountIdOf>; pub(super) type CollectionDetailsFor = CollectionDetails, BalanceOf>; pub(super) type ItemDetailsFor = ItemDetails, ItemDepositOf, ApprovalsOf>; +pub(super) type AttributeNamespaceOf = AttributeNamespace>; From 9c5eb78718059e14c5bb167597f7d31f4bf293db Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 17 Oct 2024 19:45:16 +0700 Subject: [PATCH 47/76] feat(nonfungibles + nfts): add new methods to manage attributes --- Cargo.lock | 8 +- pallets/api/src/nonfungibles/mod.rs | 198 ++++++++++++++---- pallets/api/src/nonfungibles/types.rs | 17 +- pallets/nfts/src/features/approvals.rs | 4 +- .../src/features/create_delete_collection.rs | 4 +- .../nfts/src/features/create_delete_item.rs | 4 +- pallets/nfts/src/features/transfer.rs | 4 +- pallets/nfts/src/lib.rs | 18 +- pallets/nfts/src/tests.rs | 66 +++--- 9 files changed, 228 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed534195c..48f7b34c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 4 +version = 3 [[package]] name = "Inflector" @@ -822,7 +822,7 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object 0.36.4", + "object 0.36.0", "rustc-demangle", ] @@ -7195,9 +7195,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index 83d23585a..efef2386b 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -14,11 +14,14 @@ mod types; pub mod pallet { use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; use frame_system::pallet_prelude::*; - use pallet_nfts::MintWitness; + use pallet_nfts::{ + CancelAttributesApprovalWitness, CollectionConfig, CollectionSettings, DestroyWitness, + MintSettings, MintWitness, + }; use sp_std::vec::Vec; use types::{ AccountIdOf, AttributeNamespaceOf, BalanceOf, CollectionDetailsFor, CollectionIdOf, - ItemDetailsFor, ItemIdOf, ItemPriceOf, NftsOf, NftsWeightInfoOf, + CreateCollectionConfigFor, ItemDetailsFor, ItemIdOf, ItemPriceOf, NftsOf, NftsWeightInfoOf, }; use super::*; @@ -29,24 +32,12 @@ pub mod pallet { #[repr(u8)] #[allow(clippy::unnecessary_cast)] pub enum Read { - /// Returns the owner of an item. - #[codec(index = 0)] - OwnerOf { collection: CollectionIdOf, item: ItemIdOf }, - /// Returns the owner of a collection. - #[codec(index = 1)] - CollectionOwner(CollectionIdOf), /// Number of items existing in a concrete collection. #[codec(index = 2)] TotalSupply(CollectionIdOf), /// Returns the total number of items in the collection owned by the account. #[codec(index = 3)] BalanceOf { collection: CollectionIdOf, owner: AccountIdOf }, - /// Returns the details of a collection. - #[codec(index = 4)] - Collection(CollectionIdOf), - /// Returns the details of an item. - #[codec(index = 5)] - Item { collection: CollectionIdOf, item: ItemIdOf }, /// Whether a spender is allowed to transfer an item or items from owner. #[codec(index = 6)] Allowance { @@ -55,6 +46,9 @@ pub mod pallet { operator: AccountIdOf, item: Option>, }, + /// Returns the owner of an item. + #[codec(index = 0)] + OwnerOf { collection: CollectionIdOf, item: ItemIdOf }, /// Returns the attribute of `item` for the given `key`. #[codec(index = 6)] GetAttribute { @@ -63,20 +57,29 @@ pub mod pallet { namespace: AttributeNamespaceOf, key: BoundedVec, }, + /// Returns the owner of a collection. + #[codec(index = 1)] + CollectionOwner(CollectionIdOf), + /// Returns the details of a collection. + #[codec(index = 4)] + Collection(CollectionIdOf), + /// Returns the details of an item. + #[codec(index = 5)] + Item { collection: CollectionIdOf, item: ItemIdOf }, } /// Results of state reads for the non-fungibles API. #[derive(Debug)] #[cfg_attr(feature = "std", derive(PartialEq, Clone))] pub enum ReadResult { - OwnerOf(Option>), - CollectionOwner(Option>), TotalSupply(u128), BalanceOf(u32), - Collection(Option>), - Item(Option>), Allowance(bool), + OwnerOf(Option>), GetAttribute(Option>), + CollectionOwner(Option>), + Collection(Option>), + Item(Option>), } impl ReadResult { @@ -141,19 +144,6 @@ pub mod pallet { #[pallet::call] impl Pallet { - #[pallet::call_index(20)] - #[pallet::weight(NftsWeightInfoOf::::create())] - pub fn create(_origin: OriginFor) -> DispatchResult { - Ok(()) - } - - // TODO: Fix weight - #[pallet::call_index(21)] - #[pallet::weight(NftsWeightInfoOf::::create())] - pub fn destroy(_origin: OriginFor) -> DispatchResult { - Ok(()) - } - #[pallet::call_index(0)] #[pallet::weight(NftsWeightInfoOf::::mint())] pub fn mint( @@ -250,6 +240,131 @@ pub mod pallet { Self::deposit_event(Event::Approval { collection, item, operator, owner, approved }); Ok(()) } + + #[pallet::call_index(4)] + #[pallet::weight(NftsWeightInfoOf::::create())] + pub fn create( + origin: OriginFor, + admin: AccountIdOf, + config: CreateCollectionConfigFor, + ) -> DispatchResult { + let collection_config = CollectionConfig { + settings: CollectionSettings::all_enabled(), + max_supply: config.max_supply, + mint_settings: MintSettings { + mint_type: config.mint_type, + start_block: config.start_block, + end_block: config.end_block, + ..MintSettings::default() + }, + }; + NftsOf::::create(origin, T::Lookup::unlookup(admin.clone()), collection_config)?; + Ok(()) + } + + #[pallet::call_index(5)] + #[pallet::weight(NftsWeightInfoOf::::destroy( + witness.item_metadatas, + witness.item_configs, + witness.attributes, + ))] + pub fn destroy( + origin: OriginFor, + collection: CollectionIdOf, + witness: DestroyWitness, + ) -> DispatchResultWithPostInfo { + NftsOf::::destroy(origin, collection, witness) + } + + #[pallet::call_index(6)] + #[pallet::weight(NftsWeightInfoOf::::set_attribute())] + pub fn set_attribute( + origin: OriginFor, + collection: CollectionIdOf, + item: Option>, + namespace: AttributeNamespaceOf, + key: BoundedVec, + value: BoundedVec, + ) -> DispatchResult { + NftsOf::::set_attribute(origin, collection, item, namespace, key, value) + } + + #[pallet::call_index(7)] + #[pallet::weight(NftsWeightInfoOf::::clear_attribute())] + pub fn clear_attribute( + origin: OriginFor, + collection: CollectionIdOf, + item: Option>, + namespace: AttributeNamespaceOf, + key: BoundedVec, + ) -> DispatchResult { + NftsOf::::clear_attribute(origin, collection, item, namespace, key) + } + + #[pallet::call_index(8)] + #[pallet::weight(NftsWeightInfoOf::::set_metadata())] + pub fn set_metadata( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + data: BoundedVec, + ) -> DispatchResult { + NftsOf::::set_metadata(origin, collection, item, data) + } + + #[pallet::call_index(9)] + #[pallet::weight(NftsWeightInfoOf::::clear_metadata())] + pub fn clear_metadata( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + ) -> DispatchResult { + NftsOf::::clear_metadata(origin, collection, item) + } + + #[pallet::call_index(10)] + #[pallet::weight(NftsWeightInfoOf::::approve_item_attributes())] + pub fn approve_item_attributes( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + delegate: AccountIdOf, + ) -> DispatchResult { + NftsOf::::approve_item_attributes( + origin, + collection, + item, + T::Lookup::unlookup(delegate.clone()), + ) + } + + #[pallet::call_index(11)] + #[pallet::weight(NftsWeightInfoOf::::cancel_item_attributes_approval(witness.account_attributes))] + pub fn cancel_item_attributes_approval( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + delegate: AccountIdOf, + witness: CancelAttributesApprovalWitness, + ) -> DispatchResult { + NftsOf::::cancel_item_attributes_approval( + origin, + collection, + item, + T::Lookup::unlookup(delegate.clone()), + witness, + ) + } + + #[pallet::call_index(12)] + #[pallet::weight(NftsWeightInfoOf::::set_collection_max_supply())] + pub fn set_max_supply( + origin: OriginFor, + collection: CollectionIdOf, + max_supply: u32, + ) -> DispatchResult { + NftsOf::::set_collection_max_supply(origin, collection, max_supply) + } } impl crate::Read for Pallet { @@ -274,27 +389,26 @@ pub mod pallet { fn read(value: Self::Read) -> Self::Result { use Read::*; match value { - OwnerOf { collection, item } => - ReadResult::OwnerOf(NftsOf::::owner(collection, item)), - CollectionOwner(collection) => - ReadResult::CollectionOwner(NftsOf::::collection_owner(collection)), TotalSupply(collection) => ReadResult::TotalSupply( NftsOf::::collection_items(collection).unwrap_or_default().into(), ), - Collection(collection) => - ReadResult::Collection(pallet_nfts::Collection::::get(collection)), - Item { collection, item } => - ReadResult::Item(pallet_nfts::Item::::get(collection, item)), + BalanceOf { collection, owner } => + ReadResult::BalanceOf(pallet_nfts::AccountBalance::::get(collection, owner)), Allowance { collection, owner, operator, item } => ReadResult::Allowance( NftsOf::::check_allowance(&collection, &item, &owner, &operator).is_ok(), ), - BalanceOf { collection, owner } => ReadResult::BalanceOf( - pallet_nfts::AccountBalance::::get((collection, owner)), - ), + OwnerOf { collection, item } => + ReadResult::OwnerOf(NftsOf::::owner(collection, item)), GetAttribute { collection, item, namespace, key } => ReadResult::GetAttribute( pallet_nfts::Attribute::::get((collection, item, namespace, key)) .map(|attribute| attribute.0), ), + CollectionOwner(collection) => + ReadResult::CollectionOwner(NftsOf::::collection_owner(collection)), + Collection(collection) => + ReadResult::Collection(pallet_nfts::Collection::::get(collection)), + Item { collection, item } => + ReadResult::Item(pallet_nfts::Item::::get(collection, item)), } } } diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs index da9491715..8c53ffd33 100644 --- a/pallets/api/src/nonfungibles/types.rs +++ b/pallets/api/src/nonfungibles/types.rs @@ -1,7 +1,9 @@ +use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; use frame_system::pallet_prelude::BlockNumberFor; -use pallet_nfts::{AttributeNamespace, CollectionDetails, ItemDeposit, ItemDetails}; -use sp_runtime::BoundedBTreeMap; +use pallet_nfts::{AttributeNamespace, CollectionDetails, ItemDeposit, ItemDetails, MintType}; +use scale_info::TypeInfo; +use sp_runtime::{BoundedBTreeMap, RuntimeDebug}; // Type aliases for pallet-nfts. pub(super) type NftsOf = pallet_nfts::Pallet; @@ -28,3 +30,14 @@ pub(super) type CollectionDetailsFor = pub(super) type ItemDetailsFor = ItemDetails, ItemDepositOf, ApprovalsOf>; pub(super) type AttributeNamespaceOf = AttributeNamespace>; +pub(super) type CreateCollectionConfigFor = + CreateCollectionConfig, BlockNumberFor, CollectionIdOf>; + +#[derive(Clone, Copy, Decode, Encode, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] +pub struct CreateCollectionConfig { + pub max_supply: Option, + pub mint_type: MintType, + pub price: Option, + pub start_block: Option, + pub end_block: Option, +} diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index 05696fee5..6d71c1a22 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -171,7 +171,7 @@ impl, I: 'static> Pallet { Ok(()) } - pub(crate) fn do_approve_transfer_collection( + pub(crate) fn do_approve_collection( maybe_check_origin: Option, collection: T::CollectionId, delegate: T::AccountId, @@ -204,7 +204,7 @@ impl, I: 'static> Pallet { Ok(()) } - pub(crate) fn do_cancel_approval_collection( + pub(crate) fn do_cancel_collection( maybe_check_origin: Option, collection: T::CollectionId, delegate: T::AccountId, diff --git a/pallets/nfts/src/features/create_delete_collection.rs b/pallets/nfts/src/features/create_delete_collection.rs index 2ea5cd732..b7efd03ac 100644 --- a/pallets/nfts/src/features/create_delete_collection.rs +++ b/pallets/nfts/src/features/create_delete_collection.rs @@ -137,8 +137,10 @@ impl, I: 'static> Pallet { } } + // TODO: Do we need another storage item to keep track of number of holders of a + // collection let _ = - AccountBalance::::clear_prefix((collection,), collection_details.items, None); + AccountBalance::::clear_prefix(collection, collection_details.items, None); let _ = Allowances::::clear_prefix((collection,), collection_details.items, None); CollectionAccount::::remove(&collection_details.owner, &collection); T::Currency::unreserve(&collection_details.owner, collection_details.owner_deposit); diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index 036a63b70..cc29f8dab 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -69,7 +69,7 @@ impl, I: 'static> Pallet { } collection_details.items.saturating_inc(); - AccountBalance::::mutate((collection, &mint_to), |balance| { + AccountBalance::::mutate(collection, &mint_to, |balance| { balance.saturating_inc(); }); @@ -266,7 +266,7 @@ impl, I: 'static> Pallet { ItemPriceOf::::remove(&collection, &item); PendingSwapOf::::remove(&collection, &item); ItemAttributesApprovalsOf::::remove(&collection, &item); - AccountBalance::::mutate((collection, &owner), |balance| { + AccountBalance::::mutate(collection, &owner, |balance| { balance.saturating_dec(); }); diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index 04d9f4fe8..3b25b0145 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -88,10 +88,10 @@ impl, I: 'static> Pallet { with_details(&collection_details, &mut details)?; // Update account balances. - AccountBalance::::mutate((collection, &details.owner), |balance| { + AccountBalance::::mutate(collection, &details.owner, |balance| { balance.saturating_dec(); }); - AccountBalance::::mutate((collection, &dest), |balance| { + AccountBalance::::mutate(collection, &dest, |balance| { balance.saturating_inc(); }); diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index c7d826b54..bc8b67b61 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -404,14 +404,12 @@ pub mod pallet { /// Number of collection items that accounts own. #[pallet::storage] - pub type AccountBalance, I: 'static = ()> = StorageNMap< + pub type AccountBalance, I: 'static = ()> = StorageDoubleMap< _, - ( - // Collection Id. - NMapKey, - // Collection Owner Id. - NMapKey, - ), + Twox64Concat, + T::CollectionId, + Blake2_128Concat, + T::AccountId, u32, ValueQuery, >; @@ -1333,8 +1331,7 @@ pub mod pallet { delegate, maybe_deadline, ), - None => - Self::do_approve_transfer_collection(maybe_check_origin, collection, delegate), + None => Self::do_approve_collection(maybe_check_origin, collection, delegate), } } @@ -1367,8 +1364,7 @@ pub mod pallet { match maybe_item { Some(item) => Self::do_cancel_approval(maybe_check_origin, collection, item, delegate), - None => - Self::do_cancel_approval_collection(maybe_check_origin, collection, delegate), + None => Self::do_cancel_collection(maybe_check_origin, collection, delegate), } } diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 10c95bd6c..397a715c2 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -164,7 +164,7 @@ fn basic_minting_should_work() { )); assert_eq!(collections(), vec![(account(1), 0)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); - assert_eq!(AccountBalance::::get((0, account(1))), 1); + assert_eq!(AccountBalance::::get(0, account(1)), 1); assert_eq!(items(), vec![(account(1), 0, 42)]); assert_ok!(Nfts::force_create( @@ -174,7 +174,7 @@ fn basic_minting_should_work() { )); assert_eq!(collections(), vec![(account(1), 0), (account(2), 1)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(2)), 1, 69, account(1), None)); - assert_eq!(AccountBalance::::get((1, account(1))), 1); + assert_eq!(AccountBalance::::get(1, account(1)), 1); assert_eq!(items(), vec![(account(1), 0, 42), (account(1), 1, 69)]); }); } @@ -206,7 +206,7 @@ fn lifecycle_should_work() { account(10), default_item_config() )); - assert_eq!(AccountBalance::::get((0, account(10))), 1); + assert_eq!(AccountBalance::::get(0, account(10)), 1); assert_eq!(Balances::reserved_balance(&account(1)), 6); assert_ok!(Nfts::force_mint( RuntimeOrigin::signed(account(1)), @@ -215,10 +215,10 @@ fn lifecycle_should_work() { account(20), default_item_config() )); - assert_eq!(AccountBalance::::get((0, account(20))), 1); + assert_eq!(AccountBalance::::get(0, account(20)), 1); assert_eq!(Balances::reserved_balance(&account(1)), 7); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 70, account(1), None)); - assert_eq!(AccountBalance::::get((0, account(1))), 1); + assert_eq!(AccountBalance::::get(0, account(1)), 1); assert_eq!(items(), vec![(account(1), 0, 70), (account(10), 0, 42), (account(20), 0, 69)]); assert_eq!(Collection::::get(0).unwrap().items, 3); assert_eq!(Collection::::get(0).unwrap().item_metadatas, 0); @@ -226,8 +226,8 @@ fn lifecycle_should_work() { assert_eq!(Balances::reserved_balance(&account(1)), 8); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 70, account(2))); - assert_eq!(AccountBalance::::get((0, account(1))), 0); - assert_eq!(AccountBalance::::get((0, account(2))), 1); + assert_eq!(AccountBalance::::get(0, account(1)), 0); + assert_eq!(AccountBalance::::get(0, account(2)), 1); assert_eq!(Balances::reserved_balance(&account(1)), 8); assert_eq!(Balances::reserved_balance(&account(2)), 0); @@ -245,7 +245,7 @@ fn lifecycle_should_work() { Nfts::destroy(RuntimeOrigin::signed(account(1)), 0, w), Error::::CollectionNotEmpty ); - assert_eq!(AccountBalance::::get((0, account(1))), 0); + assert_eq!(AccountBalance::::get(0, account(1)), 0); assert_ok!(Nfts::set_attribute( RuntimeOrigin::signed(account(1)), @@ -256,9 +256,9 @@ fn lifecycle_should_work() { bvec![0], )); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(10)), 0, 42)); - assert_eq!(AccountBalance::::get((0, account(10))), 0); + assert_eq!(AccountBalance::::get(0, account(10)), 0); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(20)), 0, 69)); - assert_eq!(AccountBalance::::get((0, account(10))), 0); + assert_eq!(AccountBalance::::get(0, account(10)), 0); assert_ok!(Nfts::burn(RuntimeOrigin::root(), 0, 70)); let w = Nfts::get_destroy_witness(&0).unwrap(); @@ -266,7 +266,7 @@ fn lifecycle_should_work() { assert_eq!(w.item_metadatas, 0); assert_eq!(w.item_configs, 0); assert_ok!(Nfts::destroy(RuntimeOrigin::signed(account(1)), 0, w)); - assert_eq!(AccountBalance::::get((0, account(1))), 0); + assert_eq!(AccountBalance::::get(0, account(1)), 0); assert_eq!(Balances::reserved_balance(&account(1)), 0); assert!(!Collection::::contains_key(0)); @@ -316,7 +316,14 @@ fn destroy_should_work() { )); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(2), None)); - assert_eq!(AccountBalance::::get((0, account(2))), 1); + assert_eq!(AccountBalance::::get(0, account(2)), 1); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(account(2)), + 0, + None, + account(3), + None + )); assert_noop!( Nfts::destroy( RuntimeOrigin::signed(account(1)), @@ -335,7 +342,8 @@ fn destroy_should_work() { 0, Nfts::get_destroy_witness(&0).unwrap() )); - assert_eq!(AccountBalance::::get((0, account(1))), 0); + assert_eq!(AccountBalance::::iter_prefix(0).count(), 0); + assert_eq!(Allowances::::iter_prefix((0,)).count(), 0); assert!(!ItemConfigOf::::contains_key(0, 42)); assert_eq!(ItemConfigOf::::iter_prefix(0).count() as u32, 0); }); @@ -350,7 +358,7 @@ fn mint_should_work() { default_collection_config() )); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); - assert_eq!(AccountBalance::::get((0, account(1))), 1); + assert_eq!(AccountBalance::::get(0, account(1)), 1); assert_eq!(Nfts::owner(0, 42).unwrap(), account(1)); assert_eq!(collections(), vec![(account(1), 0)]); assert_eq!(items(), vec![(account(1), 0, 42)]); @@ -416,7 +424,7 @@ fn mint_should_work() { account(2), Some(MintWitness { mint_price: Some(1), ..Default::default() }) )); - assert_eq!(AccountBalance::::get((0, account(2))), 1); + assert_eq!(AccountBalance::::get(0, account(2)), 1); assert_eq!(Balances::total_balance(&account(2)), 99); // validate types @@ -455,7 +463,7 @@ fn mint_should_work() { account(2), Some(MintWitness { owned_item: Some(43), ..Default::default() }) )); - assert_eq!(AccountBalance::::get((1, account(2))), 1); + assert_eq!(AccountBalance::::get(1, account(2)), 1); assert!(events().contains(&Event::::PalletAttributeSet { collection: 0, item: Some(43), @@ -494,8 +502,8 @@ fn transfer_should_work() { )); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); - assert_eq!(AccountBalance::::get((0, account(2))), 0); - assert_eq!(AccountBalance::::get((0, account(3))), 1); + assert_eq!(AccountBalance::::get(0, account(2)), 0); + assert_eq!(AccountBalance::::get(0, account(3)), 1); assert_eq!(items(), vec![(account(3), 0, 42)]); assert_noop!( Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4)), @@ -510,9 +518,9 @@ fn transfer_should_work() { None )); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4))); - assert_eq!(AccountBalance::::get((0, account(2))), 0); - assert_eq!(AccountBalance::::get((0, account(3))), 0); - assert_eq!(AccountBalance::::get((0, account(4))), 1); + assert_eq!(AccountBalance::::get(0, account(2)), 0); + assert_eq!(AccountBalance::::get(0, account(3)), 0); + assert_eq!(AccountBalance::::get(0, account(4)), 1); // validate we can't transfer non-transferable items let collection_id = 1; assert_ok!(Nfts::force_create( @@ -1766,7 +1774,7 @@ fn burn_works() { account(5), default_item_config() )); - assert_eq!(AccountBalance::::get((0, account(5))), 2); + assert_eq!(AccountBalance::::get(0, account(5)), 2); assert_eq!(Balances::reserved_balance(account(1)), 2); assert_noop!( @@ -1774,9 +1782,9 @@ fn burn_works() { Error::::NoPermission ); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 42)); - assert_eq!(AccountBalance::::get((0, account(5))), 1); + assert_eq!(AccountBalance::::get(0, account(5)), 1); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 69)); - assert_eq!(AccountBalance::::get((0, account(5))), 0); + assert_eq!(AccountBalance::::get(0, account(5)), 0); assert_eq!(Balances::reserved_balance(account(1)), 0); }); } @@ -2755,7 +2763,7 @@ fn buy_item_should_work() { item_1, price_1 + 1, )); - assert_eq!(AccountBalance::::get((collection_id, user_2.clone())), 1); + assert_eq!(AccountBalance::::get(collection_id, user_2.clone()), 1); // validate the new owner & balances let item = Item::::get(collection_id, item_1).unwrap(); @@ -3123,8 +3131,8 @@ fn claim_swap_should_work() { default_item_config(), )); - assert_eq!(AccountBalance::::get((collection_id, user_1.clone())), 2); - assert_eq!(AccountBalance::::get((collection_id, user_2.clone())), 3); + assert_eq!(AccountBalance::::get(collection_id, user_1.clone()), 2); + assert_eq!(AccountBalance::::get(collection_id, user_2.clone()), 3); assert_ok!(Nfts::create_swap( RuntimeOrigin::signed(user_1.clone()), collection_id, @@ -3215,8 +3223,8 @@ fn claim_swap_should_work() { item_1, Some(price_with_direction.clone()), )); - assert_eq!(AccountBalance::::get((collection_id, user_1.clone())), 2); - assert_eq!(AccountBalance::::get((collection_id, user_2.clone())), 3); + assert_eq!(AccountBalance::::get(collection_id, user_1.clone()), 2); + assert_eq!(AccountBalance::::get(collection_id, user_2.clone()), 3); // validate the new owner let item = Item::::get(collection_id, item_1).unwrap(); From 9096b3f705ea996798e323c8ed85b69c2916757f Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 18 Oct 2024 10:04:01 +0700 Subject: [PATCH 48/76] refactor(nfts): toml lock file --- Cargo.lock | 20 ++++++++++---------- pallets/nfts/Cargo.toml | 3 +-- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 48f7b34c7..71903ca0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7366,7 +7366,7 @@ dependencies = [ "log", "pallet-assets", "pallet-balances", - "pallet-nfts 31.0.0", + "pallet-nfts 0.1.0", "parity-scale-codec", "pop-chain-extension", "scale-info", @@ -8240,39 +8240,39 @@ dependencies = [ [[package]] name = "pallet-nfts" -version = "30.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e1cd476809de3840e19091a083d5a79178af1f108ad489706e1f9e04c8836a4" +version = "0.1.0" dependencies = [ "enumflags2", "frame-benchmarking", "frame-support", "frame-system", "log", + "pallet-balances", "parity-scale-codec", "scale-info", "sp-core", "sp-io", + "sp-keystore", "sp-runtime", - "sp-std", ] [[package]] name = "pallet-nfts" -version = "31.0.0" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e1cd476809de3840e19091a083d5a79178af1f108ad489706e1f9e04c8836a4" dependencies = [ "enumflags2", "frame-benchmarking", "frame-support", "frame-system", "log", - "pallet-balances", "parity-scale-codec", "scale-info", "sp-core", "sp-io", - "sp-keystore", "sp-runtime", + "sp-std", ] [[package]] @@ -10857,7 +10857,7 @@ dependencies = [ "pallet-message-queue", "pallet-multisig", "pallet-nft-fractionalization", - "pallet-nfts 31.0.0", + "pallet-nfts 0.1.0", "pallet-nfts-runtime-api", "pallet-preimage", "pallet-proxy", @@ -11002,7 +11002,7 @@ dependencies = [ "pallet-message-queue", "pallet-multisig", "pallet-nft-fractionalization", - "pallet-nfts 31.0.0", + "pallet-nfts 0.1.0", "pallet-nfts-runtime-api", "pallet-preimage", "pallet-proxy", diff --git a/pallets/nfts/Cargo.toml b/pallets/nfts/Cargo.toml index 791db0a73..722e8ef8b 100644 --- a/pallets/nfts/Cargo.toml +++ b/pallets/nfts/Cargo.toml @@ -6,8 +6,7 @@ homepage = "https://substrate.io" license.workspace = true name = "pallet-nfts" readme = "README.md" -repository.workspace = true -version = "31.0.0" +version = "0.1.0" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] From 43349448c026c07626d8d7ea3f9745bb507251ff Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 18 Oct 2024 10:06:00 +0700 Subject: [PATCH 49/76] fix(pallet-api): propagate try-runtime feature --- pallets/api/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pallets/api/Cargo.toml b/pallets/api/Cargo.toml index 5d3987244..31ccc076d 100644 --- a/pallets/api/Cargo.toml +++ b/pallets/api/Cargo.toml @@ -60,5 +60,6 @@ std = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", + "pallet-nfts/try-runtime", "sp-runtime/try-runtime", ] From a38fc47df3478162068fa290a271d23095cd27a6 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 18 Oct 2024 17:36:29 +0700 Subject: [PATCH 50/76] fix(api/nonfungibles): unit tests --- pallets/api/src/nonfungibles/mod.rs | 4 +- pallets/api/src/nonfungibles/tests.rs | 407 ++++++++++++++------------ 2 files changed, 225 insertions(+), 186 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index efef2386b..9655bbeab 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -72,7 +72,7 @@ pub mod pallet { #[derive(Debug)] #[cfg_attr(feature = "std", derive(PartialEq, Clone))] pub enum ReadResult { - TotalSupply(u128), + TotalSupply(u32), BalanceOf(u32), Allowance(bool), OwnerOf(Option>), @@ -390,7 +390,7 @@ pub mod pallet { use Read::*; match value { TotalSupply(collection) => ReadResult::TotalSupply( - NftsOf::::collection_items(collection).unwrap_or_default().into(), + NftsOf::::collection_items(collection).unwrap_or_default(), ), BalanceOf { collection, owner } => ReadResult::BalanceOf(pallet_nfts::AccountBalance::::get(collection, owner)), diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index 54d855167..d757508af 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -1,184 +1,223 @@ -// TODO -// use codec::Encode; -// use frame_support::{assert_ok, traits::nonfungibles_v2::InspectEnumerable}; -// use frame_system::pallet_prelude::BlockNumberFor; -// use pallet_nfts::{CollectionConfig, CollectionSettings, MintSettings}; - -// use super::types::*; -// use crate::{ -// mock::*, -// nonfungibles::{Event, Read::*}, -// }; - -// const ITEM: u32 = 1; - -// #[test] -// fn mint_works() { -// new_test_ext().execute_with(|| { -// let owner = account(ALICE); -// let collection = create_collection(owner.clone()); -// // Successfully mint a new collection item. -// assert_ok!(NonFungibles::mint(signed(owner.clone()), owner.clone(), collection, ITEM)); -// System::assert_last_event(Event::Mint { to: owner, collection, item: ITEM }.into()); -// }); -// } - -// #[test] -// fn burn_works() { -// new_test_ext().execute_with(|| { -// let owner = account(ALICE); -// let (collection, item) = create_collection_mint(owner.clone(), ITEM); -// // Successfully burn an existing new collection item. -// assert_ok!(NonFungibles::burn(signed(owner.clone()), collection, ITEM)); -// System::assert_last_event(Event::Burn { collection, item }.into()); -// }); -// } - -// #[test] -// fn transfer() { -// new_test_ext().execute_with(|| { -// let owner = account(ALICE); -// let dest = account(BOB); -// let (collection, item) = create_collection_mint(owner.clone(), ITEM); -// // Successfully burn an existing new collection item. -// assert_ok!(NonFungibles::transfer(signed(owner.clone()), collection, ITEM, dest.clone())); -// System::assert_last_event( -// Event::Transfer { collection, item, from: owner, to: dest }.into(), -// ); -// }); -// } - -// #[test] -// fn approve_works() { -// new_test_ext().execute_with(|| { -// let owner = account(ALICE); -// let spender = account(BOB); -// let (collection, item) = create_collection_mint(owner.clone(), ITEM); -// // Successfully approve `spender` to transfer the collection item. -// assert_ok!(NonFungibles::approve(signed(owner.clone()), collection, item, spender.clone())); -// System::assert_last_event( -// Event::Approval { collection, item, owner, spender: spender.clone() }.into(), -// ); -// // Successfully transfer the item by the delegated account `spender`. -// assert_ok!(Nfts::transfer(signed(spender.clone()), collection, item, spender)); -// }); -// } - -// #[test] -// fn cancel_approval_works() { -// new_test_ext().execute_with(|| { -// let owner = account(ALICE); -// let spender = account(BOB); -// let (collection, item) = -// create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); -// // Successfully cancel the transfer approval of `spender` by `owner`. -// assert_ok!(NonFungibles::cancel_approval(signed(owner), collection, item, spender.clone())); -// // Failed to transfer the item by `spender` without permission. -// assert!(Nfts::transfer(signed(spender.clone()), collection, item, spender).is_err()); -// }); -// } - -// #[test] -// fn owner_of_works() {} - -// #[test] -// fn collection_owner_works() { -// new_test_ext().execute_with(|| { -// let collection = create_collection(account(ALICE)); -// assert_eq!( -// NonFungibles::read_state(CollectionOwner(collection)), -// Nfts::collection_owner(collection).encode() -// ); -// }); -// } - -// #[test] -// fn total_supply_works() { -// new_test_ext().execute_with(|| { -// let (collection, _) = create_collection_mint(account(ALICE), ITEM); -// assert_eq!( -// NonFungibles::read_state(TotalSupply(collection)), -// (Nfts::items(&collection).count() as u8).encode() -// ); -// }); -// } - -// #[test] -// fn collection_works() { -// new_test_ext().execute_with(|| { -// let (collection, _) = create_collection_mint(account(ALICE), ITEM); -// assert_eq!( -// NonFungibles::read_state(Collection(collection)), -// pallet_nfts::Collection::::get(&collection).encode(), -// ); -// }); -// } - -// #[test] -// fn balance_of_works() { -// new_test_ext().execute_with(|| { -// let owner = account(ALICE); -// let (collection, _) = create_collection_mint(owner.clone(), ITEM); -// assert_eq!( -// NonFungibles::read_state(BalanceOf { collection, owner: owner.clone() }), -// (Nfts::owned_in_collection(&collection, &owner).count() as u8).encode() -// ); -// }); -// } - -// #[test] -// fn allowance_works() { -// new_test_ext().execute_with(|| { -// let owner = account(ALICE); -// let spender = account(BOB); -// let (collection, item) = -// create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); -// assert_eq!( -// NonFungibles::read_state(Allowance { spender: spender.clone(), collection, item }), -// super::Pallet::::allowance(collection, item, spender).encode() -// ); -// }); -// } - -// fn signed(account: AccountId) -> RuntimeOrigin { -// RuntimeOrigin::signed(account) -// } - -// fn create_collection_mint_and_approve( -// owner: AccountIdOf, -// item: ItemIdOf, -// spender: AccountIdOf, -// ) -> (u32, u32) { -// let (collection, item) = create_collection_mint(owner.clone(), item); -// assert_ok!(Nfts::approve_transfer(signed(owner), collection, item, spender, None)); -// (collection, item) -// } - -// fn create_collection_mint(owner: AccountIdOf, item: ItemIdOf) -> (u32, u32) { -// let collection = create_collection(owner.clone()); -// assert_ok!(Nfts::mint(signed(owner.clone()), collection, item, owner, None)); -// (collection, item) -// } - -// fn create_collection(owner: AccountIdOf) -> u32 { -// let next_id = next_collection_id(); -// assert_ok!(Nfts::create( -// signed(owner.clone()), -// owner.clone(), -// collection_config_with_all_settings_enabled() -// )); -// next_id -// } - -// fn next_collection_id() -> u32 { -// pallet_nfts::NextCollectionId::::get().unwrap_or_default() -// } - -// fn collection_config_with_all_settings_enabled( -// ) -> CollectionConfig, CollectionIdOf> { -// CollectionConfig { -// settings: CollectionSettings::all_enabled(), -// max_supply: None, -// mint_settings: MintSettings::default(), -// } -// } +use codec::Encode; +use frame_support::{assert_ok, traits::nonfungibles_v2::InspectEnumerable}; +use frame_system::pallet_prelude::BlockNumberFor; +use pallet_nfts::{AccountBalance, CollectionConfig, CollectionSettings, MintSettings}; + +use super::types::{AccountIdOf, CollectionIdOf, ItemIdOf}; +use crate::{ + mock::*, + nonfungibles::{Event, Read::*}, + Read, +}; + +const ITEM: u32 = 1; + +#[test] +fn mint_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let collection = create_collection(owner.clone()); + // Successfully mint a new collection item. + assert_ok!(NonFungibles::mint( + signed(owner.clone()), + owner.clone(), + collection, + ITEM, + None + )); + System::assert_last_event( + Event::Transfer { collection, item: ITEM, from: None, to: Some(owner), value: None } + .into(), + ); + }); +} + +#[test] +fn burn_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let (collection, item) = create_collection_mint(owner.clone(), ITEM); + // Successfully burn an existing new collection item. + assert_ok!(NonFungibles::burn(signed(owner.clone()), collection, ITEM)); + System::assert_last_event( + Event::Transfer { collection, item, from: Some(owner), to: None, value: None }.into(), + ); + }); +} + +#[test] +fn transfer() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let dest = account(BOB); + let (collection, item) = create_collection_mint(owner.clone(), ITEM); + // Successfully burn an existing new collection item. + assert_ok!(NonFungibles::transfer(signed(owner.clone()), collection, ITEM, dest.clone())); + System::assert_last_event( + Event::Transfer { collection, item, from: Some(owner), to: Some(dest), value: None } + .into(), + ); + }); +} + +#[test] +fn approve_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let operator = account(BOB); + let (collection, item) = create_collection_mint(owner.clone(), ITEM); + // Successfully approve `spender` to transfer the collection item. + assert_ok!(NonFungibles::approve( + signed(owner.clone()), + collection, + Some(item), + operator.clone(), + true + )); + System::assert_last_event( + Event::Approval { + collection, + item: Some(item), + owner, + operator: operator.clone(), + approved: true, + } + .into(), + ); + // Successfully transfer the item by the delegated account `spender`. + assert_ok!(Nfts::transfer(signed(operator.clone()), collection, item, operator)); + }); +} + +#[test] +fn cancel_approval_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let spender = account(BOB); + let (collection, item) = + create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); + // Successfully cancel the transfer approval of `spender` by `owner`. + assert_ok!(NonFungibles::approve( + signed(owner), + collection, + Some(item), + spender.clone(), + false + )); + // Failed to transfer the item by `spender` without permission. + assert!(Nfts::transfer(signed(spender.clone()), collection, item, spender).is_err()); + }); +} + +#[test] +fn owner_of_works() {} + +#[test] +fn collection_owner_works() { + new_test_ext().execute_with(|| { + let collection = create_collection(account(ALICE)); + assert_eq!( + NonFungibles::read(CollectionOwner(collection)).encode(), + Nfts::collection_owner(collection).encode() + ); + }); +} + +#[test] +fn total_supply_works() { + new_test_ext().execute_with(|| { + let (collection, _) = create_collection_mint(account(ALICE), ITEM); + assert_eq!( + NonFungibles::read(TotalSupply(collection)).encode(), + Nfts::collection_items(collection).unwrap_or_default().encode() + ); + }); +} + +#[test] +fn collection_works() { + new_test_ext().execute_with(|| { + let (collection, _) = create_collection_mint(account(ALICE), ITEM); + assert_eq!( + NonFungibles::read(Collection(collection)).encode(), + pallet_nfts::Collection::::get(&collection).encode(), + ); + }); +} + +#[test] +fn balance_of_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let (collection, _) = create_collection_mint(owner.clone(), ITEM); + assert_eq!( + NonFungibles::read(BalanceOf { collection, owner: owner.clone() }).encode(), + AccountBalance::::get(collection, owner).encode() + ); + }); +} + +#[test] +fn allowance_works() { + new_test_ext().execute_with(|| { + let owner = account(ALICE); + let operator = account(BOB); + let (collection, item) = + create_collection_mint_and_approve(owner.clone(), ITEM, operator.clone()); + assert_eq!( + NonFungibles::read(Allowance { + collection, + item: Some(item), + owner: owner.clone(), + operator: operator.clone(), + }) + .encode(), + Nfts::check_allowance(&collection, &Some(item), &owner, &operator) + .is_ok() + .encode() + ); + }); +} + +fn signed(account: AccountId) -> RuntimeOrigin { + RuntimeOrigin::signed(account) +} + +fn create_collection_mint_and_approve( + owner: AccountIdOf, + item: ItemIdOf, + spender: AccountIdOf, +) -> (u32, u32) { + let (collection, item) = create_collection_mint(owner.clone(), item); + assert_ok!(Nfts::approve_transfer(signed(owner), collection, Some(item), spender, None)); + (collection, item) +} + +fn create_collection_mint(owner: AccountIdOf, item: ItemIdOf) -> (u32, u32) { + let collection = create_collection(owner.clone()); + assert_ok!(Nfts::mint(signed(owner.clone()), collection, item, owner, None)); + (collection, item) +} + +fn create_collection(owner: AccountIdOf) -> u32 { + let next_id = next_collection_id(); + assert_ok!(Nfts::create( + signed(owner.clone()), + owner.clone(), + collection_config_with_all_settings_enabled() + )); + next_id +} + +fn next_collection_id() -> u32 { + pallet_nfts::NextCollectionId::::get().unwrap_or_default() +} + +fn collection_config_with_all_settings_enabled( +) -> CollectionConfig, CollectionIdOf> { + CollectionConfig { + settings: CollectionSettings::all_enabled(), + max_supply: None, + mint_settings: MintSettings::default(), + } +} From a1f446816566bfba4574a9f754c9f110c8f8b8db Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:15:11 +0700 Subject: [PATCH 51/76] test(api/nonfungibles): encoding_read_result --- pallets/api/src/nonfungibles/mod.rs | 10 +-- pallets/api/src/nonfungibles/tests.rs | 109 ++++++++++++++++++++++++-- pallets/nfts/src/types.rs | 22 +++--- 3 files changed, 120 insertions(+), 21 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index 9655bbeab..eb88bfa67 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -137,8 +137,8 @@ pub mod pallet { from: Option>, /// The recipient of the transfer. `None` when burning. to: Option>, - /// The amount minted. - value: Option>, + /// The price of the collection item. + price: Option>, }, } @@ -167,7 +167,7 @@ pub mod pallet { item, from: None, to: Some(account), - value: mint_price, + price: mint_price, }); Ok(()) } @@ -186,7 +186,7 @@ pub mod pallet { item, from: Some(account), to: None, - value: None, + price: None, }); Ok(()) } @@ -206,7 +206,7 @@ pub mod pallet { item, from: Some(from), to: Some(to), - value: None, + price: None, }); Ok(()) } diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index d757508af..063ceee33 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -1,23 +1,119 @@ use codec::Encode; -use frame_support::{assert_ok, traits::nonfungibles_v2::InspectEnumerable}; +use frame_support::assert_ok; use frame_system::pallet_prelude::BlockNumberFor; use pallet_nfts::{AccountBalance, CollectionConfig, CollectionSettings, MintSettings}; use super::types::{AccountIdOf, CollectionIdOf, ItemIdOf}; use crate::{ mock::*, - nonfungibles::{Event, Read::*}, + nonfungibles::{Event, Read::*, ReadResult}, Read, }; const ITEM: u32 = 1; +mod encoding_read_result { + use pallet_nfts::{CollectionDetails, ItemDeposit, ItemDetails}; + use sp_runtime::{BoundedBTreeMap, BoundedVec}; + + use super::*; + + #[test] + fn total_supply() { + let total_supply: u32 = 1_000_000; + assert_eq!(ReadResult::TotalSupply::(total_supply).encode(), total_supply.encode()); + } + + #[test] + fn balance_of() { + let balance: u32 = 100; + assert_eq!(ReadResult::BalanceOf::(balance).encode(), balance.encode()); + } + + #[test] + fn allowance() { + let allowance = false; + assert_eq!(ReadResult::Allowance::(allowance).encode(), allowance.encode()); + } + + #[test] + fn owner_of() { + let mut owner = Some(account(ALICE)); + assert_eq!(ReadResult::OwnerOf::(owner.clone()).encode(), owner.encode()); + owner = None; + assert_eq!(ReadResult::OwnerOf::(owner.clone()).encode(), owner.encode()); + } + + #[test] + fn get_attribute() { + let mut attribute = Some(BoundedVec::truncate_from("some attribute".as_bytes().to_vec())); + assert_eq!( + ReadResult::GetAttribute::(attribute.clone()).encode(), + attribute.encode() + ); + attribute = None; + assert_eq!( + ReadResult::GetAttribute::(attribute.clone()).encode(), + attribute.encode() + ); + } + + #[test] + fn collection_owner() { + let mut collection_owner = Some(account(ALICE)); + assert_eq!( + ReadResult::CollectionOwner::(collection_owner.clone()).encode(), + collection_owner.encode() + ); + collection_owner = None; + assert_eq!( + ReadResult::CollectionOwner::(collection_owner.clone()).encode(), + collection_owner.encode() + ); + } + + #[test] + fn collection() { + let mut collection_details = Some(CollectionDetails { + owner: account(ALICE), + owner_deposit: 0, + items: 0, + item_metadatas: 0, + item_configs: 0, + attributes: 0, + }); + assert_eq!( + ReadResult::Collection::(collection_details.clone()).encode(), + collection_details.encode() + ); + collection_details = None; + assert_eq!( + ReadResult::Collection::(collection_details.clone()).encode(), + collection_details.encode() + ); + } + + #[test] + fn item() { + let mut item_details = Some(ItemDetails { + owner: account(ALICE), + approvals: BoundedBTreeMap::default(), + deposit: ItemDeposit { amount: 0, account: account(BOB) }, + }); + assert_eq!(ReadResult::Item::(item_details.clone()).encode(), item_details.encode()); + item_details = None; + assert_eq!(ReadResult::Item::(item_details.clone()).encode(), item_details.encode()); + } +} + #[test] fn mint_works() { new_test_ext().execute_with(|| { let owner = account(ALICE); let collection = create_collection(owner.clone()); // Successfully mint a new collection item. + let balance_before_mint = AccountBalance::::get(collection.clone(), owner.clone()); + // assert_ok!(NonFungibles::mint( signed(owner.clone()), owner.clone(), @@ -25,8 +121,11 @@ fn mint_works() { ITEM, None )); + let balance_after_mint = AccountBalance::::get(collection.clone(), owner.clone()); + assert_eq!(balance_after_mint, 1); + assert_eq!(balance_after_mint - balance_before_mint, 1); System::assert_last_event( - Event::Transfer { collection, item: ITEM, from: None, to: Some(owner), value: None } + Event::Transfer { collection, item: ITEM, from: None, to: Some(owner), price: None } .into(), ); }); @@ -40,7 +139,7 @@ fn burn_works() { // Successfully burn an existing new collection item. assert_ok!(NonFungibles::burn(signed(owner.clone()), collection, ITEM)); System::assert_last_event( - Event::Transfer { collection, item, from: Some(owner), to: None, value: None }.into(), + Event::Transfer { collection, item, from: Some(owner), to: None, price: None }.into(), ); }); } @@ -54,7 +153,7 @@ fn transfer() { // Successfully burn an existing new collection item. assert_ok!(NonFungibles::transfer(signed(owner.clone()), collection, ITEM, dest.clone())); System::assert_last_event( - Event::Transfer { collection, item, from: Some(owner), to: Some(dest), value: None } + Event::Transfer { collection, item, from: Some(owner), to: Some(dest), price: None } .into(), ); }); diff --git a/pallets/nfts/src/types.rs b/pallets/nfts/src/types.rs index f08f1d097..061352c09 100644 --- a/pallets/nfts/src/types.rs +++ b/pallets/nfts/src/types.rs @@ -94,18 +94,18 @@ pub(super) type PreSignedAttributesOf = PreSignedAttributes< #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct CollectionDetails { /// Collection's owner. - pub(super) owner: AccountId, + pub owner: AccountId, /// The total balance deposited by the owner for all the storage data associated with this /// collection. Used by `destroy`. - pub(super) owner_deposit: DepositBalance, + pub owner_deposit: DepositBalance, /// The total number of outstanding items of this collection. - pub(super) items: u32, + pub items: u32, /// The total number of outstanding item metadata of this collection. - pub(super) item_metadatas: u32, + pub item_metadatas: u32, /// The total number of outstanding item configs of this collection. - pub(super) item_configs: u32, + pub item_configs: u32, /// The total number of attributes for this collection. - pub(super) attributes: u32, + pub attributes: u32, } /// Witness data for the destroy transactions. @@ -145,21 +145,21 @@ pub struct MintWitness { #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo, MaxEncodedLen)] pub struct ItemDetails { /// The owner of this item. - pub(super) owner: AccountId, + pub owner: AccountId, /// The approved transferrer of this item, if one is set. - pub(super) approvals: Approvals, + pub approvals: Approvals, /// The amount held in the pallet's default account for this item. Free-hold items will have /// this as zero. - pub(super) deposit: Deposit, + pub deposit: Deposit, } /// Information about the reserved item deposit. #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct ItemDeposit { /// A depositor account. - pub(super) account: AccountId, + pub account: AccountId, /// An amount that gets reserved. - pub(super) amount: DepositBalance, + pub amount: DepositBalance, } /// Information about the collection's metadata. From 80b378e2fe5b0e12ae27b1f9ebb34ebc62987574 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:51:50 +0700 Subject: [PATCH 52/76] refactor(api/nonfungibles): pallet tests --- pallets/api/src/nonfungibles/tests.rs | 243 +++++++++++++++----------- 1 file changed, 143 insertions(+), 100 deletions(-) diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index 063ceee33..05c82f60b 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -1,7 +1,11 @@ use codec::Encode; -use frame_support::assert_ok; +use frame_support::{assert_noop, assert_ok}; use frame_system::pallet_prelude::BlockNumberFor; -use pallet_nfts::{AccountBalance, CollectionConfig, CollectionSettings, MintSettings}; +use pallet_nfts::{ + AccountBalance, CollectionConfig, CollectionDetails, CollectionSettings, ItemDeposit, + ItemDetails, MintSettings, +}; +use sp_runtime::{BoundedBTreeMap, BoundedVec, DispatchError::BadOrigin}; use super::types::{AccountIdOf, CollectionIdOf, ItemIdOf}; use crate::{ @@ -12,10 +16,9 @@ use crate::{ const ITEM: u32 = 1; -mod encoding_read_result { - use pallet_nfts::{CollectionDetails, ItemDeposit, ItemDetails}; - use sp_runtime::{BoundedBTreeMap, BoundedVec}; +type NftsError = pallet_nfts::Error; +mod encoding_read_result { use super::*; #[test] @@ -107,53 +110,72 @@ mod encoding_read_result { } #[test] -fn mint_works() { +fn transfer() { new_test_ext().execute_with(|| { - let owner = account(ALICE); - let collection = create_collection(owner.clone()); - // Successfully mint a new collection item. - let balance_before_mint = AccountBalance::::get(collection.clone(), owner.clone()); - // - assert_ok!(NonFungibles::mint( - signed(owner.clone()), - owner.clone(), - collection, - ITEM, - None - )); - let balance_after_mint = AccountBalance::::get(collection.clone(), owner.clone()); - assert_eq!(balance_after_mint, 1); - assert_eq!(balance_after_mint - balance_before_mint, 1); + let owner = ALICE; + let dest = BOB; + + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + for origin in vec![root(), none()] { + assert_noop!( + NonFungibles::transfer(origin, collection, item, account(dest)), + BadOrigin + ); + } + // Successfully burn an existing new collection item. + let balance_before_transfer = AccountBalance::::get(collection, &account(dest)); + assert_ok!(NonFungibles::transfer(signed(owner), collection, ITEM, account(dest))); + let balance_after_transfer = AccountBalance::::get(collection, &account(dest)); + assert_eq!(AccountBalance::::get(collection, &account(owner)), 0); + assert_eq!(balance_after_transfer - balance_before_transfer, 1); System::assert_last_event( - Event::Transfer { collection, item: ITEM, from: None, to: Some(owner), price: None } - .into(), + Event::Transfer { + collection, + item, + from: Some(account(owner)), + to: Some(account(dest)), + price: None, + } + .into(), ); }); } #[test] -fn burn_works() { +fn mint_works() { new_test_ext().execute_with(|| { - let owner = account(ALICE); - let (collection, item) = create_collection_mint(owner.clone(), ITEM); - // Successfully burn an existing new collection item. - assert_ok!(NonFungibles::burn(signed(owner.clone()), collection, ITEM)); + let owner = ALICE; + let collection = nfts::create_collection(owner); + + // Successfully mint a new collection item. + let balance_before_mint = AccountBalance::::get(collection, account(owner)); + assert_ok!(NonFungibles::mint(signed(owner), account(owner), collection, ITEM, None)); + let balance_after_mint = AccountBalance::::get(collection, account(owner)); + assert_eq!(balance_after_mint, 1); + assert_eq!(balance_after_mint - balance_before_mint, 1); System::assert_last_event( - Event::Transfer { collection, item, from: Some(owner), to: None, price: None }.into(), + Event::Transfer { + collection, + item: ITEM, + from: None, + to: Some(account(owner)), + price: None, + } + .into(), ); }); } #[test] -fn transfer() { +fn burn_works() { new_test_ext().execute_with(|| { - let owner = account(ALICE); - let dest = account(BOB); - let (collection, item) = create_collection_mint(owner.clone(), ITEM); + let owner = ALICE; + // Successfully burn an existing new collection item. - assert_ok!(NonFungibles::transfer(signed(owner.clone()), collection, ITEM, dest.clone())); + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + assert_ok!(NonFungibles::burn(signed(owner), collection, ITEM)); System::assert_last_event( - Event::Transfer { collection, item, from: Some(owner), to: Some(dest), price: None } + Event::Transfer { collection, item, from: Some(account(owner)), to: None, price: None } .into(), ); }); @@ -162,59 +184,63 @@ fn transfer() { #[test] fn approve_works() { new_test_ext().execute_with(|| { - let owner = account(ALICE); - let operator = account(BOB); - let (collection, item) = create_collection_mint(owner.clone(), ITEM); - // Successfully approve `spender` to transfer the collection item. + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + // Successfully approve `oeprator` to transfer the collection item. assert_ok!(NonFungibles::approve( - signed(owner.clone()), + signed(owner), collection, Some(item), - operator.clone(), + account(operator), true )); System::assert_last_event( Event::Approval { collection, item: Some(item), - owner, - operator: operator.clone(), + owner: account(owner), + operator: account(operator), approved: true, } .into(), ); - // Successfully transfer the item by the delegated account `spender`. - assert_ok!(Nfts::transfer(signed(operator.clone()), collection, item, operator)); + // Successfully transfer the item by the delegated account `operator`. + assert_ok!(Nfts::transfer(signed(operator), collection, item, account(operator))); }); } #[test] fn cancel_approval_works() { new_test_ext().execute_with(|| { - let owner = account(ALICE); - let spender = account(BOB); - let (collection, item) = - create_collection_mint_and_approve(owner.clone(), ITEM, spender.clone()); - // Successfully cancel the transfer approval of `spender` by `owner`. + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); + // Successfully cancel the transfer approval of `operator` by `owner`. assert_ok!(NonFungibles::approve( signed(owner), collection, Some(item), - spender.clone(), + account(operator), false )); - // Failed to transfer the item by `spender` without permission. - assert!(Nfts::transfer(signed(spender.clone()), collection, item, spender).is_err()); + // Failed to transfer the item by `operator` without permission. + assert_noop!( + Nfts::transfer(signed(operator), collection, item, account(operator)), + NftsError::NoPermission + ); }); } #[test] -fn owner_of_works() {} +fn owner_of_works() { + unimplemented!() +} #[test] fn collection_owner_works() { new_test_ext().execute_with(|| { - let collection = create_collection(account(ALICE)); + let collection = nfts::create_collection(ALICE); assert_eq!( NonFungibles::read(CollectionOwner(collection)).encode(), Nfts::collection_owner(collection).encode() @@ -225,7 +251,7 @@ fn collection_owner_works() { #[test] fn total_supply_works() { new_test_ext().execute_with(|| { - let (collection, _) = create_collection_mint(account(ALICE), ITEM); + let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!( NonFungibles::read(TotalSupply(collection)).encode(), Nfts::collection_items(collection).unwrap_or_default().encode() @@ -236,7 +262,7 @@ fn total_supply_works() { #[test] fn collection_works() { new_test_ext().execute_with(|| { - let (collection, _) = create_collection_mint(account(ALICE), ITEM); + let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!( NonFungibles::read(Collection(collection)).encode(), pallet_nfts::Collection::::get(&collection).encode(), @@ -247,11 +273,11 @@ fn collection_works() { #[test] fn balance_of_works() { new_test_ext().execute_with(|| { - let owner = account(ALICE); - let (collection, _) = create_collection_mint(owner.clone(), ITEM); + let owner = ALICE; + let (collection, _) = nfts::create_collection_mint(owner, ITEM); assert_eq!( - NonFungibles::read(BalanceOf { collection, owner: owner.clone() }).encode(), - AccountBalance::::get(collection, owner).encode() + NonFungibles::read(BalanceOf { collection, owner: account(owner) }).encode(), + AccountBalance::::get(collection, account(owner)).encode() ); }); } @@ -259,64 +285,81 @@ fn balance_of_works() { #[test] fn allowance_works() { new_test_ext().execute_with(|| { - let owner = account(ALICE); - let operator = account(BOB); - let (collection, item) = - create_collection_mint_and_approve(owner.clone(), ITEM, operator.clone()); + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); assert_eq!( NonFungibles::read(Allowance { collection, item: Some(item), - owner: owner.clone(), - operator: operator.clone(), + owner: account(owner), + operator: account(operator), }) .encode(), - Nfts::check_allowance(&collection, &Some(item), &owner, &operator) + Nfts::check_allowance(&collection, &Some(item), &account(owner), &account(operator)) .is_ok() .encode() ); }); } -fn signed(account: AccountId) -> RuntimeOrigin { - RuntimeOrigin::signed(account) +fn signed(account_id: u8) -> RuntimeOrigin { + RuntimeOrigin::signed(account(account_id)) } -fn create_collection_mint_and_approve( - owner: AccountIdOf, - item: ItemIdOf, - spender: AccountIdOf, -) -> (u32, u32) { - let (collection, item) = create_collection_mint(owner.clone(), item); - assert_ok!(Nfts::approve_transfer(signed(owner), collection, Some(item), spender, None)); - (collection, item) +fn root() -> RuntimeOrigin { + RuntimeOrigin::root() } -fn create_collection_mint(owner: AccountIdOf, item: ItemIdOf) -> (u32, u32) { - let collection = create_collection(owner.clone()); - assert_ok!(Nfts::mint(signed(owner.clone()), collection, item, owner, None)); - (collection, item) +fn none() -> RuntimeOrigin { + RuntimeOrigin::none() } -fn create_collection(owner: AccountIdOf) -> u32 { - let next_id = next_collection_id(); - assert_ok!(Nfts::create( - signed(owner.clone()), - owner.clone(), - collection_config_with_all_settings_enabled() - )); - next_id -} +mod nfts { + use super::*; -fn next_collection_id() -> u32 { - pallet_nfts::NextCollectionId::::get().unwrap_or_default() -} + pub(super) fn create_collection_mint_and_approve( + owner: u8, + item: ItemIdOf, + operator: u8, + ) -> (u32, u32) { + let (collection, item) = create_collection_mint(owner, item); + assert_ok!(Nfts::approve_transfer( + signed(owner), + collection, + Some(item), + account(operator), + None + )); + (collection, item) + } + + pub(super) fn create_collection_mint(owner: u8, item: ItemIdOf) -> (u32, u32) { + let collection = create_collection(owner); + assert_ok!(Nfts::mint(signed(owner), collection, item, account(owner), None)); + (collection, item) + } + + pub(super) fn create_collection(owner: u8) -> u32 { + let next_id = next_collection_id(); + assert_ok!(Nfts::create( + signed(owner), + account(owner), + collection_config_with_all_settings_enabled() + )); + next_id + } + + pub(super) fn next_collection_id() -> u32 { + pallet_nfts::NextCollectionId::::get().unwrap_or_default() + } -fn collection_config_with_all_settings_enabled( -) -> CollectionConfig, CollectionIdOf> { - CollectionConfig { - settings: CollectionSettings::all_enabled(), - max_supply: None, - mint_settings: MintSettings::default(), + pub(super) fn collection_config_with_all_settings_enabled( + ) -> CollectionConfig, CollectionIdOf> { + CollectionConfig { + settings: CollectionSettings::all_enabled(), + max_supply: None, + mint_settings: MintSettings::default(), + } } } From f3e7e4a414aed1ec7406ae6f8cf82048eb514a03 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:30:10 +0700 Subject: [PATCH 53/76] test(nonfungibles): add tests and remove collection owner read --- pallets/api/src/nonfungibles/mod.rs | 70 ++++--- pallets/api/src/nonfungibles/tests.rs | 267 +++++++++++++++++++++++--- pallets/api/src/nonfungibles/types.rs | 2 + 3 files changed, 286 insertions(+), 53 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index eb88bfa67..7377048fc 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -12,7 +12,7 @@ mod types; #[frame_support::pallet] pub mod pallet { - use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; + use frame_support::{dispatch::DispatchResult, pallet_prelude::*, traits::Incrementable}; use frame_system::pallet_prelude::*; use pallet_nfts::{ CancelAttributesApprovalWitness, CollectionConfig, CollectionSettings, DestroyWitness, @@ -21,7 +21,8 @@ pub mod pallet { use sp_std::vec::Vec; use types::{ AccountIdOf, AttributeNamespaceOf, BalanceOf, CollectionDetailsFor, CollectionIdOf, - CreateCollectionConfigFor, ItemDetailsFor, ItemIdOf, ItemPriceOf, NftsOf, NftsWeightInfoOf, + CreateCollectionConfigFor, ItemDetailsFor, ItemIdOf, ItemPriceOf, NextCollectionIdOf, + NftsOf, NftsWeightInfoOf, }; use super::*; @@ -32,54 +33,62 @@ pub mod pallet { #[repr(u8)] #[allow(clippy::unnecessary_cast)] pub enum Read { - /// Number of items existing in a concrete collection. - #[codec(index = 2)] + /// Total item supply of a collection. + #[codec(index = 0)] TotalSupply(CollectionIdOf), - /// Returns the total number of items in the collection owned by the account. - #[codec(index = 3)] + /// Account balance for a specified collection. + #[codec(index = 1)] BalanceOf { collection: CollectionIdOf, owner: AccountIdOf }, - /// Whether a spender is allowed to transfer an item or items from owner. - #[codec(index = 6)] + /// Allowance for an operator approved by an owner, for a specified collection or item. + #[codec(index = 2)] Allowance { collection: CollectionIdOf, owner: AccountIdOf, operator: AccountIdOf, item: Option>, }, - /// Returns the owner of an item. - #[codec(index = 0)] + /// Owner of a specified collection item. + #[codec(index = 3)] OwnerOf { collection: CollectionIdOf, item: ItemIdOf }, - /// Returns the attribute of `item` for the given `key`. - #[codec(index = 6)] + /// Attribute value of a collection item. + #[codec(index = 4)] GetAttribute { collection: CollectionIdOf, item: Option>, namespace: AttributeNamespaceOf, key: BoundedVec, }, - /// Returns the owner of a collection. - #[codec(index = 1)] - CollectionOwner(CollectionIdOf), - /// Returns the details of a collection. - #[codec(index = 4)] + /// Details of a collection. + #[codec(index = 6)] Collection(CollectionIdOf), - /// Returns the details of an item. - #[codec(index = 5)] + /// Details of a collection item. + #[codec(index = 7)] Item { collection: CollectionIdOf, item: ItemIdOf }, + /// Next collection ID. + #[codec(index = 8)] + NextCollectionId, } /// Results of state reads for the non-fungibles API. #[derive(Debug)] #[cfg_attr(feature = "std", derive(PartialEq, Clone))] pub enum ReadResult { + /// Total item supply of a collection. TotalSupply(u32), + /// Account balance for a specified collection. BalanceOf(u32), + /// Allowance for an operator approved by an owner, for a specified collection or item. Allowance(bool), + /// Owner of a specified collection owner. OwnerOf(Option>), + /// Attribute value of a collection item. GetAttribute(Option>), - CollectionOwner(Option>), + /// Details of a collection. Collection(Option>), + /// Details of a collection item. Item(Option>), + /// Next collection ID. + NextCollectionId(Option>), } impl ReadResult { @@ -88,13 +97,13 @@ pub mod pallet { use ReadResult::*; match self { OwnerOf(result) => result.encode(), - CollectionOwner(result) => result.encode(), TotalSupply(result) => result.encode(), BalanceOf(result) => result.encode(), Collection(result) => result.encode(), Item(result) => result.encode(), Allowance(result) => result.encode(), GetAttribute(result) => result.encode(), + NextCollectionId(result) => result.encode(), } } } @@ -140,6 +149,15 @@ pub mod pallet { /// The price of the collection item. price: Option>, }, + /// Event emitted when a collection is created. + Created { + /// The collection identifier. + id: CollectionIdOf, + /// The creator of the collection. + creator: AccountIdOf, + /// The administrator of the collection. + admin: AccountIdOf, + }, } #[pallet::call] @@ -248,6 +266,10 @@ pub mod pallet { admin: AccountIdOf, config: CreateCollectionConfigFor, ) -> DispatchResult { + let id = NextCollectionIdOf::::get() + .or(T::CollectionId::initial_value()) + .ok_or(pallet_nfts::Error::::UnknownCollection)?; + let creator = ensure_signed(origin.clone())?; let collection_config = CollectionConfig { settings: CollectionSettings::all_enabled(), max_supply: config.max_supply, @@ -259,6 +281,7 @@ pub mod pallet { }, }; NftsOf::::create(origin, T::Lookup::unlookup(admin.clone()), collection_config)?; + Self::deposit_event(Event::Created { id, admin, creator }); Ok(()) } @@ -403,12 +426,13 @@ pub mod pallet { pallet_nfts::Attribute::::get((collection, item, namespace, key)) .map(|attribute| attribute.0), ), - CollectionOwner(collection) => - ReadResult::CollectionOwner(NftsOf::::collection_owner(collection)), Collection(collection) => ReadResult::Collection(pallet_nfts::Collection::::get(collection)), Item { collection, item } => ReadResult::Item(pallet_nfts::Item::::get(collection, item)), + NextCollectionId => ReadResult::NextCollectionId( + NextCollectionIdOf::::get().or(T::CollectionId::initial_value()), + ), } } } diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index 05c82f60b..e89ba0bd2 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -1,5 +1,5 @@ use codec::Encode; -use frame_support::{assert_noop, assert_ok}; +use frame_support::{assert_noop, assert_ok, traits::Incrementable}; use frame_system::pallet_prelude::BlockNumberFor; use pallet_nfts::{ AccountBalance, CollectionConfig, CollectionDetails, CollectionSettings, ItemDeposit, @@ -7,7 +7,7 @@ use pallet_nfts::{ }; use sp_runtime::{BoundedBTreeMap, BoundedVec, DispatchError::BadOrigin}; -use super::types::{AccountIdOf, CollectionIdOf, ItemIdOf}; +use super::types::{CollectionIdOf, ItemIdOf}; use crate::{ mock::*, nonfungibles::{Event, Read::*, ReadResult}, @@ -61,20 +61,6 @@ mod encoding_read_result { ); } - #[test] - fn collection_owner() { - let mut collection_owner = Some(account(ALICE)); - assert_eq!( - ReadResult::CollectionOwner::(collection_owner.clone()).encode(), - collection_owner.encode() - ); - collection_owner = None; - assert_eq!( - ReadResult::CollectionOwner::(collection_owner.clone()).encode(), - collection_owner.encode() - ); - } - #[test] fn collection() { let mut collection_details = Some(CollectionDetails { @@ -107,6 +93,20 @@ mod encoding_read_result { item_details = None; assert_eq!(ReadResult::Item::(item_details.clone()).encode(), item_details.encode()); } + + #[test] + fn next_collection_id_works() { + let mut next_collection_id = Some(0); + assert_eq!( + ReadResult::NextCollectionId::(next_collection_id).encode(), + next_collection_id.encode() + ); + next_collection_id = None; + assert_eq!( + ReadResult::NextCollectionId::(next_collection_id).encode(), + next_collection_id.encode() + ); + } } #[test] @@ -232,33 +232,212 @@ fn cancel_approval_works() { }); } +#[test] +fn set_max_supply_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let collection = nfts::create_collection(owner); + assert_ok!(NonFungibles::set_max_supply(signed(owner), collection, 10)); + (0..10).into_iter().for_each(|i| { + assert_ok!(Nfts::mint(signed(owner), collection, i, account(owner), None)); + }); + assert_noop!( + Nfts::mint(signed(owner), collection, 42, account(owner), None), + NftsError::MaxSupplyReached + ); + }); +} + #[test] fn owner_of_works() { - unimplemented!() + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!( + NonFungibles::read(OwnerOf { collection, item }).encode(), + Nfts::owner(collection, item).encode() + ); + }); +} + +#[test] +fn get_attribute_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); + let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); + let mut result: Option::ValueLimit>> = None; + // No attribute set. + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item: Some(item), + namespace: pallet_nfts::AttributeNamespace::CollectionOwner, + key: attribute.clone() + }) + .encode(), + result.encode() + ); + // Successfully get an existing attribute. + result = Some(value.clone()); + assert_ok!(Nfts::set_attribute( + signed(ALICE), + collection, + Some(item), + pallet_nfts::AttributeNamespace::CollectionOwner, + attribute.clone(), + value, + )); + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item: Some(item), + namespace: pallet_nfts::AttributeNamespace::CollectionOwner, + key: attribute + }) + .encode(), + result.encode() + ); + }); } #[test] -fn collection_owner_works() { +fn clear_attribute_works() { new_test_ext().execute_with(|| { - let collection = nfts::create_collection(ALICE); + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); + let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let mut result: Option::ValueLimit>> = None; + assert_ok!(Nfts::set_attribute( + signed(ALICE), + collection, + Some(item), + pallet_nfts::AttributeNamespace::CollectionOwner, + attribute.clone(), + BoundedVec::truncate_from("some value".as_bytes().to_vec()) + )); + // Successfully clear an attribute. + assert_ok!(Nfts::clear_attribute( + signed(ALICE), + collection, + Some(item), + pallet_nfts::AttributeNamespace::CollectionOwner, + attribute.clone(), + )); assert_eq!( - NonFungibles::read(CollectionOwner(collection)).encode(), - Nfts::collection_owner(collection).encode() + NonFungibles::read(GetAttribute { + collection, + item: Some(item), + namespace: pallet_nfts::AttributeNamespace::CollectionOwner, + key: attribute + }) + .encode(), + result.encode() ); }); } #[test] -fn total_supply_works() { +fn approve_item_attribute_works() { new_test_ext().execute_with(|| { - let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); + let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); + let mut result: Option::ValueLimit>> = None; + // Successfully approve delegate to set attributes. + assert_ok!(Nfts::approve_item_attributes(signed(ALICE), collection, item, account(BOB))); + assert_ok!(Nfts::set_attribute( + signed(BOB), + collection, + Some(item), + pallet_nfts::AttributeNamespace::Account(account(BOB)), + attribute.clone(), + value.clone() + )); + result = Some(value); + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item: Some(item), + namespace: pallet_nfts::AttributeNamespace::Account(account(BOB)), + key: attribute + }) + .encode(), + result.encode() + ); + }); +} + +#[test] +fn cancel_item_attribute_approval_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); + let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); + let mut result: Option::ValueLimit>> = None; + // Successfully approve delegate to set attributes. + assert_ok!(Nfts::approve_item_attributes(signed(ALICE), collection, item, account(BOB))); + assert_ok!(Nfts::set_attribute( + signed(BOB), + collection, + Some(item), + pallet_nfts::AttributeNamespace::Account(account(BOB)), + attribute.clone(), + value.clone() + )); + assert_ok!(Nfts::cancel_item_attributes_approval( + signed(ALICE), + collection, + item, + account(BOB), + pallet_nfts::CancelAttributesApprovalWitness { account_attributes: 1 } + )); + assert_noop!( + Nfts::set_attribute( + signed(BOB), + collection, + Some(item), + pallet_nfts::AttributeNamespace::Account(account(BOB)), + attribute.clone(), + value.clone() + ), + NftsError::NoPermission + ); + }); +} + +#[test] +fn next_collection_id_works() { + new_test_ext().execute_with(|| { + let _ = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); assert_eq!( - NonFungibles::read(TotalSupply(collection)).encode(), - Nfts::collection_items(collection).unwrap_or_default().encode() + NonFungibles::read(NextCollectionId).encode(), + pallet_nfts::NextCollectionId::::get() + .or(CollectionIdOf::::initial_value()) + .encode(), ); }); } +#[test] +fn total_supply_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let collection = nfts::create_collection(owner); + (0..10).into_iter().for_each(|i| { + assert_ok!(Nfts::mint(signed(owner), collection, i, account(owner), None)); + assert_eq!(NonFungibles::read(TotalSupply(collection)).encode(), (i + 1).encode()); + assert_eq!( + NonFungibles::read(TotalSupply(collection)).encode(), + Nfts::collection_items(collection).unwrap_or_default().encode() + ); + }); + }); +} + #[test] fn collection_works() { new_test_ext().execute_with(|| { @@ -271,23 +450,51 @@ fn collection_works() { } #[test] -fn balance_of_works() { +fn item_works() { new_test_ext().execute_with(|| { - let owner = ALICE; - let (collection, _) = nfts::create_collection_mint(owner, ITEM); + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!( - NonFungibles::read(BalanceOf { collection, owner: account(owner) }).encode(), - AccountBalance::::get(collection, account(owner)).encode() + NonFungibles::read(Item { collection, item }).encode(), + pallet_nfts::Item::::get(&collection, &item).encode(), ); }); } +#[test] +fn balance_of_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let collection = nfts::create_collection(owner); + (0..10).into_iter().for_each(|i| { + assert_ok!(Nfts::mint(signed(owner), collection, i, account(owner), None)); + assert_eq!( + NonFungibles::read(BalanceOf { collection, owner: account(owner) }).encode(), + (i + 1).encode() + ); + assert_eq!( + NonFungibles::read(BalanceOf { collection, owner: account(owner) }).encode(), + AccountBalance::::get(collection, account(owner)).encode() + ); + }); + }); +} + #[test] fn allowance_works() { new_test_ext().execute_with(|| { let owner = ALICE; let operator = BOB; let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); + assert_eq!( + NonFungibles::read(Allowance { + collection, + item: Some(item), + owner: account(owner), + operator: account(operator), + }) + .encode(), + true.encode() + ); assert_eq!( NonFungibles::read(Allowance { collection, diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs index 8c53ffd33..f57ee6976 100644 --- a/pallets/api/src/nonfungibles/types.rs +++ b/pallets/api/src/nonfungibles/types.rs @@ -7,12 +7,14 @@ use sp_runtime::{BoundedBTreeMap, RuntimeDebug}; // Type aliases for pallet-nfts. pub(super) type NftsOf = pallet_nfts::Pallet; +pub(super) type NftsErrorOf = pallet_nfts::Error; pub(super) type NftsWeightInfoOf = ::WeightInfo; // Type aliases for pallet-nfts storage items. pub(super) type AccountIdOf = ::AccountId; pub(super) type BalanceOf = <>::Currency as Currency< ::AccountId, >>::Balance; +pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId; pub(super) type CollectionIdOf = as Inspect<::AccountId>>::CollectionId; pub(super) type ItemIdOf = From e0c896cbe26bd351ce2e07ee1d83e42835b6410c Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 12 Nov 2024 01:17:21 +0700 Subject: [PATCH 54/76] chore: update pallet & runtime --- pallets/api/src/fungibles/tests.rs | 286 ++++------- pallets/api/src/mock.rs | 61 ++- pallets/api/src/nonfungibles/mod.rs | 184 ++++--- pallets/api/src/nonfungibles/tests.rs | 285 +++++----- pallets/api/src/nonfungibles/types.rs | 30 +- pallets/nfts/src/benchmarking.rs | 12 +- pallets/nfts/src/common_functions.rs | 8 + pallets/nfts/src/features/approvals.rs | 31 +- pallets/nfts/src/tests.rs | 18 +- pallets/nfts/src/types.rs | 10 +- pallets/nfts/src/weights.rs | 685 +++++++++++++------------ runtime/devnet/src/config/api/mod.rs | 189 ++++++- runtime/devnet/src/config/assets.rs | 13 +- runtime/devnet/src/lib.rs | 5 +- 14 files changed, 963 insertions(+), 854 deletions(-) diff --git a/pallets/api/src/fungibles/tests.rs b/pallets/api/src/fungibles/tests.rs index 6e181a6f7..f5c560bb7 100644 --- a/pallets/api/src/fungibles/tests.rs +++ b/pallets/api/src/fungibles/tests.rs @@ -83,21 +83,17 @@ fn transfer_works() { let to = BOB; for origin in vec![root(), none()] { - assert_noop!(Fungibles::transfer(origin, token, account(to), value), BadOrigin); + assert_noop!(Fungibles::transfer(origin, token, to, value), BadOrigin); } // Check error works for `Assets::transfer_keep_alive()`. - assert_noop!( - Fungibles::transfer(signed(from), token, account(to), value), - AssetsError::Unknown - ); + assert_noop!(Fungibles::transfer(signed(from), token, to, value), AssetsError::Unknown); assets::create_and_mint_to(from, token, from, value * 2); - let balance_before_transfer = Assets::balance(token, &account(to)); - assert_ok!(Fungibles::transfer(signed(from), token, account(to), value)); - let balance_after_transfer = Assets::balance(token, &account(to)); + let balance_before_transfer = Assets::balance(token, &to); + assert_ok!(Fungibles::transfer(signed(from), token, to, value)); + let balance_after_transfer = Assets::balance(token, &to); assert_eq!(balance_after_transfer, balance_before_transfer + value); System::assert_last_event( - Event::Transfer { token, from: Some(account(from)), to: Some(account(to)), value } - .into(), + Event::Transfer { token, from: Some(from), to: Some(to), value }.into(), ); }); } @@ -112,36 +108,26 @@ fn transfer_from_works() { let spender = CHARLIE; for origin in vec![root(), none()] { - assert_noop!( - Fungibles::transfer_from(origin, token, account(from), account(to), value), - BadOrigin - ); + assert_noop!(Fungibles::transfer_from(origin, token, from, to, value), BadOrigin); } // Check error works for `Assets::transfer_approved()`. assert_noop!( - Fungibles::transfer_from(signed(spender), token, account(from), account(to), value), + Fungibles::transfer_from(signed(spender), token, from, to, value), AssetsError::Unknown ); // Approve `spender` to transfer up to `value`. assets::create_mint_and_approve(spender, token, from, value * 2, spender, value); // Successfully call transfer from. - let from_balance_before_transfer = Assets::balance(token, &account(from)); - let to_balance_before_transfer = Assets::balance(token, &account(to)); - assert_ok!(Fungibles::transfer_from( - signed(spender), - token, - account(from), - account(to), - value - )); - let from_balance_after_transfer = Assets::balance(token, &account(from)); - let to_balance_after_transfer = Assets::balance(token, &account(to)); + let from_balance_before_transfer = Assets::balance(token, &from); + let to_balance_before_transfer = Assets::balance(token, &to); + assert_ok!(Fungibles::transfer_from(signed(spender), token, from, to, value)); + let from_balance_after_transfer = Assets::balance(token, &from); + let to_balance_after_transfer = Assets::balance(token, &to); // Check that `to` has received the `value` tokens from `from`. assert_eq!(to_balance_after_transfer, to_balance_before_transfer + value); assert_eq!(from_balance_after_transfer, from_balance_before_transfer - value); System::assert_last_event( - Event::Transfer { token, from: Some(account(from)), to: Some(account(to)), value } - .into(), + Event::Transfer { token, from: Some(from), to: Some(to), value }.into(), ); }); } @@ -158,7 +144,7 @@ mod approve { for origin in vec![root(), none()] { assert_noop!( - Fungibles::approve(origin, token, account(spender), value), + Fungibles::approve(origin, token, spender, value), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } @@ -175,20 +161,20 @@ mod approve { for origin in vec![root(), none()] { assert_noop!( - Fungibles::approve(origin, token, account(spender), value), + Fungibles::approve(origin, token, spender, value), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } // Check error works for `Assets::approve_transfer()` in `Greater` match arm. assert_noop!( - Fungibles::approve(signed(owner), token, account(spender), value), + Fungibles::approve(signed(owner), token, spender, value), AssetsError::Unknown.with_weight(WeightInfo::approve(1, 0)) ); assets::create_mint_and_approve(owner, token, owner, value, spender, value); // Check error works for `Assets::cancel_approval()` in `Less` match arm. assert_ok!(Assets::freeze_asset(signed(owner), token)); assert_noop!( - Fungibles::approve(signed(owner), token, account(spender), value / 2), + Fungibles::approve(signed(owner), token, spender, value / 2), AssetsError::AssetNotLive.with_weight(WeightInfo::approve(0, 1)) ); assert_ok!(Assets::thaw_asset(signed(owner), token)); @@ -207,61 +193,38 @@ mod approve { // Approves a value to spend that is higher than the current allowance. assets::create_and_mint_to(owner, token, owner, value); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), 0); + assert_eq!(Assets::allowance(token, &owner, &spender), 0); assert_eq!( - Fungibles::approve(signed(owner), token, account(spender), value), + Fungibles::approve(signed(owner), token, spender, value), Ok(Some(WeightInfo::approve(1, 0)).into()) ); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); - System::assert_last_event( - Event::Approval { token, owner: account(owner), spender: account(spender), value } - .into(), - ); + assert_eq!(Assets::allowance(token, &owner, &spender), value); + System::assert_last_event(Event::Approval { token, owner, spender, value }.into()); // Approves a value to spend that is lower than the current allowance. assert_eq!( - Fungibles::approve(signed(owner), token, account(spender), value / 2), + Fungibles::approve(signed(owner), token, spender, value / 2), Ok(Some(WeightInfo::approve(1, 1)).into()) ); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value / 2); + assert_eq!(Assets::allowance(token, &owner, &spender), value / 2); System::assert_last_event( - Event::Approval { - token, - owner: account(owner), - spender: account(spender), - value: value / 2, - } - .into(), + Event::Approval { token, owner, spender, value: value / 2 }.into(), ); // Approves a value to spend that is equal to the current allowance. assert_eq!( - Fungibles::approve(signed(owner), token, account(spender), value / 2), + Fungibles::approve(signed(owner), token, spender, value / 2), Ok(Some(WeightInfo::approve(0, 0)).into()) ); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value / 2); + assert_eq!(Assets::allowance(token, &owner, &spender), value / 2); System::assert_last_event( - Event::Approval { - token, - owner: account(owner), - spender: account(spender), - value: value / 2, - } - .into(), + Event::Approval { token, owner, spender, value: value / 2 }.into(), ); // Sets allowance to zero. assert_eq!( - Fungibles::approve(signed(owner), token, account(spender), 0), + Fungibles::approve(signed(owner), token, spender, 0), Ok(Some(WeightInfo::approve(0, 1)).into()) ); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), 0); - System::assert_last_event( - Event::Approval { - token, - owner: account(owner), - spender: account(spender), - value: 0, - } - .into(), - ); + assert_eq!(Assets::allowance(token, &owner, &spender), 0); + System::assert_last_event(Event::Approval { token, owner, spender, value: 0 }.into()); }); } } @@ -276,34 +239,25 @@ fn increase_allowance_works() { for origin in vec![root(), none()] { assert_noop!( - Fungibles::increase_allowance(origin, token, account(spender), value), + Fungibles::increase_allowance(origin, token, spender, value), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } // Check error works for `Assets::approve_transfer()`. assert_noop!( - Fungibles::increase_allowance(signed(owner), token, account(spender), value), + Fungibles::increase_allowance(signed(owner), token, spender, value), AssetsError::Unknown.with_weight(AssetsWeightInfo::approve_transfer()) ); assets::create_and_mint_to(owner, token, owner, value); - assert_eq!(0, Assets::allowance(token, &account(owner), &account(spender))); - assert_ok!(Fungibles::increase_allowance(signed(owner), token, account(spender), value)); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); - System::assert_last_event( - Event::Approval { token, owner: account(owner), spender: account(spender), value } - .into(), - ); + assert_eq!(0, Assets::allowance(token, &owner, &spender)); + assert_ok!(Fungibles::increase_allowance(signed(owner), token, spender, value)); + assert_eq!(Assets::allowance(token, &owner, &spender), value); + System::assert_last_event(Event::Approval { token, owner, spender, value }.into()); // Additive. - assert_ok!(Fungibles::increase_allowance(signed(owner), token, account(spender), value)); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value * 2); + assert_ok!(Fungibles::increase_allowance(signed(owner), token, spender, value)); + assert_eq!(Assets::allowance(token, &owner, &spender), value * 2); System::assert_last_event( - Event::Approval { - token, - owner: account(owner), - spender: account(spender), - value: value * 2, - } - .into(), + Event::Approval { token, owner, spender, value: value * 2 }.into(), ); }); } @@ -318,46 +272,40 @@ fn decrease_allowance_works() { for origin in vec![root(), none()] { assert_noop!( - Fungibles::decrease_allowance(origin, token, account(spender), 0), + Fungibles::decrease_allowance(origin, token, spender, 0), BadOrigin.with_weight(WeightInfo::approve(0, 0)) ); } assets::create_mint_and_approve(owner, token, owner, value, spender, value); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); + assert_eq!(Assets::allowance(token, &owner, &spender), value); // Check error works for `Assets::cancel_approval()`. No error test for `approve_transfer` // because it is not possible. assert_ok!(Assets::freeze_asset(signed(owner), token)); assert_noop!( - Fungibles::decrease_allowance(signed(owner), token, account(spender), value / 2), + Fungibles::decrease_allowance(signed(owner), token, spender, value / 2), AssetsError::AssetNotLive.with_weight(WeightInfo::approve(0, 1)) ); assert_ok!(Assets::thaw_asset(signed(owner), token)); // Owner balance is not changed if decreased by zero. assert_eq!( - Fungibles::decrease_allowance(signed(owner), token, account(spender), 0), + Fungibles::decrease_allowance(signed(owner), token, spender, 0), Ok(Some(WeightInfo::approve(0, 0)).into()) ); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value); + assert_eq!(Assets::allowance(token, &owner, &spender), value); // "Unapproved" error is returned if the current allowance is less than amount to decrease // with. assert_noop!( - Fungibles::decrease_allowance(signed(owner), token, account(spender), value * 2), + Fungibles::decrease_allowance(signed(owner), token, spender, value * 2), AssetsError::Unapproved ); // Decrease allowance successfully. assert_eq!( - Fungibles::decrease_allowance(signed(owner), token, account(spender), value / 2), + Fungibles::decrease_allowance(signed(owner), token, spender, value / 2), Ok(Some(WeightInfo::approve(1, 1)).into()) ); - assert_eq!(Assets::allowance(token, &account(owner), &account(spender)), value / 2); + assert_eq!(Assets::allowance(token, &owner, &spender), value / 2); System::assert_last_event( - Event::Approval { - token, - owner: account(owner), - spender: account(spender), - value: value / 2, - } - .into(), + Event::Approval { token, owner, spender, value: value / 2 }.into(), ); }); } @@ -370,19 +318,14 @@ fn create_works() { let admin = ALICE; for origin in vec![root(), none()] { - assert_noop!(Fungibles::create(origin, id, account(admin), 100), BadOrigin); + assert_noop!(Fungibles::create(origin, id, admin, 100), BadOrigin); } assert!(!Assets::asset_exists(id)); - assert_ok!(Fungibles::create(signed(creator), id, account(admin), 100)); + assert_ok!(Fungibles::create(signed(creator), id, admin, 100)); assert!(Assets::asset_exists(id)); - System::assert_last_event( - Event::Created { id, creator: account(creator), admin: account(admin) }.into(), - ); + System::assert_last_event(Event::Created { id, creator, admin }.into()); // Check error works for `Assets::create()`. - assert_noop!( - Fungibles::create(signed(creator), id, account(admin), 100), - AssetsError::InUse - ); + assert_noop!(Fungibles::create(signed(creator), id, admin, 100), AssetsError::InUse); }); } @@ -393,11 +336,11 @@ fn start_destroy_works() { // Check error works for `Assets::start_destroy()`. assert_noop!(Fungibles::start_destroy(signed(ALICE), token), AssetsError::Unknown); - assert_ok!(Assets::create(signed(ALICE), token, account(ALICE), 1)); + assert_ok!(Assets::create(signed(ALICE), token, ALICE, 1)); assert_ok!(Fungibles::start_destroy(signed(ALICE), token)); // Check that the token is not live after starting the destroy process. assert_noop!( - Assets::mint(signed(ALICE), token, account(ALICE), 10 * UNIT), + Assets::mint(signed(ALICE), token, ALICE, 10 * UNIT), AssetsError::AssetNotLive ); }); @@ -416,7 +359,7 @@ fn set_metadata_works() { Fungibles::set_metadata(signed(ALICE), token, name.clone(), symbol.clone(), decimals), AssetsError::Unknown ); - assert_ok!(Assets::create(signed(ALICE), token, account(ALICE), 1)); + assert_ok!(Assets::create(signed(ALICE), token, ALICE, 1)); assert_ok!(Fungibles::set_metadata( signed(ALICE), token, @@ -455,16 +398,16 @@ fn mint_works() { // Check error works for `Assets::mint()`. assert_noop!( - Fungibles::mint(signed(from), token, account(to), value), + Fungibles::mint(signed(from), token, to, value), sp_runtime::TokenError::UnknownAsset ); - assert_ok!(Assets::create(signed(from), token, account(from), 1)); - let balance_before_mint = Assets::balance(token, &account(to)); - assert_ok!(Fungibles::mint(signed(from), token, account(to), value)); - let balance_after_mint = Assets::balance(token, &account(to)); + assert_ok!(Assets::create(signed(from), token, from, 1)); + let balance_before_mint = Assets::balance(token, &to); + assert_ok!(Fungibles::mint(signed(from), token, to, value)); + let balance_after_mint = Assets::balance(token, &to); assert_eq!(balance_after_mint, balance_before_mint + value); System::assert_last_event( - Event::Transfer { token, from: None, to: Some(account(to)), value }.into(), + Event::Transfer { token, from: None, to: Some(to), value }.into(), ); }); } @@ -480,30 +423,27 @@ fn burn_works() { // "BalanceLow" error is returned if token is not created. assert_noop!( - Fungibles::burn(signed(owner), token, account(from), value), + Fungibles::burn(signed(owner), token, from, value), AssetsError::BalanceLow.with_weight(WeightInfo::balance_of()) ); assets::create_and_mint_to(owner, token, from, total_supply); assert_eq!(Assets::total_supply(TOKEN), total_supply); // Check error works for `Assets::burn()`. assert_ok!(Assets::freeze_asset(signed(owner), token)); - assert_noop!( - Fungibles::burn(signed(owner), token, account(from), value), - AssetsError::AssetNotLive - ); + assert_noop!(Fungibles::burn(signed(owner), token, from, value), AssetsError::AssetNotLive); assert_ok!(Assets::thaw_asset(signed(owner), token)); // "BalanceLow" error is returned if the balance is less than amount to burn. assert_noop!( - Fungibles::burn(signed(owner), token, account(from), total_supply * 2), + Fungibles::burn(signed(owner), token, from, total_supply * 2), AssetsError::BalanceLow.with_weight(WeightInfo::balance_of()) ); - let balance_before_burn = Assets::balance(token, &account(from)); - assert_ok!(Fungibles::burn(signed(owner), token, account(from), value)); + let balance_before_burn = Assets::balance(token, &from); + assert_ok!(Fungibles::burn(signed(owner), token, from, value)); assert_eq!(Assets::total_supply(TOKEN), total_supply - value); - let balance_after_burn = Assets::balance(token, &account(from)); + let balance_after_burn = Assets::balance(token, &from); assert_eq!(balance_after_burn, balance_before_burn - value); System::assert_last_event( - Event::Transfer { token, from: Some(account(from)), to: None, value }.into(), + Event::Transfer { token, from: Some(from), to: None, value }.into(), ); }); } @@ -530,17 +470,17 @@ fn balance_of_works() { new_test_ext().execute_with(|| { let value = 1_000 * UNIT; assert_eq!( - Fungibles::read(BalanceOf { token: TOKEN, owner: account(ALICE) }), + Fungibles::read(BalanceOf { token: TOKEN, owner: ALICE }), ReadResult::BalanceOf(Default::default()) ); assets::create_and_mint_to(ALICE, TOKEN, ALICE, value); assert_eq!( - Fungibles::read(BalanceOf { token: TOKEN, owner: account(ALICE) }), + Fungibles::read(BalanceOf { token: TOKEN, owner: ALICE }), ReadResult::BalanceOf(value) ); assert_eq!( - Fungibles::read(BalanceOf { token: TOKEN, owner: account(ALICE) }).encode(), - Assets::balance(TOKEN, account(ALICE)).encode(), + Fungibles::read(BalanceOf { token: TOKEN, owner: ALICE }).encode(), + Assets::balance(TOKEN, ALICE).encode(), ); }); } @@ -550,30 +490,17 @@ fn allowance_works() { new_test_ext().execute_with(|| { let value = 1_000 * UNIT; assert_eq!( - Fungibles::read(Allowance { - token: TOKEN, - owner: account(ALICE), - spender: account(BOB) - }), + Fungibles::read(Allowance { token: TOKEN, owner: ALICE, spender: BOB }), ReadResult::Allowance(Default::default()) ); assets::create_mint_and_approve(ALICE, TOKEN, ALICE, value * 2, BOB, value); assert_eq!( - Fungibles::read(Allowance { - token: TOKEN, - owner: account(ALICE), - spender: account(BOB) - }), + Fungibles::read(Allowance { token: TOKEN, owner: ALICE, spender: BOB }), ReadResult::Allowance(value) ); assert_eq!( - Fungibles::read(Allowance { - token: TOKEN, - owner: account(ALICE), - spender: account(BOB) - }) - .encode(), - Assets::allowance(TOKEN, &account(ALICE), &account(BOB)).encode(), + Fungibles::read(Allowance { token: TOKEN, owner: ALICE, spender: BOB }).encode(), + Assets::allowance(TOKEN, &ALICE, &BOB).encode(), ); }); } @@ -607,7 +534,7 @@ fn token_metadata_works() { fn token_exists_works() { new_test_ext().execute_with(|| { assert_eq!(Fungibles::read(TokenExists(TOKEN)), ReadResult::TokenExists(false)); - assert_ok!(Assets::create(signed(ALICE), TOKEN, account(ALICE), 1)); + assert_ok!(Assets::create(signed(ALICE), TOKEN, ALICE, 1)); assert_eq!(Fungibles::read(TokenExists(TOKEN)), ReadResult::TokenExists(true)); assert_eq!( Fungibles::read(TokenExists(TOKEN)).encode(), @@ -616,8 +543,8 @@ fn token_exists_works() { }); } -fn signed(account_id: u8) -> RuntimeOrigin { - RuntimeOrigin::signed(account(account_id)) +fn signed(account: AccountId) -> RuntimeOrigin { + RuntimeOrigin::signed(account) } fn root() -> RuntimeOrigin { @@ -632,31 +559,36 @@ fn none() -> RuntimeOrigin { mod assets { use super::*; - pub(super) fn create_and_mint_to(owner: u8, token: TokenId, to: u8, value: Balance) { - assert_ok!(Assets::create(signed(owner), token, account(owner), 1)); - assert_ok!(Assets::mint(signed(owner), token, account(to), value)); + pub(super) fn create_and_mint_to( + owner: AccountId, + token: TokenId, + to: AccountId, + value: Balance, + ) { + assert_ok!(Assets::create(signed(owner), token, owner, 1)); + assert_ok!(Assets::mint(signed(owner), token, to, value)); } pub(super) fn create_mint_and_approve( - owner: u8, + owner: AccountId, token: TokenId, - to: u8, + to: AccountId, mint: Balance, - spender: u8, + spender: AccountId, approve: Balance, ) { create_and_mint_to(owner, token, to, mint); - assert_ok!(Assets::approve_transfer(signed(to), token, account(spender), approve,)); + assert_ok!(Assets::approve_transfer(signed(to), token, spender, approve,)); } pub(super) fn create_and_set_metadata( - owner: u8, + owner: AccountId, token: TokenId, name: Vec, symbol: Vec, decimals: u8, ) { - assert_ok!(Assets::create(signed(owner), token, account(owner), 1)); + assert_ok!(Assets::create(signed(owner), token, owner, 1)); assert_ok!(Assets::set_metadata(signed(owner), token, name, symbol, decimals)); } } @@ -681,11 +613,11 @@ mod read_weights { fn new() -> Self { Self { total_supply: Fungibles::weight(&TotalSupply(TOKEN)), - balance_of: Fungibles::weight(&BalanceOf { token: TOKEN, owner: account(ALICE) }), + balance_of: Fungibles::weight(&BalanceOf { token: TOKEN, owner: ALICE }), allowance: Fungibles::weight(&Allowance { token: TOKEN, - owner: account(ALICE), - spender: account(BOB), + owner: ALICE, + spender: BOB, }), token_name: Fungibles::weight(&TokenName(TOKEN)), token_symbol: Fungibles::weight(&TokenSymbol(TOKEN)), @@ -767,15 +699,15 @@ mod ensure_codec_indexes { [ (TotalSupply::(Default::default()), 0u8, "TotalSupply"), ( - BalanceOf:: { token: Default::default(), owner: account(Default::default()) }, + BalanceOf:: { token: Default::default(), owner: Default::default() }, 1, "BalanceOf", ), ( Allowance:: { token: Default::default(), - owner: account(Default::default()), - spender: account(Default::default()), + owner: Default::default(), + spender: Default::default(), }, 2, "Allowance", @@ -799,7 +731,7 @@ mod ensure_codec_indexes { ( transfer { token: Default::default(), - to: account(Default::default()), + to: Default::default(), value: Default::default(), }, 3u8, @@ -808,8 +740,8 @@ mod ensure_codec_indexes { ( transfer_from { token: Default::default(), - from: account(Default::default()), - to: account(Default::default()), + from: Default::default(), + to: Default::default(), value: Default::default(), }, 4, @@ -818,7 +750,7 @@ mod ensure_codec_indexes { ( approve { token: Default::default(), - spender: account(Default::default()), + spender: Default::default(), value: Default::default(), }, 5, @@ -827,7 +759,7 @@ mod ensure_codec_indexes { ( increase_allowance { token: Default::default(), - spender: account(Default::default()), + spender: Default::default(), value: Default::default(), }, 6, @@ -836,7 +768,7 @@ mod ensure_codec_indexes { ( decrease_allowance { token: Default::default(), - spender: account(Default::default()), + spender: Default::default(), value: Default::default(), }, 7, @@ -845,7 +777,7 @@ mod ensure_codec_indexes { ( create { id: Default::default(), - admin: account(Default::default()), + admin: Default::default(), min_balance: Default::default(), }, 11, @@ -866,7 +798,7 @@ mod ensure_codec_indexes { ( mint { token: Default::default(), - account: account(Default::default()), + account: Default::default(), value: Default::default(), }, 19, @@ -875,7 +807,7 @@ mod ensure_codec_indexes { ( burn { token: Default::default(), - account: account(Default::default()), + account: Default::default(), value: Default::default(), }, 20, diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs index 920d590f9..8a4ad27d0 100644 --- a/pallets/api/src/mock.rs +++ b/pallets/api/src/mock.rs @@ -1,28 +1,28 @@ +use codec::{Decode, Encode}; use frame_support::{ derive_impl, parameter_types, traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, ConstU64, Everything}, }; use frame_system::{EnsureRoot, EnsureSigned}; use pallet_nfts::PalletFeatures; +use scale_info::TypeInfo; use sp_core::H256; use sp_runtime::{ - traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Verify}, - BuildStorage, MultiSignature, + traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Lazy, Verify}, + BuildStorage, }; -pub(crate) const ALICE: u8 = 1; -pub(crate) const BOB: u8 = 2; -pub(crate) const CHARLIE: u8 = 3; +pub(crate) const ALICE: AccountId = 1; +pub(crate) const BOB: AccountId = 2; +pub(crate) const CHARLIE: AccountId = 3; pub(crate) const INIT_AMOUNT: Balance = 100_000_000 * UNIT; pub(crate) const UNIT: Balance = 10_000_000_000; type Block = frame_system::mocking::MockBlock; -pub(crate) type AccountId = ::AccountId; +pub(crate) type AccountId = u64; pub(crate) type Balance = u128; // For terminology in tests. pub(crate) type TokenId = u32; -type Signature = MultiSignature; -type AccountPublic = ::Signer; // Configure a mock runtime to test the pallet. frame_support::construct_runtime!( @@ -99,7 +99,7 @@ impl pallet_assets::Config for Test { type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; type Extra = (); - type ForceOrigin = EnsureRoot; + type ForceOrigin = EnsureRoot; type Freezer = (); type MetadataDepositBase = ConstU128<1>; type MetadataDepositPerByte = ConstU128<1>; @@ -119,12 +119,35 @@ parameter_types! { pub storage Features: PalletFeatures = PalletFeatures::all_enabled(); } +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, TypeInfo)] +pub struct Noop; + +impl IdentifyAccount for Noop { + type AccountId = AccountId; + + fn into_account(self) -> Self::AccountId { + 0 + } +} + +impl Verify for Noop { + type Signer = Noop; + + fn verify>( + &self, + _msg: L, + _signer: &::AccountId, + ) -> bool { + false + } +} + impl pallet_nfts::Config for Test { type ApprovalsLimit = ConstU32<10>; type AttributeDepositBase = ConstU128<1>; type CollectionDeposit = ConstU128<2>; type CollectionId = u32; - type CreateOrigin = AsEnsureOriginWithArg>; + type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; type DepositPerByte = ConstU128<1>; type Features = Features; @@ -140,11 +163,8 @@ impl pallet_nfts::Config for Test { type MaxDeadlineDuration = ConstU64<10000>; type MaxTips = ConstU32<10>; type MetadataDepositBase = ConstU128<1>; - /// Using `AccountPublic` here makes it trivial to convert to `AccountId` via `into_account()`. - type OffchainPublic = AccountPublic; - /// Off-chain = signature On-chain - therefore no conversion needed. - /// It needs to be From for benchmarking. - type OffchainSignature = Signature; + type OffchainPublic = Noop; + type OffchainSignature = Noop; type RuntimeEvent = RuntimeEvent; type StringLimit = ConstU32<50>; type ValueLimit = ConstU32<50>; @@ -155,22 +175,13 @@ impl crate::nonfungibles::Config for Test { type RuntimeEvent = RuntimeEvent; } -/// Initialize a new account ID. -pub(crate) fn account(id: u8) -> AccountId { - [id; 32].into() -} - pub(crate) fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::::default() .build_storage() .expect("Frame system builds valid default genesis config"); pallet_balances::GenesisConfig:: { - balances: vec![ - (account(ALICE), INIT_AMOUNT), - (account(BOB), INIT_AMOUNT), - (account(CHARLIE), INIT_AMOUNT), - ], + balances: vec![(ALICE, INIT_AMOUNT), (BOB, INIT_AMOUNT), (CHARLIE, INIT_AMOUNT)], } .assimilate_storage(&mut t) .expect("Pallet balances storage can be assimilated"); diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index 7377048fc..1a5b07b89 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -5,24 +5,22 @@ pub use pallet::*; use pallet_nfts::WeightInfo; use sp_runtime::traits::StaticLookup; +pub use types::*; #[cfg(test)] mod tests; -mod types; +pub mod types; #[frame_support::pallet] pub mod pallet { use frame_support::{dispatch::DispatchResult, pallet_prelude::*, traits::Incrementable}; use frame_system::pallet_prelude::*; - use pallet_nfts::{ - CancelAttributesApprovalWitness, CollectionConfig, CollectionSettings, DestroyWitness, - MintSettings, MintWitness, - }; + use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness, MintWitness}; + use sp_runtime::BoundedVec; use sp_std::vec::Vec; use types::{ - AccountIdOf, AttributeNamespaceOf, BalanceOf, CollectionDetailsFor, CollectionIdOf, - CreateCollectionConfigFor, ItemDetailsFor, ItemIdOf, ItemPriceOf, NextCollectionIdOf, - NftsOf, NftsWeightInfoOf, + AccountIdOf, AttributeNamespaceOf, BalanceOf, CollectionConfigFor, CollectionDetailsFor, + CollectionIdOf, ItemIdOf, ItemPriceOf, NextCollectionIdOf, NftsOf, NftsWeightInfoOf, }; use super::*; @@ -48,25 +46,24 @@ pub mod pallet { item: Option>, }, /// Owner of a specified collection item. - #[codec(index = 3)] + #[codec(index = 5)] OwnerOf { collection: CollectionIdOf, item: ItemIdOf }, - /// Attribute value of a collection item. - #[codec(index = 4)] + /// Attribute value of a collection item. (Error: bounded collection is not partial) + #[codec(index = 6)] GetAttribute { collection: CollectionIdOf, - item: Option>, + item: ItemIdOf, namespace: AttributeNamespaceOf, key: BoundedVec, }, /// Details of a collection. - #[codec(index = 6)] + #[codec(index = 9)] Collection(CollectionIdOf), - /// Details of a collection item. - #[codec(index = 7)] - Item { collection: CollectionIdOf, item: ItemIdOf }, /// Next collection ID. - #[codec(index = 8)] + #[codec(index = 10)] NextCollectionId, + #[codec(index = 11)] + ItemMetadata { collection: CollectionIdOf, item: ItemIdOf }, } /// Results of state reads for the non-fungibles API. @@ -74,7 +71,7 @@ pub mod pallet { #[cfg_attr(feature = "std", derive(PartialEq, Clone))] pub enum ReadResult { /// Total item supply of a collection. - TotalSupply(u32), + TotalSupply(u128), /// Account balance for a specified collection. BalanceOf(u32), /// Allowance for an operator approved by an owner, for a specified collection or item. @@ -82,13 +79,13 @@ pub mod pallet { /// Owner of a specified collection owner. OwnerOf(Option>), /// Attribute value of a collection item. - GetAttribute(Option>), + GetAttribute(Option>), /// Details of a collection. Collection(Option>), - /// Details of a collection item. - Item(Option>), /// Next collection ID. NextCollectionId(Option>), + /// Collection item metadata. + ItemMetadata(Option>), } impl ReadResult { @@ -100,10 +97,10 @@ pub mod pallet { TotalSupply(result) => result.encode(), BalanceOf(result) => result.encode(), Collection(result) => result.encode(), - Item(result) => result.encode(), Allowance(result) => result.encode(), GetAttribute(result) => result.encode(), NextCollectionId(result) => result.encode(), + ItemMetadata(result) => result.encode(), } } } @@ -162,54 +159,7 @@ pub mod pallet { #[pallet::call] impl Pallet { - #[pallet::call_index(0)] - #[pallet::weight(NftsWeightInfoOf::::mint())] - pub fn mint( - origin: OriginFor, - to: AccountIdOf, - collection: CollectionIdOf, - item: ItemIdOf, - mint_price: Option>, - ) -> DispatchResult { - let account = ensure_signed(origin.clone())?; - let witness_data = MintWitness { mint_price, owned_item: Some(item) }; - NftsOf::::mint( - origin, - collection, - item, - T::Lookup::unlookup(to.clone()), - Some(witness_data), - )?; - Self::deposit_event(Event::Transfer { - collection, - item, - from: None, - to: Some(account), - price: mint_price, - }); - Ok(()) - } - - #[pallet::call_index(1)] - #[pallet::weight(NftsWeightInfoOf::::burn())] - pub fn burn( - origin: OriginFor, - collection: CollectionIdOf, - item: ItemIdOf, - ) -> DispatchResult { - let account = ensure_signed(origin.clone())?; - NftsOf::::burn(origin, collection, item)?; - Self::deposit_event(Event::Transfer { - collection, - item, - from: Some(account), - to: None, - price: None, - }); - Ok(()) - } - - #[pallet::call_index(2)] + #[pallet::call_index(3)] #[pallet::weight(NftsWeightInfoOf::::transfer())] pub fn transfer( origin: OriginFor, @@ -229,7 +179,7 @@ pub mod pallet { Ok(()) } - #[pallet::call_index(3)] + #[pallet::call_index(4)] #[pallet::weight(NftsWeightInfoOf::::approve_transfer() + NftsWeightInfoOf::::cancel_approval())] pub fn approve( origin: OriginFor, @@ -259,33 +209,25 @@ pub mod pallet { Ok(()) } - #[pallet::call_index(4)] + #[pallet::call_index(7)] #[pallet::weight(NftsWeightInfoOf::::create())] pub fn create( origin: OriginFor, admin: AccountIdOf, - config: CreateCollectionConfigFor, + config: CollectionConfigFor, ) -> DispatchResult { + // TODO: re-evaluate next collection id in nfts pallet. The `Incrementable` trait causes + // issues for setting it to xcm's `Location`. This can easily be done differently. let id = NextCollectionIdOf::::get() .or(T::CollectionId::initial_value()) .ok_or(pallet_nfts::Error::::UnknownCollection)?; let creator = ensure_signed(origin.clone())?; - let collection_config = CollectionConfig { - settings: CollectionSettings::all_enabled(), - max_supply: config.max_supply, - mint_settings: MintSettings { - mint_type: config.mint_type, - start_block: config.start_block, - end_block: config.end_block, - ..MintSettings::default() - }, - }; - NftsOf::::create(origin, T::Lookup::unlookup(admin.clone()), collection_config)?; + NftsOf::::create(origin, T::Lookup::unlookup(admin.clone()), config)?; Self::deposit_event(Event::Created { id, admin, creator }); Ok(()) } - #[pallet::call_index(5)] + #[pallet::call_index(8)] #[pallet::weight(NftsWeightInfoOf::::destroy( witness.item_metadatas, witness.item_configs, @@ -299,7 +241,7 @@ pub mod pallet { NftsOf::::destroy(origin, collection, witness) } - #[pallet::call_index(6)] + #[pallet::call_index(12)] #[pallet::weight(NftsWeightInfoOf::::set_attribute())] pub fn set_attribute( origin: OriginFor, @@ -312,7 +254,7 @@ pub mod pallet { NftsOf::::set_attribute(origin, collection, item, namespace, key, value) } - #[pallet::call_index(7)] + #[pallet::call_index(13)] #[pallet::weight(NftsWeightInfoOf::::clear_attribute())] pub fn clear_attribute( origin: OriginFor, @@ -324,7 +266,7 @@ pub mod pallet { NftsOf::::clear_attribute(origin, collection, item, namespace, key) } - #[pallet::call_index(8)] + #[pallet::call_index(14)] #[pallet::weight(NftsWeightInfoOf::::set_metadata())] pub fn set_metadata( origin: OriginFor, @@ -335,7 +277,7 @@ pub mod pallet { NftsOf::::set_metadata(origin, collection, item, data) } - #[pallet::call_index(9)] + #[pallet::call_index(15)] #[pallet::weight(NftsWeightInfoOf::::clear_metadata())] pub fn clear_metadata( origin: OriginFor, @@ -345,7 +287,7 @@ pub mod pallet { NftsOf::::clear_metadata(origin, collection, item) } - #[pallet::call_index(10)] + #[pallet::call_index(16)] #[pallet::weight(NftsWeightInfoOf::::approve_item_attributes())] pub fn approve_item_attributes( origin: OriginFor, @@ -361,7 +303,7 @@ pub mod pallet { ) } - #[pallet::call_index(11)] + #[pallet::call_index(17)] #[pallet::weight(NftsWeightInfoOf::::cancel_item_attributes_approval(witness.account_attributes))] pub fn cancel_item_attributes_approval( origin: OriginFor, @@ -379,7 +321,7 @@ pub mod pallet { ) } - #[pallet::call_index(12)] + #[pallet::call_index(18)] #[pallet::weight(NftsWeightInfoOf::::set_collection_max_supply())] pub fn set_max_supply( origin: OriginFor, @@ -388,6 +330,53 @@ pub mod pallet { ) -> DispatchResult { NftsOf::::set_collection_max_supply(origin, collection, max_supply) } + + #[pallet::call_index(19)] + #[pallet::weight(NftsWeightInfoOf::::mint())] + pub fn mint( + origin: OriginFor, + to: AccountIdOf, + collection: CollectionIdOf, + item: ItemIdOf, + witness: MintWitness, ItemPriceOf>, + ) -> DispatchResult { + let account = ensure_signed(origin.clone())?; + let mint_price = witness.mint_price; + NftsOf::::mint( + origin, + collection, + item, + T::Lookup::unlookup(to.clone()), + Some(witness), + )?; + Self::deposit_event(Event::Transfer { + collection, + item, + from: None, + to: Some(account), + price: mint_price, + }); + Ok(()) + } + + #[pallet::call_index(20)] + #[pallet::weight(NftsWeightInfoOf::::burn())] + pub fn burn( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + ) -> DispatchResult { + let account = ensure_signed(origin.clone())?; + NftsOf::::burn(origin, collection, item)?; + Self::deposit_event(Event::Transfer { + collection, + item, + from: Some(account), + to: None, + price: None, + }); + Ok(()) + } } impl crate::Read for Pallet { @@ -413,7 +402,7 @@ pub mod pallet { use Read::*; match value { TotalSupply(collection) => ReadResult::TotalSupply( - NftsOf::::collection_items(collection).unwrap_or_default(), + NftsOf::::collection_items(collection).unwrap_or_default() as u128, ), BalanceOf { collection, owner } => ReadResult::BalanceOf(pallet_nfts::AccountBalance::::get(collection, owner)), @@ -423,13 +412,14 @@ pub mod pallet { OwnerOf { collection, item } => ReadResult::OwnerOf(NftsOf::::owner(collection, item)), GetAttribute { collection, item, namespace, key } => ReadResult::GetAttribute( - pallet_nfts::Attribute::::get((collection, item, namespace, key)) - .map(|attribute| attribute.0), + pallet_nfts::Attribute::::get((collection, Some(item), namespace, key)) + .map(|attribute| attribute.0.into()), ), Collection(collection) => ReadResult::Collection(pallet_nfts::Collection::::get(collection)), - Item { collection, item } => - ReadResult::Item(pallet_nfts::Item::::get(collection, item)), + ItemMetadata { collection, item } => ReadResult::ItemMetadata( + NftsOf::::item_metadata(collection, item).map(|metadata| metadata.into()), + ), NextCollectionId => ReadResult::NextCollectionId( NextCollectionIdOf::::get().or(T::CollectionId::initial_value()), ), diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index e89ba0bd2..79d484a2f 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -2,10 +2,10 @@ use codec::Encode; use frame_support::{assert_noop, assert_ok, traits::Incrementable}; use frame_system::pallet_prelude::BlockNumberFor; use pallet_nfts::{ - AccountBalance, CollectionConfig, CollectionDetails, CollectionSettings, ItemDeposit, - ItemDetails, MintSettings, + AccountBalance, CollectionConfig, CollectionDetails, CollectionSettings, DestroyWitness, + MintSettings, MintWitness, }; -use sp_runtime::{BoundedBTreeMap, BoundedVec, DispatchError::BadOrigin}; +use sp_runtime::{BoundedVec, DispatchError::BadOrigin}; use super::types::{CollectionIdOf, ItemIdOf}; use crate::{ @@ -23,7 +23,7 @@ mod encoding_read_result { #[test] fn total_supply() { - let total_supply: u32 = 1_000_000; + let total_supply: u128 = 1_000_000; assert_eq!(ReadResult::TotalSupply::(total_supply).encode(), total_supply.encode()); } @@ -41,7 +41,7 @@ mod encoding_read_result { #[test] fn owner_of() { - let mut owner = Some(account(ALICE)); + let mut owner = Some(ALICE); assert_eq!(ReadResult::OwnerOf::(owner.clone()).encode(), owner.encode()); owner = None; assert_eq!(ReadResult::OwnerOf::(owner.clone()).encode(), owner.encode()); @@ -49,7 +49,7 @@ mod encoding_read_result { #[test] fn get_attribute() { - let mut attribute = Some(BoundedVec::truncate_from("some attribute".as_bytes().to_vec())); + let mut attribute = Some("some attribute".as_bytes().to_vec()); assert_eq!( ReadResult::GetAttribute::(attribute.clone()).encode(), attribute.encode() @@ -64,7 +64,7 @@ mod encoding_read_result { #[test] fn collection() { let mut collection_details = Some(CollectionDetails { - owner: account(ALICE), + owner: ALICE, owner_deposit: 0, items: 0, item_metadatas: 0, @@ -82,18 +82,6 @@ mod encoding_read_result { ); } - #[test] - fn item() { - let mut item_details = Some(ItemDetails { - owner: account(ALICE), - approvals: BoundedBTreeMap::default(), - deposit: ItemDeposit { amount: 0, account: account(BOB) }, - }); - assert_eq!(ReadResult::Item::(item_details.clone()).encode(), item_details.encode()); - item_details = None; - assert_eq!(ReadResult::Item::(item_details.clone()).encode(), item_details.encode()); - } - #[test] fn next_collection_id_works() { let mut next_collection_id = Some(0); @@ -107,6 +95,14 @@ mod encoding_read_result { next_collection_id.encode() ); } + + #[test] + fn item_metadata_works() { + let mut data = Some("some metadata".as_bytes().to_vec()); + assert_eq!(ReadResult::ItemMetadata::(data.clone()).encode(), data.encode()); + data = None; + assert_eq!(ReadResult::ItemMetadata::(data.clone()).encode(), data.encode()); + } } #[test] @@ -117,26 +113,17 @@ fn transfer() { let (collection, item) = nfts::create_collection_mint(owner, ITEM); for origin in vec![root(), none()] { - assert_noop!( - NonFungibles::transfer(origin, collection, item, account(dest)), - BadOrigin - ); + assert_noop!(NonFungibles::transfer(origin, collection, item, dest), BadOrigin); } // Successfully burn an existing new collection item. - let balance_before_transfer = AccountBalance::::get(collection, &account(dest)); - assert_ok!(NonFungibles::transfer(signed(owner), collection, ITEM, account(dest))); - let balance_after_transfer = AccountBalance::::get(collection, &account(dest)); - assert_eq!(AccountBalance::::get(collection, &account(owner)), 0); + let balance_before_transfer = AccountBalance::::get(collection, &dest); + assert_ok!(NonFungibles::transfer(signed(owner), collection, ITEM, dest)); + let balance_after_transfer = AccountBalance::::get(collection, &dest); + assert_eq!(AccountBalance::::get(collection, &owner), 0); assert_eq!(balance_after_transfer - balance_before_transfer, 1); System::assert_last_event( - Event::Transfer { - collection, - item, - from: Some(account(owner)), - to: Some(account(dest)), - price: None, - } - .into(), + Event::Transfer { collection, item, from: Some(owner), to: Some(dest), price: None } + .into(), ); }); } @@ -148,20 +135,20 @@ fn mint_works() { let collection = nfts::create_collection(owner); // Successfully mint a new collection item. - let balance_before_mint = AccountBalance::::get(collection, account(owner)); - assert_ok!(NonFungibles::mint(signed(owner), account(owner), collection, ITEM, None)); - let balance_after_mint = AccountBalance::::get(collection, account(owner)); + let balance_before_mint = AccountBalance::::get(collection, owner); + assert_ok!(NonFungibles::mint( + signed(owner), + owner, + collection, + ITEM, + MintWitness { mint_price: None, owned_item: None } + )); + let balance_after_mint = AccountBalance::::get(collection, owner); assert_eq!(balance_after_mint, 1); assert_eq!(balance_after_mint - balance_before_mint, 1); System::assert_last_event( - Event::Transfer { - collection, - item: ITEM, - from: None, - to: Some(account(owner)), - price: None, - } - .into(), + Event::Transfer { collection, item: ITEM, from: None, to: Some(owner), price: None } + .into(), ); }); } @@ -175,8 +162,7 @@ fn burn_works() { let (collection, item) = nfts::create_collection_mint(owner, ITEM); assert_ok!(NonFungibles::burn(signed(owner), collection, ITEM)); System::assert_last_event( - Event::Transfer { collection, item, from: Some(account(owner)), to: None, price: None } - .into(), + Event::Transfer { collection, item, from: Some(owner), to: None, price: None }.into(), ); }); } @@ -188,25 +174,13 @@ fn approve_works() { let operator = BOB; let (collection, item) = nfts::create_collection_mint(owner, ITEM); // Successfully approve `oeprator` to transfer the collection item. - assert_ok!(NonFungibles::approve( - signed(owner), - collection, - Some(item), - account(operator), - true - )); + assert_ok!(NonFungibles::approve(signed(owner), collection, Some(item), operator, true)); System::assert_last_event( - Event::Approval { - collection, - item: Some(item), - owner: account(owner), - operator: account(operator), - approved: true, - } - .into(), + Event::Approval { collection, item: Some(item), owner, operator, approved: true } + .into(), ); // Successfully transfer the item by the delegated account `operator`. - assert_ok!(Nfts::transfer(signed(operator), collection, item, account(operator))); + assert_ok!(Nfts::transfer(signed(operator), collection, item, operator)); }); } @@ -217,16 +191,10 @@ fn cancel_approval_works() { let operator = BOB; let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); // Successfully cancel the transfer approval of `operator` by `owner`. - assert_ok!(NonFungibles::approve( - signed(owner), - collection, - Some(item), - account(operator), - false - )); + assert_ok!(NonFungibles::approve(signed(owner), collection, Some(item), operator, false)); // Failed to transfer the item by `operator` without permission. assert_noop!( - Nfts::transfer(signed(operator), collection, item, account(operator)), + Nfts::transfer(signed(operator), collection, item, operator), NftsError::NoPermission ); }); @@ -239,10 +207,10 @@ fn set_max_supply_works() { let collection = nfts::create_collection(owner); assert_ok!(NonFungibles::set_max_supply(signed(owner), collection, 10)); (0..10).into_iter().for_each(|i| { - assert_ok!(Nfts::mint(signed(owner), collection, i, account(owner), None)); + assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); }); assert_noop!( - Nfts::mint(signed(owner), collection, 42, account(owner), None), + Nfts::mint(signed(owner), collection, 42, owner, None), NftsError::MaxSupplyReached ); }); @@ -263,15 +231,14 @@ fn owner_of_works() { fn get_attribute_works() { new_test_ext().execute_with(|| { let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); - assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); - let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); let mut result: Option::ValueLimit>> = None; // No attribute set. assert_eq!( NonFungibles::read(GetAttribute { collection, - item: Some(item), + item, namespace: pallet_nfts::AttributeNamespace::CollectionOwner, key: attribute.clone() }) @@ -291,7 +258,7 @@ fn get_attribute_works() { assert_eq!( NonFungibles::read(GetAttribute { collection, - item: Some(item), + item, namespace: pallet_nfts::AttributeNamespace::CollectionOwner, key: attribute }) @@ -301,13 +268,44 @@ fn get_attribute_works() { }); } +#[test] +fn set_metadata_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + let value = BoundedVec::truncate_from("some metadata".as_bytes().to_vec()); + assert_ok!(NonFungibles::set_metadata(signed(ALICE), collection, item, value.clone())); + assert_eq!( + NonFungibles::read(ItemMetadata { collection, item }).encode(), + Some(value).encode() + ); + }); +} + +#[test] +fn clear_metadata_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_ok!(NonFungibles::set_metadata( + signed(ALICE), + collection, + item, + BoundedVec::truncate_from("some metadata".as_bytes().to_vec()) + )); + assert_ok!(NonFungibles::clear_metadata(signed(ALICE), collection, item)); + assert_eq!( + NonFungibles::read(ItemMetadata { collection, item }).encode(), + ReadResult::::ItemMetadata(None).encode() + ); + }); +} + #[test] fn clear_attribute_works() { new_test_ext().execute_with(|| { let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); - let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); - let mut result: Option::ValueLimit>> = None; + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let result: Option::ValueLimit>> = None; assert_ok!(Nfts::set_attribute( signed(ALICE), collection, @@ -327,7 +325,7 @@ fn clear_attribute_works() { assert_eq!( NonFungibles::read(GetAttribute { collection, - item: Some(item), + item, namespace: pallet_nfts::AttributeNamespace::CollectionOwner, key: attribute }) @@ -342,25 +340,24 @@ fn approve_item_attribute_works() { new_test_ext().execute_with(|| { let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); - let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); - let mut result: Option::ValueLimit>> = None; // Successfully approve delegate to set attributes. - assert_ok!(Nfts::approve_item_attributes(signed(ALICE), collection, item, account(BOB))); + assert_ok!(Nfts::approve_item_attributes(signed(ALICE), collection, item, BOB)); assert_ok!(Nfts::set_attribute( signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(account(BOB)), + pallet_nfts::AttributeNamespace::Account(BOB), attribute.clone(), value.clone() )); - result = Some(value); + let result: Option::ValueLimit>> = Some(value); assert_eq!( NonFungibles::read(GetAttribute { collection, - item: Some(item), - namespace: pallet_nfts::AttributeNamespace::Account(account(BOB)), + item, + namespace: pallet_nfts::AttributeNamespace::Account(BOB), key: attribute }) .encode(), @@ -374,16 +371,15 @@ fn cancel_item_attribute_approval_works() { new_test_ext().execute_with(|| { let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); - let mut attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); - let mut result: Option::ValueLimit>> = None; // Successfully approve delegate to set attributes. - assert_ok!(Nfts::approve_item_attributes(signed(ALICE), collection, item, account(BOB))); + assert_ok!(Nfts::approve_item_attributes(signed(ALICE), collection, item, BOB)); assert_ok!(Nfts::set_attribute( signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(account(BOB)), + pallet_nfts::AttributeNamespace::Account(BOB), attribute.clone(), value.clone() )); @@ -391,7 +387,7 @@ fn cancel_item_attribute_approval_works() { signed(ALICE), collection, item, - account(BOB), + BOB, pallet_nfts::CancelAttributesApprovalWitness { account_attributes: 1 } )); assert_noop!( @@ -399,7 +395,7 @@ fn cancel_item_attribute_approval_works() { signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(account(BOB)), + pallet_nfts::AttributeNamespace::Account(BOB), attribute.clone(), value.clone() ), @@ -428,34 +424,57 @@ fn total_supply_works() { let owner = ALICE; let collection = nfts::create_collection(owner); (0..10).into_iter().for_each(|i| { - assert_ok!(Nfts::mint(signed(owner), collection, i, account(owner), None)); - assert_eq!(NonFungibles::read(TotalSupply(collection)).encode(), (i + 1).encode()); + assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); + assert_eq!( + NonFungibles::read(TotalSupply(collection)).encode(), + ((i + 1) as u128).encode() + ); assert_eq!( NonFungibles::read(TotalSupply(collection)).encode(), - Nfts::collection_items(collection).unwrap_or_default().encode() + (Nfts::collection_items(collection).unwrap_or_default() as u128).encode() ); }); }); } #[test] -fn collection_works() { +fn create_works() { new_test_ext().execute_with(|| { - let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); - assert_eq!( - NonFungibles::read(Collection(collection)).encode(), - pallet_nfts::Collection::::get(&collection).encode(), - ); + let owner = ALICE; + let next_collection_id = pallet_nfts::NextCollectionId::::get().unwrap_or_default(); + assert_ok!(NonFungibles::create( + signed(owner), + owner, + CollectionConfig { + max_supply: None, + mint_settings: MintSettings::default(), + settings: CollectionSettings::all_enabled() + }, + )); + assert_eq!(Nfts::collection_owner(next_collection_id), Some(owner)); }); } #[test] -fn item_works() { +fn destroy_works() { new_test_ext().execute_with(|| { - let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + let collection = nfts::create_collection(ALICE); + assert_ok!(NonFungibles::destroy( + signed(ALICE), + collection, + DestroyWitness { item_metadatas: 0, item_configs: 0, attributes: 0 } + )); + assert_eq!(Nfts::collection_owner(collection), None); + }); +} + +#[test] +fn collection_works() { + new_test_ext().execute_with(|| { + let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!( - NonFungibles::read(Item { collection, item }).encode(), - pallet_nfts::Item::::get(&collection, &item).encode(), + NonFungibles::read(Collection(collection)).encode(), + pallet_nfts::Collection::::get(&collection).encode(), ); }); } @@ -466,14 +485,14 @@ fn balance_of_works() { let owner = ALICE; let collection = nfts::create_collection(owner); (0..10).into_iter().for_each(|i| { - assert_ok!(Nfts::mint(signed(owner), collection, i, account(owner), None)); + assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); assert_eq!( - NonFungibles::read(BalanceOf { collection, owner: account(owner) }).encode(), + NonFungibles::read(BalanceOf { collection, owner }).encode(), (i + 1).encode() ); assert_eq!( - NonFungibles::read(BalanceOf { collection, owner: account(owner) }).encode(), - AccountBalance::::get(collection, account(owner)).encode() + NonFungibles::read(BalanceOf { collection, owner }).encode(), + AccountBalance::::get(collection, owner).encode() ); }); }); @@ -486,32 +505,22 @@ fn allowance_works() { let operator = BOB; let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); assert_eq!( - NonFungibles::read(Allowance { - collection, - item: Some(item), - owner: account(owner), - operator: account(operator), - }) - .encode(), + NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }) + .encode(), true.encode() ); assert_eq!( - NonFungibles::read(Allowance { - collection, - item: Some(item), - owner: account(owner), - operator: account(operator), - }) - .encode(), - Nfts::check_allowance(&collection, &Some(item), &account(owner), &account(operator)) + NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }) + .encode(), + Nfts::check_allowance(&collection, &Some(item), &owner, &operator) .is_ok() .encode() ); }); } -fn signed(account_id: u8) -> RuntimeOrigin { - RuntimeOrigin::signed(account(account_id)) +fn signed(account_id: AccountId) -> RuntimeOrigin { + RuntimeOrigin::signed(account_id) } fn root() -> RuntimeOrigin { @@ -526,32 +535,26 @@ mod nfts { use super::*; pub(super) fn create_collection_mint_and_approve( - owner: u8, + owner: AccountId, item: ItemIdOf, - operator: u8, + operator: AccountId, ) -> (u32, u32) { let (collection, item) = create_collection_mint(owner, item); - assert_ok!(Nfts::approve_transfer( - signed(owner), - collection, - Some(item), - account(operator), - None - )); + assert_ok!(Nfts::approve_transfer(signed(owner), collection, Some(item), operator, None)); (collection, item) } - pub(super) fn create_collection_mint(owner: u8, item: ItemIdOf) -> (u32, u32) { + pub(super) fn create_collection_mint(owner: AccountId, item: ItemIdOf) -> (u32, u32) { let collection = create_collection(owner); - assert_ok!(Nfts::mint(signed(owner), collection, item, account(owner), None)); + assert_ok!(Nfts::mint(signed(owner), collection, item, owner, None)); (collection, item) } - pub(super) fn create_collection(owner: u8) -> u32 { + pub(super) fn create_collection(owner: AccountId) -> u32 { let next_id = next_collection_id(); assert_ok!(Nfts::create( signed(owner), - account(owner), + owner, collection_config_with_all_settings_enabled() )); next_id diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs index f57ee6976..6e686389d 100644 --- a/pallets/api/src/nonfungibles/types.rs +++ b/pallets/api/src/nonfungibles/types.rs @@ -1,13 +1,12 @@ -use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; use frame_system::pallet_prelude::BlockNumberFor; -use pallet_nfts::{AttributeNamespace, CollectionDetails, ItemDeposit, ItemDetails, MintType}; -use scale_info::TypeInfo; -use sp_runtime::{BoundedBTreeMap, RuntimeDebug}; +pub use pallet_nfts::{ + AttributeNamespace, CollectionConfig, CollectionDetails, CollectionSetting, CollectionSettings, + DestroyWitness, ItemDeposit, ItemDetails, ItemSetting, MintSettings, MintType, MintWitness, +}; // Type aliases for pallet-nfts. pub(super) type NftsOf = pallet_nfts::Pallet; -pub(super) type NftsErrorOf = pallet_nfts::Error; pub(super) type NftsWeightInfoOf = ::WeightInfo; // Type aliases for pallet-nfts storage items. pub(super) type AccountIdOf = ::AccountId; @@ -19,27 +18,10 @@ pub(super) type CollectionIdOf = as Inspect<::AccountId>>::CollectionId; pub(super) type ItemIdOf = as Inspect<::AccountId>>::ItemId; -pub(super) type ApprovalsOf = BoundedBTreeMap< - AccountIdOf, - Option>, - ::ApprovalsLimit, ->; pub(super) type ItemPriceOf = BalanceOf; // TODO: Multi-instances. -pub(super) type ItemDepositOf = ItemDeposit, AccountIdOf>; pub(super) type CollectionDetailsFor = CollectionDetails, BalanceOf>; -pub(super) type ItemDetailsFor = - ItemDetails, ItemDepositOf, ApprovalsOf>; pub(super) type AttributeNamespaceOf = AttributeNamespace>; -pub(super) type CreateCollectionConfigFor = - CreateCollectionConfig, BlockNumberFor, CollectionIdOf>; - -#[derive(Clone, Copy, Decode, Encode, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] -pub struct CreateCollectionConfig { - pub max_supply: Option, - pub mint_type: MintType, - pub price: Option, - pub start_block: Option, - pub end_block: Option, -} +pub(super) type CollectionConfigFor = + CollectionConfig, BlockNumberFor, CollectionIdOf>; diff --git a/pallets/nfts/src/benchmarking.rs b/pallets/nfts/src/benchmarking.rs index 8fa87557c..ab66da26d 100644 --- a/pallets/nfts/src/benchmarking.rs +++ b/pallets/nfts/src/benchmarking.rs @@ -578,9 +578,9 @@ benchmarks_instance_pallet! { let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let deadline = BlockNumberFor::::max_value(); - }: _(SystemOrigin::Signed(caller.clone()), collection, item, delegate_lookup, Some(deadline)) + }: _(SystemOrigin::Signed(caller.clone()), collection, Some(item), delegate_lookup, Some(deadline)) verify { - assert_last_event::(Event::TransferApproved { collection, item, owner: caller, delegate, deadline: Some(deadline) }.into()); + assert_last_event::(Event::TransferApproved { collection, item: Some(item), owner: caller, delegate, deadline: Some(deadline) }.into()); } cancel_approval { @@ -590,10 +590,10 @@ benchmarks_instance_pallet! { let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let origin = SystemOrigin::Signed(caller.clone()).into(); let deadline = BlockNumberFor::::max_value(); - Nfts::::approve_transfer(origin, collection, item, delegate_lookup.clone(), Some(deadline))?; - }: _(SystemOrigin::Signed(caller.clone()), collection, item, delegate_lookup) + Nfts::::approve_transfer(origin, collection, Some(item), delegate_lookup.clone(), Some(deadline))?; + }: _(SystemOrigin::Signed(caller.clone()), collection, Some(item), delegate_lookup) verify { - assert_last_event::(Event::ApprovalCancelled { collection, item, owner: caller, delegate }.into()); + assert_last_event::(Event::ApprovalCancelled { collection, item: Some(item), owner: caller, delegate }.into()); } clear_all_transfer_approvals { @@ -603,7 +603,7 @@ benchmarks_instance_pallet! { let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let origin = SystemOrigin::Signed(caller.clone()).into(); let deadline = BlockNumberFor::::max_value(); - Nfts::::approve_transfer(origin, collection, item, delegate_lookup.clone(), Some(deadline))?; + Nfts::::approve_transfer(origin, collection, Some(item), delegate_lookup.clone(), Some(deadline))?; }: _(SystemOrigin::Signed(caller.clone()), collection, item) verify { assert_last_event::(Event::AllApprovalsCancelled {collection, item, owner: caller}.into()); diff --git a/pallets/nfts/src/common_functions.rs b/pallets/nfts/src/common_functions.rs index 6fe483f1a..89de1f051 100644 --- a/pallets/nfts/src/common_functions.rs +++ b/pallets/nfts/src/common_functions.rs @@ -39,6 +39,14 @@ impl, I: 'static> Pallet { Collection::::get(collection).map(|i| i.items) } + /// Get the metadata of the collection item. + pub fn item_metadata( + collection: T::CollectionId, + item: T::ItemId, + ) -> Option> { + ItemMetadataOf::::get(collection, item).map(|metadata| metadata.data) + } + /// Validates the signature of the given data with the provided signer's account ID. /// /// # Errors diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index 6d71c1a22..e1e79ef4a 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -180,24 +180,26 @@ impl, I: 'static> Pallet { Self::is_pallet_feature_enabled(PalletFeature::Approvals), Error::::MethodDisabled ); - if !Collection::::contains_key(collection) { - return Err(Error::::UnknownCollection.into()); - } + let owner = Self::collection_owner(collection).ok_or(Error::::UnknownCollection)?; + let collection_config = Self::get_collection_config(&collection)?; ensure!( collection_config.is_setting_enabled(CollectionSetting::TransferableItems), Error::::ItemsNonTransferable ); - let origin = maybe_check_origin.ok_or(Error::::WrongOrigin)?; - Allowances::::mutate((&collection, &origin, &delegate), |allowance| { + if let Some(check_origin) = maybe_check_origin { + ensure!(check_origin == owner, Error::::NoPermission); + } + + Allowances::::mutate((&collection, &owner, &delegate), |allowance| { *allowance = true; }); Self::deposit_event(Event::TransferApproved { collection, item: None, - owner: origin, + owner, delegate, deadline: None, }); @@ -209,19 +211,14 @@ impl, I: 'static> Pallet { collection: T::CollectionId, delegate: T::AccountId, ) -> DispatchResult { - if !Collection::::contains_key(collection) { - return Err(Error::::UnknownCollection.into()); - } + let owner = Self::collection_owner(collection).ok_or(Error::::UnknownCollection)?; - let origin = maybe_check_origin.ok_or(Error::::WrongOrigin)?; - Allowances::::remove((&collection, &origin, &delegate)); + if let Some(check_origin) = maybe_check_origin { + ensure!(check_origin == owner, Error::::NoPermission); + } + Allowances::::remove((&collection, &owner, &delegate)); - Self::deposit_event(Event::ApprovalCancelled { - collection, - owner: origin, - item: None, - delegate, - }); + Self::deposit_event(Event::ApprovalCancelled { collection, owner, item: None, delegate }); Ok(()) } diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 397a715c2..4d0f08c93 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -318,7 +318,7 @@ fn destroy_should_work() { assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(2), None)); assert_eq!(AccountBalance::::get(0, account(2)), 1); assert_ok!(Nfts::approve_transfer( - RuntimeOrigin::signed(account(2)), + RuntimeOrigin::signed(account(1)), 0, None, account(3), @@ -2017,22 +2017,22 @@ fn cancel_approval_collection_works_with_admin() { )); assert_ok!(Nfts::approve_transfer( - RuntimeOrigin::signed(account(2)), + RuntimeOrigin::signed(account(1)), 0, None, account(3), None )); assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 1, None, account(3)), + Nfts::cancel_approval(RuntimeOrigin::signed(account(1)), 1, None, account(3)), Error::::UnknownCollection ); - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, None, account(3))); + assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(1)), 0, None, account(3))); assert!(events().contains(&Event::::ApprovalCancelled { collection: 0, item: None, - owner: account(2), + owner: account(1), delegate: account(3) })); assert_eq!(Allowances::::get((0, account(2), account(3))), false); @@ -2156,7 +2156,7 @@ fn approval_collection_works_with_admin() { RuntimeOrigin::signed(account(1)), 0, 42, - account(2), + account(1), default_item_config() )); @@ -2178,7 +2178,7 @@ fn approval_collection_works_with_admin() { ); assert_ok!(Nfts::approve_transfer( - RuntimeOrigin::signed(account(2)), + RuntimeOrigin::signed(account(1)), 0, None, account(3), @@ -2187,11 +2187,11 @@ fn approval_collection_works_with_admin() { assert!(events().contains(&Event::::TransferApproved { collection: 0, item: None, - owner: account(2), + owner: account(1), delegate: account(3), deadline: None })); - assert_eq!(Allowances::::get((0, account(2), account(3))), true); + assert_eq!(Allowances::::get((0, account(1), account(3))), true); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4))); }); } diff --git a/pallets/nfts/src/types.rs b/pallets/nfts/src/types.rs index 061352c09..941da6cad 100644 --- a/pallets/nfts/src/types.rs +++ b/pallets/nfts/src/types.rs @@ -145,21 +145,21 @@ pub struct MintWitness { #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo, MaxEncodedLen)] pub struct ItemDetails { /// The owner of this item. - pub owner: AccountId, + pub(super) owner: AccountId, /// The approved transferrer of this item, if one is set. - pub approvals: Approvals, + pub(super) approvals: Approvals, /// The amount held in the pallet's default account for this item. Free-hold items will have /// this as zero. - pub deposit: Deposit, + pub(super) deposit: Deposit, } /// Information about the reserved item deposit. #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct ItemDeposit { /// A depositor account. - pub account: AccountId, + pub(super) account: AccountId, /// An amount that gets reserved. - pub amount: DepositBalance, + pub(super) amount: DepositBalance, } /// Information about the collection's metadata. diff --git a/pallets/nfts/src/weights.rs b/pallets/nfts/src/weights.rs index c5fb60a22..c374d6dbc 100644 --- a/pallets/nfts/src/weights.rs +++ b/pallets/nfts/src/weights.rs @@ -1,30 +1,14 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. //! Autogenerated weights for `pallet_nfts` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-04-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 40.0.0 +//! DATE: 2024-10-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `R0GUE`, CPU: `` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// ./target/release/pop-node // benchmark // pallet // --chain=dev @@ -34,12 +18,11 @@ // --no-storage-info // --no-median-slopes // --no-min-squares -// --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/nfts/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./pallets/nfts/src/weights.rs +// --template=./scripts/pallet-weights-template.hbs +// --extrinsic= #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -107,10 +90,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: - // Measured: `216` + // Measured: `105` // Estimated: `3549` - // Minimum execution time: 34_863_000 picoseconds. - Weight::from_parts(36_679_000, 3549) + // Minimum execution time: 27_000_000 picoseconds. + Weight::from_parts(27_000_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -126,10 +109,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_create() -> Weight { // Proof Size summary in bytes: - // Measured: `76` + // Measured: `3` // Estimated: `3549` - // Minimum execution time: 19_631_000 picoseconds. - Weight::from_parts(20_384_000, 3549) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(15_000_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -141,6 +124,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1001 w:1000) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) @@ -152,15 +137,19 @@ impl WeightInfo for SubstrateWeight { /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. - fn destroy(_m: u32, _c: u32, a: u32, ) -> Weight { + fn destroy(m: u32, c: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32204 + a * (366 ±0)` + // Measured: `32216 + a * (366 ±0)` // Estimated: `2523990 + a * (2954 ±0)` - // Minimum execution time: 1_282_083_000 picoseconds. - Weight::from_parts(1_249_191_963, 2523990) - // Standard Error: 4_719 - .saturating_add(Weight::from_parts(6_470_227, 0).saturating_mul(a.into())) - .saturating_add(T::DbWeight::get().reads(1004_u64)) + // Minimum execution time: 982_000_000 picoseconds. + Weight::from_parts(937_587_516, 2523990) + // Standard Error: 12_288 + .saturating_add(Weight::from_parts(34_348, 0).saturating_mul(m.into())) + // Standard Error: 12_288 + .saturating_add(Weight::from_parts(23_800, 0).saturating_mul(c.into())) + // Standard Error: 12_288 + .saturating_add(Weight::from_parts(5_095_505, 0).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(1005_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(1005_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) @@ -174,18 +163,20 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: - // Measured: `455` + // Measured: `382` // Estimated: `4326` - // Minimum execution time: 49_055_000 picoseconds. - Weight::from_parts(50_592_000, 4326) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + // Minimum execution time: 41_000_000 picoseconds. + Weight::from_parts(42_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -195,18 +186,20 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn force_mint() -> Weight { // Proof Size summary in bytes: - // Measured: `455` + // Measured: `382` // Estimated: `4326` - // Minimum execution time: 47_102_000 picoseconds. - Weight::from_parts(48_772_000, 4326) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + // Minimum execution time: 39_000_000 picoseconds. + Weight::from_parts(40_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) @@ -218,22 +211,24 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:0 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: - // Measured: `564` + // Measured: `576` // Estimated: `4326` - // Minimum execution time: 52_968_000 picoseconds. - Weight::from_parts(55_136_000, 4326) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + // Minimum execution time: 46_000_000 picoseconds. + Weight::from_parts(59_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) @@ -245,6 +240,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:2) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) @@ -253,12 +250,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `593` - // Estimated: `4326` - // Minimum execution time: 41_140_000 picoseconds. - Weight::from_parts(43_288_000, 4326) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + // Measured: `605` + // Estimated: `6068` + // Minimum execution time: 38_000_000 picoseconds. + Weight::from_parts(83_000_000, 6068) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) @@ -269,12 +266,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `763 + i * (108 ±0)` + // Measured: `690 + i * (108 ±0)` // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 14_433_000 picoseconds. - Weight::from_parts(14_664_000, 3549) - // Standard Error: 23_078 - .saturating_add(Weight::from_parts(15_911_377, 0).saturating_mul(i.into())) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3549) + // Standard Error: 20_022 + .saturating_add(Weight::from_parts(16_005_327, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -286,10 +283,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 18_307_000 picoseconds. - Weight::from_parts(18_966_000, 3534) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(14_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -299,10 +296,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn unlock_item_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 18_078_000 picoseconds. - Weight::from_parts(18_593_000, 3534) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(14_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -312,10 +309,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn lock_collection() -> Weight { // Proof Size summary in bytes: - // Measured: `340` + // Measured: `267` // Estimated: `3549` - // Minimum execution time: 15_175_000 picoseconds. - Weight::from_parts(15_762_000, 3549) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -329,10 +326,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `562` + // Measured: `417` // Estimated: `3593` - // Minimum execution time: 26_164_000 picoseconds. - Weight::from_parts(27_117_000, 3593) + // Minimum execution time: 18_000_000 picoseconds. + Weight::from_parts(19_000_000, 3593) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -342,10 +339,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: - // Measured: `369` + // Measured: `296` // Estimated: `6078` - // Minimum execution time: 38_523_000 picoseconds. - Weight::from_parts(39_486_000, 6078) + // Minimum execution time: 30_000_000 picoseconds. + Weight::from_parts(31_000_000, 6078) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -355,10 +352,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: - // Measured: `311` + // Measured: `238` // Estimated: `3549` - // Minimum execution time: 15_733_000 picoseconds. - Weight::from_parts(16_227_000, 3549) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 3549) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -368,10 +365,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn force_collection_config() -> Weight { // Proof Size summary in bytes: - // Measured: `276` + // Measured: `203` // Estimated: `3549` - // Minimum execution time: 12_042_000 picoseconds. - Weight::from_parts(12_690_000, 3549) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(9_000_000, 3549) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -381,10 +378,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_properties() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 17_165_000 picoseconds. - Weight::from_parts(17_769_000, 3534) + // Minimum execution time: 12_000_000 picoseconds. + Weight::from_parts(13_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -400,10 +397,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `499` // Estimated: `3944` - // Minimum execution time: 48_862_000 picoseconds. - Weight::from_parts(50_584_000, 3944) + // Minimum execution time: 37_000_000 picoseconds. + Weight::from_parts(38_000_000, 3944) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -413,10 +410,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `344` + // Measured: `271` // Estimated: `3944` - // Minimum execution time: 24_665_000 picoseconds. - Weight::from_parts(25_465_000, 3944) + // Minimum execution time: 19_000_000 picoseconds. + Weight::from_parts(19_000_000, 3944) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -430,30 +427,30 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `983` + // Measured: `943` // Estimated: `3944` - // Minimum execution time: 44_617_000 picoseconds. - Weight::from_parts(46_458_000, 3944) + // Minimum execution time: 35_000_000 picoseconds. + Weight::from_parts(36_000_000, 3944) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) fn approve_item_attributes() -> Weight { // Proof Size summary in bytes: - // Measured: `381` - // Estimated: `4326` - // Minimum execution time: 15_710_000 picoseconds. - Weight::from_parts(16_191_000, 4326) + // Measured: `308` + // Estimated: `4466` + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4466) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1001 w:1000) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -461,12 +458,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1000]`. fn cancel_item_attributes_approval(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `831 + n * (398 ±0)` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 24_447_000 picoseconds. - Weight::from_parts(25_144_000, 4326) - // Standard Error: 4_872 - .saturating_add(Weight::from_parts(6_523_101, 0).saturating_mul(n.into())) + // Measured: `686 + n * (398 ±0)` + // Estimated: `4466 + n * (2954 ±0)` + // Minimum execution time: 18_000_000 picoseconds. + Weight::from_parts(19_000_000, 4466) + // Standard Error: 6_379 + .saturating_add(Weight::from_parts(5_018_740, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -485,10 +482,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `499` // Estimated: `3812` - // Minimum execution time: 39_990_000 picoseconds. - Weight::from_parts(41_098_000, 3812) + // Minimum execution time: 30_000_000 picoseconds. + Weight::from_parts(31_000_000, 3812) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -502,10 +499,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `849` + // Measured: `809` // Estimated: `3812` - // Minimum execution time: 38_030_000 picoseconds. - Weight::from_parts(39_842_000, 3812) + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(29_000_000, 3812) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -519,10 +516,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `398` + // Measured: `325` // Estimated: `3759` - // Minimum execution time: 36_778_000 picoseconds. - Weight::from_parts(38_088_000, 3759) + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(30_000_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -536,10 +533,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `716` + // Measured: `643` // Estimated: `3759` - // Minimum execution time: 36_887_000 picoseconds. - Weight::from_parts(38_406_000, 3759) + // Minimum execution time: 27_000_000 picoseconds. + Weight::from_parts(29_000_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -549,10 +546,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn approve_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `410` + // Measured: `337` // Estimated: `4326` - // Minimum execution time: 18_734_000 picoseconds. - Weight::from_parts(19_267_000, 4326) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(14_000_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -560,10 +557,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn cancel_approval() -> Weight { // Proof Size summary in bytes: - // Measured: `418` + // Measured: `345` // Estimated: `4326` - // Minimum execution time: 16_080_000 picoseconds. - Weight::from_parts(16_603_000, 4326) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4326) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -571,10 +568,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn clear_all_transfer_approvals() -> Weight { // Proof Size summary in bytes: - // Measured: `418` + // Measured: `345` // Estimated: `4326` - // Minimum execution time: 15_013_000 picoseconds. - Weight::from_parts(15_607_000, 4326) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 4326) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -582,10 +579,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn set_accept_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `76` + // Measured: `3` // Estimated: `3517` - // Minimum execution time: 13_077_000 picoseconds. - Weight::from_parts(13_635_000, 3517) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 3517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -595,10 +592,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: - // Measured: `340` + // Measured: `267` // Estimated: `3549` - // Minimum execution time: 17_146_000 picoseconds. - Weight::from_parts(17_453_000, 3549) + // Minimum execution time: 12_000_000 picoseconds. + Weight::from_parts(13_000_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -608,10 +605,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn update_mint_settings() -> Weight { // Proof Size summary in bytes: - // Measured: `323` + // Measured: `250` // Estimated: `3538` - // Minimum execution time: 16_102_000 picoseconds. - Weight::from_parts(16_629_000, 3538) + // Minimum execution time: 12_000_000 picoseconds. + Weight::from_parts(13_000_000, 3538) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -625,10 +622,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn set_price() -> Weight { // Proof Size summary in bytes: - // Measured: `518` + // Measured: `478` // Estimated: `4326` - // Minimum execution time: 22_118_000 picoseconds. - Weight::from_parts(22_849_000, 4326) + // Minimum execution time: 16_000_000 picoseconds. + Weight::from_parts(17_000_000, 4326) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -644,28 +641,30 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:2) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn buy_item() -> Weight { // Proof Size summary in bytes: - // Measured: `705` - // Estimated: `4326` - // Minimum execution time: 50_369_000 picoseconds. - Weight::from_parts(51_816_000, 4326) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + // Measured: `717` + // Estimated: `6068` + // Minimum execution time: 42_000_000 picoseconds. + Weight::from_parts(45_000_000, 6068) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) } /// The range of component `n` is `[0, 10]`. fn pay_tips(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_203_000 picoseconds. - Weight::from_parts(3_710_869, 0) - // Standard Error: 8_094 - .saturating_add(Weight::from_parts(2_201_869, 0).saturating_mul(n.into())) + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(390_532, 0) + // Standard Error: 84_277 + .saturating_add(Weight::from_parts(3_087_492, 0).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:2 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -673,10 +672,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn create_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `494` + // Measured: `421` // Estimated: `7662` - // Minimum execution time: 18_893_000 picoseconds. - Weight::from_parts(19_506_000, 7662) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(15_000_000, 7662) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -686,10 +685,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn cancel_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `513` + // Measured: `440` // Estimated: `4326` - // Minimum execution time: 19_086_000 picoseconds. - Weight::from_parts(19_609_000, 4326) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(14_000_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -705,18 +704,20 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:2 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:4) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:2) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn claim_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `834` + // Measured: `907` // Estimated: `7662` - // Minimum execution time: 84_103_000 picoseconds. - Weight::from_parts(85_325_000, 7662) - .saturating_add(T::DbWeight::get().reads(9_u64)) - .saturating_add(T::DbWeight::get().writes(10_u64)) + // Minimum execution time: 75_000_000 picoseconds. + Weight::from_parts(77_000_000, 7662) + .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(T::DbWeight::get().writes(12_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -726,6 +727,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -739,22 +742,22 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `629` + // Measured: `485` // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 128_363_000 picoseconds. - Weight::from_parts(139_474_918, 6078) - // Standard Error: 79_252 - .saturating_add(Weight::from_parts(31_384_027, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Minimum execution time: 100_000_000 picoseconds. + Weight::from_parts(107_476_765, 6078) + // Standard Error: 61_259 + .saturating_add(Weight::from_parts(27_610_007, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) @@ -766,12 +769,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `659` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 66_688_000 picoseconds. - Weight::from_parts(79_208_379, 4326) - // Standard Error: 74_020 - .saturating_add(Weight::from_parts(31_028_221, 0).saturating_mul(n.into())) + // Measured: `514` + // Estimated: `4466 + n * (2954 ±0)` + // Minimum execution time: 51_000_000 picoseconds. + Weight::from_parts(57_358_180, 4466) + // Standard Error: 54_968 + .saturating_add(Weight::from_parts(27_429_606, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -794,10 +797,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: - // Measured: `216` + // Measured: `105` // Estimated: `3549` - // Minimum execution time: 34_863_000 picoseconds. - Weight::from_parts(36_679_000, 3549) + // Minimum execution time: 27_000_000 picoseconds. + Weight::from_parts(27_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -813,10 +816,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_create() -> Weight { // Proof Size summary in bytes: - // Measured: `76` + // Measured: `3` // Estimated: `3549` - // Minimum execution time: 19_631_000 picoseconds. - Weight::from_parts(20_384_000, 3549) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(15_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -828,6 +831,8 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1001 w:1000) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) @@ -839,15 +844,19 @@ impl WeightInfo for () { /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. - fn destroy(_m: u32, _c: u32, a: u32, ) -> Weight { + fn destroy(m: u32, c: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32204 + a * (366 ±0)` + // Measured: `32216 + a * (366 ±0)` // Estimated: `2523990 + a * (2954 ±0)` - // Minimum execution time: 1_282_083_000 picoseconds. - Weight::from_parts(1_249_191_963, 2523990) - // Standard Error: 4_719 - .saturating_add(Weight::from_parts(6_470_227, 0).saturating_mul(a.into())) - .saturating_add(RocksDbWeight::get().reads(1004_u64)) + // Minimum execution time: 982_000_000 picoseconds. + Weight::from_parts(937_587_516, 2523990) + // Standard Error: 12_288 + .saturating_add(Weight::from_parts(34_348, 0).saturating_mul(m.into())) + // Standard Error: 12_288 + .saturating_add(Weight::from_parts(23_800, 0).saturating_mul(c.into())) + // Standard Error: 12_288 + .saturating_add(Weight::from_parts(5_095_505, 0).saturating_mul(a.into())) + .saturating_add(RocksDbWeight::get().reads(1005_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(RocksDbWeight::get().writes(1005_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(a.into()))) @@ -861,18 +870,20 @@ impl WeightInfo for () { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: - // Measured: `455` + // Measured: `382` // Estimated: `4326` - // Minimum execution time: 49_055_000 picoseconds. - Weight::from_parts(50_592_000, 4326) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + // Minimum execution time: 41_000_000 picoseconds. + Weight::from_parts(42_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -882,18 +893,20 @@ impl WeightInfo for () { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn force_mint() -> Weight { // Proof Size summary in bytes: - // Measured: `455` + // Measured: `382` // Estimated: `4326` - // Minimum execution time: 47_102_000 picoseconds. - Weight::from_parts(48_772_000, 4326) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + // Minimum execution time: 39_000_000 picoseconds. + Weight::from_parts(40_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) @@ -905,22 +918,24 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:0 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: - // Measured: `564` + // Measured: `576` // Estimated: `4326` - // Minimum execution time: 52_968_000 picoseconds. - Weight::from_parts(55_136_000, 4326) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + // Minimum execution time: 46_000_000 picoseconds. + Weight::from_parts(59_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) @@ -932,6 +947,8 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:2) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) @@ -940,12 +957,12 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `593` - // Estimated: `4326` - // Minimum execution time: 41_140_000 picoseconds. - Weight::from_parts(43_288_000, 4326) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + // Measured: `605` + // Estimated: `6068` + // Minimum execution time: 38_000_000 picoseconds. + Weight::from_parts(83_000_000, 6068) + .saturating_add(RocksDbWeight::get().reads(7_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) @@ -956,12 +973,12 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `763 + i * (108 ±0)` + // Measured: `690 + i * (108 ±0)` // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 14_433_000 picoseconds. - Weight::from_parts(14_664_000, 3549) - // Standard Error: 23_078 - .saturating_add(Weight::from_parts(15_911_377, 0).saturating_mul(i.into())) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3549) + // Standard Error: 20_022 + .saturating_add(Weight::from_parts(16_005_327, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -973,10 +990,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 18_307_000 picoseconds. - Weight::from_parts(18_966_000, 3534) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(14_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -986,10 +1003,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn unlock_item_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 18_078_000 picoseconds. - Weight::from_parts(18_593_000, 3534) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(14_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -999,10 +1016,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn lock_collection() -> Weight { // Proof Size summary in bytes: - // Measured: `340` + // Measured: `267` // Estimated: `3549` - // Minimum execution time: 15_175_000 picoseconds. - Weight::from_parts(15_762_000, 3549) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1016,10 +1033,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `562` + // Measured: `417` // Estimated: `3593` - // Minimum execution time: 26_164_000 picoseconds. - Weight::from_parts(27_117_000, 3593) + // Minimum execution time: 18_000_000 picoseconds. + Weight::from_parts(19_000_000, 3593) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -1029,10 +1046,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: - // Measured: `369` + // Measured: `296` // Estimated: `6078` - // Minimum execution time: 38_523_000 picoseconds. - Weight::from_parts(39_486_000, 6078) + // Minimum execution time: 30_000_000 picoseconds. + Weight::from_parts(31_000_000, 6078) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -1042,10 +1059,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: - // Measured: `311` + // Measured: `238` // Estimated: `3549` - // Minimum execution time: 15_733_000 picoseconds. - Weight::from_parts(16_227_000, 3549) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -1055,10 +1072,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn force_collection_config() -> Weight { // Proof Size summary in bytes: - // Measured: `276` + // Measured: `203` // Estimated: `3549` - // Minimum execution time: 12_042_000 picoseconds. - Weight::from_parts(12_690_000, 3549) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(9_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1068,10 +1085,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_properties() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 17_165_000 picoseconds. - Weight::from_parts(17_769_000, 3534) + // Minimum execution time: 12_000_000 picoseconds. + Weight::from_parts(13_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1087,10 +1104,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `499` // Estimated: `3944` - // Minimum execution time: 48_862_000 picoseconds. - Weight::from_parts(50_584_000, 3944) + // Minimum execution time: 37_000_000 picoseconds. + Weight::from_parts(38_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1100,10 +1117,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `344` + // Measured: `271` // Estimated: `3944` - // Minimum execution time: 24_665_000 picoseconds. - Weight::from_parts(25_465_000, 3944) + // Minimum execution time: 19_000_000 picoseconds. + Weight::from_parts(19_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1117,30 +1134,30 @@ impl WeightInfo for () { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `983` + // Measured: `943` // Estimated: `3944` - // Minimum execution time: 44_617_000 picoseconds. - Weight::from_parts(46_458_000, 3944) + // Minimum execution time: 35_000_000 picoseconds. + Weight::from_parts(36_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) fn approve_item_attributes() -> Weight { // Proof Size summary in bytes: - // Measured: `381` - // Estimated: `4326` - // Minimum execution time: 15_710_000 picoseconds. - Weight::from_parts(16_191_000, 4326) + // Measured: `308` + // Estimated: `4466` + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4466) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1001 w:1000) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -1148,12 +1165,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1000]`. fn cancel_item_attributes_approval(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `831 + n * (398 ±0)` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 24_447_000 picoseconds. - Weight::from_parts(25_144_000, 4326) - // Standard Error: 4_872 - .saturating_add(Weight::from_parts(6_523_101, 0).saturating_mul(n.into())) + // Measured: `686 + n * (398 ±0)` + // Estimated: `4466 + n * (2954 ±0)` + // Minimum execution time: 18_000_000 picoseconds. + Weight::from_parts(19_000_000, 4466) + // Standard Error: 6_379 + .saturating_add(Weight::from_parts(5_018_740, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -1172,10 +1189,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `499` // Estimated: `3812` - // Minimum execution time: 39_990_000 picoseconds. - Weight::from_parts(41_098_000, 3812) + // Minimum execution time: 30_000_000 picoseconds. + Weight::from_parts(31_000_000, 3812) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1189,10 +1206,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `849` + // Measured: `809` // Estimated: `3812` - // Minimum execution time: 38_030_000 picoseconds. - Weight::from_parts(39_842_000, 3812) + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(29_000_000, 3812) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1206,10 +1223,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `398` + // Measured: `325` // Estimated: `3759` - // Minimum execution time: 36_778_000 picoseconds. - Weight::from_parts(38_088_000, 3759) + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(30_000_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1223,10 +1240,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `716` + // Measured: `643` // Estimated: `3759` - // Minimum execution time: 36_887_000 picoseconds. - Weight::from_parts(38_406_000, 3759) + // Minimum execution time: 27_000_000 picoseconds. + Weight::from_parts(29_000_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1236,10 +1253,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn approve_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `410` + // Measured: `337` // Estimated: `4326` - // Minimum execution time: 18_734_000 picoseconds. - Weight::from_parts(19_267_000, 4326) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(14_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1247,10 +1264,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn cancel_approval() -> Weight { // Proof Size summary in bytes: - // Measured: `418` + // Measured: `345` // Estimated: `4326` - // Minimum execution time: 16_080_000 picoseconds. - Weight::from_parts(16_603_000, 4326) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1258,10 +1275,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn clear_all_transfer_approvals() -> Weight { // Proof Size summary in bytes: - // Measured: `418` + // Measured: `345` // Estimated: `4326` - // Minimum execution time: 15_013_000 picoseconds. - Weight::from_parts(15_607_000, 4326) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1269,10 +1286,10 @@ impl WeightInfo for () { /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn set_accept_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `76` + // Measured: `3` // Estimated: `3517` - // Minimum execution time: 13_077_000 picoseconds. - Weight::from_parts(13_635_000, 3517) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 3517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1282,10 +1299,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: - // Measured: `340` + // Measured: `267` // Estimated: `3549` - // Minimum execution time: 17_146_000 picoseconds. - Weight::from_parts(17_453_000, 3549) + // Minimum execution time: 12_000_000 picoseconds. + Weight::from_parts(13_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1295,10 +1312,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn update_mint_settings() -> Weight { // Proof Size summary in bytes: - // Measured: `323` + // Measured: `250` // Estimated: `3538` - // Minimum execution time: 16_102_000 picoseconds. - Weight::from_parts(16_629_000, 3538) + // Minimum execution time: 12_000_000 picoseconds. + Weight::from_parts(13_000_000, 3538) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1312,10 +1329,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn set_price() -> Weight { // Proof Size summary in bytes: - // Measured: `518` + // Measured: `478` // Estimated: `4326` - // Minimum execution time: 22_118_000 picoseconds. - Weight::from_parts(22_849_000, 4326) + // Minimum execution time: 16_000_000 picoseconds. + Weight::from_parts(17_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1331,28 +1348,30 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:2) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn buy_item() -> Weight { // Proof Size summary in bytes: - // Measured: `705` - // Estimated: `4326` - // Minimum execution time: 50_369_000 picoseconds. - Weight::from_parts(51_816_000, 4326) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + // Measured: `717` + // Estimated: `6068` + // Minimum execution time: 42_000_000 picoseconds. + Weight::from_parts(45_000_000, 6068) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) } /// The range of component `n` is `[0, 10]`. fn pay_tips(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_203_000 picoseconds. - Weight::from_parts(3_710_869, 0) - // Standard Error: 8_094 - .saturating_add(Weight::from_parts(2_201_869, 0).saturating_mul(n.into())) + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(390_532, 0) + // Standard Error: 84_277 + .saturating_add(Weight::from_parts(3_087_492, 0).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:2 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -1360,10 +1379,10 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn create_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `494` + // Measured: `421` // Estimated: `7662` - // Minimum execution time: 18_893_000 picoseconds. - Weight::from_parts(19_506_000, 7662) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(15_000_000, 7662) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1373,10 +1392,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn cancel_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `513` + // Measured: `440` // Estimated: `4326` - // Minimum execution time: 19_086_000 picoseconds. - Weight::from_parts(19_609_000, 4326) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(14_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1392,18 +1411,20 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:2 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:4) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:2) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn claim_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `834` + // Measured: `907` // Estimated: `7662` - // Minimum execution time: 84_103_000 picoseconds. - Weight::from_parts(85_325_000, 7662) - .saturating_add(RocksDbWeight::get().reads(9_u64)) - .saturating_add(RocksDbWeight::get().writes(10_u64)) + // Minimum execution time: 75_000_000 picoseconds. + Weight::from_parts(77_000_000, 7662) + .saturating_add(RocksDbWeight::get().reads(11_u64)) + .saturating_add(RocksDbWeight::get().writes(12_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -1413,6 +1434,8 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -1426,22 +1449,22 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `629` + // Measured: `485` // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 128_363_000 picoseconds. - Weight::from_parts(139_474_918, 6078) - // Standard Error: 79_252 - .saturating_add(Weight::from_parts(31_384_027, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Minimum execution time: 100_000_000 picoseconds. + Weight::from_parts(107_476_765, 6078) + // Standard Error: 61_259 + .saturating_add(Weight::from_parts(27_610_007, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(6_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) @@ -1453,16 +1476,16 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `659` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 66_688_000 picoseconds. - Weight::from_parts(79_208_379, 4326) - // Standard Error: 74_020 - .saturating_add(Weight::from_parts(31_028_221, 0).saturating_mul(n.into())) + // Measured: `514` + // Estimated: `4466 + n * (2954 ±0)` + // Minimum execution time: 51_000_000 picoseconds. + Weight::from_parts(57_358_180, 4466) + // Standard Error: 54_968 + .saturating_add(Weight::from_parts(27_429_606, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } -} +} \ No newline at end of file diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs index 035a6014f..93f4853f1 100644 --- a/runtime/devnet/src/config/api/mod.rs +++ b/runtime/devnet/src/config/api/mod.rs @@ -2,7 +2,7 @@ use core::marker::PhantomData; use codec::Decode; use cumulus_primitives_core::Weight; -use frame_support::traits::Contains; +use frame_support::traits::{ConstU32, Contains}; pub(crate) use pallet_api::Extension; use pallet_api::{extension::*, Read}; use sp_core::ConstU8; @@ -11,7 +11,9 @@ use sp_std::vec::Vec; use versioning::*; use crate::{ - config::assets::TrustBackedAssetsInstance, fungibles, Runtime, RuntimeCall, RuntimeEvent, + config::{assets::TrustBackedAssetsInstance, xcm::LocalOriginToLocation}, + fungibles, nonfungibles, Balances, Ismp, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, + RuntimeHoldReason, TransactionByteFee, }; mod versioning; @@ -32,6 +34,9 @@ pub enum RuntimeRead { /// Fungible token queries. #[codec(index = 150)] Fungibles(fungibles::Read), + /// Non-fungible token queries. + #[codec(index = 151)] + NonFungibles(nonfungibles::Read), } impl Readable for RuntimeRead { @@ -43,6 +48,7 @@ impl Readable for RuntimeRead { fn weight(&self) -> Weight { match self { RuntimeRead::Fungibles(key) => fungibles::Pallet::weight(key), + RuntimeRead::NonFungibles(key) => nonfungibles::Pallet::weight(key), } } @@ -50,16 +56,20 @@ impl Readable for RuntimeRead { fn read(self) -> Self::Result { match self { RuntimeRead::Fungibles(key) => RuntimeResult::Fungibles(fungibles::Pallet::read(key)), + RuntimeRead::NonFungibles(key) => + RuntimeResult::NonFungibles(nonfungibles::Pallet::read(key)), } } } /// The result of a runtime state read. #[derive(Debug)] -#[cfg_attr(test, derive(PartialEq, Clone))] +#[cfg_attr(feature = "std", derive(PartialEq, Clone))] pub enum RuntimeResult { /// Fungible token read results. Fungibles(fungibles::ReadResult), + /// Non-fungible token read results. + NonFungibles(nonfungibles::ReadResult), } impl RuntimeResult { @@ -67,6 +77,7 @@ impl RuntimeResult { fn encode(&self) -> Vec { match self { RuntimeResult::Fungibles(result) => result.encode(), + RuntimeResult::NonFungibles(result) => result.encode(), } } } @@ -77,6 +88,10 @@ impl fungibles::Config for Runtime { type WeightInfo = fungibles::weights::SubstrateWeight; } +impl nonfungibles::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} + #[derive(Default)] pub struct Config; impl pallet_api::extension::Config for Config { @@ -130,8 +145,8 @@ pub struct Filter(PhantomData); impl> Contains for Filter { fn contains(c: &RuntimeCall) -> bool { - use fungibles::Call::*; - T::BaseCallFilter::contains(c) && + let contain_fungibles: bool = { + use fungibles::Call::*; matches!( c, RuntimeCall::Fungibles( @@ -142,26 +157,63 @@ impl> Contains f create { .. } | set_metadata { .. } | start_destroy { .. } | clear_metadata { .. } | - mint { .. } | burn { .. } + mint { .. } | burn { .. }, + ) + ) + }; + + let contain_nonfungibles: bool = { + use nonfungibles::Call::*; + matches!( + c, + RuntimeCall::NonFungibles( + transfer { .. } | + approve { .. } | create { .. } | + destroy { .. } | set_metadata { .. } | + clear_metadata { .. } | + set_attribute { .. } | + clear_attribute { .. } | + approve_item_attributes { .. } | + cancel_item_attributes_approval { .. } | + mint { .. } | burn { .. } | + set_max_supply { .. }, ) ) + }; + + T::BaseCallFilter::contains(c) && contain_fungibles | contain_nonfungibles } } impl Contains for Filter { fn contains(r: &RuntimeRead) -> bool { - use fungibles::Read::*; - matches!( - r, - RuntimeRead::Fungibles( - TotalSupply(..) | - BalanceOf { .. } | - Allowance { .. } | - TokenName(..) | TokenSymbol(..) | - TokenDecimals(..) | - TokenExists(..) + let contain_fungibles: bool = { + use fungibles::Read::*; + matches!( + r, + RuntimeRead::Fungibles( + TotalSupply(..) | + BalanceOf { .. } | Allowance { .. } | + TokenName(..) | TokenSymbol(..) | + TokenDecimals(..) | TokenExists(..), + ) + ) + }; + let contain_nonfungibles: bool = { + use nonfungibles::Read::*; + matches!( + r, + RuntimeRead::NonFungibles( + TotalSupply(..) | + BalanceOf { .. } | Allowance { .. } | + OwnerOf { .. } | GetAttribute { .. } | + Collection { .. } | NextCollectionId | + ItemMetadata { .. }, + ) ) - ) + }; + + contain_fungibles | contain_nonfungibles } } @@ -169,8 +221,9 @@ impl Contains for Filter { mod tests { use codec::Encode; use pallet_api::fungibles::Call::*; - use sp_core::crypto::AccountId32; - use RuntimeCall::{Balances, Fungibles}; + use pallet_nfts::MintWitness; + use sp_core::{bounded_vec, crypto::AccountId32}; + use RuntimeCall::{Balances, Fungibles, NonFungibles}; use super::*; @@ -181,6 +234,10 @@ mod tests { let value = 1_000; let result = fungibles::ReadResult::::TotalSupply(value); assert_eq!(RuntimeResult::Fungibles(result).encode(), value.encode()); + + let value = 1_000; + let result = nonfungibles::ReadResult::::TotalSupply(value); + assert_eq!(RuntimeResult::NonFungibles(result).encode(), value.encode()); } #[test] @@ -228,6 +285,71 @@ mod tests { } } + #[test] + fn filter_allows_nonfungibles_calls() { + use pallet_api::nonfungibles::{ + types::{CollectionConfig, CollectionSettings, MintSettings}, + Call::*, + }; + use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness}; + + for call in vec![ + NonFungibles(transfer { collection: 0, item: 0, to: ACCOUNT }), + NonFungibles(approve { + collection: 0, + item: Some(0), + operator: ACCOUNT, + approved: false, + }), + NonFungibles(create { + admin: ACCOUNT, + config: CollectionConfig { + max_supply: Some(0), + mint_settings: MintSettings::default(), + settings: CollectionSettings::all_enabled(), + }, + }), + NonFungibles(destroy { + collection: 0, + witness: DestroyWitness { attributes: 0, item_configs: 0, item_metadatas: 0 }, + }), + NonFungibles(set_attribute { + collection: 0, + item: Some(0), + namespace: pallet_nfts::AttributeNamespace::Pallet, + key: bounded_vec![], + value: bounded_vec![], + }), + NonFungibles(clear_attribute { + collection: 0, + item: Some(0), + namespace: pallet_nfts::AttributeNamespace::Pallet, + key: bounded_vec![], + }), + NonFungibles(set_metadata { collection: 0, item: 0, data: bounded_vec![] }), + NonFungibles(clear_metadata { collection: 0, item: 0 }), + NonFungibles(approve_item_attributes { collection: 0, item: 0, delegate: ACCOUNT }), + NonFungibles(cancel_item_attributes_approval { + collection: 0, + item: 0, + delegate: ACCOUNT, + witness: CancelAttributesApprovalWitness { account_attributes: 0 }, + }), + NonFungibles(set_max_supply { collection: 0, max_supply: 0 }), + NonFungibles(mint { + to: ACCOUNT, + collection: 0, + item: 0, + witness: MintWitness { mint_price: None, owned_item: None }, + }), + NonFungibles(burn { collection: 0, item: 0 }), + ] + .iter() + { + assert!(Filter::::contains(call)) + } + } + #[test] fn filter_allows_fungibles_reads() { use super::{fungibles::Read::*, RuntimeRead::*}; @@ -245,4 +367,33 @@ mod tests { assert!(Filter::::contains(&read)) } } + + #[test] + fn filter_allows_nonfungibles_reads() { + use super::{nonfungibles::Read::*, RuntimeRead::*}; + + for read in vec![ + NonFungibles(TotalSupply(1)), + NonFungibles(BalanceOf { collection: 1, owner: ACCOUNT }), + NonFungibles(Allowance { + collection: 1, + item: None, + owner: ACCOUNT, + operator: ACCOUNT, + }), + NonFungibles(OwnerOf { collection: 1, item: 1 }), + NonFungibles(GetAttribute { + collection: 0, + item: 0, + namespace: pallet_nfts::AttributeNamespace::CollectionOwner, + key: bounded_vec![], + }), + NonFungibles(Collection(1)), + NonFungibles(NextCollectionId), + ] + .iter() + { + assert!(Filter::::contains(read)) + } + } } diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 326b7e594..28a51d521 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -6,7 +6,7 @@ use frame_support::{ use frame_system::{EnsureRoot, EnsureSigned}; use pallet_nfts::PalletFeatures; use parachains_common::{AssetIdForTrustBackedAssets, CollectionId, ItemId, Signature}; -use sp_runtime::traits::Verify; +use sp_runtime::traits::{Get, Verify}; use crate::{ deposit, AccountId, Assets, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, @@ -37,6 +37,15 @@ parameter_types! { pub const NftsMaxDeadlineDuration: BlockNumber = 12 * 30 * DAYS; } +#[derive(Debug)] +#[cfg_attr(feature = "std", derive(PartialEq, Clone))] +pub struct KeyLimit; +impl Get for KeyLimit { + fn get() -> u32 { + N + } +} + impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ApprovalsLimit = ConstU32<20>; @@ -56,7 +65,7 @@ impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ItemId = ItemId; // TODO: source from primitives - type KeyLimit = ConstU32<64>; + type KeyLimit = KeyLimit<64>; type Locker = (); type MaxAttributesPerCall = ConstU32<10>; type MaxDeadlineDuration = NftsMaxDeadlineDuration; diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index f539cbdee..1d860f626 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -39,7 +39,7 @@ use frame_system::{ limits::{BlockLength, BlockWeights}, EnsureRoot, }; -use pallet_api::fungibles; +use pallet_api::{fungibles, nonfungibles}; use pallet_balances::Call as BalancesCall; use pallet_ismp::mmr::{Leaf, Proof, ProofKeys}; use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; @@ -637,6 +637,8 @@ mod runtime { // Pop API #[runtime::pallet_index(150)] pub type Fungibles = fungibles::Pallet; + #[runtime::pallet_index(151)] + pub type NonFungibles = nonfungibles::Pallet; } #[cfg(feature = "runtime-benchmarks")] @@ -648,6 +650,7 @@ mod benches { [pallet_session, SessionBench::] [pallet_timestamp, Timestamp] [pallet_message_queue, MessageQueue] + [pallet_nfts, Nfts] [pallet_sudo, Sudo] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] From f67dab1ae98fe0f04c278ab7f2de363859d6ae36 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 12 Nov 2024 12:42:12 +0700 Subject: [PATCH 55/76] fix: becnhmark helper --- pallets/api/src/mock.rs | 19 +++++++++++++++++++ runtime/devnet/src/config/api/mod.rs | 7 +++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs index 8a4ad27d0..1e6216f54 100644 --- a/pallets/api/src/mock.rs +++ b/pallets/api/src/mock.rs @@ -142,6 +142,25 @@ impl Verify for Noop { } } +#[cfg(feature = "runtime-benchmarks")] +impl pallet_nfts::pallet::BenchmarkHelper for () { + fn collection(i: u16) -> u32 { + i.into() + } + + fn item(i: u16) -> u32 { + i.into() + } + + fn signer() -> (Noop, u64) { + unimplemented!() + } + + fn sign(signer: &Noop, message: &[u8]) -> Noop { + unimplemented!() + } +} + impl pallet_nfts::Config for Test { type ApprovalsLimit = ConstU32<10>; type AttributeDepositBase = ConstU128<1>; diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs index 93f4853f1..b7c332798 100644 --- a/runtime/devnet/src/config/api/mod.rs +++ b/runtime/devnet/src/config/api/mod.rs @@ -2,7 +2,7 @@ use core::marker::PhantomData; use codec::Decode; use cumulus_primitives_core::Weight; -use frame_support::traits::{ConstU32, Contains}; +use frame_support::traits::Contains; pub(crate) use pallet_api::Extension; use pallet_api::{extension::*, Read}; use sp_core::ConstU8; @@ -11,9 +11,8 @@ use sp_std::vec::Vec; use versioning::*; use crate::{ - config::{assets::TrustBackedAssetsInstance, xcm::LocalOriginToLocation}, - fungibles, nonfungibles, Balances, Ismp, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, - RuntimeHoldReason, TransactionByteFee, + config::assets::TrustBackedAssetsInstance, fungibles, nonfungibles, Runtime, RuntimeCall, + RuntimeEvent, }; mod versioning; From a4e16e8822f4ce16fe909d5ee918c22c99df37ea Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:39:46 +0700 Subject: [PATCH 56/76] feat: multi instances & function comments --- pallets/api/src/mock.rs | 7 +- pallets/api/src/nonfungibles/mod.rs | 172 ++++++++++++++++++++++---- pallets/api/src/nonfungibles/tests.rs | 52 ++++---- pallets/api/src/nonfungibles/types.rs | 27 ---- 4 files changed, 186 insertions(+), 72 deletions(-) delete mode 100644 pallets/api/src/nonfungibles/types.rs diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs index 1e6216f54..d11a8c983 100644 --- a/pallets/api/src/mock.rs +++ b/pallets/api/src/mock.rs @@ -32,7 +32,7 @@ frame_support::construct_runtime!( Assets: pallet_assets::, Balances: pallet_balances, Fungibles: crate::fungibles, - Nfts: pallet_nfts, + Nfts: pallet_nfts::, NonFungibles: crate::nonfungibles } ); @@ -161,7 +161,8 @@ impl pallet_nfts::pallet::BenchmarkHelper for () { } } -impl pallet_nfts::Config for Test { +type NftsInstance = pallet_nfts::Instance1; +impl pallet_nfts::Config for Test { type ApprovalsLimit = ConstU32<10>; type AttributeDepositBase = ConstU128<1>; type CollectionDeposit = ConstU128<2>; @@ -191,7 +192,9 @@ impl pallet_nfts::Config for Test { } impl crate::nonfungibles::Config for Test { + type NftsInstance = NftsInstance; type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); } pub(crate) fn new_test_ext() -> sp_io::TestExternalities { diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index 1a5b07b89..b3370a84a 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -2,14 +2,40 @@ //! assets. The goal is to provide a simplified, consistent API that adheres to standards in the //! smart contract space. +use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; +use frame_system::pallet_prelude::BlockNumberFor; pub use pallet::*; use pallet_nfts::WeightInfo; +pub use pallet_nfts::{ + AttributeNamespace, CollectionConfig, CollectionDetails, CollectionSetting, CollectionSettings, + DestroyWitness, ItemDeposit, ItemDetails, ItemSetting, MintSettings, MintType, MintWitness, +}; use sp_runtime::traits::StaticLookup; -pub use types::*; #[cfg(test)] mod tests; -pub mod types; + +type AccountIdOf = ::AccountId; +type NftsOf = pallet_nfts::Pallet>; +type NftsErrorOf = pallet_nfts::Error>; +type NftsWeightInfoOf = >>::WeightInfo; +type NftsInstanceOf = ::NftsInstance; +type BalanceOf = <>>::Currency as Currency< + ::AccountId, +>>::Balance; +type CollectionIdOf = + as Inspect<::AccountId>>::CollectionId; +type ItemIdOf = as Inspect<::AccountId>>::ItemId; +type ItemPriceOf = BalanceOf; +type CollectionDetailsFor = CollectionDetails, BalanceOf>; +type AttributeNamespaceOf = AttributeNamespace>; +type CollectionConfigFor = + CollectionConfig, BlockNumberFor, CollectionIdOf>; +// Type aliases for storage items. +pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId>; +pub(super) type AccountBalanceOf = pallet_nfts::AccountBalance>; +pub(super) type AttributeOf = pallet_nfts::Attribute>; +pub(super) type CollectionOf = pallet_nfts::Collection>; #[frame_support::pallet] pub mod pallet { @@ -18,10 +44,6 @@ pub mod pallet { use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness, MintWitness}; use sp_runtime::BoundedVec; use sp_std::vec::Vec; - use types::{ - AccountIdOf, AttributeNamespaceOf, BalanceOf, CollectionConfigFor, CollectionDetailsFor, - CollectionIdOf, ItemIdOf, ItemPriceOf, NextCollectionIdOf, NftsOf, NftsWeightInfoOf, - }; use super::*; @@ -31,39 +53,64 @@ pub mod pallet { #[repr(u8)] #[allow(clippy::unnecessary_cast)] pub enum Read { - /// Total item supply of a collection. + /// Total item supply of a specified collection. #[codec(index = 0)] TotalSupply(CollectionIdOf), /// Account balance for a specified collection. #[codec(index = 1)] - BalanceOf { collection: CollectionIdOf, owner: AccountIdOf }, + BalanceOf { + // The collection. + collection: CollectionIdOf, + // The owner of the collection . + owner: AccountIdOf, + }, /// Allowance for an operator approved by an owner, for a specified collection or item. #[codec(index = 2)] Allowance { + // The collection. collection: CollectionIdOf, + // The collection item. + item: Option>, + // The owner of the collection item. owner: AccountIdOf, + // The delegated operator of collection item. operator: AccountIdOf, - item: Option>, }, /// Owner of a specified collection item. #[codec(index = 5)] - OwnerOf { collection: CollectionIdOf, item: ItemIdOf }, - /// Attribute value of a collection item. (Error: bounded collection is not partial) + OwnerOf { + // The collection. + collection: CollectionIdOf, + // The collection item. + item: ItemIdOf, + }, + /// Attribute value of a specified collection item. (Error: bounded collection is not + /// partial) #[codec(index = 6)] GetAttribute { + // The collection. collection: CollectionIdOf, + // The collection item. item: ItemIdOf, + // The namespace of the attribute. namespace: AttributeNamespaceOf, + // The key of the attribute. key: BoundedVec, }, - /// Details of a collection. + /// Details of a specified collection. #[codec(index = 9)] Collection(CollectionIdOf), /// Next collection ID. #[codec(index = 10)] NextCollectionId, + /// Metadata of a specified collection item. #[codec(index = 11)] - ItemMetadata { collection: CollectionIdOf, item: ItemIdOf }, + ItemMetadata { + // The collection. + collection: CollectionIdOf, + // The collection item. + item: ItemIdOf, + }, } /// Results of state reads for the non-fungibles API. @@ -78,13 +125,13 @@ pub mod pallet { Allowance(bool), /// Owner of a specified collection owner. OwnerOf(Option>), - /// Attribute value of a collection item. + /// Attribute value of a specified collection item. GetAttribute(Option>), - /// Details of a collection. + /// Details of a specified collection. Collection(Option>), /// Next collection ID. NextCollectionId(Option>), - /// Collection item metadata. + /// Metadata of a specified collection item. ItemMetadata(Option>), } @@ -107,9 +154,13 @@ pub mod pallet { /// Configure the pallet by specifying the parameters and types on which it depends. #[pallet::config] - pub trait Config: frame_system::Config + pallet_nfts::Config { + pub trait Config: frame_system::Config + pallet_nfts::Config { /// Because this pallet emits events, it depends on the runtime's definition of an event. type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// The instance of pallet-nfts. + type NftsInstance; + /// Weight information for dispatchables in this pallet. + type WeightInfo: WeightInfo; } #[pallet::pallet] @@ -159,6 +210,12 @@ pub mod pallet { #[pallet::call] impl Pallet { + /// Transfers the collection item from the caller's account to account `to`. + /// + /// # Parameters + /// - `collection` - The collection of the item to be transferred. + /// - `item` - The item to be transferred. + /// - `to` - The recipient account. #[pallet::call_index(3)] #[pallet::weight(NftsWeightInfoOf::::transfer())] pub fn transfer( @@ -179,6 +236,13 @@ pub mod pallet { Ok(()) } + /// Approves `operator` to spend the collection item on behalf of the caller. + /// + /// # Parameters + /// - `collection` - The collection of the item to be approved for delegated transfer. + /// - `item` - The item to be approved for delegated transfer. + /// - `operator` - The account that is allowed to spend the collection item. + /// - `approved` - The approval status of the collection item. #[pallet::call_index(4)] #[pallet::weight(NftsWeightInfoOf::::approve_transfer() + NftsWeightInfoOf::::cancel_approval())] pub fn approve( @@ -209,6 +273,12 @@ pub mod pallet { Ok(()) } + /// Issue a new collection of non-fungible items from a public origin. + /// + /// # Parameters + /// - `admin` - The admin of this collection. The admin is the initial address of each + /// member of the collection's admin team. + /// - `config` - The configuration of the collection. #[pallet::call_index(7)] #[pallet::weight(NftsWeightInfoOf::::create())] pub fn create( @@ -220,13 +290,19 @@ pub mod pallet { // issues for setting it to xcm's `Location`. This can easily be done differently. let id = NextCollectionIdOf::::get() .or(T::CollectionId::initial_value()) - .ok_or(pallet_nfts::Error::::UnknownCollection)?; + .ok_or(NftsErrorOf::::UnknownCollection)?; let creator = ensure_signed(origin.clone())?; NftsOf::::create(origin, T::Lookup::unlookup(admin.clone()), config)?; Self::deposit_event(Event::Created { id, admin, creator }); Ok(()) } + /// Destroy a collection of fungible items. + /// + /// # Parameters + /// - `collection` - The identifier of the collection to be destroyed. + /// - `witness` - Information on the items minted in the collection. This must be + /// correct. #[pallet::call_index(8)] #[pallet::weight(NftsWeightInfoOf::::destroy( witness.item_metadatas, @@ -241,6 +317,14 @@ pub mod pallet { NftsOf::::destroy(origin, collection, witness) } + /// Set an attribute for a collection or item. + /// + /// # Parameters + /// - `collection` - The collection whose item's metadata to set. + /// - `maybe_item` - The item whose metadata to set. + /// - `namespace` - Attribute's namespace. + /// - `key` - The key of the attribute. + /// - `value` - The value to which to set the attribute. #[pallet::call_index(12)] #[pallet::weight(NftsWeightInfoOf::::set_attribute())] pub fn set_attribute( @@ -254,6 +338,13 @@ pub mod pallet { NftsOf::::set_attribute(origin, collection, item, namespace, key, value) } + /// Clear an attribute for the collection or item. + /// + /// # Parameters + /// - `collection` - The collection whose item's metadata to clear. + /// - `maybe_item` - The item whose metadata to clear. + /// - `namespace` - Attribute's namespace. + /// - `key` - The key of the attribute. #[pallet::call_index(13)] #[pallet::weight(NftsWeightInfoOf::::clear_attribute())] pub fn clear_attribute( @@ -266,6 +357,12 @@ pub mod pallet { NftsOf::::clear_attribute(origin, collection, item, namespace, key) } + /// Set the metadata for an item. + /// + /// # Parameters + /// - `collection` - The collection whose item's metadata to set. + /// - `item` - The item whose metadata to set. + /// - `data` - The general information of this item. Limited in length by `StringLimit`. #[pallet::call_index(14)] #[pallet::weight(NftsWeightInfoOf::::set_metadata())] pub fn set_metadata( @@ -287,6 +384,12 @@ pub mod pallet { NftsOf::::clear_metadata(origin, collection, item) } + /// Approve item's attributes to be changed by a delegated third-party account. + /// + /// # Parameters + /// - `collection` - The collection of the item. + /// - `item` - The item that holds attributes. + /// - `delegate` - The account to delegate permission to change attributes of the item. #[pallet::call_index(16)] #[pallet::weight(NftsWeightInfoOf::::approve_item_attributes())] pub fn approve_item_attributes( @@ -303,6 +406,14 @@ pub mod pallet { ) } + /// Cancel the previously provided approval to change item's attributes. + /// All the previously set attributes by the `delegate` will be removed. + /// + /// # Parameters + /// - `collection` - Collection that the item is contained within. + /// - `item` - The item that holds attributes. + /// - `delegate` - The previously approved account to remove. + /// - `witness` - A witness data to cancel attributes approval operation. #[pallet::call_index(17)] #[pallet::weight(NftsWeightInfoOf::::cancel_item_attributes_approval(witness.account_attributes))] pub fn cancel_item_attributes_approval( @@ -321,6 +432,11 @@ pub mod pallet { ) } + /// Set the maximum number of items a collection could have. + /// + /// # Parameters + /// - `collection` - The identifier of the collection to change. + /// - `max_supply` - The maximum number of items a collection could have. #[pallet::call_index(18)] #[pallet::weight(NftsWeightInfoOf::::set_collection_max_supply())] pub fn set_max_supply( @@ -331,6 +447,15 @@ pub mod pallet { NftsOf::::set_collection_max_supply(origin, collection, max_supply) } + /// Mint an item of a particular collection. + /// + /// # Parameters + /// - `collection` - The collection of the item to be minted. + /// - `item` - An identifier of the new item. + /// - `mint_to` - Account into which the item will be minted. + /// - `witness_data` - When the mint type is `HolderOf(collection_id)`, then the owned + /// item_id from that collection needs to be provided within the witness data object. If + /// the mint price is set, then it should be additionally confirmed in the `witness_data`. #[pallet::call_index(19)] #[pallet::weight(NftsWeightInfoOf::::mint())] pub fn mint( @@ -359,6 +484,11 @@ pub mod pallet { Ok(()) } + /// Destroy a single collection item. + /// + /// # Parameters + /// - `collection` - The collection of the item to be burned. + /// - `item` - The item to be burned. #[pallet::call_index(20)] #[pallet::weight(NftsWeightInfoOf::::burn())] pub fn burn( @@ -405,18 +535,18 @@ pub mod pallet { NftsOf::::collection_items(collection).unwrap_or_default() as u128, ), BalanceOf { collection, owner } => - ReadResult::BalanceOf(pallet_nfts::AccountBalance::::get(collection, owner)), + ReadResult::BalanceOf(AccountBalanceOf::::get(collection, owner)), Allowance { collection, owner, operator, item } => ReadResult::Allowance( NftsOf::::check_allowance(&collection, &item, &owner, &operator).is_ok(), ), OwnerOf { collection, item } => ReadResult::OwnerOf(NftsOf::::owner(collection, item)), GetAttribute { collection, item, namespace, key } => ReadResult::GetAttribute( - pallet_nfts::Attribute::::get((collection, Some(item), namespace, key)) + AttributeOf::::get((collection, Some(item), namespace, key)) .map(|attribute| attribute.0.into()), ), Collection(collection) => - ReadResult::Collection(pallet_nfts::Collection::::get(collection)), + ReadResult::Collection(CollectionOf::::get(collection)), ItemMetadata { collection, item } => ReadResult::ItemMetadata( NftsOf::::item_metadata(collection, item).map(|metadata| metadata.into()), ), diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index 79d484a2f..290f49f23 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -1,22 +1,24 @@ use codec::Encode; -use frame_support::{assert_noop, assert_ok, traits::Incrementable}; -use frame_system::pallet_prelude::BlockNumberFor; -use pallet_nfts::{ - AccountBalance, CollectionConfig, CollectionDetails, CollectionSettings, DestroyWitness, - MintSettings, MintWitness, +use frame_support::{ + assert_noop, assert_ok, + sp_runtime::{BoundedVec, DispatchError::BadOrigin}, + traits::Incrementable, }; -use sp_runtime::{BoundedVec, DispatchError::BadOrigin}; -use super::types::{CollectionIdOf, ItemIdOf}; use crate::{ mock::*, - nonfungibles::{Event, Read::*, ReadResult}, + nonfungibles::{ + AccountBalanceOf, BlockNumberFor, CollectionConfig, CollectionDetails, CollectionIdOf, + CollectionOf, CollectionSettings, DestroyWitness, ItemIdOf, MintSettings, MintWitness, + NextCollectionIdOf, NftsInstanceOf, Read::*, ReadResult, + }, Read, }; const ITEM: u32 = 1; -type NftsError = pallet_nfts::Error; +type NftsError = pallet_nfts::Error>; +type Event = crate::nonfungibles::Event; mod encoding_read_result { use super::*; @@ -116,10 +118,10 @@ fn transfer() { assert_noop!(NonFungibles::transfer(origin, collection, item, dest), BadOrigin); } // Successfully burn an existing new collection item. - let balance_before_transfer = AccountBalance::::get(collection, &dest); + let balance_before_transfer = AccountBalanceOf::::get(collection, &dest); assert_ok!(NonFungibles::transfer(signed(owner), collection, ITEM, dest)); - let balance_after_transfer = AccountBalance::::get(collection, &dest); - assert_eq!(AccountBalance::::get(collection, &owner), 0); + let balance_after_transfer = AccountBalanceOf::::get(collection, &dest); + assert_eq!(AccountBalanceOf::::get(collection, &owner), 0); assert_eq!(balance_after_transfer - balance_before_transfer, 1); System::assert_last_event( Event::Transfer { collection, item, from: Some(owner), to: Some(dest), price: None } @@ -135,7 +137,7 @@ fn mint_works() { let collection = nfts::create_collection(owner); // Successfully mint a new collection item. - let balance_before_mint = AccountBalance::::get(collection, owner); + let balance_before_mint = AccountBalanceOf::::get(collection, owner); assert_ok!(NonFungibles::mint( signed(owner), owner, @@ -143,7 +145,7 @@ fn mint_works() { ITEM, MintWitness { mint_price: None, owned_item: None } )); - let balance_after_mint = AccountBalance::::get(collection, owner); + let balance_after_mint = AccountBalanceOf::::get(collection, owner); assert_eq!(balance_after_mint, 1); assert_eq!(balance_after_mint - balance_before_mint, 1); System::assert_last_event( @@ -233,7 +235,9 @@ fn get_attribute_works() { let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); - let mut result: Option::ValueLimit>> = None; + let mut result: Option< + BoundedVec>>::ValueLimit>, + > = None; // No attribute set. assert_eq!( NonFungibles::read(GetAttribute { @@ -305,7 +309,9 @@ fn clear_attribute_works() { let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); - let result: Option::ValueLimit>> = None; + let result: Option< + BoundedVec>>::ValueLimit>, + > = None; assert_ok!(Nfts::set_attribute( signed(ALICE), collection, @@ -352,7 +358,9 @@ fn approve_item_attribute_works() { attribute.clone(), value.clone() )); - let result: Option::ValueLimit>> = Some(value); + let result: Option< + BoundedVec>>::ValueLimit>, + > = Some(value); assert_eq!( NonFungibles::read(GetAttribute { collection, @@ -411,7 +419,7 @@ fn next_collection_id_works() { assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); assert_eq!( NonFungibles::read(NextCollectionId).encode(), - pallet_nfts::NextCollectionId::::get() + NextCollectionIdOf::::get() .or(CollectionIdOf::::initial_value()) .encode(), ); @@ -441,7 +449,7 @@ fn total_supply_works() { fn create_works() { new_test_ext().execute_with(|| { let owner = ALICE; - let next_collection_id = pallet_nfts::NextCollectionId::::get().unwrap_or_default(); + let next_collection_id = NextCollectionIdOf::::get().unwrap_or_default(); assert_ok!(NonFungibles::create( signed(owner), owner, @@ -474,7 +482,7 @@ fn collection_works() { let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); assert_eq!( NonFungibles::read(Collection(collection)).encode(), - pallet_nfts::Collection::::get(&collection).encode(), + CollectionOf::::get(&collection).encode(), ); }); } @@ -492,7 +500,7 @@ fn balance_of_works() { ); assert_eq!( NonFungibles::read(BalanceOf { collection, owner }).encode(), - AccountBalance::::get(collection, owner).encode() + AccountBalanceOf::::get(collection, owner).encode() ); }); }); @@ -561,7 +569,7 @@ mod nfts { } pub(super) fn next_collection_id() -> u32 { - pallet_nfts::NextCollectionId::::get().unwrap_or_default() + NextCollectionIdOf::::get().unwrap_or_default() } pub(super) fn collection_config_with_all_settings_enabled( diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs deleted file mode 100644 index 6e686389d..000000000 --- a/pallets/api/src/nonfungibles/types.rs +++ /dev/null @@ -1,27 +0,0 @@ -use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; -use frame_system::pallet_prelude::BlockNumberFor; -pub use pallet_nfts::{ - AttributeNamespace, CollectionConfig, CollectionDetails, CollectionSetting, CollectionSettings, - DestroyWitness, ItemDeposit, ItemDetails, ItemSetting, MintSettings, MintType, MintWitness, -}; - -// Type aliases for pallet-nfts. -pub(super) type NftsOf = pallet_nfts::Pallet; -pub(super) type NftsWeightInfoOf = ::WeightInfo; -// Type aliases for pallet-nfts storage items. -pub(super) type AccountIdOf = ::AccountId; -pub(super) type BalanceOf = <>::Currency as Currency< - ::AccountId, ->>::Balance; -pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId; -pub(super) type CollectionIdOf = - as Inspect<::AccountId>>::CollectionId; -pub(super) type ItemIdOf = - as Inspect<::AccountId>>::ItemId; -pub(super) type ItemPriceOf = BalanceOf; -// TODO: Multi-instances. -pub(super) type CollectionDetailsFor = - CollectionDetails, BalanceOf>; -pub(super) type AttributeNamespaceOf = AttributeNamespace>; -pub(super) type CollectionConfigFor = - CollectionConfig, BlockNumberFor, CollectionIdOf>; From 73e1df5a48751531b28f5715232c4a43a98472cb Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:31:33 +0700 Subject: [PATCH 57/76] feat(devnet): pallet nfts instance configuration --- runtime/devnet/src/config/api/mod.rs | 9 ++++--- runtime/devnet/src/config/assets.rs | 8 +++--- runtime/devnet/src/config/proxy.rs | 38 ++++++++++++++-------------- runtime/devnet/src/lib.rs | 2 +- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs index b7c332798..5ea1d9235 100644 --- a/runtime/devnet/src/config/api/mod.rs +++ b/runtime/devnet/src/config/api/mod.rs @@ -11,8 +11,8 @@ use sp_std::vec::Vec; use versioning::*; use crate::{ - config::assets::TrustBackedAssetsInstance, fungibles, nonfungibles, Runtime, RuntimeCall, - RuntimeEvent, + config::assets::{NftsInstance, TrustBackedAssetsInstance}, + fungibles, nonfungibles, Runtime, RuntimeCall, RuntimeEvent, }; mod versioning; @@ -88,7 +88,9 @@ impl fungibles::Config for Runtime { } impl nonfungibles::Config for Runtime { + type NftsInstance = NftsInstance; type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); } #[derive(Default)] @@ -287,8 +289,7 @@ mod tests { #[test] fn filter_allows_nonfungibles_calls() { use pallet_api::nonfungibles::{ - types::{CollectionConfig, CollectionSettings, MintSettings}, - Call::*, + Call::*, CollectionConfig, CollectionSettings, MintSettings, }; use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness}; diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 28a51d521..97c2a9e7d 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -46,7 +46,9 @@ impl Get for KeyLimit { } } -impl pallet_nfts::Config for Runtime { +pub(crate) type NftsInstance = pallet_nfts::Instance1; +pub type NftsCall = pallet_nfts::Call; +impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ApprovalsLimit = ConstU32<20>; type AttributeDepositBase = NftsAttributeDepositBase; @@ -95,8 +97,8 @@ impl pallet_nft_fractionalization::Config for Runtime { type Deposit = AssetDeposit; type NewAssetName = NewAssetName; type NewAssetSymbol = NewAssetSymbol; - type NftCollectionId = ::CollectionId; - type NftId = ::ItemId; + type NftCollectionId = >::CollectionId; + type NftId = >::ItemId; type Nfts = Nfts; type PalletId = NftFractionalizationPalletId; type RuntimeEvent = RuntimeEvent; diff --git a/runtime/devnet/src/config/proxy.rs b/runtime/devnet/src/config/proxy.rs index ff70240e7..161178dc5 100644 --- a/runtime/devnet/src/config/proxy.rs +++ b/runtime/devnet/src/config/proxy.rs @@ -5,7 +5,7 @@ use pop_runtime_common::proxy::{ }; use sp_runtime::traits::BlakeTwo256; -use super::assets::TrustBackedAssetsCall; +use super::assets::{NftsCall, TrustBackedAssetsCall}; use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; impl InstanceFilter for ProxyType { @@ -45,13 +45,13 @@ impl InstanceFilter for ProxyType { RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::transfer_ownership { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_team { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_collection_max_supply { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_collection { .. }) | + RuntimeCall::Nfts(NftsCall::create { .. }) | + RuntimeCall::Nfts(NftsCall::destroy { .. }) | + RuntimeCall::Nfts(NftsCall::redeposit { .. }) | + RuntimeCall::Nfts(NftsCall::transfer_ownership { .. }) | + RuntimeCall::Nfts(NftsCall::set_team { .. }) | + RuntimeCall::Nfts(NftsCall::set_collection_max_supply { .. }) | + RuntimeCall::Nfts(NftsCall::lock_collection { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), @@ -66,17 +66,17 @@ impl InstanceFilter for ProxyType { RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_attributes_pre_signed { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_item_transfer { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::unlock_item_transfer { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_item_properties { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::clear_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_collection_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::clear_collection_metadata { .. }) | + RuntimeCall::Nfts(NftsCall::force_mint { .. }) | + RuntimeCall::Nfts(NftsCall::update_mint_settings { .. }) | + RuntimeCall::Nfts(NftsCall::mint_pre_signed { .. }) | + RuntimeCall::Nfts(NftsCall::set_attributes_pre_signed { .. }) | + RuntimeCall::Nfts(NftsCall::lock_item_transfer { .. }) | + RuntimeCall::Nfts(NftsCall::unlock_item_transfer { .. }) | + RuntimeCall::Nfts(NftsCall::lock_item_properties { .. }) | + RuntimeCall::Nfts(NftsCall::set_metadata { .. }) | + RuntimeCall::Nfts(NftsCall::clear_metadata { .. }) | + RuntimeCall::Nfts(NftsCall::set_collection_metadata { .. }) | + RuntimeCall::Nfts(NftsCall::clear_collection_metadata { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index 1d860f626..839f819dc 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -628,7 +628,7 @@ mod runtime { // Assets #[runtime::pallet_index(50)] - pub type Nfts = pallet_nfts::Pallet; + pub type Nfts = pallet_nfts::Pallet; #[runtime::pallet_index(51)] pub type NftFractionalization = pallet_nft_fractionalization::Pallet; #[runtime::pallet_index(52)] From bbb9bb4f4a1c61d5d0cb335e31667789cef243b6 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Sat, 16 Nov 2024 13:46:04 +0700 Subject: [PATCH 58/76] chore: resolve feedback --- Cargo.lock | 22 +++++++++++----------- pallets/nfts/Cargo.toml | 3 ++- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 71903ca0c..3414de0bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "Inflector" @@ -7366,7 +7366,7 @@ dependencies = [ "log", "pallet-assets", "pallet-balances", - "pallet-nfts 0.1.0", + "pallet-nfts 31.0.0", "parity-scale-codec", "pop-chain-extension", "scale-info", @@ -8240,39 +8240,39 @@ dependencies = [ [[package]] name = "pallet-nfts" -version = "0.1.0" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e1cd476809de3840e19091a083d5a79178af1f108ad489706e1f9e04c8836a4" dependencies = [ "enumflags2", "frame-benchmarking", "frame-support", "frame-system", "log", - "pallet-balances", "parity-scale-codec", "scale-info", "sp-core", "sp-io", - "sp-keystore", "sp-runtime", + "sp-std", ] [[package]] name = "pallet-nfts" -version = "30.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e1cd476809de3840e19091a083d5a79178af1f108ad489706e1f9e04c8836a4" +version = "31.0.0" dependencies = [ "enumflags2", "frame-benchmarking", "frame-support", "frame-system", "log", + "pallet-balances", "parity-scale-codec", "scale-info", "sp-core", "sp-io", + "sp-keystore", "sp-runtime", - "sp-std", ] [[package]] @@ -10857,7 +10857,7 @@ dependencies = [ "pallet-message-queue", "pallet-multisig", "pallet-nft-fractionalization", - "pallet-nfts 0.1.0", + "pallet-nfts 31.0.0", "pallet-nfts-runtime-api", "pallet-preimage", "pallet-proxy", @@ -11002,7 +11002,7 @@ dependencies = [ "pallet-message-queue", "pallet-multisig", "pallet-nft-fractionalization", - "pallet-nfts 0.1.0", + "pallet-nfts 31.0.0", "pallet-nfts-runtime-api", "pallet-preimage", "pallet-proxy", diff --git a/pallets/nfts/Cargo.toml b/pallets/nfts/Cargo.toml index 722e8ef8b..791db0a73 100644 --- a/pallets/nfts/Cargo.toml +++ b/pallets/nfts/Cargo.toml @@ -6,7 +6,8 @@ homepage = "https://substrate.io" license.workspace = true name = "pallet-nfts" readme = "README.md" -version = "0.1.0" +repository.workspace = true +version = "31.0.0" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] From e07565dc8c292a64ba9df1267bb0b731d47f4c72 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Sat, 16 Nov 2024 17:53:09 +0700 Subject: [PATCH 59/76] feat(api/nonfungibles): destroy collection witness data & weights (#383) chore: rename nfts instance feat(api/nonfungibles): destroy collection witness data & weights (#383) chore: rename nfts instance fix(api/nonfungibles): pallet weight testing --- pallets/api/src/nonfungibles/benchmarking.rs | 110 +++ pallets/api/src/nonfungibles/mod.rs | 114 +-- pallets/api/src/nonfungibles/tests.rs | 674 ++++++++++++++---- pallets/api/src/nonfungibles/weights.rs | 217 ++++++ pallets/nfts/src/benchmarking.rs | 62 +- pallets/nfts/src/common_functions.rs | 5 + pallets/nfts/src/features/approvals.rs | 18 + .../src/features/create_delete_collection.rs | 11 +- .../nfts/src/features/create_delete_item.rs | 16 +- pallets/nfts/src/features/transfer.rs | 23 +- pallets/nfts/src/lib.rs | 9 +- pallets/nfts/src/migration.rs | 120 ---- pallets/nfts/src/tests.rs | 50 +- pallets/nfts/src/types.rs | 12 + pallets/nfts/src/weights.rs | 570 ++++++++------- runtime/devnet/src/config/api/mod.rs | 12 +- runtime/devnet/src/config/assets.rs | 10 +- runtime/devnet/src/config/proxy.rs | 38 +- runtime/devnet/src/lib.rs | 1 + 19 files changed, 1461 insertions(+), 611 deletions(-) create mode 100644 pallets/api/src/nonfungibles/benchmarking.rs create mode 100644 pallets/api/src/nonfungibles/weights.rs delete mode 100644 pallets/nfts/src/migration.rs diff --git a/pallets/api/src/nonfungibles/benchmarking.rs b/pallets/api/src/nonfungibles/benchmarking.rs new file mode 100644 index 000000000..45d9d5bd2 --- /dev/null +++ b/pallets/api/src/nonfungibles/benchmarking.rs @@ -0,0 +1,110 @@ +//! Benchmarking setup for pallet_api::nonfungibles + +use frame_benchmarking::{account, v2::*}; +use frame_support::{traits::nonfungibles_v2::Inspect, BoundedVec}; +use sp_runtime::traits::Zero; + +use super::{AttributeNamespace, CollectionIdOf, Config, ItemIdOf, NftsInstanceOf, Pallet, Read}; +use crate::Read as _; + +const SEED: u32 = 1; + +#[benchmarks( + where + > as Inspect<::AccountId>>::ItemId: Zero, + > as Inspect<::AccountId>>::CollectionId: Zero, +)] +mod benchmarks { + use super::*; + + #[benchmark] + // Storage: `Collection` + fn total_supply() { + #[block] + { + Pallet::::read(Read::TotalSupply(CollectionIdOf::::zero())); + } + } + + #[benchmark] + // Storage: `AccountBalance` + fn balance_of() { + #[block] + { + Pallet::::read(Read::BalanceOf { + collection: CollectionIdOf::::zero(), + owner: account("Alice", 0, SEED), + }); + } + } + + #[benchmark] + // Storage: `Allowances`, `Item` + fn allowance() { + #[block] + { + Pallet::::read(Read::Allowance { + collection: CollectionIdOf::::zero(), + owner: account("Alice", 0, SEED), + operator: account("Bob", 0, SEED), + item: Some(ItemIdOf::::zero()), + }); + } + } + + #[benchmark] + // Storage: `Item` + fn owner_of() { + #[block] + { + Pallet::::read(Read::OwnerOf { + collection: CollectionIdOf::::zero(), + item: ItemIdOf::::zero(), + }); + } + } + + #[benchmark] + // Storage: `Attribute` + fn get_attribute() { + #[block] + { + Pallet::::read(Read::GetAttribute { + key: BoundedVec::default(), + collection: CollectionIdOf::::zero(), + item: ItemIdOf::::zero(), + namespace: AttributeNamespace::CollectionOwner, + }); + } + } + + #[benchmark] + // Storage: `Collection` + fn collection() { + #[block] + { + Pallet::::read(Read::Collection(CollectionIdOf::::zero())); + } + } + + #[benchmark] + // Storage: `NextCollectionId` + fn next_collection_id() { + #[block] + { + Pallet::::read(Read::NextCollectionId); + } + } + + #[benchmark] + // Storage: `ItemMetadata` + fn item_metadata() { + #[block] + { + Pallet::::read(Read::ItemMetadata { + collection: CollectionIdOf::::zero(), + item: ItemIdOf::::zero(), + }); + } + } +} diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index b3370a84a..6da7de5f1 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -5,15 +5,20 @@ use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; use frame_system::pallet_prelude::BlockNumberFor; pub use pallet::*; -use pallet_nfts::WeightInfo; +use pallet_nfts::WeightInfo as NftsWeightInfoTrait; pub use pallet_nfts::{ - AttributeNamespace, CollectionConfig, CollectionDetails, CollectionSetting, CollectionSettings, - DestroyWitness, ItemDeposit, ItemDetails, ItemSetting, MintSettings, MintType, MintWitness, + AttributeNamespace, CancelAttributesApprovalWitness, CollectionConfig, CollectionDetails, + CollectionSetting, CollectionSettings, DestroyWitness, ItemDeposit, ItemDetails, ItemMetadata, + ItemSetting, MintSettings, MintType, MintWitness, }; use sp_runtime::traits::StaticLookup; +use weights::WeightInfo; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; #[cfg(test)] mod tests; +pub mod weights; type AccountIdOf = ::AccountId; type NftsOf = pallet_nfts::Pallet>; @@ -31,15 +36,19 @@ type CollectionDetailsFor = CollectionDetails, BalanceOf>; type AttributeNamespaceOf = AttributeNamespace>; type CollectionConfigFor = CollectionConfig, BlockNumberFor, CollectionIdOf>; -// Type aliases for storage items. -pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId>; +// Type aliases for pallet-nfts storage items. pub(super) type AccountBalanceOf = pallet_nfts::AccountBalance>; pub(super) type AttributeOf = pallet_nfts::Attribute>; +pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId>; pub(super) type CollectionOf = pallet_nfts::Collection>; #[frame_support::pallet] pub mod pallet { - use frame_support::{dispatch::DispatchResult, pallet_prelude::*, traits::Incrementable}; + use frame_support::{ + dispatch::{DispatchResult, DispatchResultWithPostInfo, WithPostDispatchInfo}, + pallet_prelude::*, + traits::Incrementable, + }; use frame_system::pallet_prelude::*; use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness, MintWitness}; use sp_runtime::BoundedVec; @@ -59,42 +68,42 @@ pub mod pallet { /// Account balance for a specified collection. #[codec(index = 1)] BalanceOf { - // The collection. + /// The collection. collection: CollectionIdOf, - // The owner of the collection . + /// The owner of the collection . owner: AccountIdOf, }, /// Allowance for an operator approved by an owner, for a specified collection or item. #[codec(index = 2)] Allowance { - // The collection. + /// The collection. collection: CollectionIdOf, - // The collection item. + /// The collection item. item: Option>, - // The owner of the collection item. + /// The owner of the collection item. owner: AccountIdOf, - // The delegated operator of collection item. + /// The delegated operator of collection item. operator: AccountIdOf, }, /// Owner of a specified collection item. #[codec(index = 5)] OwnerOf { - // The collection. + /// The collection. collection: CollectionIdOf, - // The collection item. + /// The collection item. item: ItemIdOf, }, /// Attribute value of a specified collection item. (Error: bounded collection is not /// partial) #[codec(index = 6)] GetAttribute { - // The collection. + /// The collection. collection: CollectionIdOf, - // The collection item. + /// The collection item. item: ItemIdOf, - // The namespace of the attribute. + /// The namespace of the attribute. namespace: AttributeNamespaceOf, - // The key of the attribute. + /// The key of the attribute. key: BoundedVec, }, /// Details of a specified collection. @@ -106,9 +115,9 @@ pub mod pallet { /// Metadata of a specified collection item. #[codec(index = 11)] ItemMetadata { - // The collection. + /// The collection. collection: CollectionIdOf, - // The collection item. + /// The collection item. item: ItemIdOf, }, } @@ -213,8 +222,8 @@ pub mod pallet { /// Transfers the collection item from the caller's account to account `to`. /// /// # Parameters - /// - `collection` - The collection of the item to be transferred. - /// - `item` - The item to be transferred. + /// - `collection` - The collection of the item to transfer. + /// - `item` - The item to transfer. /// - `to` - The recipient account. #[pallet::call_index(3)] #[pallet::weight(NftsWeightInfoOf::::transfer())] @@ -239,38 +248,49 @@ pub mod pallet { /// Approves `operator` to spend the collection item on behalf of the caller. /// /// # Parameters - /// - `collection` - The collection of the item to be approved for delegated transfer. - /// - `item` - The item to be approved for delegated transfer. + /// - `collection` - The collection of the item to approve for a delegated transfer. + /// - `item` - The item to approve for a delegated transfer. /// - `operator` - The account that is allowed to spend the collection item. /// - `approved` - The approval status of the collection item. #[pallet::call_index(4)] - #[pallet::weight(NftsWeightInfoOf::::approve_transfer() + NftsWeightInfoOf::::cancel_approval())] + #[pallet::weight( + NftsWeightInfoOf::::approve_transfer(item.is_some() as u32) + + NftsWeightInfoOf::::cancel_approval(item.is_some() as u32) + )] pub fn approve( origin: OriginFor, collection: CollectionIdOf, item: Option>, operator: AccountIdOf, approved: bool, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { let owner = ensure_signed(origin.clone())?; - if approved { + let weight = if approved { NftsOf::::approve_transfer( origin, collection, item, T::Lookup::unlookup(operator.clone()), None, - )?; + ) + .map_err(|e| { + e.with_weight(NftsWeightInfoOf::::approve_transfer(item.is_some() as u32)) + })?; + NftsWeightInfoOf::::approve_transfer(item.is_some() as u32) } else { NftsOf::::cancel_approval( origin, collection, item, T::Lookup::unlookup(operator.clone()), - )?; - } + ) + .map_err(|e| { + e.with_weight(NftsWeightInfoOf::::cancel_approval(item.is_some() as u32)) + })?; + NftsWeightInfoOf::::cancel_approval(item.is_some() as u32) + }; Self::deposit_event(Event::Approval { collection, item, operator, owner, approved }); - Ok(()) + Ok(Some(weight).into()) } /// Issue a new collection of non-fungible items from a public origin. @@ -286,21 +306,21 @@ pub mod pallet { admin: AccountIdOf, config: CollectionConfigFor, ) -> DispatchResult { + let creator = ensure_signed(origin.clone())?; // TODO: re-evaluate next collection id in nfts pallet. The `Incrementable` trait causes // issues for setting it to xcm's `Location`. This can easily be done differently. let id = NextCollectionIdOf::::get() .or(T::CollectionId::initial_value()) .ok_or(NftsErrorOf::::UnknownCollection)?; - let creator = ensure_signed(origin.clone())?; NftsOf::::create(origin, T::Lookup::unlookup(admin.clone()), config)?; - Self::deposit_event(Event::Created { id, admin, creator }); + Self::deposit_event(Event::Created { id, creator, admin }); Ok(()) } /// Destroy a collection of fungible items. /// /// # Parameters - /// - `collection` - The identifier of the collection to be destroyed. + /// - `collection` - The collection to destroy. /// - `witness` - Information on the items minted in the collection. This must be /// correct. #[pallet::call_index(8)] @@ -308,6 +328,8 @@ pub mod pallet { witness.item_metadatas, witness.item_configs, witness.attributes, + witness.item_holders, + witness.allowances, ))] pub fn destroy( origin: OriginFor, @@ -410,7 +432,7 @@ pub mod pallet { /// All the previously set attributes by the `delegate` will be removed. /// /// # Parameters - /// - `collection` - Collection that the item is contained within. + /// - `collection` - The collection that the item is contained within. /// - `item` - The item that holds attributes. /// - `delegate` - The previously approved account to remove. /// - `witness` - A witness data to cancel attributes approval operation. @@ -450,9 +472,9 @@ pub mod pallet { /// Mint an item of a particular collection. /// /// # Parameters - /// - `collection` - The collection of the item to be minted. + /// - `to` - Account into which the item will be minted. + /// - `collection` - The collection of the item to mint. /// - `item` - An identifier of the new item. - /// - `mint_to` - Account into which the item will be minted. /// - `witness_data` - When the mint type is `HolderOf(collection_id)`, then the owned /// item_id from that collection needs to be provided within the witness data object. If /// the mint price is set, then it should be additionally confirmed in the `witness_data`. @@ -487,8 +509,8 @@ pub mod pallet { /// Destroy a single collection item. /// /// # Parameters - /// - `collection` - The collection of the item to be burned. - /// - `item` - The item to be burned. + /// - `collection` - The collection of the item to burn. + /// - `item` - The item to burn. #[pallet::call_index(20)] #[pallet::weight(NftsWeightInfoOf::::burn())] pub fn burn( @@ -520,8 +542,18 @@ pub mod pallet { /// /// # Parameters /// - `request` - The read request. - fn weight(_request: &Self::Read) -> Weight { - Default::default() + fn weight(request: &Self::Read) -> Weight { + use Read::*; + match request { + TotalSupply(_) => ::WeightInfo::total_supply(), + BalanceOf { .. } => ::WeightInfo::balance_of(), + Allowance { .. } => ::WeightInfo::allowance(), + OwnerOf { .. } => ::WeightInfo::owner_of(), + GetAttribute { .. } => ::WeightInfo::get_attribute(), + Collection(_) => ::WeightInfo::collection(), + ItemMetadata { .. } => ::WeightInfo::item_metadata(), + NextCollectionId => ::WeightInfo::next_collection_id(), + } } /// Performs the requested read and returns the result. diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index 290f49f23..68260ab23 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -2,19 +2,21 @@ use codec::Encode; use frame_support::{ assert_noop, assert_ok, sp_runtime::{BoundedVec, DispatchError::BadOrigin}, - traits::Incrementable, }; +use pallet_nfts::WeightInfo as NftsWeightInfoTrait; use crate::{ mock::*, nonfungibles::{ - AccountBalanceOf, BlockNumberFor, CollectionConfig, CollectionDetails, CollectionIdOf, + AccountBalanceOf, AttributeNamespace, AttributeOf, BlockNumberFor, + CancelAttributesApprovalWitness, CollectionConfig, CollectionDetails, CollectionIdOf, CollectionOf, CollectionSettings, DestroyWitness, ItemIdOf, MintSettings, MintWitness, - NextCollectionIdOf, NftsInstanceOf, Read::*, ReadResult, + NextCollectionIdOf, NftsInstanceOf, NftsWeightInfoOf, Read::*, ReadResult, }, Read, }; +const COLLECTION: u32 = 0; const ITEM: u32 = 1; type NftsError = pallet_nfts::Error>; @@ -71,7 +73,9 @@ mod encoding_read_result { items: 0, item_metadatas: 0, item_configs: 0, + item_holders: 0, attributes: 0, + allowances: 0, }); assert_eq!( ReadResult::Collection::(collection_details.clone()).encode(), @@ -160,9 +164,14 @@ fn burn_works() { new_test_ext().execute_with(|| { let owner = ALICE; + // "UnknownItem" error is returned if collection item is not created. + assert_noop!(NonFungibles::burn(signed(owner), COLLECTION, ITEM), NftsError::UnknownItem); // Successfully burn an existing new collection item. let (collection, item) = nfts::create_collection_mint(owner, ITEM); + let balance_before_burn = AccountBalanceOf::::get(collection, owner); assert_ok!(NonFungibles::burn(signed(owner), collection, ITEM)); + let balance_after_burn = AccountBalanceOf::::get(collection, owner); + assert_eq!(balance_after_burn, balance_before_burn - 1); System::assert_last_event( Event::Transfer { collection, item, from: Some(owner), to: None, price: None }.into(), ); @@ -175,8 +184,12 @@ fn approve_works() { let owner = ALICE; let operator = BOB; let (collection, item) = nfts::create_collection_mint(owner, ITEM); - // Successfully approve `oeprator` to transfer the collection item. - assert_ok!(NonFungibles::approve(signed(owner), collection, Some(item), operator, true)); + // Successfully approve `operator` to transfer the collection item. + assert_eq!( + NonFungibles::approve(signed(owner), collection, Some(item), operator, true), + Ok(Some(NftsWeightInfoOf::::approve_transfer(1)).into()) + ); + assert_ok!(Nfts::check_allowance(&collection, &Some(item), &owner, &operator)); System::assert_last_event( Event::Approval { collection, item: Some(item), owner, operator, approved: true } .into(), @@ -186,6 +199,26 @@ fn approve_works() { }); } +#[test] +fn approve_collection_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + // Successfully approve `operator` to transfer all items within the collection. + assert_eq!( + NonFungibles::approve(signed(owner), collection, None, operator, true), + Ok(Some(NftsWeightInfoOf::::approve_transfer(0)).into()) + ); + assert_ok!(Nfts::check_allowance(&collection, &None, &owner, &operator)); + System::assert_last_event( + Event::Approval { collection, item: None, owner, operator, approved: true }.into(), + ); + // Successfully transfer the item by the delegated account `operator`. + assert_ok!(Nfts::transfer(signed(operator), collection, item, operator)); + }); +} + #[test] fn cancel_approval_works() { new_test_ext().execute_with(|| { @@ -193,7 +226,38 @@ fn cancel_approval_works() { let operator = BOB; let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); // Successfully cancel the transfer approval of `operator` by `owner`. - assert_ok!(NonFungibles::approve(signed(owner), collection, Some(item), operator, false)); + assert_eq!( + NonFungibles::approve(signed(owner), collection, Some(item), operator, false), + Ok(Some(NftsWeightInfoOf::::cancel_approval(1)).into()) + ); + assert_eq!( + Nfts::check_allowance(&collection, &Some(item), &owner, &operator), + Err(NftsError::NoPermission.into()) + ); + // Failed to transfer the item by `operator` without permission. + assert_noop!( + Nfts::transfer(signed(operator), collection, item, operator), + NftsError::NoPermission + ); + }); +} + +#[test] +fn cancel_collection_approval_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + // Successfully cancel the transfer collection approval of `operator` by `owner`. + assert_ok!(Nfts::approve_transfer(signed(owner), collection, None, operator, None)); + assert_eq!( + NonFungibles::approve(signed(owner), collection, None, operator, false), + Ok(Some(NftsWeightInfoOf::::cancel_approval(0)).into()) + ); + assert_eq!( + Nfts::check_allowance(&collection, &None, &owner, &operator), + Err(NftsError::NoPermission.into()) + ); // Failed to transfer the item by `operator` without permission. assert_noop!( Nfts::transfer(signed(operator), collection, item, operator), @@ -218,60 +282,6 @@ fn set_max_supply_works() { }); } -#[test] -fn owner_of_works() { - new_test_ext().execute_with(|| { - let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); - assert_eq!( - NonFungibles::read(OwnerOf { collection, item }).encode(), - Nfts::owner(collection, item).encode() - ); - }); -} - -#[test] -fn get_attribute_works() { - new_test_ext().execute_with(|| { - let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); - let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); - let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); - let mut result: Option< - BoundedVec>>::ValueLimit>, - > = None; - // No attribute set. - assert_eq!( - NonFungibles::read(GetAttribute { - collection, - item, - namespace: pallet_nfts::AttributeNamespace::CollectionOwner, - key: attribute.clone() - }) - .encode(), - result.encode() - ); - // Successfully get an existing attribute. - result = Some(value.clone()); - assert_ok!(Nfts::set_attribute( - signed(ALICE), - collection, - Some(item), - pallet_nfts::AttributeNamespace::CollectionOwner, - attribute.clone(), - value, - )); - assert_eq!( - NonFungibles::read(GetAttribute { - collection, - item, - namespace: pallet_nfts::AttributeNamespace::CollectionOwner, - key: attribute - }) - .encode(), - result.encode() - ); - }); -} - #[test] fn set_metadata_works() { new_test_ext().execute_with(|| { @@ -316,7 +326,7 @@ fn clear_attribute_works() { signed(ALICE), collection, Some(item), - pallet_nfts::AttributeNamespace::CollectionOwner, + AttributeNamespace::CollectionOwner, attribute.clone(), BoundedVec::truncate_from("some value".as_bytes().to_vec()) )); @@ -325,14 +335,14 @@ fn clear_attribute_works() { signed(ALICE), collection, Some(item), - pallet_nfts::AttributeNamespace::CollectionOwner, + AttributeNamespace::CollectionOwner, attribute.clone(), )); assert_eq!( NonFungibles::read(GetAttribute { collection, item, - namespace: pallet_nfts::AttributeNamespace::CollectionOwner, + namespace: AttributeNamespace::CollectionOwner, key: attribute }) .encode(), @@ -354,7 +364,7 @@ fn approve_item_attribute_works() { signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(BOB), + AttributeNamespace::Account(BOB), attribute.clone(), value.clone() )); @@ -365,7 +375,7 @@ fn approve_item_attribute_works() { NonFungibles::read(GetAttribute { collection, item, - namespace: pallet_nfts::AttributeNamespace::Account(BOB), + namespace: AttributeNamespace::Account(BOB), key: attribute }) .encode(), @@ -387,7 +397,7 @@ fn cancel_item_attribute_approval_works() { signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(BOB), + AttributeNamespace::Account(BOB), attribute.clone(), value.clone() )); @@ -396,14 +406,14 @@ fn cancel_item_attribute_approval_works() { collection, item, BOB, - pallet_nfts::CancelAttributesApprovalWitness { account_attributes: 1 } + CancelAttributesApprovalWitness { account_attributes: 1 } )); assert_noop!( Nfts::set_attribute( signed(BOB), collection, Some(item), - pallet_nfts::AttributeNamespace::Account(BOB), + AttributeNamespace::Account(BOB), attribute.clone(), value.clone() ), @@ -412,78 +422,79 @@ fn cancel_item_attribute_approval_works() { }); } -#[test] -fn next_collection_id_works() { - new_test_ext().execute_with(|| { - let _ = nfts::create_collection_mint(ALICE, ITEM); - assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); - assert_eq!( - NonFungibles::read(NextCollectionId).encode(), - NextCollectionIdOf::::get() - .or(CollectionIdOf::::initial_value()) - .encode(), - ); - }); -} - -#[test] -fn total_supply_works() { - new_test_ext().execute_with(|| { - let owner = ALICE; - let collection = nfts::create_collection(owner); - (0..10).into_iter().for_each(|i| { - assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); - assert_eq!( - NonFungibles::read(TotalSupply(collection)).encode(), - ((i + 1) as u128).encode() - ); - assert_eq!( - NonFungibles::read(TotalSupply(collection)).encode(), - (Nfts::collection_items(collection).unwrap_or_default() as u128).encode() - ); - }); - }); -} - #[test] fn create_works() { new_test_ext().execute_with(|| { - let owner = ALICE; + let creator = ALICE; + let admin = ALICE; let next_collection_id = NextCollectionIdOf::::get().unwrap_or_default(); + for origin in vec![root(), none()] { + assert_noop!( + NonFungibles::create( + origin, + admin, + CollectionConfig { + max_supply: None, + mint_settings: MintSettings::default(), + settings: CollectionSettings::all_enabled() + }, + ), + BadOrigin + ); + } assert_ok!(NonFungibles::create( - signed(owner), - owner, + signed(creator), + admin, CollectionConfig { max_supply: None, mint_settings: MintSettings::default(), settings: CollectionSettings::all_enabled() }, )); - assert_eq!(Nfts::collection_owner(next_collection_id), Some(owner)); + assert_eq!(Nfts::collection_owner(next_collection_id), Some(creator)); + System::assert_last_event(Event::Created { id: next_collection_id, creator, admin }.into()); }); } #[test] fn destroy_works() { new_test_ext().execute_with(|| { - let collection = nfts::create_collection(ALICE); - assert_ok!(NonFungibles::destroy( - signed(ALICE), - collection, - DestroyWitness { item_metadatas: 0, item_configs: 0, attributes: 0 } - )); + let collection = COLLECTION; + let witness = DestroyWitness { + item_metadatas: 0, + item_configs: 0, + item_holders: 0, + attributes: 0, + allowances: 0, + }; + // Check error works for `Nfts::destroy()`. + assert_noop!( + NonFungibles::destroy(signed(ALICE), collection, witness), + NftsError::UnknownCollection + ); + nfts::create_collection(ALICE); + assert_ok!(NonFungibles::destroy(signed(ALICE), collection, witness)); assert_eq!(Nfts::collection_owner(collection), None); }); } #[test] -fn collection_works() { +fn total_supply_works() { new_test_ext().execute_with(|| { - let (collection, _) = nfts::create_collection_mint(ALICE, ITEM); - assert_eq!( - NonFungibles::read(Collection(collection)).encode(), - CollectionOf::::get(&collection).encode(), - ); + let owner = ALICE; + let collection = nfts::create_collection(owner); + assert_eq!(NonFungibles::read(TotalSupply(collection)), ReadResult::TotalSupply(0)); + (0..10).into_iter().for_each(|i| { + assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); + assert_eq!( + NonFungibles::read(TotalSupply(collection)), + ReadResult::TotalSupply((i + 1).into()) + ); + assert_eq!( + NonFungibles::read(TotalSupply(collection)).encode(), + (Nfts::collection_items(collection).unwrap_or_default() as u128).encode() + ); + }); }); } @@ -492,11 +503,15 @@ fn balance_of_works() { new_test_ext().execute_with(|| { let owner = ALICE; let collection = nfts::create_collection(owner); + assert_eq!( + NonFungibles::read(BalanceOf { collection, owner }), + ReadResult::BalanceOf(Default::default()) + ); (0..10).into_iter().for_each(|i| { assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); assert_eq!( - NonFungibles::read(BalanceOf { collection, owner }).encode(), - (i + 1).encode() + NonFungibles::read(BalanceOf { collection, owner }), + ReadResult::BalanceOf(i + 1) ); assert_eq!( NonFungibles::read(BalanceOf { collection, owner }).encode(), @@ -513,9 +528,8 @@ fn allowance_works() { let operator = BOB; let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); assert_eq!( - NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }) - .encode(), - true.encode() + NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }), + ReadResult::Allowance(true) ); assert_eq!( NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }) @@ -527,6 +541,131 @@ fn allowance_works() { }); } +#[test] +fn owner_of_works() { + new_test_ext().execute_with(|| { + assert_eq!( + NonFungibles::read(OwnerOf { collection: COLLECTION, item: ITEM }), + ReadResult::OwnerOf(None) + ); + nfts::create_collection_mint(ALICE, ITEM); + assert_eq!( + NonFungibles::read(OwnerOf { collection: COLLECTION, item: ITEM }), + ReadResult::OwnerOf(Some(ALICE)) + ); + assert_eq!( + NonFungibles::read(OwnerOf { collection: COLLECTION, item: ITEM }).encode(), + Nfts::owner(COLLECTION, ITEM).encode() + ); + }); +} + +#[test] +fn get_attribute_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let raw_value = "some value".as_bytes().to_vec(); + let value = BoundedVec::truncate_from(raw_value.clone()); + let namespace = AttributeNamespace::CollectionOwner; + // No attribute set. + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item, + namespace: namespace.clone(), + key: attribute.clone() + }), + ReadResult::GetAttribute(None) + ); + // Successfully get an existing attribute. + assert_ok!(Nfts::set_attribute( + signed(ALICE), + collection, + Some(item), + namespace.clone(), + attribute.clone(), + value, + )); + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item, + namespace: namespace.clone(), + key: attribute.clone() + }), + ReadResult::GetAttribute(Some(raw_value)) + ); + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item, + namespace: namespace.clone(), + key: attribute.clone() + }) + .encode(), + AttributeOf::::get((collection, Some(item), namespace, attribute)) + .map(|result| result.0) + .encode() + ); + }); +} + +#[test] +fn collection_works() { + new_test_ext().execute_with(|| { + assert_eq!(NonFungibles::read(Collection(COLLECTION)), ReadResult::Collection(None),); + nfts::create_collection_mint(ALICE, ITEM); + assert_eq!( + NonFungibles::read(Collection(COLLECTION)), + ReadResult::Collection(CollectionOf::::get(COLLECTION)), + ); + assert_eq!( + NonFungibles::read(Collection(COLLECTION)).encode(), + CollectionOf::::get(COLLECTION).encode(), + ); + }); +} + +#[test] +fn item_metadata_works() { + new_test_ext().execute_with(|| { + assert_eq!( + NonFungibles::read(ItemMetadata { collection: COLLECTION, item: ITEM }), + ReadResult::ItemMetadata(None) + ); + nfts::create_collection_mint(ALICE, ITEM); + let value = "some metadata".as_bytes().to_vec(); + assert_ok!(NonFungibles::set_metadata( + signed(ALICE), + COLLECTION, + ITEM, + BoundedVec::truncate_from(value.clone()) + )); + assert_eq!( + NonFungibles::read(ItemMetadata { collection: COLLECTION, item: ITEM }), + ReadResult::ItemMetadata(Some(value)) + ); + assert_eq!( + NonFungibles::read(ItemMetadata { collection: COLLECTION, item: ITEM }).encode(), + Nfts::item_metadata(COLLECTION, ITEM).encode() + ); + }); +} + +#[test] +fn next_collection_id_works() { + new_test_ext().execute_with(|| { + assert_eq!(NonFungibles::read(NextCollectionId), ReadResult::NextCollectionId(Some(0))); + nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId), ReadResult::NextCollectionId(Some(1))); + assert_eq!( + NonFungibles::read(NextCollectionId).encode(), + Some(NextCollectionIdOf::::get().unwrap_or_default()).encode(), + ); + }); +} + fn signed(account_id: AccountId) -> RuntimeOrigin { RuntimeOrigin::signed(account_id) } @@ -539,6 +678,7 @@ fn none() -> RuntimeOrigin { RuntimeOrigin::none() } +// Helper functions for interacting with pallet-nfts. mod nfts { use super::*; @@ -559,7 +699,7 @@ mod nfts { } pub(super) fn create_collection(owner: AccountId) -> u32 { - let next_id = next_collection_id(); + let next_id = NextCollectionIdOf::::get().unwrap_or_default(); assert_ok!(Nfts::create( signed(owner), owner, @@ -568,10 +708,6 @@ mod nfts { next_id } - pub(super) fn next_collection_id() -> u32 { - NextCollectionIdOf::::get().unwrap_or_default() - } - pub(super) fn collection_config_with_all_settings_enabled( ) -> CollectionConfig, CollectionIdOf> { CollectionConfig { @@ -581,3 +717,287 @@ mod nfts { } } } + +mod read_weights { + use frame_support::weights::Weight; + + use super::*; + use crate::nonfungibles::{weights::WeightInfo, Config}; + + struct ReadWeightInfo { + total_supply: Weight, + balance_of: Weight, + allowance: Weight, + owner_of: Weight, + get_attribute: Weight, + collection: Weight, + next_collection_id: Weight, + item_metadata: Weight, + } + + impl ReadWeightInfo { + fn new() -> Self { + Self { + total_supply: NonFungibles::weight(&TotalSupply(COLLECTION)), + balance_of: NonFungibles::weight(&BalanceOf { + collection: COLLECTION, + owner: ALICE, + }), + allowance: NonFungibles::weight(&Allowance { + collection: COLLECTION, + item: Some(ITEM), + owner: ALICE, + operator: BOB, + }), + owner_of: NonFungibles::weight(&OwnerOf { collection: COLLECTION, item: ITEM }), + get_attribute: NonFungibles::weight(&GetAttribute { + collection: COLLECTION, + item: ITEM, + namespace: AttributeNamespace::CollectionOwner, + key: BoundedVec::default(), + }), + collection: NonFungibles::weight(&Collection(COLLECTION)), + next_collection_id: NonFungibles::weight(&NextCollectionId), + item_metadata: NonFungibles::weight(&ItemMetadata { + collection: COLLECTION, + item: ITEM, + }), + } + } + } + + #[test] + fn ensure_read_matches_benchmarks() { + let ReadWeightInfo { + allowance, + balance_of, + collection, + get_attribute, + item_metadata, + next_collection_id, + owner_of, + total_supply, + } = ReadWeightInfo::new(); + + assert_eq!(total_supply, ::WeightInfo::total_supply()); + assert_eq!(balance_of, ::WeightInfo::balance_of()); + assert_eq!(allowance, ::WeightInfo::allowance()); + assert_eq!(owner_of, ::WeightInfo::owner_of()); + assert_eq!(get_attribute, ::WeightInfo::get_attribute()); + assert_eq!(collection, ::WeightInfo::collection()); + assert_eq!(next_collection_id, ::WeightInfo::next_collection_id()); + assert_eq!(item_metadata, ::WeightInfo::item_metadata()); + } + + // These types read from the `Collection` storage. + #[test] + fn ensure_collection_variants_match() { + let ReadWeightInfo { total_supply, collection, .. } = ReadWeightInfo::new(); + + assert_eq!(total_supply, collection); + } + + // Proof size is based on `MaxEncodedLen`, not hardware. + // This test ensures that the data structure sizes do not change with upgrades. + #[test] + fn ensure_expected_proof_size_does_not_change() { + let ReadWeightInfo { + allowance, + balance_of, + collection, + get_attribute, + item_metadata, + next_collection_id, + owner_of, + total_supply, + } = ReadWeightInfo::new(); + + // These values come from `weights.rs`. + assert_eq!(total_supply.proof_size(), 3557); + assert_eq!(balance_of.proof_size(), 3529); + assert_eq!(allowance.proof_size(), 4326); + assert_eq!(owner_of.proof_size(), 4326); + assert_eq!(get_attribute.proof_size(), 3944); + assert_eq!(collection.proof_size(), 3557); + assert_eq!(next_collection_id.proof_size(), 1489); + assert_eq!(item_metadata.proof_size(), 3812); + } +} + +mod ensure_codec_indexes { + use super::{Encode, *}; + use crate::{mock::RuntimeCall::NonFungibles, nonfungibles}; + + #[test] + fn ensure_read_variant_indexes() { + [ + (TotalSupply::(Default::default()), 0u8, "TotalSupply"), + ( + BalanceOf:: { collection: Default::default(), owner: Default::default() }, + 1, + "BalanceOf", + ), + ( + Allowance:: { + collection: Default::default(), + item: Default::default(), + owner: Default::default(), + operator: Default::default(), + }, + 2, + "Allowance", + ), + ( + OwnerOf:: { collection: Default::default(), item: Default::default() }, + 5, + "OwnerOf", + ), + ( + GetAttribute:: { + collection: Default::default(), + item: Default::default(), + namespace: AttributeNamespace::CollectionOwner, + key: Default::default(), + }, + 6, + "GetAttribute", + ), + (Collection::(Default::default()), 9, "Collection"), + (NextCollectionId, 10, "NextCollectionId"), + ( + ItemMetadata { collection: Default::default(), item: Default::default() }, + 11, + "ItemMetadata", + ), + ] + .iter() + .for_each(|(variant, expected_index, name)| { + assert_eq!(variant.encode()[0], *expected_index, "{name} variant index changed"); + }) + } + + #[test] + fn ensure_dispatchable_indexes() { + use nonfungibles::Call::*; + + [ + ( + transfer { + collection: Default::default(), + item: Default::default(), + to: Default::default(), + }, + 3u8, + "transfer", + ), + ( + approve { + collection: Default::default(), + item: Default::default(), + operator: Default::default(), + approved: Default::default(), + }, + 4, + "approve", + ), + (create { admin: Default::default(), config: Default::default() }, 7, "create"), + ( + destroy { + collection: Default::default(), + witness: DestroyWitness { + item_metadatas: Default::default(), + item_configs: Default::default(), + item_holders: Default::default(), + attributes: Default::default(), + allowances: Default::default(), + }, + }, + 8, + "destroy", + ), + ( + set_attribute { + collection: Default::default(), + item: Default::default(), + namespace: AttributeNamespace::CollectionOwner, + key: Default::default(), + value: Default::default(), + }, + 12, + "set_attribute", + ), + ( + clear_attribute { + collection: Default::default(), + item: Default::default(), + namespace: AttributeNamespace::CollectionOwner, + key: Default::default(), + }, + 13, + "clear_attribute", + ), + ( + set_metadata { + collection: Default::default(), + item: Default::default(), + data: Default::default(), + }, + 14, + "set_metadata", + ), + ( + clear_metadata { collection: Default::default(), item: Default::default() }, + 15, + "clear_metadata", + ), + ( + approve_item_attributes { + collection: Default::default(), + item: Default::default(), + delegate: Default::default(), + }, + 16, + "approve_item_attributes", + ), + ( + cancel_item_attributes_approval { + collection: Default::default(), + item: Default::default(), + delegate: Default::default(), + witness: CancelAttributesApprovalWitness { + account_attributes: Default::default(), + }, + }, + 17, + "cancel_item_attributes_approval", + ), + ( + set_max_supply { collection: Default::default(), max_supply: Default::default() }, + 18, + "set_max_supply", + ), + ( + mint { + to: Default::default(), + collection: Default::default(), + item: Default::default(), + witness: MintWitness { + owned_item: Default::default(), + mint_price: Default::default(), + }, + }, + 19, + "mint", + ), + (burn { collection: Default::default(), item: Default::default() }, 20, "burn"), + ] + .iter() + .for_each(|(variant, expected_index, name)| { + assert_eq!( + NonFungibles(variant.to_owned()).encode()[1], + *expected_index, + "{name} dispatchable index changed" + ); + }) + } +} diff --git a/pallets/api/src/nonfungibles/weights.rs b/pallets/api/src/nonfungibles/weights.rs new file mode 100644 index 000000000..f0b8fa833 --- /dev/null +++ b/pallets/api/src/nonfungibles/weights.rs @@ -0,0 +1,217 @@ + +//! Autogenerated weights for `nonfungibles` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 40.0.0 +//! DATE: 2024-11-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `R0GUE`, CPU: `` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// ./target/release/pop-node +// benchmark +// pallet +// --chain=dev +// --wasm-execution=compiled +// --pallet=nonfungibles +// --steps=50 +// --repeat=20 +// --json +// --template +// ./scripts/pallet-weights-template.hbs +// --output=./pallets/api/src/nonfungibles/weights.rs +// --extrinsic= + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `nonfungibles`. +pub trait WeightInfo { + fn total_supply() -> Weight; + fn balance_of() -> Weight; + fn allowance() -> Weight; + fn owner_of() -> Weight; + fn get_attribute() -> Weight; + fn collection() -> Weight; + fn next_collection_id() -> Weight; + fn item_metadata() -> Weight; +} + +/// Weights for `nonfungibles` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn total_supply() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + fn balance_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3529` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3529) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Allowances` (r:1 w:0) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn allowance() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(7_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn owner_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + fn get_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3944` + // Minimum execution time: 5_000_000 picoseconds. + Weight::from_parts(5_000_000, 3944) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn collection() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::NextCollectionId` (r:1 w:0) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn next_collection_id() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `1489` + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(1_000_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + fn item_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3812` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3812) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn total_supply() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + fn balance_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3529` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3529) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Allowances` (r:1 w:0) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn allowance() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(7_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn owner_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + fn get_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3944` + // Minimum execution time: 5_000_000 picoseconds. + Weight::from_parts(5_000_000, 3944) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn collection() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::NextCollectionId` (r:1 w:0) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn next_collection_id() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `1489` + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(1_000_000, 1489) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + fn item_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3812` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3812) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } +} + diff --git a/pallets/nfts/src/benchmarking.rs b/pallets/nfts/src/benchmarking.rs index ab66da26d..58209b8bb 100644 --- a/pallets/nfts/src/benchmarking.rs +++ b/pallets/nfts/src/benchmarking.rs @@ -64,6 +64,27 @@ fn add_collection_metadata, I: 'static>() -> (T::AccountId, Account (caller, caller_lookup) } +fn approve_collection, I: 'static>( + index: u32, +) -> (T::AccountId, AccountIdLookupOf) { + let caller = Collection::::get(T::Helper::collection(0)).unwrap().owner; + if caller != whitelisted_caller() { + whitelist_account!(caller); + } + let caller_lookup = T::Lookup::unlookup(caller.clone()); + let delegate: T::AccountId = account("delegate", 0, SEED + index); + let delegate_lookup = T::Lookup::unlookup(delegate.clone()); + let deadline = BlockNumberFor::::max_value(); + assert_ok!(Nfts::::approve_transfer( + SystemOrigin::Signed(caller.clone()).into(), + T::Helper::collection(0), + None, + delegate_lookup.clone(), + Some(deadline), + )); + (caller, caller_lookup) +} + fn mint_item, I: 'static>( index: u16, ) -> (T::ItemId, T::AccountId, AccountIdLookupOf) { @@ -77,7 +98,7 @@ fn mint_item, I: 'static>( let item_exists = Item::::contains_key(&collection, &item); let item_config = ItemConfigOf::::get(&collection, &item); if item_exists { - return (item, caller, caller_lookup) + return (item, caller, caller_lookup); } else if let Some(item_config) = item_config { assert_ok!(Nfts::::force_mint( SystemOrigin::Signed(caller.clone()).into(), @@ -250,6 +271,8 @@ benchmarks_instance_pallet! { let m in 0 .. 1_000; let c in 0 .. 1_000; let a in 0 .. 1_000; + let h in 0 .. 1_000; + let l in 0 .. 1_000; let (collection, caller, _) = create_collection::(); add_collection_metadata::(); @@ -267,6 +290,13 @@ benchmarks_instance_pallet! { for i in 0..a { add_collection_attribute::(i as u16); } + for i in 0..h { + mint_item::(i as u16); + burn_item::(i as u16); + } + for i in 0..l { + approve_collection::(i as u32); + } let witness = Collection::::get(collection).unwrap().destroy_witness(); }: _(SystemOrigin::Signed(caller), collection, witness) verify { @@ -573,27 +603,45 @@ benchmarks_instance_pallet! { } approve_transfer { + let i in 0..1; + let (collection, caller, _) = create_collection::(); let (item, ..) = mint_item::(0); let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); - let deadline = BlockNumberFor::::max_value(); - }: _(SystemOrigin::Signed(caller.clone()), collection, Some(item), delegate_lookup, Some(deadline)) + let maybe_deadline = if i == 0 { + None + } else { + Some(BlockNumberFor::::max_value()) + }; + let maybe_item = if i == 0 { + None + } else { + Some(item) + }; + }: _(SystemOrigin::Signed(caller.clone()), collection, maybe_item, delegate_lookup, maybe_deadline) verify { - assert_last_event::(Event::TransferApproved { collection, item: Some(item), owner: caller, delegate, deadline: Some(deadline) }.into()); + assert_last_event::(Event::TransferApproved { collection, item: maybe_item, owner: caller, delegate, deadline: maybe_deadline }.into()); } cancel_approval { + let i in 0..1; + let (collection, caller, _) = create_collection::(); let (item, ..) = mint_item::(0); let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let origin = SystemOrigin::Signed(caller.clone()).into(); let deadline = BlockNumberFor::::max_value(); - Nfts::::approve_transfer(origin, collection, Some(item), delegate_lookup.clone(), Some(deadline))?; - }: _(SystemOrigin::Signed(caller.clone()), collection, Some(item), delegate_lookup) + let maybe_item = if i == 0 { + None + } else { + Some(item) + }; + Nfts::::approve_transfer(origin, collection, maybe_item, delegate_lookup.clone(), Some(deadline))?; + }: _(SystemOrigin::Signed(caller.clone()), collection, maybe_item, delegate_lookup) verify { - assert_last_event::(Event::ApprovalCancelled { collection, item: Some(item), owner: caller, delegate }.into()); + assert_last_event::(Event::ApprovalCancelled { collection, item: maybe_item, owner: caller, delegate }.into()); } clear_all_transfer_approvals { diff --git a/pallets/nfts/src/common_functions.rs b/pallets/nfts/src/common_functions.rs index 89de1f051..abd8b61d0 100644 --- a/pallets/nfts/src/common_functions.rs +++ b/pallets/nfts/src/common_functions.rs @@ -39,6 +39,11 @@ impl, I: 'static> Pallet { Collection::::get(collection).map(|i| i.items) } + /// Get the allowances to spend items within the collection. + pub fn collection_allowances(collection: T::CollectionId) -> Option { + Collection::::get(collection).map(|i| i.allowances) + } + /// Get the metadata of the collection item. pub fn item_metadata( collection: T::CollectionId, diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index e1e79ef4a..2647492ca 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -195,6 +195,15 @@ impl, I: 'static> Pallet { Allowances::::mutate((&collection, &owner, &delegate), |allowance| { *allowance = true; }); + Collection::::try_mutate( + &collection, + |maybe_collection_details| -> Result<(), DispatchError> { + let collection_details = + maybe_collection_details.as_mut().ok_or(Error::::UnknownCollection)?; + collection_details.allowances.saturating_inc(); + Ok(()) + }, + )?; Self::deposit_event(Event::TransferApproved { collection, @@ -217,6 +226,15 @@ impl, I: 'static> Pallet { ensure!(check_origin == owner, Error::::NoPermission); } Allowances::::remove((&collection, &owner, &delegate)); + Collection::::try_mutate( + &collection, + |maybe_collection_details| -> Result<(), DispatchError> { + let collection_details = + maybe_collection_details.as_mut().ok_or(Error::::UnknownCollection)?; + collection_details.allowances.saturating_dec(); + Ok(()) + }, + )?; Self::deposit_event(Event::ApprovalCancelled { collection, owner, item: None, delegate }); diff --git a/pallets/nfts/src/features/create_delete_collection.rs b/pallets/nfts/src/features/create_delete_collection.rs index b7efd03ac..1d08cd1b6 100644 --- a/pallets/nfts/src/features/create_delete_collection.rs +++ b/pallets/nfts/src/features/create_delete_collection.rs @@ -54,7 +54,9 @@ impl, I: 'static> Pallet { items: 0, item_metadatas: 0, item_configs: 0, + item_holders: 0, attributes: 0, + allowances: 0, }, ); CollectionRoleOf::::insert( @@ -119,6 +121,11 @@ impl, I: 'static> Pallet { collection_details.item_configs == witness.item_configs, Error::::BadWitness ); + ensure!( + collection_details.item_holders == witness.item_holders, + Error::::BadWitness + ); + ensure!(collection_details.allowances == witness.allowances, Error::::BadWitness); for (_, metadata) in ItemMetadataOf::::drain_prefix(&collection) { if let Some(depositor) = metadata.deposit.account { @@ -137,8 +144,6 @@ impl, I: 'static> Pallet { } } - // TODO: Do we need another storage item to keep track of number of holders of a - // collection let _ = AccountBalance::::clear_prefix(collection, collection_details.items, None); let _ = Allowances::::clear_prefix((collection,), collection_details.items, None); @@ -152,7 +157,9 @@ impl, I: 'static> Pallet { Ok(DestroyWitness { item_metadatas: collection_details.item_metadatas, item_configs: collection_details.item_configs, + item_holders: collection_details.item_holders, attributes: collection_details.attributes, + allowances: collection_details.allowances, }) }) } diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index cc29f8dab..a7b7ddf38 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -69,9 +69,15 @@ impl, I: 'static> Pallet { } collection_details.items.saturating_inc(); - AccountBalance::::mutate(collection, &mint_to, |balance| { - balance.saturating_inc(); - }); + + let account_balance = + AccountBalance::::mutate(collection, &mint_to, |balance| -> u32 { + balance.saturating_inc(); + balance.clone() + }); + if account_balance == 1 { + collection_details.item_holders.saturating_inc(); + } let collection_config = Self::get_collection_config(&collection)?; let deposit_amount = match collection_config @@ -257,6 +263,10 @@ impl, I: 'static> Pallet { } } + if AccountBalance::::get(collection, &details.owner) == 1 { + collection_details.item_holders.saturating_dec(); + } + Ok(details.owner) }, )?; diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index 3b25b0145..dbe6f3b09 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -54,7 +54,7 @@ impl, I: 'static> Pallet { ) -> DispatchResult, ) -> DispatchResult { // Retrieve collection details. - let collection_details = + let mut collection_details = Collection::::get(&collection).ok_or(Error::::UnknownCollection)?; // Ensure the item is not locked. @@ -87,13 +87,23 @@ impl, I: 'static> Pallet { // Perform the transfer with custom details using the provided closure. with_details(&collection_details, &mut details)?; - // Update account balances. - AccountBalance::::mutate(collection, &details.owner, |balance| { - balance.saturating_dec(); - }); - AccountBalance::::mutate(collection, &dest, |balance| { + // Update account balance of the owner. + let owner_balance = + AccountBalance::::mutate(collection, &details.owner, |balance| -> u32 { + balance.saturating_dec(); + balance.clone() + }); + if owner_balance == 0 { + collection_details.item_holders.saturating_dec(); + } + // Update account balance of the destination account. + let dest_balance = AccountBalance::::mutate(collection, &dest, |balance| -> u32 { balance.saturating_inc(); + balance.clone() }); + if dest_balance == 1 { + collection_details.item_holders.saturating_inc(); + } // Update account ownership information. Account::::remove((&details.owner, &collection, &item)); @@ -108,6 +118,7 @@ impl, I: 'static> Pallet { // Update item details. Item::::insert(&collection, &item, &details); + Collection::::insert(&collection, &collection_details); ItemPriceOf::::remove(&collection, &item); PendingSwapOf::::remove(&collection, &item); diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index bc8b67b61..37e8b29cc 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -30,7 +30,6 @@ #[cfg(feature = "runtime-benchmarks")] mod benchmarking; -pub mod migration; #[cfg(test)] pub mod mock; #[cfg(test)] @@ -832,6 +831,8 @@ pub mod pallet { witness.item_metadatas, witness.item_configs, witness.attributes, + witness.item_holders, + witness.allowances, ))] pub fn destroy( origin: OriginFor, @@ -847,6 +848,8 @@ pub mod pallet { details.item_metadatas, details.item_configs, details.attributes, + details.item_holders, + details.allowances, )) .into()) } @@ -1311,7 +1314,7 @@ pub mod pallet { /// /// Weight: `O(1)` #[pallet::call_index(15)] - #[pallet::weight(T::WeightInfo::approve_transfer())] + #[pallet::weight(T::WeightInfo::approve_transfer(maybe_item.is_some() as u32))] pub fn approve_transfer( origin: OriginFor, collection: T::CollectionId, @@ -1350,7 +1353,7 @@ pub mod pallet { /// /// Weight: `O(1)` #[pallet::call_index(16)] - #[pallet::weight(T::WeightInfo::cancel_approval())] + #[pallet::weight(T::WeightInfo::cancel_approval(maybe_item.is_some() as u32))] pub fn cancel_approval( origin: OriginFor, collection: T::CollectionId, diff --git a/pallets/nfts/src/migration.rs b/pallets/nfts/src/migration.rs deleted file mode 100644 index af611bf16..000000000 --- a/pallets/nfts/src/migration.rs +++ /dev/null @@ -1,120 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use frame_support::traits::OnRuntimeUpgrade; -use log; -#[cfg(feature = "try-runtime")] -use sp_runtime::TryRuntimeError; - -use super::*; - -pub mod v1 { - use frame_support::{pallet_prelude::*, weights::Weight}; - - use super::*; - - #[derive(Decode)] - pub struct OldCollectionDetails { - pub owner: AccountId, - pub owner_deposit: DepositBalance, - pub items: u32, - pub item_metadatas: u32, - pub attributes: u32, - } - - impl OldCollectionDetails { - /// Migrates the old collection details to the new v1 format. - fn migrate_to_v1(self, item_configs: u32) -> CollectionDetails { - CollectionDetails { - owner: self.owner, - owner_deposit: self.owner_deposit, - items: self.items, - item_metadatas: self.item_metadatas, - item_configs, - attributes: self.attributes, - } - } - } - - /// A migration utility to update the storage version from v0 to v1 for the pallet. - pub struct MigrateToV1(core::marker::PhantomData); - impl OnRuntimeUpgrade for MigrateToV1 { - fn on_runtime_upgrade() -> Weight { - let in_code_version = Pallet::::in_code_storage_version(); - let on_chain_version = Pallet::::on_chain_storage_version(); - - log::info!( - target: LOG_TARGET, - "Running migration with in-code storage version {:?} / onchain {:?}", - in_code_version, - on_chain_version - ); - - if on_chain_version == 0 && in_code_version == 1 { - let mut translated = 0u64; - let mut configs_iterated = 0u64; - Collection::::translate::< - OldCollectionDetails>, - _, - >(|key, old_value| { - let item_configs = ItemConfigOf::::iter_prefix(&key).count() as u32; - configs_iterated += item_configs as u64; - translated.saturating_inc(); - Some(old_value.migrate_to_v1(item_configs)) - }); - - in_code_version.put::>(); - - log::info!( - target: LOG_TARGET, - "Upgraded {} records, storage to version {:?}", - translated, - in_code_version - ); - T::DbWeight::get().reads_writes(translated + configs_iterated + 1, translated + 1) - } else { - log::info!( - target: LOG_TARGET, - "Migration did not execute. This probably should be removed" - ); - T::DbWeight::get().reads(1) - } - } - - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - let prev_count = Collection::::iter().count(); - Ok((prev_count as u32).encode()) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(prev_count: Vec) -> Result<(), TryRuntimeError> { - let prev_count: u32 = Decode::decode(&mut prev_count.as_slice()).expect( - "the state parameter should be something that was generated by pre_upgrade", - ); - let post_count = Collection::::iter().count() as u32; - ensure!( - prev_count == post_count, - "the records count before and after the migration should be the same" - ); - - ensure!(Pallet::::on_chain_storage_version() >= 1, "wrong storage version"); - - Ok(()) - } - } -} diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 4d0f08c93..6d0c894aa 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -165,6 +165,7 @@ fn basic_minting_should_work() { assert_eq!(collections(), vec![(account(1), 0)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); assert_eq!(AccountBalance::::get(0, account(1)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(items(), vec![(account(1), 0, 42)]); assert_ok!(Nfts::force_create( @@ -175,10 +176,37 @@ fn basic_minting_should_work() { assert_eq!(collections(), vec![(account(1), 0), (account(2), 1)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(2)), 1, 69, account(1), None)); assert_eq!(AccountBalance::::get(1, account(1)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(items(), vec![(account(1), 0, 42), (account(1), 1, 69)]); }); } +#[test] +fn collection_item_holders_should_works() { + new_test_ext().execute_with(|| { + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + account(1), + default_collection_config() + )); + assert_eq!(collections(), vec![(account(1), 0)]); + let total = 5; + for i in 0..total { + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, i, account(1), None)); + } + assert_eq!(AccountBalance::::get(0, account(1)), total); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); + + assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, total, account(2), None)); + assert_eq!(AccountBalance::::get(0, account(2)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 2); + + assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(2)), 0, total)); + assert_eq!(AccountBalance::::get(0, account(2)), 0); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); + }); +} + #[test] fn lifecycle_should_work() { new_test_ext().execute_with(|| { @@ -223,6 +251,7 @@ fn lifecycle_should_work() { assert_eq!(Collection::::get(0).unwrap().items, 3); assert_eq!(Collection::::get(0).unwrap().item_metadatas, 0); assert_eq!(Collection::::get(0).unwrap().item_configs, 3); + assert_eq!(Collection::::get(0).unwrap().item_holders, 3); assert_eq!(Balances::reserved_balance(&account(1)), 8); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 70, account(2))); @@ -317,6 +346,7 @@ fn destroy_should_work() { assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(2), None)); assert_eq!(AccountBalance::::get(0, account(2)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(account(1)), 0, @@ -360,6 +390,7 @@ fn mint_should_work() { assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); assert_eq!(AccountBalance::::get(0, account(1)), 1); assert_eq!(Nfts::owner(0, 42).unwrap(), account(1)); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(collections(), vec![(account(1), 0)]); assert_eq!(items(), vec![(account(1), 0, 42)]); @@ -425,6 +456,7 @@ fn mint_should_work() { Some(MintWitness { mint_price: Some(1), ..Default::default() }) )); assert_eq!(AccountBalance::::get(0, account(2)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 2); assert_eq!(Balances::total_balance(&account(2)), 99); // validate types @@ -464,6 +496,7 @@ fn mint_should_work() { Some(MintWitness { owned_item: Some(43), ..Default::default() }) )); assert_eq!(AccountBalance::::get(1, account(2)), 1); + assert_eq!(Collection::::get(1).unwrap().item_holders, 1); assert!(events().contains(&Event::::PalletAttributeSet { collection: 0, item: Some(43), @@ -500,10 +533,11 @@ fn transfer_should_work() { account(2), default_item_config() )); - + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); assert_eq!(AccountBalance::::get(0, account(2)), 0); assert_eq!(AccountBalance::::get(0, account(3)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(items(), vec![(account(3), 0, 42)]); assert_noop!( Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4)), @@ -521,6 +555,7 @@ fn transfer_should_work() { assert_eq!(AccountBalance::::get(0, account(2)), 0); assert_eq!(AccountBalance::::get(0, account(3)), 0); assert_eq!(AccountBalance::::get(0, account(4)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); // validate we can't transfer non-transferable items let collection_id = 1; assert_ok!(Nfts::force_create( @@ -1775,6 +1810,7 @@ fn burn_works() { default_item_config() )); assert_eq!(AccountBalance::::get(0, account(5)), 2); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_eq!(Balances::reserved_balance(account(1)), 2); assert_noop!( @@ -1783,8 +1819,10 @@ fn burn_works() { ); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 42)); assert_eq!(AccountBalance::::get(0, account(5)), 1); + assert_eq!(Collection::::get(0).unwrap().item_holders, 1); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 69)); assert_eq!(AccountBalance::::get(0, account(5)), 0); + assert_eq!(Collection::::get(0).unwrap().item_holders, 0); assert_eq!(Balances::reserved_balance(account(1)), 0); }); } @@ -2036,6 +2074,7 @@ fn cancel_approval_collection_works_with_admin() { delegate: account(3) })); assert_eq!(Allowances::::get((0, account(2), account(3))), false); + assert_eq!(Nfts::collection_allowances(0).unwrap(), 0); assert_noop!( Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4)), @@ -2192,6 +2231,7 @@ fn approval_collection_works_with_admin() { deadline: None })); assert_eq!(Allowances::::get((0, account(1), account(3))), true); + assert_eq!(Nfts::collection_allowances(0).unwrap(), 1); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(3)), 0, 42, account(4))); }); } @@ -4114,7 +4154,13 @@ fn clear_collection_metadata_works() { assert_ok!(Nfts::destroy( RuntimeOrigin::signed(account(1)), 0, - DestroyWitness { item_configs: 0, item_metadatas: 0, attributes: 0 } + DestroyWitness { + item_configs: 0, + item_metadatas: 0, + attributes: 0, + allowances: 0, + item_holders: 0 + } )); assert_eq!(Collection::::get(0), None); assert_eq!(Balances::reserved_balance(&account(1)), 10); diff --git a/pallets/nfts/src/types.rs b/pallets/nfts/src/types.rs index 941da6cad..46148d63d 100644 --- a/pallets/nfts/src/types.rs +++ b/pallets/nfts/src/types.rs @@ -104,8 +104,12 @@ pub struct CollectionDetails { pub item_metadatas: u32, /// The total number of outstanding item configs of this collection. pub item_configs: u32, + /// The total number of accounts that hold items of the collection. + pub item_holders: u32, /// The total number of attributes for this collection. pub attributes: u32, + /// The total number of allowances to spend all items within collections. + pub allowances: u32, } /// Witness data for the destroy transactions. @@ -117,9 +121,15 @@ pub struct DestroyWitness { /// The total number of outstanding item configs of this collection. #[codec(compact)] pub item_configs: u32, + /// The total number of accounts that hold items of the collection. + #[codec(compact)] + pub item_holders: u32, /// The total number of attributes for this collection. #[codec(compact)] pub attributes: u32, + /// The total number of allowances to spend all items within collections. + #[codec(compact)] + pub allowances: u32, } impl CollectionDetails { @@ -127,7 +137,9 @@ impl CollectionDetails { DestroyWitness { item_metadatas: self.item_metadatas, item_configs: self.item_configs, + item_holders: self.item_holders, attributes: self.attributes, + allowances: self.allowances, } } } diff --git a/pallets/nfts/src/weights.rs b/pallets/nfts/src/weights.rs index c374d6dbc..b33075032 100644 --- a/pallets/nfts/src/weights.rs +++ b/pallets/nfts/src/weights.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `pallet_nfts` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 40.0.0 -//! DATE: 2024-10-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-11-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `R0GUE`, CPU: `` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` @@ -36,7 +36,7 @@ use core::marker::PhantomData; pub trait WeightInfo { fn create() -> Weight; fn force_create() -> Weight; - fn destroy(m: u32, c: u32, a: u32, ) -> Weight; + fn destroy(m: u32, c: u32, a: u32, h: u32, l: u32, ) -> Weight; fn mint() -> Weight; fn force_mint() -> Weight; fn burn() -> Weight; @@ -59,8 +59,8 @@ pub trait WeightInfo { fn clear_metadata() -> Weight; fn set_collection_metadata() -> Weight; fn clear_collection_metadata() -> Weight; - fn approve_transfer() -> Weight; - fn cancel_approval() -> Weight; + fn approve_transfer(i: u32, ) -> Weight; + fn cancel_approval(i: u32, ) -> Weight; fn clear_all_transfer_approvals() -> Weight; fn set_accept_ownership() -> Weight; fn set_collection_max_supply() -> Weight; @@ -81,7 +81,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::NextCollectionId` (r:1 w:1) /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) @@ -91,16 +91,16 @@ impl WeightInfo for SubstrateWeight { fn create() -> Weight { // Proof Size summary in bytes: // Measured: `105` - // Estimated: `3549` - // Minimum execution time: 27_000_000 picoseconds. - Weight::from_parts(27_000_000, 3549) + // Estimated: `3557` + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(29_000_000, 3557) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::NextCollectionId` (r:1 w:1) /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) @@ -110,14 +110,14 @@ impl WeightInfo for SubstrateWeight { fn force_create() -> Weight { // Proof Size summary in bytes: // Measured: `3` - // Estimated: `3549` - // Minimum execution time: 14_000_000 picoseconds. - Weight::from_parts(15_000_000, 3549) + // Estimated: `3557` + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(15_000_000, 3557) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) @@ -126,6 +126,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:0) /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:1 w:0) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) @@ -137,19 +139,17 @@ impl WeightInfo for SubstrateWeight { /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. - fn destroy(m: u32, c: u32, a: u32, ) -> Weight { + /// The range of component `h` is `[0, 1000]`. + /// The range of component `l` is `[0, 1000]`. + fn destroy(_m: u32, _c: u32, a: u32, _h: u32, _l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32216 + a * (366 ±0)` + // Measured: `32875 + a * (366 ±0)` // Estimated: `2523990 + a * (2954 ±0)` // Minimum execution time: 982_000_000 picoseconds. - Weight::from_parts(937_587_516, 2523990) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(34_348, 0).saturating_mul(m.into())) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(23_800, 0).saturating_mul(c.into())) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(5_095_505, 0).saturating_mul(a.into())) - .saturating_add(T::DbWeight::get().reads(1005_u64)) + Weight::from_parts(4_613_129_128, 2523990) + // Standard Error: 125_087 + .saturating_add(Weight::from_parts(5_072_767, 0).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(1006_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(1005_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) @@ -160,7 +160,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) @@ -171,10 +171,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: - // Measured: `382` + // Measured: `390` // Estimated: `4326` - // Minimum execution time: 41_000_000 picoseconds. - Weight::from_parts(42_000_000, 4326) + // Minimum execution time: 40_000_000 picoseconds. + Weight::from_parts(41_000_000, 4326) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -183,7 +183,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) @@ -194,10 +194,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn force_mint() -> Weight { // Proof Size summary in bytes: - // Measured: `382` + // Measured: `390` // Estimated: `4326` // Minimum execution time: 39_000_000 picoseconds. - Weight::from_parts(40_000_000, 4326) + Weight::from_parts(39_000_000, 4326) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -206,7 +206,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) @@ -223,15 +223,15 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: - // Measured: `576` + // Measured: `584` // Estimated: `4326` - // Minimum execution time: 46_000_000 picoseconds. - Weight::from_parts(59_000_000, 4326) + // Minimum execution time: 45_000_000 picoseconds. + Weight::from_parts(46_000_000, 4326) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -250,15 +250,15 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `605` + // Measured: `613` // Estimated: `6068` // Minimum execution time: 38_000_000 picoseconds. - Weight::from_parts(83_000_000, 6068) + Weight::from_parts(38_000_000, 6068) .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:5000 w:5000) @@ -266,12 +266,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `690 + i * (108 ±0)` - // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 3549) - // Standard Error: 20_022 - .saturating_add(Weight::from_parts(16_005_327, 0).saturating_mul(i.into())) + // Measured: `698 + i * (108 ±0)` + // Estimated: `3557 + i * (3336 ±0)` + // Minimum execution time: 10_000_000 picoseconds. + Weight::from_parts(11_000_000, 3557) + // Standard Error: 30_743 + .saturating_add(Weight::from_parts(15_569_470, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -285,7 +285,7 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3534` - // Minimum execution time: 13_000_000 picoseconds. + // Minimum execution time: 14_000_000 picoseconds. Weight::from_parts(14_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) @@ -298,35 +298,35 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3534` - // Minimum execution time: 14_000_000 picoseconds. + // Minimum execution time: 13_000_000 picoseconds. Weight::from_parts(14_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn lock_collection() -> Weight { // Proof Size summary in bytes: - // Measured: `267` - // Estimated: `3549` + // Measured: `275` + // Estimated: `3557` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 3549) + Weight::from_parts(11_000_000, 3557) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionAccount` (r:0 w:2) /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `417` + // Measured: `425` // Estimated: `3593` // Minimum execution time: 18_000_000 picoseconds. Weight::from_parts(19_000_000, 3593) @@ -334,12 +334,12 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:2 w:4) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: - // Measured: `296` + // Measured: `304` // Estimated: `6078` // Minimum execution time: 30_000_000 picoseconds. Weight::from_parts(31_000_000, 6078) @@ -347,28 +347,28 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionAccount` (r:0 w:2) /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: - // Measured: `238` - // Estimated: `3549` + // Measured: `246` + // Estimated: `3557` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(12_000_000, 3549) + Weight::from_parts(12_000_000, 3557) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn force_collection_config() -> Weight { // Proof Size summary in bytes: // Measured: `203` - // Estimated: `3549` + // Estimated: `3557` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(9_000_000, 3549) + Weight::from_parts(9_000_000, 3557) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -386,7 +386,7 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -397,20 +397,20 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `499` + // Measured: `507` // Estimated: `3944` - // Minimum execution time: 37_000_000 picoseconds. - Weight::from_parts(38_000_000, 3944) + // Minimum execution time: 38_000_000 picoseconds. + Weight::from_parts(39_000_000, 3944) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:1) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `271` + // Measured: `279` // Estimated: `3944` // Minimum execution time: 19_000_000 picoseconds. Weight::from_parts(19_000_000, 3944) @@ -424,13 +424,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `943` + // Measured: `951` // Estimated: `3944` // Minimum execution time: 35_000_000 picoseconds. - Weight::from_parts(36_000_000, 3944) + Weight::from_parts(37_000_000, 3944) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -462,8 +462,8 @@ impl WeightInfo for SubstrateWeight { // Estimated: `4466 + n * (2954 ±0)` // Minimum execution time: 18_000_000 picoseconds. Weight::from_parts(19_000_000, 4466) - // Standard Error: 6_379 - .saturating_add(Weight::from_parts(5_018_740, 0).saturating_mul(n.into())) + // Standard Error: 10_431 + .saturating_add(Weight::from_parts(4_776_454, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -473,7 +473,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -482,7 +482,7 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `499` + // Measured: `507` // Estimated: `3812` // Minimum execution time: 30_000_000 picoseconds. Weight::from_parts(31_000_000, 3812) @@ -494,15 +494,15 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `809` + // Measured: `817` // Estimated: `3812` - // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(29_000_000, 3812) + // Minimum execution time: 29_000_000 picoseconds. + Weight::from_parts(30_000_000, 3812) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -511,32 +511,32 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `325` + // Measured: `333` // Estimated: `3759` // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(30_000_000, 3759) + Weight::from_parts(28_000_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `643` + // Measured: `651` // Estimated: `3759` // Minimum execution time: 27_000_000 picoseconds. - Weight::from_parts(29_000_000, 3759) + Weight::from_parts(28_000_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -544,25 +544,37 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - fn approve_transfer() -> Weight { - // Proof Size summary in bytes: - // Measured: `337` - // Estimated: `4326` - // Minimum execution time: 13_000_000 picoseconds. - Weight::from_parts(14_000_000, 4326) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:1 w:1) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 1]`. + fn approve_transfer(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `308 + i * (29 ±0)` + // Estimated: `3574 + i * (2163 ±0)` + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(16_969_387, 3574) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 2163).saturating_mul(i.into())) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - fn cancel_approval() -> Weight { - // Proof Size summary in bytes: - // Measured: `345` - // Estimated: `4326` + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:0 w:1) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 1]`. + fn cancel_approval(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `312 + i * (33 ±0)` + // Estimated: `3557 + i * (2163 ±0)` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(12_000_000, 4326) + Weight::from_parts(14_000_000, 3557) .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 2163).saturating_mul(i.into())) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -582,20 +594,20 @@ impl WeightInfo for SubstrateWeight { // Measured: `3` // Estimated: `3517` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(10_000_000, 3517) + Weight::from_parts(9_000_000, 3517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: - // Measured: `267` - // Estimated: `3549` + // Measured: `275` + // Estimated: `3557` // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 3549) + Weight::from_parts(13_000_000, 3557) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -608,7 +620,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `250` // Estimated: `3538` // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 3538) + Weight::from_parts(12_000_000, 3538) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -624,8 +636,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `478` // Estimated: `4326` - // Minimum execution time: 16_000_000 picoseconds. - Weight::from_parts(17_000_000, 4326) + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(16_000_000, 4326) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -633,8 +645,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:1 w:1) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -649,12 +661,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn buy_item() -> Weight { // Proof Size summary in bytes: - // Measured: `717` + // Measured: `725` // Estimated: `6068` - // Minimum execution time: 42_000_000 picoseconds. - Weight::from_parts(45_000_000, 6068) + // Minimum execution time: 43_000_000 picoseconds. + Weight::from_parts(44_000_000, 6068) .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) } /// The range of component `n` is `[0, 10]`. fn pay_tips(n: u32, ) -> Weight { @@ -662,9 +674,9 @@ impl WeightInfo for SubstrateWeight { // Measured: `0` // Estimated: `0` // Minimum execution time: 1_000_000 picoseconds. - Weight::from_parts(390_532, 0) - // Standard Error: 84_277 - .saturating_add(Weight::from_parts(3_087_492, 0).saturating_mul(n.into())) + Weight::from_parts(2_101_372, 0) + // Standard Error: 5_552 + .saturating_add(Weight::from_parts(1_704_563, 0).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:2 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -674,8 +686,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `421` // Estimated: `7662` - // Minimum execution time: 14_000_000 picoseconds. - Weight::from_parts(15_000_000, 7662) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(14_000_000, 7662) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -687,7 +699,7 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `440` // Estimated: `4326` - // Minimum execution time: 14_000_000 picoseconds. + // Minimum execution time: 13_000_000 picoseconds. Weight::from_parts(14_000_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) @@ -696,8 +708,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:1 w:2) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:2 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -712,12 +724,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn claim_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `907` + // Measured: `915` // Estimated: `7662` - // Minimum execution time: 75_000_000 picoseconds. - Weight::from_parts(77_000_000, 7662) + // Minimum execution time: 78_000_000 picoseconds. + Weight::from_parts(79_000_000, 7662) .saturating_add(T::DbWeight::get().reads(11_u64)) - .saturating_add(T::DbWeight::get().writes(12_u64)) + .saturating_add(T::DbWeight::get().writes(13_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -726,7 +738,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) @@ -742,12 +754,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `485` + // Measured: `493` // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 100_000_000 picoseconds. - Weight::from_parts(107_476_765, 6078) - // Standard Error: 61_259 - .saturating_add(Weight::from_parts(27_610_007, 0).saturating_mul(n.into())) + // Minimum execution time: 101_000_000 picoseconds. + Weight::from_parts(102_689_064, 6078) + // Standard Error: 25_175 + .saturating_add(Weight::from_parts(27_553_304, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(7_u64)) @@ -761,7 +773,7 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:10 w:10) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -769,12 +781,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `514` + // Measured: `522` // Estimated: `4466 + n * (2954 ±0)` - // Minimum execution time: 51_000_000 picoseconds. - Weight::from_parts(57_358_180, 4466) - // Standard Error: 54_968 - .saturating_add(Weight::from_parts(27_429_606, 0).saturating_mul(n.into())) + // Minimum execution time: 50_000_000 picoseconds. + Weight::from_parts(55_735_551, 4466) + // Standard Error: 34_490 + .saturating_add(Weight::from_parts(26_799_214, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -788,7 +800,7 @@ impl WeightInfo for () { /// Storage: `Nfts::NextCollectionId` (r:1 w:1) /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) @@ -798,16 +810,16 @@ impl WeightInfo for () { fn create() -> Weight { // Proof Size summary in bytes: // Measured: `105` - // Estimated: `3549` - // Minimum execution time: 27_000_000 picoseconds. - Weight::from_parts(27_000_000, 3549) + // Estimated: `3557` + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(29_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::NextCollectionId` (r:1 w:1) /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) @@ -817,14 +829,14 @@ impl WeightInfo for () { fn force_create() -> Weight { // Proof Size summary in bytes: // Measured: `3` - // Estimated: `3549` - // Minimum execution time: 14_000_000 picoseconds. - Weight::from_parts(15_000_000, 3549) + // Estimated: `3557` + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(15_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) @@ -833,6 +845,8 @@ impl WeightInfo for () { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:0) /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:1 w:0) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) @@ -844,19 +858,17 @@ impl WeightInfo for () { /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. - fn destroy(m: u32, c: u32, a: u32, ) -> Weight { + /// The range of component `h` is `[0, 1000]`. + /// The range of component `l` is `[0, 1000]`. + fn destroy(_m: u32, _c: u32, a: u32, _h: u32, _l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32216 + a * (366 ±0)` + // Measured: `32875 + a * (366 ±0)` // Estimated: `2523990 + a * (2954 ±0)` // Minimum execution time: 982_000_000 picoseconds. - Weight::from_parts(937_587_516, 2523990) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(34_348, 0).saturating_mul(m.into())) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(23_800, 0).saturating_mul(c.into())) - // Standard Error: 12_288 - .saturating_add(Weight::from_parts(5_095_505, 0).saturating_mul(a.into())) - .saturating_add(RocksDbWeight::get().reads(1005_u64)) + Weight::from_parts(4_613_129_128, 2523990) + // Standard Error: 125_087 + .saturating_add(Weight::from_parts(5_072_767, 0).saturating_mul(a.into())) + .saturating_add(RocksDbWeight::get().reads(1006_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(RocksDbWeight::get().writes(1005_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(a.into()))) @@ -867,7 +879,7 @@ impl WeightInfo for () { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) @@ -878,10 +890,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: - // Measured: `382` + // Measured: `390` // Estimated: `4326` - // Minimum execution time: 41_000_000 picoseconds. - Weight::from_parts(42_000_000, 4326) + // Minimum execution time: 40_000_000 picoseconds. + Weight::from_parts(41_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -890,7 +902,7 @@ impl WeightInfo for () { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) @@ -901,10 +913,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn force_mint() -> Weight { // Proof Size summary in bytes: - // Measured: `382` + // Measured: `390` // Estimated: `4326` // Minimum execution time: 39_000_000 picoseconds. - Weight::from_parts(40_000_000, 4326) + Weight::from_parts(39_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -913,7 +925,7 @@ impl WeightInfo for () { /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) @@ -930,15 +942,15 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: - // Measured: `576` + // Measured: `584` // Estimated: `4326` - // Minimum execution time: 46_000_000 picoseconds. - Weight::from_parts(59_000_000, 4326) + // Minimum execution time: 45_000_000 picoseconds. + Weight::from_parts(46_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -957,15 +969,15 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `605` + // Measured: `613` // Estimated: `6068` // Minimum execution time: 38_000_000 picoseconds. - Weight::from_parts(83_000_000, 6068) + Weight::from_parts(38_000_000, 6068) .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:5000 w:5000) @@ -973,12 +985,12 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `690 + i * (108 ±0)` - // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 3549) - // Standard Error: 20_022 - .saturating_add(Weight::from_parts(16_005_327, 0).saturating_mul(i.into())) + // Measured: `698 + i * (108 ±0)` + // Estimated: `3557 + i * (3336 ±0)` + // Minimum execution time: 10_000_000 picoseconds. + Weight::from_parts(11_000_000, 3557) + // Standard Error: 30_743 + .saturating_add(Weight::from_parts(15_569_470, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -992,7 +1004,7 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3534` - // Minimum execution time: 13_000_000 picoseconds. + // Minimum execution time: 14_000_000 picoseconds. Weight::from_parts(14_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) @@ -1005,35 +1017,35 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3534` - // Minimum execution time: 14_000_000 picoseconds. + // Minimum execution time: 13_000_000 picoseconds. Weight::from_parts(14_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn lock_collection() -> Weight { // Proof Size summary in bytes: - // Measured: `267` - // Estimated: `3549` + // Measured: `275` + // Estimated: `3557` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 3549) + Weight::from_parts(11_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionAccount` (r:0 w:2) /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `417` + // Measured: `425` // Estimated: `3593` // Minimum execution time: 18_000_000 picoseconds. Weight::from_parts(19_000_000, 3593) @@ -1041,12 +1053,12 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:2 w:4) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: - // Measured: `296` + // Measured: `304` // Estimated: `6078` // Minimum execution time: 30_000_000 picoseconds. Weight::from_parts(31_000_000, 6078) @@ -1054,28 +1066,28 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionAccount` (r:0 w:2) /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: - // Measured: `238` - // Estimated: `3549` + // Measured: `246` + // Estimated: `3557` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(12_000_000, 3549) + Weight::from_parts(12_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn force_collection_config() -> Weight { // Proof Size summary in bytes: // Measured: `203` - // Estimated: `3549` + // Estimated: `3557` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(9_000_000, 3549) + Weight::from_parts(9_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1093,7 +1105,7 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -1104,20 +1116,20 @@ impl WeightInfo for () { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `499` + // Measured: `507` // Estimated: `3944` - // Minimum execution time: 37_000_000 picoseconds. - Weight::from_parts(38_000_000, 3944) + // Minimum execution time: 38_000_000 picoseconds. + Weight::from_parts(39_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:1) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `271` + // Measured: `279` // Estimated: `3944` // Minimum execution time: 19_000_000 picoseconds. Weight::from_parts(19_000_000, 3944) @@ -1131,13 +1143,13 @@ impl WeightInfo for () { /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `943` + // Measured: `951` // Estimated: `3944` // Minimum execution time: 35_000_000 picoseconds. - Weight::from_parts(36_000_000, 3944) + Weight::from_parts(37_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1169,8 +1181,8 @@ impl WeightInfo for () { // Estimated: `4466 + n * (2954 ±0)` // Minimum execution time: 18_000_000 picoseconds. Weight::from_parts(19_000_000, 4466) - // Standard Error: 6_379 - .saturating_add(Weight::from_parts(5_018_740, 0).saturating_mul(n.into())) + // Standard Error: 10_431 + .saturating_add(Weight::from_parts(4_776_454, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -1180,7 +1192,7 @@ impl WeightInfo for () { /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -1189,7 +1201,7 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `499` + // Measured: `507` // Estimated: `3812` // Minimum execution time: 30_000_000 picoseconds. Weight::from_parts(31_000_000, 3812) @@ -1201,15 +1213,15 @@ impl WeightInfo for () { /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `809` + // Measured: `817` // Estimated: `3812` - // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(29_000_000, 3812) + // Minimum execution time: 29_000_000 picoseconds. + Weight::from_parts(30_000_000, 3812) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1218,32 +1230,32 @@ impl WeightInfo for () { /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `325` + // Measured: `333` // Estimated: `3759` // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(30_000_000, 3759) + Weight::from_parts(28_000_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `643` + // Measured: `651` // Estimated: `3759` // Minimum execution time: 27_000_000 picoseconds. - Weight::from_parts(29_000_000, 3759) + Weight::from_parts(28_000_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1251,25 +1263,37 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - fn approve_transfer() -> Weight { - // Proof Size summary in bytes: - // Measured: `337` - // Estimated: `4326` - // Minimum execution time: 13_000_000 picoseconds. - Weight::from_parts(14_000_000, 4326) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:1 w:1) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 1]`. + fn approve_transfer(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `308 + i * (29 ±0)` + // Estimated: `3574 + i * (2163 ±0)` + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(16_969_387, 3574) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 2163).saturating_mul(i.into())) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) - fn cancel_approval() -> Weight { - // Proof Size summary in bytes: - // Measured: `345` - // Estimated: `4326` + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Allowances` (r:0 w:1) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 1]`. + fn cancel_approval(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `312 + i * (33 ±0)` + // Estimated: `3557 + i * (2163 ±0)` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(12_000_000, 4326) + Weight::from_parts(14_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 2163).saturating_mul(i.into())) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -1289,20 +1313,20 @@ impl WeightInfo for () { // Measured: `3` // Estimated: `3517` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(10_000_000, 3517) + Weight::from_parts(9_000_000, 3517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: - // Measured: `267` - // Estimated: `3549` + // Measured: `275` + // Estimated: `3557` // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 3549) + Weight::from_parts(13_000_000, 3557) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1315,7 +1339,7 @@ impl WeightInfo for () { // Measured: `250` // Estimated: `3538` // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 3538) + Weight::from_parts(12_000_000, 3538) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1331,8 +1355,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `478` // Estimated: `4326` - // Minimum execution time: 16_000_000 picoseconds. - Weight::from_parts(17_000_000, 4326) + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(16_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1340,8 +1364,8 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:1 w:1) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -1356,12 +1380,12 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn buy_item() -> Weight { // Proof Size summary in bytes: - // Measured: `717` + // Measured: `725` // Estimated: `6068` - // Minimum execution time: 42_000_000 picoseconds. - Weight::from_parts(45_000_000, 6068) + // Minimum execution time: 43_000_000 picoseconds. + Weight::from_parts(44_000_000, 6068) .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) } /// The range of component `n` is `[0, 10]`. fn pay_tips(n: u32, ) -> Weight { @@ -1369,9 +1393,9 @@ impl WeightInfo for () { // Measured: `0` // Estimated: `0` // Minimum execution time: 1_000_000 picoseconds. - Weight::from_parts(390_532, 0) - // Standard Error: 84_277 - .saturating_add(Weight::from_parts(3_087_492, 0).saturating_mul(n.into())) + Weight::from_parts(2_101_372, 0) + // Standard Error: 5_552 + .saturating_add(Weight::from_parts(1_704_563, 0).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:2 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -1381,8 +1405,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `421` // Estimated: `7662` - // Minimum execution time: 14_000_000 picoseconds. - Weight::from_parts(15_000_000, 7662) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(14_000_000, 7662) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1394,7 +1418,7 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `440` // Estimated: `4326` - // Minimum execution time: 14_000_000 picoseconds. + // Minimum execution time: 13_000_000 picoseconds. Weight::from_parts(14_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) @@ -1403,8 +1427,8 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:1 w:2) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) - /// Storage: `Nfts::Collection` (r:1 w:0) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:2 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) @@ -1419,12 +1443,12 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn claim_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `907` + // Measured: `915` // Estimated: `7662` - // Minimum execution time: 75_000_000 picoseconds. - Weight::from_parts(77_000_000, 7662) + // Minimum execution time: 78_000_000 picoseconds. + Weight::from_parts(79_000_000, 7662) .saturating_add(RocksDbWeight::get().reads(11_u64)) - .saturating_add(RocksDbWeight::get().writes(12_u64)) + .saturating_add(RocksDbWeight::get().writes(13_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -1433,7 +1457,7 @@ impl WeightInfo for () { /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:1 w:1) /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) @@ -1449,12 +1473,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `485` + // Measured: `493` // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 100_000_000 picoseconds. - Weight::from_parts(107_476_765, 6078) - // Standard Error: 61_259 - .saturating_add(Weight::from_parts(27_610_007, 0).saturating_mul(n.into())) + // Minimum execution time: 101_000_000 picoseconds. + Weight::from_parts(102_689_064, 6078) + // Standard Error: 25_175 + .saturating_add(Weight::from_parts(27_553_304, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(7_u64)) @@ -1468,7 +1492,7 @@ impl WeightInfo for () { /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) - /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:10 w:10) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -1476,16 +1500,16 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `514` + // Measured: `522` // Estimated: `4466 + n * (2954 ±0)` - // Minimum execution time: 51_000_000 picoseconds. - Weight::from_parts(57_358_180, 4466) - // Standard Error: 54_968 - .saturating_add(Weight::from_parts(27_429_606, 0).saturating_mul(n.into())) + // Minimum execution time: 50_000_000 picoseconds. + Weight::from_parts(55_735_551, 4466) + // Standard Error: 34_490 + .saturating_add(Weight::from_parts(26_799_214, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } -} \ No newline at end of file +} diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs index 5ea1d9235..d96fd85bd 100644 --- a/runtime/devnet/src/config/api/mod.rs +++ b/runtime/devnet/src/config/api/mod.rs @@ -11,7 +11,7 @@ use sp_std::vec::Vec; use versioning::*; use crate::{ - config::assets::{NftsInstance, TrustBackedAssetsInstance}, + config::assets::{TrustBackedAssetsInstance, TrustBackedNftsInstance}, fungibles, nonfungibles, Runtime, RuntimeCall, RuntimeEvent, }; @@ -88,7 +88,7 @@ impl fungibles::Config for Runtime { } impl nonfungibles::Config for Runtime { - type NftsInstance = NftsInstance; + type NftsInstance = TrustBackedNftsInstance; type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } @@ -311,7 +311,13 @@ mod tests { }), NonFungibles(destroy { collection: 0, - witness: DestroyWitness { attributes: 0, item_configs: 0, item_metadatas: 0 }, + witness: DestroyWitness { + attributes: 0, + item_configs: 0, + item_metadatas: 0, + item_holders: 0, + allowances: 0, + }, }), NonFungibles(set_attribute { collection: 0, diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 97c2a9e7d..65405ea46 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -46,9 +46,9 @@ impl Get for KeyLimit { } } -pub(crate) type NftsInstance = pallet_nfts::Instance1; -pub type NftsCall = pallet_nfts::Call; -impl pallet_nfts::Config for Runtime { +pub(crate) type TrustBackedNftsInstance = pallet_nfts::Instance1; +pub type TrustBackedNftsCall = pallet_nfts::Call; +impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ApprovalsLimit = ConstU32<20>; type AttributeDepositBase = NftsAttributeDepositBase; @@ -97,8 +97,8 @@ impl pallet_nft_fractionalization::Config for Runtime { type Deposit = AssetDeposit; type NewAssetName = NewAssetName; type NewAssetSymbol = NewAssetSymbol; - type NftCollectionId = >::CollectionId; - type NftId = >::ItemId; + type NftCollectionId = >::CollectionId; + type NftId = >::ItemId; type Nfts = Nfts; type PalletId = NftFractionalizationPalletId; type RuntimeEvent = RuntimeEvent; diff --git a/runtime/devnet/src/config/proxy.rs b/runtime/devnet/src/config/proxy.rs index 161178dc5..486530276 100644 --- a/runtime/devnet/src/config/proxy.rs +++ b/runtime/devnet/src/config/proxy.rs @@ -5,7 +5,7 @@ use pop_runtime_common::proxy::{ }; use sp_runtime::traits::BlakeTwo256; -use super::assets::{NftsCall, TrustBackedAssetsCall}; +use super::assets::{TrustBackedAssetsCall, TrustBackedNftsCall}; use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; impl InstanceFilter for ProxyType { @@ -45,13 +45,13 @@ impl InstanceFilter for ProxyType { RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) | - RuntimeCall::Nfts(NftsCall::create { .. }) | - RuntimeCall::Nfts(NftsCall::destroy { .. }) | - RuntimeCall::Nfts(NftsCall::redeposit { .. }) | - RuntimeCall::Nfts(NftsCall::transfer_ownership { .. }) | - RuntimeCall::Nfts(NftsCall::set_team { .. }) | - RuntimeCall::Nfts(NftsCall::set_collection_max_supply { .. }) | - RuntimeCall::Nfts(NftsCall::lock_collection { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::create { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::destroy { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::redeposit { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::transfer_ownership { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_team { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_collection_max_supply { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_collection { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), @@ -66,17 +66,17 @@ impl InstanceFilter for ProxyType { RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) | - RuntimeCall::Nfts(NftsCall::force_mint { .. }) | - RuntimeCall::Nfts(NftsCall::update_mint_settings { .. }) | - RuntimeCall::Nfts(NftsCall::mint_pre_signed { .. }) | - RuntimeCall::Nfts(NftsCall::set_attributes_pre_signed { .. }) | - RuntimeCall::Nfts(NftsCall::lock_item_transfer { .. }) | - RuntimeCall::Nfts(NftsCall::unlock_item_transfer { .. }) | - RuntimeCall::Nfts(NftsCall::lock_item_properties { .. }) | - RuntimeCall::Nfts(NftsCall::set_metadata { .. }) | - RuntimeCall::Nfts(NftsCall::clear_metadata { .. }) | - RuntimeCall::Nfts(NftsCall::set_collection_metadata { .. }) | - RuntimeCall::Nfts(NftsCall::clear_collection_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::force_mint { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::update_mint_settings { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::mint_pre_signed { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_attributes_pre_signed { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_item_transfer { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::unlock_item_transfer { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_item_properties { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::clear_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_collection_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::clear_collection_metadata { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index 839f819dc..736f0be73 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -646,6 +646,7 @@ mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] [fungibles, Fungibles] + [nonfungibles, NonFungibles] [pallet_balances, Balances] [pallet_session, SessionBench::] [pallet_timestamp, Timestamp] From 9dd80cc0734236f8c052ae0353acf17677d4e26b Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 18 Nov 2024 12:14:46 +0700 Subject: [PATCH 60/76] chore: clippy --- pallets/nfts/src/benchmarking.rs | 2 +- pallets/nfts/src/features/create_delete_item.rs | 2 +- pallets/nfts/src/features/transfer.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pallets/nfts/src/benchmarking.rs b/pallets/nfts/src/benchmarking.rs index 58209b8bb..d8876d521 100644 --- a/pallets/nfts/src/benchmarking.rs +++ b/pallets/nfts/src/benchmarking.rs @@ -295,7 +295,7 @@ benchmarks_instance_pallet! { burn_item::(i as u16); } for i in 0..l { - approve_collection::(i as u32); + approve_collection::(i); } let witness = Collection::::get(collection).unwrap().destroy_witness(); }: _(SystemOrigin::Signed(caller), collection, witness) diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index a7b7ddf38..08cf5f951 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -73,7 +73,7 @@ impl, I: 'static> Pallet { let account_balance = AccountBalance::::mutate(collection, &mint_to, |balance| -> u32 { balance.saturating_inc(); - balance.clone() + *balance }); if account_balance == 1 { collection_details.item_holders.saturating_inc(); diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index dbe6f3b09..3f2dae3b9 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -91,7 +91,7 @@ impl, I: 'static> Pallet { let owner_balance = AccountBalance::::mutate(collection, &details.owner, |balance| -> u32 { balance.saturating_dec(); - balance.clone() + *balance }); if owner_balance == 0 { collection_details.item_holders.saturating_dec(); @@ -99,7 +99,7 @@ impl, I: 'static> Pallet { // Update account balance of the destination account. let dest_balance = AccountBalance::::mutate(collection, &dest, |balance| -> u32 { balance.saturating_inc(); - balance.clone() + *balance }); if dest_balance == 1 { collection_details.item_holders.saturating_inc(); From 73f49946f2dc5ef5c3785eaa4236dcf11bfe4393 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:59:35 +0700 Subject: [PATCH 61/76] chore: taplo fmt --- pallets/nfts/Cargo.toml | 8 ++++---- pallets/nfts/runtime-api/Cargo.toml | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pallets/nfts/Cargo.toml b/pallets/nfts/Cargo.toml index 791db0a73..bef584b85 100644 --- a/pallets/nfts/Cargo.toml +++ b/pallets/nfts/Cargo.toml @@ -1,5 +1,5 @@ [package] -authors = ["Parity Technologies ", "R0GUE "] +authors = [ "Parity Technologies ", "R0GUE " ] description = "Fork of FRAME NFTs pallet" edition.workspace = true homepage = "https://substrate.io" @@ -10,13 +10,13 @@ repository.workspace = true version = "31.0.0" [package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +targets = [ "x86_64-unknown-linux-gnu" ] [dependencies] codec = { workspace = true } enumflags2 = { workspace = true } log = { workspace = true } -scale-info = { features = ["derive"], workspace = true } +scale-info = { features = [ "derive" ], workspace = true } # Substrate frame-benchmarking = { optional = true, workspace = true } @@ -31,7 +31,7 @@ pallet-balances.workspace = true sp-keystore.workspace = true [features] -default = ["std"] +default = [ "std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", diff --git a/pallets/nfts/runtime-api/Cargo.toml b/pallets/nfts/runtime-api/Cargo.toml index d9a748d6c..503642ef0 100644 --- a/pallets/nfts/runtime-api/Cargo.toml +++ b/pallets/nfts/runtime-api/Cargo.toml @@ -1,5 +1,5 @@ [package] -authors = ["Parity Technologies ", "R0GUE "] +authors = [ "Parity Technologies ", "R0GUE " ] description = "Runtime API for the FRAME NFTs pallet." edition.workspace = true homepage = "https://substrate.io" @@ -13,13 +13,13 @@ version = "23.0.0" workspace = true [package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +targets = [ "x86_64-unknown-linux-gnu" ] [dependencies] -codec = { features = ["derive"], workspace = true } +codec = { features = [ "derive" ], workspace = true } pallet-nfts.workspace = true sp-api.workspace = true [features] -default = ["std"] -std = ["codec/std", "pallet-nfts/std", "sp-api/std"] +default = [ "std" ] +std = [ "codec/std", "pallet-nfts/std", "sp-api/std" ] From e303439a758cac88cefdc2d516ddce751abee648 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:51:59 +0700 Subject: [PATCH 62/76] fix: rebase & update integration tests --- pallets/api/src/nonfungibles/mod.rs | 38 +- pallets/api/src/nonfungibles/types.rs | 31 ++ pop-api/integration-tests/Cargo.toml | 2 + .../contracts/nonfungibles/lib.rs | 4 +- .../integration-tests/src/nonfungibles/mod.rs | 327 +++++++++++++----- .../src/nonfungibles/utils.rs | 56 ++- pop-api/src/v0/nonfungibles/mod.rs | 6 +- pop-api/src/v0/nonfungibles/types.rs | 10 + 8 files changed, 335 insertions(+), 139 deletions(-) create mode 100644 pallets/api/src/nonfungibles/types.rs diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index 6da7de5f1..4bdd99ce7 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -11,37 +11,17 @@ pub use pallet_nfts::{ CollectionSetting, CollectionSettings, DestroyWitness, ItemDeposit, ItemDetails, ItemMetadata, ItemSetting, MintSettings, MintType, MintWitness, }; -use sp_runtime::traits::StaticLookup; +use sp_runtime::{traits::StaticLookup, BoundedVec}; +use types::*; use weights::WeightInfo; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; #[cfg(test)] mod tests; +pub mod types; pub mod weights; -type AccountIdOf = ::AccountId; -type NftsOf = pallet_nfts::Pallet>; -type NftsErrorOf = pallet_nfts::Error>; -type NftsWeightInfoOf = >>::WeightInfo; -type NftsInstanceOf = ::NftsInstance; -type BalanceOf = <>>::Currency as Currency< - ::AccountId, ->>::Balance; -type CollectionIdOf = - as Inspect<::AccountId>>::CollectionId; -type ItemIdOf = as Inspect<::AccountId>>::ItemId; -type ItemPriceOf = BalanceOf; -type CollectionDetailsFor = CollectionDetails, BalanceOf>; -type AttributeNamespaceOf = AttributeNamespace>; -type CollectionConfigFor = - CollectionConfig, BlockNumberFor, CollectionIdOf>; -// Type aliases for pallet-nfts storage items. -pub(super) type AccountBalanceOf = pallet_nfts::AccountBalance>; -pub(super) type AttributeOf = pallet_nfts::Attribute>; -pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId>; -pub(super) type CollectionOf = pallet_nfts::Collection>; - #[frame_support::pallet] pub mod pallet { use frame_support::{ @@ -50,8 +30,6 @@ pub mod pallet { traits::Incrementable, }; use frame_system::pallet_prelude::*; - use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness, MintWitness}; - use sp_runtime::BoundedVec; use sp_std::vec::Vec; use super::*; @@ -104,7 +82,7 @@ pub mod pallet { /// The namespace of the attribute. namespace: AttributeNamespaceOf, /// The key of the attribute. - key: BoundedVec, + key: AttributeKey, }, /// Details of a specified collection. #[codec(index = 9)] @@ -354,8 +332,8 @@ pub mod pallet { collection: CollectionIdOf, item: Option>, namespace: AttributeNamespaceOf, - key: BoundedVec, - value: BoundedVec, + key: AttributeKey, + value: AttributeValue, ) -> DispatchResult { NftsOf::::set_attribute(origin, collection, item, namespace, key, value) } @@ -374,7 +352,7 @@ pub mod pallet { collection: CollectionIdOf, item: Option>, namespace: AttributeNamespaceOf, - key: BoundedVec, + key: AttributeKey, ) -> DispatchResult { NftsOf::::clear_attribute(origin, collection, item, namespace, key) } @@ -391,7 +369,7 @@ pub mod pallet { origin: OriginFor, collection: CollectionIdOf, item: ItemIdOf, - data: BoundedVec, + data: MetadataData, ) -> DispatchResult { NftsOf::::set_metadata(origin, collection, item, data) } diff --git a/pallets/api/src/nonfungibles/types.rs b/pallets/api/src/nonfungibles/types.rs new file mode 100644 index 000000000..e15d430b2 --- /dev/null +++ b/pallets/api/src/nonfungibles/types.rs @@ -0,0 +1,31 @@ +use super::*; + +pub(super) type AccountIdOf = ::AccountId; +pub(super) type NftsOf = pallet_nfts::Pallet>; +pub(super) type NftsErrorOf = pallet_nfts::Error>; +pub(super) type NftsWeightInfoOf = >>::WeightInfo; +pub(super) type NftsInstanceOf = ::NftsInstance; +pub(super) type BalanceOf = + <>>::Currency as Currency< + ::AccountId, + >>::Balance; +pub(super) type CollectionIdOf = + as Inspect<::AccountId>>::CollectionId; +pub(super) type ItemIdOf = + as Inspect<::AccountId>>::ItemId; +pub(super) type ItemPriceOf = BalanceOf; +pub(super) type CollectionDetailsFor = CollectionDetails, BalanceOf>; +pub(super) type AttributeNamespaceOf = AttributeNamespace>; +pub(super) type CollectionConfigFor = + CollectionConfig, BlockNumberFor, CollectionIdOf>; +// Public due to pop-api integration tests crate. +pub type AccountBalanceOf = pallet_nfts::AccountBalance>; +pub type AttributeOf = pallet_nfts::Attribute>; +pub type AttributeKey = BoundedVec>>::KeyLimit>; +pub type AttributeValue = + BoundedVec>>::ValueLimit>; +pub type CollectionOf = pallet_nfts::Collection>; +pub type CollectionConfigOf = pallet_nfts::CollectionConfigOf>; +pub type NextCollectionIdOf = pallet_nfts::NextCollectionId>; +pub type MetadataData = + BoundedVec>>::StringLimit>; diff --git a/pop-api/integration-tests/Cargo.toml b/pop-api/integration-tests/Cargo.toml index f87cdddb8..edc7017f4 100644 --- a/pop-api/integration-tests/Cargo.toml +++ b/pop-api/integration-tests/Cargo.toml @@ -13,6 +13,7 @@ frame-support = { version = "36.0.0", default-features = false } frame-support-procedural = { version = "=30.0.1", default-features = false } frame-system = { version = "36.1.0", default-features = false } log = "0.4.22" +pallet-api = { path = "../../pallets/api", default-features = false } pallet-assets = { version = "37.0.0", default-features = false } pallet-balances = { version = "37.0.0", default-features = false } pallet-contracts = { version = "35.0.0", default-features = false } @@ -38,6 +39,7 @@ devnet = [ ] std = [ "frame-support/std", "frame-system/std", + "pallet-api/std", "pallet-assets/std", "pallet-balances/std", "pallet-contracts/std", diff --git a/pop-api/integration-tests/contracts/nonfungibles/lib.rs b/pop-api/integration-tests/contracts/nonfungibles/lib.rs index 134467914..717498a10 100644 --- a/pop-api/integration-tests/contracts/nonfungibles/lib.rs +++ b/pop-api/integration-tests/contracts/nonfungibles/lib.rs @@ -54,11 +54,11 @@ mod nonfungibles { pub fn allowance( &self, collection: CollectionId, + item: Option, owner: AccountId, operator: AccountId, - item: Option, ) -> Result { - api::allowance(collection, owner, operator, item) + api::allowance(collection, item, owner, operator) } #[ink(message)] diff --git a/pop-api/integration-tests/src/nonfungibles/mod.rs b/pop-api/integration-tests/src/nonfungibles/mod.rs index c92652c08..5c236f9f5 100644 --- a/pop-api/integration-tests/src/nonfungibles/mod.rs +++ b/pop-api/integration-tests/src/nonfungibles/mod.rs @@ -1,8 +1,10 @@ use frame_support::BoundedVec; +use pallet_api::nonfungibles::types::*; use pop_api::{ nonfungibles::{ events::{Approval, AttributeSet, Transfer}, - types::*, + AttributeNamespace, CancelAttributesApprovalWitness, CollectionConfig, CollectionDetails, + CollectionId, CollectionSettings, DestroyWitness, ItemId, MintSettings, MintWitness, }, primitives::BlockNumber, }; @@ -13,8 +15,8 @@ use super::*; mod utils; -const COLLECTION_ID: CollectionId = 0; -const ITEM_ID: ItemId = 1; +const COLLECTION: CollectionId = 0; +const ITEM: ItemId = 0; const CONTRACT: &str = "contracts/nonfungibles/target/ink/nonfungibles.wasm"; #[test] @@ -22,20 +24,20 @@ fn total_supply_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - // No tokens in circulation. + // No collection item is created. assert_eq!( - total_supply(&addr, COLLECTION_ID), - Ok(Nfts::collection_items(COLLECTION_ID).unwrap_or_default() as u128) + total_supply(&addr, COLLECTION), + Ok(Nfts::collection_items(COLLECTION).unwrap_or_default() as u128) ); - assert_eq!(total_supply(&addr, COLLECTION_ID), Ok(0)); + assert_eq!(total_supply(&addr, COLLECTION), Ok(0)); - // Tokens in circulation. - nfts::create_collection_and_mint_to(&addr, &addr, &ALICE, ITEM_ID); + // Collection item is created. + nfts::create_collection_and_mint_to(&addr, &addr, &ALICE, ITEM); assert_eq!( - total_supply(&addr, COLLECTION_ID), - Ok(Nfts::collection_items(COLLECTION_ID).unwrap_or_default() as u128) + total_supply(&addr, COLLECTION), + Ok(Nfts::collection_items(COLLECTION).unwrap_or_default() as u128) ); - assert_eq!(total_supply(&addr, COLLECTION_ID), Ok(1)); + assert_eq!(total_supply(&addr, COLLECTION), Ok(1)); }); } @@ -44,20 +46,14 @@ fn balance_of_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - // No tokens in circulation. - assert_eq!( - balance_of(&addr, COLLECTION_ID, ALICE), - Ok(nfts::balance_of(COLLECTION_ID, ALICE)), - ); - assert_eq!(total_supply(&addr, COLLECTION_ID), Ok(0)); + // No collection item is created. + assert_eq!(balance_of(&addr, COLLECTION, ALICE), Ok(nfts::balance_of(COLLECTION, ALICE)),); + assert_eq!(total_supply(&addr, COLLECTION), Ok(0)); - // Tokens in circulation. - nfts::create_collection_and_mint_to(&addr, &addr, &ALICE, ITEM_ID); - assert_eq!( - balance_of(&addr, COLLECTION_ID, ALICE), - Ok(nfts::balance_of(COLLECTION_ID, ALICE)), - ); - assert_eq!(total_supply(&addr, COLLECTION_ID), Ok(1)); + // Collection item is created. + nfts::create_collection_and_mint_to(&addr, &addr, &ALICE, ITEM); + assert_eq!(balance_of(&addr, COLLECTION, ALICE), Ok(nfts::balance_of(COLLECTION, ALICE)),); + assert_eq!(total_supply(&addr, COLLECTION), Ok(1)); }); } @@ -65,23 +61,20 @@ fn balance_of_works() { fn allowance_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - // No tokens in circulation. + // No collection item is created. assert_eq!( - allowance(&addr.clone(), COLLECTION_ID, addr.clone(), ALICE, None), - Ok(!Nfts::check_allowance(&COLLECTION_ID, &None, &addr, &ALICE).is_err()), + allowance(&addr.clone(), COLLECTION, None, addr.clone(), ALICE), + Ok(!Nfts::check_allowance(&COLLECTION, &None, &addr, &ALICE).is_err()), ); - assert_eq!(allowance(&addr.clone(), COLLECTION_ID, addr.clone(), ALICE, None), Ok(false)); + assert_eq!(allowance(&addr.clone(), COLLECTION, None, addr.clone(), ALICE), Ok(false)); - let (_, item) = - nfts::create_collection_mint_and_approve(&addr, &addr, ITEM_ID, &addr, &ALICE); + // Collection item is created. + let (_, item) = nfts::create_collection_mint_and_approve(&addr, &addr, ITEM, &addr, &ALICE); assert_eq!( - allowance(&addr.clone(), COLLECTION_ID, addr.clone(), ALICE, Some(item)), - Ok(Nfts::check_allowance(&COLLECTION_ID, &Some(item), &addr.clone(), &ALICE).is_ok()), - ); - assert_eq!( - allowance(&addr.clone(), COLLECTION_ID, addr.clone(), ALICE, Some(item)), - Ok(true) + allowance(&addr.clone(), COLLECTION, Some(item), addr.clone(), ALICE), + Ok(Nfts::check_allowance(&COLLECTION, &Some(item), &addr.clone(), &ALICE).is_ok()), ); + assert_eq!(allowance(&addr.clone(), COLLECTION, Some(item), addr.clone(), ALICE), Ok(true)); }); } @@ -90,24 +83,86 @@ fn transfer_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); - let before_transfer_balance = nfts::balance_of(COLLECTION_ID, ALICE); + // Collection item does not exist. + assert_eq!( + transfer(&addr, COLLECTION, ITEM, ALICE), + Err(Module { index: 50, error: [1, 0] }) + ); + // Create a collection and mint to a contract address. + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); + // Privilege to transfer a collection item is locked. + nfts::lock_item_transfer(&addr, COLLECTION, ITEM); + assert_eq!( + transfer(&addr, COLLECTION, ITEM, ALICE), + Err(Module { index: 50, error: [12, 0] }) + ); + nfts::unlock_item_transfer(&addr, COLLECTION, ITEM); + // Successful transfer. + let before_transfer_balance = nfts::balance_of(COLLECTION, ALICE); assert_ok!(transfer(&addr, collection, item, ALICE)); - let after_transfer_balance = nfts::balance_of(COLLECTION_ID, ALICE); + let after_transfer_balance = nfts::balance_of(COLLECTION, ALICE); assert_eq!(after_transfer_balance - before_transfer_balance, 1); + // Successfully emit event. + let from = account_id_from_slice(addr.as_ref()); + let to = account_id_from_slice(ALICE.as_ref()); + let expected = Transfer { from: Some(from), to: Some(to), item: ITEM }.encode(); + assert_eq!(last_contract_event(), expected.as_slice()); + // Collection item does not exist, i.e. burnt. + nfts::burn(COLLECTION, ITEM, &ALICE); + assert_eq!( + transfer(&addr, COLLECTION, ITEM, ALICE), + Err(Module { index: 50, error: [20, 0] }) + ); }); } #[test] -fn approve_works() { +fn approve_item_transfer_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + // Collection item does not exist. + assert_eq!( + approve(&addr, COLLECTION, Some(ITEM), ALICE, true), + Err(Module { index: 50, error: [20, 0] }) + ); + // Successful approvals. + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); assert_ok!(approve(&addr, collection, Some(item), ALICE, true)); - assert!(Nfts::check_allowance(&collection, &Some(item), &addr.clone(), &ALICE).is_ok(),); + assert!(Nfts::check_allowance(&collection, &Some(item), &addr.clone(), &ALICE).is_ok()); + // Successfully emit event. + let owner = account_id_from_slice(addr.as_ref()); + let operator = account_id_from_slice(ALICE.as_ref()); + let expected = Approval { owner, operator, item: Some(item), approved: true }.encode(); + assert_eq!(last_contract_event(), expected.as_slice()); + // New value overrides old value. + assert_ok!(approve(&addr, collection, Some(item), ALICE, false)); + assert!(Nfts::check_allowance(&collection, &Some(item), &addr.clone(), &ALICE).is_err()); + }); +} - assert_ok!(Nfts::transfer(RuntimeOrigin::signed(ALICE), collection, item, BOB.into())); +#[test] +fn approve_collection_transfer_works() { + new_test_ext().execute_with(|| { + let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + + // Collection does not exist. + assert_eq!( + approve(&addr, COLLECTION, None, ALICE, true), + Err(Module { index: 50, error: [1, 0] }) + ); + // Successful approvals. + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); + assert_ok!(approve(&addr, collection, None, ALICE, true)); + assert!(Nfts::check_allowance(&collection, &None, &addr.clone(), &ALICE).is_ok()); + // Successfully emit event. + let owner = account_id_from_slice(addr.as_ref()); + let operator = account_id_from_slice(ALICE.as_ref()); + let expected = Approval { owner, operator, item: None, approved: true }.encode(); + assert_eq!(last_contract_event(), expected.as_slice()); + // New value overrides old value. + assert_ok!(approve(&addr, collection, None, ALICE, false)); + assert!(Nfts::check_allowance(&collection, &None, &addr.clone(), &ALICE).is_err()); }); } @@ -115,7 +170,7 @@ fn approve_works() { fn owner_of_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &ALICE, ITEM_ID); + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &ALICE, ITEM); assert_eq!(owner_of(&addr, collection, item), Ok(ALICE)); }); } @@ -125,7 +180,7 @@ fn get_attribute_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); assert_ok!(Nfts::set_attribute( RuntimeOrigin::signed(addr.clone()), @@ -153,7 +208,7 @@ fn set_attribute_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); assert_ok!(set_attribute( &addr.clone(), @@ -165,14 +220,14 @@ fn set_attribute_works() { )); assert_eq!( - pallet_nfts::Attribute::::get(( + AttributeOf::::get(( collection, Some(item), pallet_nfts::AttributeNamespace::CollectionOwner, - AttributeKey::truncate_from("some attribute".as_bytes().to_vec()), + AttributeKey::::truncate_from("some attribute".as_bytes().to_vec()), )) .map(|attribute| attribute.0), - Some(AttributeValue::truncate_from("some value".as_bytes().to_vec())) + Some(AttributeValue::::truncate_from("some value".as_bytes().to_vec())) ); }); } @@ -182,7 +237,7 @@ fn clear_attribute_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); assert_ok!(Nfts::set_attribute( RuntimeOrigin::signed(addr.clone()), collection, @@ -199,11 +254,11 @@ fn clear_attribute_works() { "some attribute".as_bytes().to_vec() )); assert_eq!( - pallet_nfts::Attribute::::get(( + AttributeOf::::get(( collection, Some(item), pallet_nfts::AttributeNamespace::CollectionOwner, - AttributeKey::truncate_from("some attribute".as_bytes().to_vec()), + AttributeKey::::truncate_from("some attribute".as_bytes().to_vec()), )) .map(|attribute| attribute.0), None @@ -216,7 +271,7 @@ fn approve_item_attributes_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); assert_ok!(approve_item_attributes(&addr.clone(), collection, item, ALICE)); assert_ok!(Nfts::set_attribute( RuntimeOrigin::signed(ALICE), @@ -227,14 +282,14 @@ fn approve_item_attributes_works() { BoundedVec::truncate_from("some value".as_bytes().to_vec()), )); assert_eq!( - pallet_nfts::Attribute::::get(( + AttributeOf::::get(( collection, Some(item), pallet_nfts::AttributeNamespace::Account(ALICE), - AttributeKey::truncate_from("some attribute".as_bytes().to_vec()), + AttributeKey::::truncate_from("some attribute".as_bytes().to_vec()), )) .map(|attribute| attribute.0), - Some(AttributeValue::truncate_from("some value".as_bytes().to_vec())) + Some(AttributeValue::::truncate_from("some value".as_bytes().to_vec())) ); }); } @@ -244,7 +299,7 @@ fn cancel_item_attributes_approval_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); assert_ok!(Nfts::approve_item_attributes( RuntimeOrigin::signed(addr.clone()), collection, @@ -283,9 +338,21 @@ fn set_metadata_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + // Collection does not exist. + assert_eq!( + set_metadata(&addr.clone(), COLLECTION, ITEM, vec![]), + Err(Module { index: 50, error: [0, 0] }) + ); + // No Permission. + let (collection, item) = nfts::create_collection_and_mint_to(&ALICE, &ALICE, &ALICE, ITEM); + assert_eq!( + set_metadata(&addr.clone(), collection, item, vec![]), + Err(Module { index: 50, error: [0, 0] }), + ); + // Successful set metadata. + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); assert_ok!(set_metadata(&addr.clone(), collection, item, vec![])); - assert_eq!(Nfts::item_metadata(collection, item), Some(MetadataData::default())); + assert_eq!(Nfts::item_metadata(collection, item), Some(MetadataData::::default())); }); } @@ -294,12 +361,18 @@ fn clear_metadata_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); + // Collection does not exist. + assert_eq!( + clear_metadata(&addr.clone(), COLLECTION, ITEM), + Err(Module { index: 50, error: [0, 0] }) + ); + // Successful clear metadata. + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); assert_ok!(Nfts::set_metadata( RuntimeOrigin::signed(addr.clone()), collection, item, - MetadataData::default() + MetadataData::::default() )); assert_ok!(clear_metadata(&addr.clone(), collection, item)); assert_eq!(Nfts::item_metadata(collection, item), None); @@ -322,7 +395,7 @@ fn create_works() { } )); assert_eq!( - pallet_nfts::Collection::::get(collection), + CollectionOf::::get(collection), Some(pallet_nfts::CollectionDetails { owner: addr.clone(), owner_deposit: 100000000000, @@ -330,6 +403,8 @@ fn create_works() { item_metadatas: 0, item_configs: 0, attributes: 0, + item_holders: 0, + allowances: 0 }) ); }); @@ -340,13 +415,51 @@ fn destroy_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + // Collection does not exist. + assert_eq!( + destroy( + &addr.clone(), + COLLECTION, + DestroyWitness { + item_metadatas: 0, + item_configs: 0, + attributes: 0, + item_holders: 0, + allowances: 0 + } + ), + Err(Module { index: 50, error: [1, 0] }) + ); + // Destroying can only be done by the collection owner. + let collection = nfts::create_collection(&ALICE, &ALICE); + assert_eq!( + destroy( + &addr.clone(), + collection, + DestroyWitness { + item_metadatas: 0, + item_configs: 0, + attributes: 0, + item_holders: 0, + allowances: 0 + } + ), + Err(Module { index: 50, error: [0, 0] }) + ); + // Successful destroy. let collection = nfts::create_collection(&addr, &addr); assert_ok!(destroy( &addr.clone(), collection, - DestroyWitness { item_metadatas: 0, item_configs: 0, attributes: 0 } + DestroyWitness { + item_metadatas: 0, + item_configs: 0, + attributes: 0, + item_holders: 0, + allowances: 0 + } )); - assert_eq!(pallet_nfts::Collection::::get(collection), None); + assert_eq!(CollectionOf::::get(collection), None); }); } @@ -356,26 +469,18 @@ fn set_max_supply_works() { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); let value = 10; + // Collection does not exist. + assert_eq!( + set_max_supply(&addr.clone(), COLLECTION, value), + Err(Module { index: 50, error: [32, 0] }) + ); + // Sucessfully set max supply. let collection = nfts::create_collection(&addr, &addr); assert_ok!(set_max_supply(&addr.clone(), collection, value)); - - (0..value).into_iter().for_each(|i| { - assert_ok!(Nfts::mint( - RuntimeOrigin::signed(addr.clone()), - collection, - i, - ALICE.into(), - None - )); - }); - assert!(Nfts::mint( - RuntimeOrigin::signed(addr.clone()), - collection, - value + 1, - ALICE.into(), - None - ) - .is_err()); + assert_eq!(nfts::max_supply(collection), Some(value)); + // Non-additive, sets new value. + assert_ok!(set_max_supply(&addr.clone(), collection, value + 1)); + assert_eq!(nfts::max_supply(collection), Some(value + 1)); }); } @@ -385,15 +490,50 @@ fn mint_works() { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); let value = 10; + // Collection does not exist. + assert_eq!( + mint( + &addr.clone(), + ALICE, + COLLECTION, + ITEM, + MintWitness { mint_price: None, owned_item: None } + ), + Err(Module { index: 50, error: [32, 0] }) + ); + // Mitning can only be done by the collection owner. + let collection = nfts::create_collection(&ALICE, &ALICE); + assert_eq!( + mint( + &addr.clone(), + ALICE, + collection, + ITEM, + MintWitness { mint_price: None, owned_item: None } + ), + Err(Module { index: 50, error: [0, 0] }) + ); + // Successful mint. let collection = nfts::create_collection(&addr, &addr); assert_ok!(mint( &addr.clone(), ALICE, collection, - ITEM_ID, - MintWitness { mint_price: None, owned_item: None } + ITEM, + MintWitness { owned_item: None, mint_price: None } )); - assert_eq!(nfts::balance_of(COLLECTION_ID, ALICE), 1); + assert_eq!(nfts::balance_of(collection, ALICE), 1); + // Minting an existing item ID. + assert_eq!( + mint( + &addr.clone(), + ALICE, + collection, + ITEM, + MintWitness { owned_item: None, mint_price: None } + ), + Err(Module { index: 50, error: [2, 0] }) + ); }); } @@ -402,8 +542,17 @@ fn burn_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM_ID); - assert_ok!(burn(&addr.clone(), collection, ITEM_ID,)); - assert_eq!(nfts::balance_of(COLLECTION_ID, addr), 0); + // Collection item does not exist. + assert_eq!( + burn(&addr.clone(), COLLECTION, ITEM), + Err(Module { index: 50, error: [20, 0] }) + ); + // Burning can only be done by the collection item owner. + let (collection, item) = nfts::create_collection_and_mint_to(&ALICE, &ALICE, &BOB, ITEM); + assert_eq!(burn(&addr.clone(), collection, item), Err(Module { index: 50, error: [0, 0] })); + // Successful burn. + let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); + assert_ok!(burn(&addr.clone(), collection, item)); + assert_eq!(nfts::balance_of(COLLECTION, addr.clone()), 0); }); } diff --git a/pop-api/integration-tests/src/nonfungibles/utils.rs b/pop-api/integration-tests/src/nonfungibles/utils.rs index 0c1c3c19b..48d4dbaae 100644 --- a/pop-api/integration-tests/src/nonfungibles/utils.rs +++ b/pop-api/integration-tests/src/nonfungibles/utils.rs @@ -1,9 +1,5 @@ use super::*; -pub(super) type AttributeKey = BoundedVec::KeyLimit>; -pub(super) type AttributeValue = BoundedVec::ValueLimit>; -pub(super) type MetadataData = BoundedVec::StringLimit>; - pub(super) fn total_supply(addr: &AccountId32, collection: CollectionId) -> Result { let result = do_bare_call("total_supply", addr, collection.encode()); decoded::>(result.clone()) @@ -24,11 +20,11 @@ pub(super) fn balance_of( pub(super) fn allowance( addr: &AccountId32, collection: CollectionId, + item: Option, owner: AccountId32, operator: AccountId32, - item: Option, ) -> Result { - let params = [collection.encode(), owner.encode(), operator.encode(), item.encode()].concat(); + let params = [collection.encode(), item.encode(), owner.encode(), operator.encode()].concat(); let result = do_bare_call("allowance", &addr, params); decoded::>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) @@ -82,11 +78,11 @@ pub(super) fn get_attribute( collection.encode(), item.encode(), namespace.encode(), - AttributeKey::truncate_from(key).encode(), + AttributeKey::::truncate_from(key).encode(), ] .concat(); let result = do_bare_call("get_attribute", &addr, params); - decoded::, Error>>(result.clone()) + decoded::>, Error>>(result.clone()) .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) .map(|value| value.map(|v| v.to_vec())) } @@ -134,8 +130,8 @@ pub(super) fn set_attribute( collection.encode(), item.encode(), namespace.encode(), - AttributeKey::truncate_from(key).encode(), - AttributeValue::truncate_from(value).encode(), + AttributeKey::::truncate_from(key).encode(), + AttributeValue::::truncate_from(value).encode(), ] .concat(); let result = do_bare_call("set_attribute", &addr, params); @@ -293,10 +289,6 @@ pub(super) mod nfts { next_id } - pub(crate) fn next_collection_id() -> u32 { - pallet_nfts::NextCollectionId::::get().unwrap_or_default() - } - pub(crate) fn mint( collection: CollectionId, item: ItemId, @@ -313,8 +305,38 @@ pub(super) mod nfts { item } + pub(crate) fn burn(collection: CollectionId, item: ItemId, owner: &AccountId32) { + assert_ok!(Nfts::burn(RuntimeOrigin::signed(owner.clone()), collection, item)); + } + + pub(crate) fn lock_item_transfer(owner: &AccountId32, collection: CollectionId, item: ItemId) { + assert_ok!(Nfts::lock_item_transfer( + RuntimeOrigin::signed(owner.clone()), + collection, + item + )); + } + + pub(crate) fn unlock_item_transfer( + owner: &AccountId32, + collection: CollectionId, + item: ItemId, + ) { + assert_ok!(Nfts::unlock_item_transfer( + RuntimeOrigin::signed(owner.clone()), + collection, + item + )); + } + pub(crate) fn balance_of(collection: CollectionId, owner: AccountId32) -> u32 { - pallet_nfts::AccountBalance::::get(collection, owner) + AccountBalanceOf::::get(collection, owner) + } + + pub(crate) fn max_supply(collection: CollectionId) -> Option { + CollectionConfigOf::::get(collection) + .map(|config| config.max_supply) + .unwrap_or_default() } pub(super) fn collection_config_with_all_settings_enabled( @@ -325,4 +347,8 @@ pub(super) mod nfts { mint_settings: pallet_nfts::MintSettings::default(), } } + + pub(crate) fn next_collection_id() -> u32 { + NextCollectionIdOf::::get().unwrap_or_default() + } } diff --git a/pop-api/src/v0/nonfungibles/mod.rs b/pop-api/src/v0/nonfungibles/mod.rs index 7b2bd187e..438b7fa54 100644 --- a/pop-api/src/v0/nonfungibles/mod.rs +++ b/pop-api/src/v0/nonfungibles/mod.rs @@ -44,15 +44,15 @@ pub fn balance_of(collection: CollectionId, owner: AccountId) -> Result { #[inline] pub fn allowance( collection: CollectionId, + item: Option, owner: AccountId, operator: AccountId, - item: Option, ) -> Result { build_read_state(ALLOWANCE) - .input::<(CollectionId, AccountId, AccountId, Option)>() + .input::<(CollectionId, Option, AccountId, AccountId)>() .output::, true>() .handle_error_code::() - .call(&(collection, owner, operator, item)) + .call(&(collection, item, owner, operator)) } #[inline] diff --git a/pop-api/src/v0/nonfungibles/types.rs b/pop-api/src/v0/nonfungibles/types.rs index c630f04b9..5cd725ae5 100644 --- a/pop-api/src/v0/nonfungibles/types.rs +++ b/pop-api/src/v0/nonfungibles/types.rs @@ -22,8 +22,12 @@ pub struct CollectionDetails { pub item_metadatas: u32, /// The total number of outstanding item configs of this collection. pub item_configs: u32, + /// The total number of accounts that hold items of the collection. + pub item_holders: u32, /// The total number of attributes for this collection. pub attributes: u32, + /// The total number of allowances to spend all items within collections. + pub allowances: u32, } /// Attribute namespaces for non-fungible tokens. @@ -69,9 +73,15 @@ pub struct DestroyWitness { /// The total number of outstanding item configs of this collection. #[codec(compact)] pub item_configs: u32, + /// The total number of accounts that hold items of the collection. + #[codec(compact)] + pub item_holders: u32, /// The total number of attributes for this collection. #[codec(compact)] pub attributes: u32, + /// The total number of allowances to spend all items within collections. + #[codec(compact)] + pub allowances: u32, } /// Witness data for items mint transactions. From 515176ca84786ed172fc45aa3ab98ef81422aa61 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:54:30 +0700 Subject: [PATCH 63/76] chore: reformatting --- pallets/api/src/nonfungibles/mod.rs | 15 ++++++--------- pallets/nfts/Cargo.toml | 8 ++++---- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index e60a9c151..4bdd99ce7 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -544,22 +544,19 @@ pub mod pallet { TotalSupply(collection) => ReadResult::TotalSupply( NftsOf::::collection_items(collection).unwrap_or_default() as u128, ), - BalanceOf { collection, owner } => { - ReadResult::BalanceOf(AccountBalanceOf::::get(collection, owner)) - }, + BalanceOf { collection, owner } => + ReadResult::BalanceOf(AccountBalanceOf::::get(collection, owner)), Allowance { collection, owner, operator, item } => ReadResult::Allowance( NftsOf::::check_allowance(&collection, &item, &owner, &operator).is_ok(), ), - OwnerOf { collection, item } => { - ReadResult::OwnerOf(NftsOf::::owner(collection, item)) - }, + OwnerOf { collection, item } => + ReadResult::OwnerOf(NftsOf::::owner(collection, item)), GetAttribute { collection, item, namespace, key } => ReadResult::GetAttribute( AttributeOf::::get((collection, Some(item), namespace, key)) .map(|attribute| attribute.0.into()), ), - Collection(collection) => { - ReadResult::Collection(CollectionOf::::get(collection)) - }, + Collection(collection) => + ReadResult::Collection(CollectionOf::::get(collection)), ItemMetadata { collection, item } => ReadResult::ItemMetadata( NftsOf::::item_metadata(collection, item).map(|metadata| metadata.into()), ), diff --git a/pallets/nfts/Cargo.toml b/pallets/nfts/Cargo.toml index 791db0a73..bef584b85 100644 --- a/pallets/nfts/Cargo.toml +++ b/pallets/nfts/Cargo.toml @@ -1,5 +1,5 @@ [package] -authors = ["Parity Technologies ", "R0GUE "] +authors = [ "Parity Technologies ", "R0GUE " ] description = "Fork of FRAME NFTs pallet" edition.workspace = true homepage = "https://substrate.io" @@ -10,13 +10,13 @@ repository.workspace = true version = "31.0.0" [package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] +targets = [ "x86_64-unknown-linux-gnu" ] [dependencies] codec = { workspace = true } enumflags2 = { workspace = true } log = { workspace = true } -scale-info = { features = ["derive"], workspace = true } +scale-info = { features = [ "derive" ], workspace = true } # Substrate frame-benchmarking = { optional = true, workspace = true } @@ -31,7 +31,7 @@ pallet-balances.workspace = true sp-keystore.workspace = true [features] -default = ["std"] +default = [ "std" ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", From e836ccb88f9c58fcf7d789650893b0f0fc9470a2 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:22:18 +0700 Subject: [PATCH 64/76] chore: feature gating integration tests --- pop-api/integration-tests/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pop-api/integration-tests/src/lib.rs b/pop-api/integration-tests/src/lib.rs index 4738d010a..a396c3a5e 100644 --- a/pop-api/integration-tests/src/lib.rs +++ b/pop-api/integration-tests/src/lib.rs @@ -16,7 +16,9 @@ use scale::{Decode, Encode}; use sp_runtime::{AccountId32, BuildStorage, DispatchError}; use utils::*; +#[cfg(any(feature = "devnet", feature = "testnet"))] mod fungibles; +#[cfg(any(feature = "devnet"))] mod nonfungibles; mod utils; From 841035a7b5d871d4be2b94f9d6430a86262e3f5d Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 19 Nov 2024 13:53:57 +0700 Subject: [PATCH 65/76] feat: add pallet-api/nonfungibles --- Cargo.lock | 7 +- pallets/api/Cargo.toml | 4 + pallets/api/src/lib.rs | 1 + pallets/api/src/mock.rs | 93 +- pallets/api/src/nonfungibles/benchmarking.rs | 110 ++ pallets/api/src/nonfungibles/mod.rs | 591 +++++++++++ pallets/api/src/nonfungibles/tests.rs | 1003 ++++++++++++++++++ pallets/api/src/nonfungibles/weights.rs | 217 ++++ 8 files changed, 2020 insertions(+), 6 deletions(-) create mode 100644 pallets/api/src/nonfungibles/benchmarking.rs create mode 100644 pallets/api/src/nonfungibles/mod.rs create mode 100644 pallets/api/src/nonfungibles/tests.rs create mode 100644 pallets/api/src/nonfungibles/weights.rs diff --git a/Cargo.lock b/Cargo.lock index d2bf2acec..3414de0bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -822,7 +822,7 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object 0.36.4", + "object 0.36.0", "rustc-demangle", ] @@ -7195,9 +7195,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] @@ -7366,6 +7366,7 @@ dependencies = [ "log", "pallet-assets", "pallet-balances", + "pallet-nfts 31.0.0", "parity-scale-codec", "pop-chain-extension", "scale-info", diff --git a/pallets/api/Cargo.toml b/pallets/api/Cargo.toml index 55a007895..31ccc076d 100644 --- a/pallets/api/Cargo.toml +++ b/pallets/api/Cargo.toml @@ -22,6 +22,7 @@ frame-benchmarking.workspace = true frame-support.workspace = true frame-system.workspace = true pallet-assets.workspace = true +pallet-nfts.workspace = true sp-runtime.workspace = true sp-std.workspace = true @@ -37,6 +38,7 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-assets/runtime-benchmarks", + "pallet-nfts/runtime-benchmarks", "pop-chain-extension/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] @@ -47,6 +49,7 @@ std = [ "frame-system/std", "pallet-assets/std", "pallet-balances/std", + "pallet-nfts/std", "pop-chain-extension/std", "scale-info/std", "sp-core/std", @@ -57,5 +60,6 @@ std = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", + "pallet-nfts/try-runtime", "sp-runtime/try-runtime", ] diff --git a/pallets/api/src/lib.rs b/pallets/api/src/lib.rs index d94d19788..e3d706e2d 100644 --- a/pallets/api/src/lib.rs +++ b/pallets/api/src/lib.rs @@ -7,6 +7,7 @@ pub mod extension; pub mod fungibles; #[cfg(test)] mod mock; +pub mod nonfungibles; /// Trait for performing reads of runtime state. pub trait Read { diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs index 42c8bf0e2..d11a8c983 100644 --- a/pallets/api/src/mock.rs +++ b/pallets/api/src/mock.rs @@ -1,11 +1,14 @@ +use codec::{Decode, Encode}; use frame_support::{ derive_impl, parameter_types, - traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, Everything}, + traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, ConstU64, Everything}, }; use frame_system::{EnsureRoot, EnsureSigned}; +use pallet_nfts::PalletFeatures; +use scale_info::TypeInfo; use sp_core::H256; use sp_runtime::{ - traits::{BlakeTwo256, IdentityLookup}, + traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Lazy, Verify}, BuildStorage, }; @@ -29,6 +32,8 @@ frame_support::construct_runtime!( Assets: pallet_assets::, Balances: pallet_balances, Fungibles: crate::fungibles, + Nfts: pallet_nfts::, + NonFungibles: crate::nonfungibles } ); @@ -91,7 +96,7 @@ impl pallet_assets::Config for Test { #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); type CallbackHandle = (); - type CreateOrigin = AsEnsureOriginWithArg>; + type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; type Extra = (); type ForceOrigin = EnsureRoot; @@ -110,6 +115,88 @@ impl crate::fungibles::Config for Test { type WeightInfo = (); } +parameter_types! { + pub storage Features: PalletFeatures = PalletFeatures::all_enabled(); +} + +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, TypeInfo)] +pub struct Noop; + +impl IdentifyAccount for Noop { + type AccountId = AccountId; + + fn into_account(self) -> Self::AccountId { + 0 + } +} + +impl Verify for Noop { + type Signer = Noop; + + fn verify>( + &self, + _msg: L, + _signer: &::AccountId, + ) -> bool { + false + } +} + +#[cfg(feature = "runtime-benchmarks")] +impl pallet_nfts::pallet::BenchmarkHelper for () { + fn collection(i: u16) -> u32 { + i.into() + } + + fn item(i: u16) -> u32 { + i.into() + } + + fn signer() -> (Noop, u64) { + unimplemented!() + } + + fn sign(signer: &Noop, message: &[u8]) -> Noop { + unimplemented!() + } +} + +type NftsInstance = pallet_nfts::Instance1; +impl pallet_nfts::Config for Test { + type ApprovalsLimit = ConstU32<10>; + type AttributeDepositBase = ConstU128<1>; + type CollectionDeposit = ConstU128<2>; + type CollectionId = u32; + type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type DepositPerByte = ConstU128<1>; + type Features = Features; + type ForceOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); + type ItemAttributesApprovalsLimit = ConstU32<2>; + type ItemDeposit = ConstU128<1>; + type ItemId = u32; + type KeyLimit = ConstU32<50>; + type Locker = (); + type MaxAttributesPerCall = ConstU32<2>; + type MaxDeadlineDuration = ConstU64<10000>; + type MaxTips = ConstU32<10>; + type MetadataDepositBase = ConstU128<1>; + type OffchainPublic = Noop; + type OffchainSignature = Noop; + type RuntimeEvent = RuntimeEvent; + type StringLimit = ConstU32<50>; + type ValueLimit = ConstU32<50>; + type WeightInfo = (); +} + +impl crate::nonfungibles::Config for Test { + type NftsInstance = NftsInstance; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); +} + pub(crate) fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::::default() .build_storage() diff --git a/pallets/api/src/nonfungibles/benchmarking.rs b/pallets/api/src/nonfungibles/benchmarking.rs new file mode 100644 index 000000000..45d9d5bd2 --- /dev/null +++ b/pallets/api/src/nonfungibles/benchmarking.rs @@ -0,0 +1,110 @@ +//! Benchmarking setup for pallet_api::nonfungibles + +use frame_benchmarking::{account, v2::*}; +use frame_support::{traits::nonfungibles_v2::Inspect, BoundedVec}; +use sp_runtime::traits::Zero; + +use super::{AttributeNamespace, CollectionIdOf, Config, ItemIdOf, NftsInstanceOf, Pallet, Read}; +use crate::Read as _; + +const SEED: u32 = 1; + +#[benchmarks( + where + > as Inspect<::AccountId>>::ItemId: Zero, + > as Inspect<::AccountId>>::CollectionId: Zero, +)] +mod benchmarks { + use super::*; + + #[benchmark] + // Storage: `Collection` + fn total_supply() { + #[block] + { + Pallet::::read(Read::TotalSupply(CollectionIdOf::::zero())); + } + } + + #[benchmark] + // Storage: `AccountBalance` + fn balance_of() { + #[block] + { + Pallet::::read(Read::BalanceOf { + collection: CollectionIdOf::::zero(), + owner: account("Alice", 0, SEED), + }); + } + } + + #[benchmark] + // Storage: `Allowances`, `Item` + fn allowance() { + #[block] + { + Pallet::::read(Read::Allowance { + collection: CollectionIdOf::::zero(), + owner: account("Alice", 0, SEED), + operator: account("Bob", 0, SEED), + item: Some(ItemIdOf::::zero()), + }); + } + } + + #[benchmark] + // Storage: `Item` + fn owner_of() { + #[block] + { + Pallet::::read(Read::OwnerOf { + collection: CollectionIdOf::::zero(), + item: ItemIdOf::::zero(), + }); + } + } + + #[benchmark] + // Storage: `Attribute` + fn get_attribute() { + #[block] + { + Pallet::::read(Read::GetAttribute { + key: BoundedVec::default(), + collection: CollectionIdOf::::zero(), + item: ItemIdOf::::zero(), + namespace: AttributeNamespace::CollectionOwner, + }); + } + } + + #[benchmark] + // Storage: `Collection` + fn collection() { + #[block] + { + Pallet::::read(Read::Collection(CollectionIdOf::::zero())); + } + } + + #[benchmark] + // Storage: `NextCollectionId` + fn next_collection_id() { + #[block] + { + Pallet::::read(Read::NextCollectionId); + } + } + + #[benchmark] + // Storage: `ItemMetadata` + fn item_metadata() { + #[block] + { + Pallet::::read(Read::ItemMetadata { + collection: CollectionIdOf::::zero(), + item: ItemIdOf::::zero(), + }); + } + } +} diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs new file mode 100644 index 000000000..6da7de5f1 --- /dev/null +++ b/pallets/api/src/nonfungibles/mod.rs @@ -0,0 +1,591 @@ +//! The non-fungibles pallet offers a streamlined interface for interacting with non-fungible +//! assets. The goal is to provide a simplified, consistent API that adheres to standards in the +//! smart contract space. + +use frame_support::traits::{nonfungibles_v2::Inspect, Currency}; +use frame_system::pallet_prelude::BlockNumberFor; +pub use pallet::*; +use pallet_nfts::WeightInfo as NftsWeightInfoTrait; +pub use pallet_nfts::{ + AttributeNamespace, CancelAttributesApprovalWitness, CollectionConfig, CollectionDetails, + CollectionSetting, CollectionSettings, DestroyWitness, ItemDeposit, ItemDetails, ItemMetadata, + ItemSetting, MintSettings, MintType, MintWitness, +}; +use sp_runtime::traits::StaticLookup; +use weights::WeightInfo; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; +#[cfg(test)] +mod tests; +pub mod weights; + +type AccountIdOf = ::AccountId; +type NftsOf = pallet_nfts::Pallet>; +type NftsErrorOf = pallet_nfts::Error>; +type NftsWeightInfoOf = >>::WeightInfo; +type NftsInstanceOf = ::NftsInstance; +type BalanceOf = <>>::Currency as Currency< + ::AccountId, +>>::Balance; +type CollectionIdOf = + as Inspect<::AccountId>>::CollectionId; +type ItemIdOf = as Inspect<::AccountId>>::ItemId; +type ItemPriceOf = BalanceOf; +type CollectionDetailsFor = CollectionDetails, BalanceOf>; +type AttributeNamespaceOf = AttributeNamespace>; +type CollectionConfigFor = + CollectionConfig, BlockNumberFor, CollectionIdOf>; +// Type aliases for pallet-nfts storage items. +pub(super) type AccountBalanceOf = pallet_nfts::AccountBalance>; +pub(super) type AttributeOf = pallet_nfts::Attribute>; +pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId>; +pub(super) type CollectionOf = pallet_nfts::Collection>; + +#[frame_support::pallet] +pub mod pallet { + use frame_support::{ + dispatch::{DispatchResult, DispatchResultWithPostInfo, WithPostDispatchInfo}, + pallet_prelude::*, + traits::Incrementable, + }; + use frame_system::pallet_prelude::*; + use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness, MintWitness}; + use sp_runtime::BoundedVec; + use sp_std::vec::Vec; + + use super::*; + + /// State reads for the non-fungibles API with required input. + #[derive(Encode, Decode, Debug, MaxEncodedLen)] + #[cfg_attr(feature = "std", derive(PartialEq, Clone))] + #[repr(u8)] + #[allow(clippy::unnecessary_cast)] + pub enum Read { + /// Total item supply of a specified collection. + #[codec(index = 0)] + TotalSupply(CollectionIdOf), + /// Account balance for a specified collection. + #[codec(index = 1)] + BalanceOf { + /// The collection. + collection: CollectionIdOf, + /// The owner of the collection . + owner: AccountIdOf, + }, + /// Allowance for an operator approved by an owner, for a specified collection or item. + #[codec(index = 2)] + Allowance { + /// The collection. + collection: CollectionIdOf, + /// The collection item. + item: Option>, + /// The owner of the collection item. + owner: AccountIdOf, + /// The delegated operator of collection item. + operator: AccountIdOf, + }, + /// Owner of a specified collection item. + #[codec(index = 5)] + OwnerOf { + /// The collection. + collection: CollectionIdOf, + /// The collection item. + item: ItemIdOf, + }, + /// Attribute value of a specified collection item. (Error: bounded collection is not + /// partial) + #[codec(index = 6)] + GetAttribute { + /// The collection. + collection: CollectionIdOf, + /// The collection item. + item: ItemIdOf, + /// The namespace of the attribute. + namespace: AttributeNamespaceOf, + /// The key of the attribute. + key: BoundedVec, + }, + /// Details of a specified collection. + #[codec(index = 9)] + Collection(CollectionIdOf), + /// Next collection ID. + #[codec(index = 10)] + NextCollectionId, + /// Metadata of a specified collection item. + #[codec(index = 11)] + ItemMetadata { + /// The collection. + collection: CollectionIdOf, + /// The collection item. + item: ItemIdOf, + }, + } + + /// Results of state reads for the non-fungibles API. + #[derive(Debug)] + #[cfg_attr(feature = "std", derive(PartialEq, Clone))] + pub enum ReadResult { + /// Total item supply of a collection. + TotalSupply(u128), + /// Account balance for a specified collection. + BalanceOf(u32), + /// Allowance for an operator approved by an owner, for a specified collection or item. + Allowance(bool), + /// Owner of a specified collection owner. + OwnerOf(Option>), + /// Attribute value of a specified collection item. + GetAttribute(Option>), + /// Details of a specified collection. + Collection(Option>), + /// Next collection ID. + NextCollectionId(Option>), + /// Metadata of a specified collection item. + ItemMetadata(Option>), + } + + impl ReadResult { + /// Encodes the result. + pub fn encode(&self) -> Vec { + use ReadResult::*; + match self { + OwnerOf(result) => result.encode(), + TotalSupply(result) => result.encode(), + BalanceOf(result) => result.encode(), + Collection(result) => result.encode(), + Allowance(result) => result.encode(), + GetAttribute(result) => result.encode(), + NextCollectionId(result) => result.encode(), + ItemMetadata(result) => result.encode(), + } + } + } + + /// Configure the pallet by specifying the parameters and types on which it depends. + #[pallet::config] + pub trait Config: frame_system::Config + pallet_nfts::Config { + /// Because this pallet emits events, it depends on the runtime's definition of an event. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// The instance of pallet-nfts. + type NftsInstance; + /// Weight information for dispatchables in this pallet. + type WeightInfo: WeightInfo; + } + + #[pallet::pallet] + pub struct Pallet(_); + + /// The events that can be emitted. + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Event emitted when allowance by `owner` to `operator` changes. + Approval { + /// The collection ID. + collection: CollectionIdOf, + /// The item which is (dis)approved. `None` for all owner's items. + item: Option>, + /// The owner providing the allowance. + owner: AccountIdOf, + /// The beneficiary of the allowance. + operator: AccountIdOf, + /// Whether allowance is set or removed. + approved: bool, + }, + /// Event emitted when a token transfer occurs. + // Differing style: event name abides by the PSP22 standard. + Transfer { + /// The collection ID. + collection: CollectionIdOf, + /// The collection item ID. + item: ItemIdOf, + /// The source of the transfer. `None` when minting. + from: Option>, + /// The recipient of the transfer. `None` when burning. + to: Option>, + /// The price of the collection item. + price: Option>, + }, + /// Event emitted when a collection is created. + Created { + /// The collection identifier. + id: CollectionIdOf, + /// The creator of the collection. + creator: AccountIdOf, + /// The administrator of the collection. + admin: AccountIdOf, + }, + } + + #[pallet::call] + impl Pallet { + /// Transfers the collection item from the caller's account to account `to`. + /// + /// # Parameters + /// - `collection` - The collection of the item to transfer. + /// - `item` - The item to transfer. + /// - `to` - The recipient account. + #[pallet::call_index(3)] + #[pallet::weight(NftsWeightInfoOf::::transfer())] + pub fn transfer( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + to: AccountIdOf, + ) -> DispatchResult { + let from = ensure_signed(origin.clone())?; + NftsOf::::transfer(origin, collection, item, T::Lookup::unlookup(to.clone()))?; + Self::deposit_event(Event::Transfer { + collection, + item, + from: Some(from), + to: Some(to), + price: None, + }); + Ok(()) + } + + /// Approves `operator` to spend the collection item on behalf of the caller. + /// + /// # Parameters + /// - `collection` - The collection of the item to approve for a delegated transfer. + /// - `item` - The item to approve for a delegated transfer. + /// - `operator` - The account that is allowed to spend the collection item. + /// - `approved` - The approval status of the collection item. + #[pallet::call_index(4)] + #[pallet::weight( + NftsWeightInfoOf::::approve_transfer(item.is_some() as u32) + + NftsWeightInfoOf::::cancel_approval(item.is_some() as u32) + )] + pub fn approve( + origin: OriginFor, + collection: CollectionIdOf, + item: Option>, + operator: AccountIdOf, + approved: bool, + ) -> DispatchResultWithPostInfo { + let owner = ensure_signed(origin.clone())?; + let weight = if approved { + NftsOf::::approve_transfer( + origin, + collection, + item, + T::Lookup::unlookup(operator.clone()), + None, + ) + .map_err(|e| { + e.with_weight(NftsWeightInfoOf::::approve_transfer(item.is_some() as u32)) + })?; + NftsWeightInfoOf::::approve_transfer(item.is_some() as u32) + } else { + NftsOf::::cancel_approval( + origin, + collection, + item, + T::Lookup::unlookup(operator.clone()), + ) + .map_err(|e| { + e.with_weight(NftsWeightInfoOf::::cancel_approval(item.is_some() as u32)) + })?; + NftsWeightInfoOf::::cancel_approval(item.is_some() as u32) + }; + Self::deposit_event(Event::Approval { collection, item, operator, owner, approved }); + Ok(Some(weight).into()) + } + + /// Issue a new collection of non-fungible items from a public origin. + /// + /// # Parameters + /// - `admin` - The admin of this collection. The admin is the initial address of each + /// member of the collection's admin team. + /// - `config` - The configuration of the collection. + #[pallet::call_index(7)] + #[pallet::weight(NftsWeightInfoOf::::create())] + pub fn create( + origin: OriginFor, + admin: AccountIdOf, + config: CollectionConfigFor, + ) -> DispatchResult { + let creator = ensure_signed(origin.clone())?; + // TODO: re-evaluate next collection id in nfts pallet. The `Incrementable` trait causes + // issues for setting it to xcm's `Location`. This can easily be done differently. + let id = NextCollectionIdOf::::get() + .or(T::CollectionId::initial_value()) + .ok_or(NftsErrorOf::::UnknownCollection)?; + NftsOf::::create(origin, T::Lookup::unlookup(admin.clone()), config)?; + Self::deposit_event(Event::Created { id, creator, admin }); + Ok(()) + } + + /// Destroy a collection of fungible items. + /// + /// # Parameters + /// - `collection` - The collection to destroy. + /// - `witness` - Information on the items minted in the collection. This must be + /// correct. + #[pallet::call_index(8)] + #[pallet::weight(NftsWeightInfoOf::::destroy( + witness.item_metadatas, + witness.item_configs, + witness.attributes, + witness.item_holders, + witness.allowances, + ))] + pub fn destroy( + origin: OriginFor, + collection: CollectionIdOf, + witness: DestroyWitness, + ) -> DispatchResultWithPostInfo { + NftsOf::::destroy(origin, collection, witness) + } + + /// Set an attribute for a collection or item. + /// + /// # Parameters + /// - `collection` - The collection whose item's metadata to set. + /// - `maybe_item` - The item whose metadata to set. + /// - `namespace` - Attribute's namespace. + /// - `key` - The key of the attribute. + /// - `value` - The value to which to set the attribute. + #[pallet::call_index(12)] + #[pallet::weight(NftsWeightInfoOf::::set_attribute())] + pub fn set_attribute( + origin: OriginFor, + collection: CollectionIdOf, + item: Option>, + namespace: AttributeNamespaceOf, + key: BoundedVec, + value: BoundedVec, + ) -> DispatchResult { + NftsOf::::set_attribute(origin, collection, item, namespace, key, value) + } + + /// Clear an attribute for the collection or item. + /// + /// # Parameters + /// - `collection` - The collection whose item's metadata to clear. + /// - `maybe_item` - The item whose metadata to clear. + /// - `namespace` - Attribute's namespace. + /// - `key` - The key of the attribute. + #[pallet::call_index(13)] + #[pallet::weight(NftsWeightInfoOf::::clear_attribute())] + pub fn clear_attribute( + origin: OriginFor, + collection: CollectionIdOf, + item: Option>, + namespace: AttributeNamespaceOf, + key: BoundedVec, + ) -> DispatchResult { + NftsOf::::clear_attribute(origin, collection, item, namespace, key) + } + + /// Set the metadata for an item. + /// + /// # Parameters + /// - `collection` - The collection whose item's metadata to set. + /// - `item` - The item whose metadata to set. + /// - `data` - The general information of this item. Limited in length by `StringLimit`. + #[pallet::call_index(14)] + #[pallet::weight(NftsWeightInfoOf::::set_metadata())] + pub fn set_metadata( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + data: BoundedVec, + ) -> DispatchResult { + NftsOf::::set_metadata(origin, collection, item, data) + } + + #[pallet::call_index(15)] + #[pallet::weight(NftsWeightInfoOf::::clear_metadata())] + pub fn clear_metadata( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + ) -> DispatchResult { + NftsOf::::clear_metadata(origin, collection, item) + } + + /// Approve item's attributes to be changed by a delegated third-party account. + /// + /// # Parameters + /// - `collection` - The collection of the item. + /// - `item` - The item that holds attributes. + /// - `delegate` - The account to delegate permission to change attributes of the item. + #[pallet::call_index(16)] + #[pallet::weight(NftsWeightInfoOf::::approve_item_attributes())] + pub fn approve_item_attributes( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + delegate: AccountIdOf, + ) -> DispatchResult { + NftsOf::::approve_item_attributes( + origin, + collection, + item, + T::Lookup::unlookup(delegate.clone()), + ) + } + + /// Cancel the previously provided approval to change item's attributes. + /// All the previously set attributes by the `delegate` will be removed. + /// + /// # Parameters + /// - `collection` - The collection that the item is contained within. + /// - `item` - The item that holds attributes. + /// - `delegate` - The previously approved account to remove. + /// - `witness` - A witness data to cancel attributes approval operation. + #[pallet::call_index(17)] + #[pallet::weight(NftsWeightInfoOf::::cancel_item_attributes_approval(witness.account_attributes))] + pub fn cancel_item_attributes_approval( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + delegate: AccountIdOf, + witness: CancelAttributesApprovalWitness, + ) -> DispatchResult { + NftsOf::::cancel_item_attributes_approval( + origin, + collection, + item, + T::Lookup::unlookup(delegate.clone()), + witness, + ) + } + + /// Set the maximum number of items a collection could have. + /// + /// # Parameters + /// - `collection` - The identifier of the collection to change. + /// - `max_supply` - The maximum number of items a collection could have. + #[pallet::call_index(18)] + #[pallet::weight(NftsWeightInfoOf::::set_collection_max_supply())] + pub fn set_max_supply( + origin: OriginFor, + collection: CollectionIdOf, + max_supply: u32, + ) -> DispatchResult { + NftsOf::::set_collection_max_supply(origin, collection, max_supply) + } + + /// Mint an item of a particular collection. + /// + /// # Parameters + /// - `to` - Account into which the item will be minted. + /// - `collection` - The collection of the item to mint. + /// - `item` - An identifier of the new item. + /// - `witness_data` - When the mint type is `HolderOf(collection_id)`, then the owned + /// item_id from that collection needs to be provided within the witness data object. If + /// the mint price is set, then it should be additionally confirmed in the `witness_data`. + #[pallet::call_index(19)] + #[pallet::weight(NftsWeightInfoOf::::mint())] + pub fn mint( + origin: OriginFor, + to: AccountIdOf, + collection: CollectionIdOf, + item: ItemIdOf, + witness: MintWitness, ItemPriceOf>, + ) -> DispatchResult { + let account = ensure_signed(origin.clone())?; + let mint_price = witness.mint_price; + NftsOf::::mint( + origin, + collection, + item, + T::Lookup::unlookup(to.clone()), + Some(witness), + )?; + Self::deposit_event(Event::Transfer { + collection, + item, + from: None, + to: Some(account), + price: mint_price, + }); + Ok(()) + } + + /// Destroy a single collection item. + /// + /// # Parameters + /// - `collection` - The collection of the item to burn. + /// - `item` - The item to burn. + #[pallet::call_index(20)] + #[pallet::weight(NftsWeightInfoOf::::burn())] + pub fn burn( + origin: OriginFor, + collection: CollectionIdOf, + item: ItemIdOf, + ) -> DispatchResult { + let account = ensure_signed(origin.clone())?; + NftsOf::::burn(origin, collection, item)?; + Self::deposit_event(Event::Transfer { + collection, + item, + from: Some(account), + to: None, + price: None, + }); + Ok(()) + } + } + + impl crate::Read for Pallet { + /// The type of read requested. + type Read = Read; + /// The type or result returned. + type Result = ReadResult; + + /// Determines the weight of the requested read, used to charge the appropriate weight + /// before the read is performed. + /// + /// # Parameters + /// - `request` - The read request. + fn weight(request: &Self::Read) -> Weight { + use Read::*; + match request { + TotalSupply(_) => ::WeightInfo::total_supply(), + BalanceOf { .. } => ::WeightInfo::balance_of(), + Allowance { .. } => ::WeightInfo::allowance(), + OwnerOf { .. } => ::WeightInfo::owner_of(), + GetAttribute { .. } => ::WeightInfo::get_attribute(), + Collection(_) => ::WeightInfo::collection(), + ItemMetadata { .. } => ::WeightInfo::item_metadata(), + NextCollectionId => ::WeightInfo::next_collection_id(), + } + } + + /// Performs the requested read and returns the result. + /// + /// # Parameters + /// - `request` - The read request. + fn read(value: Self::Read) -> Self::Result { + use Read::*; + match value { + TotalSupply(collection) => ReadResult::TotalSupply( + NftsOf::::collection_items(collection).unwrap_or_default() as u128, + ), + BalanceOf { collection, owner } => + ReadResult::BalanceOf(AccountBalanceOf::::get(collection, owner)), + Allowance { collection, owner, operator, item } => ReadResult::Allowance( + NftsOf::::check_allowance(&collection, &item, &owner, &operator).is_ok(), + ), + OwnerOf { collection, item } => + ReadResult::OwnerOf(NftsOf::::owner(collection, item)), + GetAttribute { collection, item, namespace, key } => ReadResult::GetAttribute( + AttributeOf::::get((collection, Some(item), namespace, key)) + .map(|attribute| attribute.0.into()), + ), + Collection(collection) => + ReadResult::Collection(CollectionOf::::get(collection)), + ItemMetadata { collection, item } => ReadResult::ItemMetadata( + NftsOf::::item_metadata(collection, item).map(|metadata| metadata.into()), + ), + NextCollectionId => ReadResult::NextCollectionId( + NextCollectionIdOf::::get().or(T::CollectionId::initial_value()), + ), + } + } + } +} diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs new file mode 100644 index 000000000..68260ab23 --- /dev/null +++ b/pallets/api/src/nonfungibles/tests.rs @@ -0,0 +1,1003 @@ +use codec::Encode; +use frame_support::{ + assert_noop, assert_ok, + sp_runtime::{BoundedVec, DispatchError::BadOrigin}, +}; +use pallet_nfts::WeightInfo as NftsWeightInfoTrait; + +use crate::{ + mock::*, + nonfungibles::{ + AccountBalanceOf, AttributeNamespace, AttributeOf, BlockNumberFor, + CancelAttributesApprovalWitness, CollectionConfig, CollectionDetails, CollectionIdOf, + CollectionOf, CollectionSettings, DestroyWitness, ItemIdOf, MintSettings, MintWitness, + NextCollectionIdOf, NftsInstanceOf, NftsWeightInfoOf, Read::*, ReadResult, + }, + Read, +}; + +const COLLECTION: u32 = 0; +const ITEM: u32 = 1; + +type NftsError = pallet_nfts::Error>; +type Event = crate::nonfungibles::Event; + +mod encoding_read_result { + use super::*; + + #[test] + fn total_supply() { + let total_supply: u128 = 1_000_000; + assert_eq!(ReadResult::TotalSupply::(total_supply).encode(), total_supply.encode()); + } + + #[test] + fn balance_of() { + let balance: u32 = 100; + assert_eq!(ReadResult::BalanceOf::(balance).encode(), balance.encode()); + } + + #[test] + fn allowance() { + let allowance = false; + assert_eq!(ReadResult::Allowance::(allowance).encode(), allowance.encode()); + } + + #[test] + fn owner_of() { + let mut owner = Some(ALICE); + assert_eq!(ReadResult::OwnerOf::(owner.clone()).encode(), owner.encode()); + owner = None; + assert_eq!(ReadResult::OwnerOf::(owner.clone()).encode(), owner.encode()); + } + + #[test] + fn get_attribute() { + let mut attribute = Some("some attribute".as_bytes().to_vec()); + assert_eq!( + ReadResult::GetAttribute::(attribute.clone()).encode(), + attribute.encode() + ); + attribute = None; + assert_eq!( + ReadResult::GetAttribute::(attribute.clone()).encode(), + attribute.encode() + ); + } + + #[test] + fn collection() { + let mut collection_details = Some(CollectionDetails { + owner: ALICE, + owner_deposit: 0, + items: 0, + item_metadatas: 0, + item_configs: 0, + item_holders: 0, + attributes: 0, + allowances: 0, + }); + assert_eq!( + ReadResult::Collection::(collection_details.clone()).encode(), + collection_details.encode() + ); + collection_details = None; + assert_eq!( + ReadResult::Collection::(collection_details.clone()).encode(), + collection_details.encode() + ); + } + + #[test] + fn next_collection_id_works() { + let mut next_collection_id = Some(0); + assert_eq!( + ReadResult::NextCollectionId::(next_collection_id).encode(), + next_collection_id.encode() + ); + next_collection_id = None; + assert_eq!( + ReadResult::NextCollectionId::(next_collection_id).encode(), + next_collection_id.encode() + ); + } + + #[test] + fn item_metadata_works() { + let mut data = Some("some metadata".as_bytes().to_vec()); + assert_eq!(ReadResult::ItemMetadata::(data.clone()).encode(), data.encode()); + data = None; + assert_eq!(ReadResult::ItemMetadata::(data.clone()).encode(), data.encode()); + } +} + +#[test] +fn transfer() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let dest = BOB; + + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + for origin in vec![root(), none()] { + assert_noop!(NonFungibles::transfer(origin, collection, item, dest), BadOrigin); + } + // Successfully burn an existing new collection item. + let balance_before_transfer = AccountBalanceOf::::get(collection, &dest); + assert_ok!(NonFungibles::transfer(signed(owner), collection, ITEM, dest)); + let balance_after_transfer = AccountBalanceOf::::get(collection, &dest); + assert_eq!(AccountBalanceOf::::get(collection, &owner), 0); + assert_eq!(balance_after_transfer - balance_before_transfer, 1); + System::assert_last_event( + Event::Transfer { collection, item, from: Some(owner), to: Some(dest), price: None } + .into(), + ); + }); +} + +#[test] +fn mint_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let collection = nfts::create_collection(owner); + + // Successfully mint a new collection item. + let balance_before_mint = AccountBalanceOf::::get(collection, owner); + assert_ok!(NonFungibles::mint( + signed(owner), + owner, + collection, + ITEM, + MintWitness { mint_price: None, owned_item: None } + )); + let balance_after_mint = AccountBalanceOf::::get(collection, owner); + assert_eq!(balance_after_mint, 1); + assert_eq!(balance_after_mint - balance_before_mint, 1); + System::assert_last_event( + Event::Transfer { collection, item: ITEM, from: None, to: Some(owner), price: None } + .into(), + ); + }); +} + +#[test] +fn burn_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + + // "UnknownItem" error is returned if collection item is not created. + assert_noop!(NonFungibles::burn(signed(owner), COLLECTION, ITEM), NftsError::UnknownItem); + // Successfully burn an existing new collection item. + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + let balance_before_burn = AccountBalanceOf::::get(collection, owner); + assert_ok!(NonFungibles::burn(signed(owner), collection, ITEM)); + let balance_after_burn = AccountBalanceOf::::get(collection, owner); + assert_eq!(balance_after_burn, balance_before_burn - 1); + System::assert_last_event( + Event::Transfer { collection, item, from: Some(owner), to: None, price: None }.into(), + ); + }); +} + +#[test] +fn approve_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + // Successfully approve `operator` to transfer the collection item. + assert_eq!( + NonFungibles::approve(signed(owner), collection, Some(item), operator, true), + Ok(Some(NftsWeightInfoOf::::approve_transfer(1)).into()) + ); + assert_ok!(Nfts::check_allowance(&collection, &Some(item), &owner, &operator)); + System::assert_last_event( + Event::Approval { collection, item: Some(item), owner, operator, approved: true } + .into(), + ); + // Successfully transfer the item by the delegated account `operator`. + assert_ok!(Nfts::transfer(signed(operator), collection, item, operator)); + }); +} + +#[test] +fn approve_collection_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + // Successfully approve `operator` to transfer all items within the collection. + assert_eq!( + NonFungibles::approve(signed(owner), collection, None, operator, true), + Ok(Some(NftsWeightInfoOf::::approve_transfer(0)).into()) + ); + assert_ok!(Nfts::check_allowance(&collection, &None, &owner, &operator)); + System::assert_last_event( + Event::Approval { collection, item: None, owner, operator, approved: true }.into(), + ); + // Successfully transfer the item by the delegated account `operator`. + assert_ok!(Nfts::transfer(signed(operator), collection, item, operator)); + }); +} + +#[test] +fn cancel_approval_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); + // Successfully cancel the transfer approval of `operator` by `owner`. + assert_eq!( + NonFungibles::approve(signed(owner), collection, Some(item), operator, false), + Ok(Some(NftsWeightInfoOf::::cancel_approval(1)).into()) + ); + assert_eq!( + Nfts::check_allowance(&collection, &Some(item), &owner, &operator), + Err(NftsError::NoPermission.into()) + ); + // Failed to transfer the item by `operator` without permission. + assert_noop!( + Nfts::transfer(signed(operator), collection, item, operator), + NftsError::NoPermission + ); + }); +} + +#[test] +fn cancel_collection_approval_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint(owner, ITEM); + // Successfully cancel the transfer collection approval of `operator` by `owner`. + assert_ok!(Nfts::approve_transfer(signed(owner), collection, None, operator, None)); + assert_eq!( + NonFungibles::approve(signed(owner), collection, None, operator, false), + Ok(Some(NftsWeightInfoOf::::cancel_approval(0)).into()) + ); + assert_eq!( + Nfts::check_allowance(&collection, &None, &owner, &operator), + Err(NftsError::NoPermission.into()) + ); + // Failed to transfer the item by `operator` without permission. + assert_noop!( + Nfts::transfer(signed(operator), collection, item, operator), + NftsError::NoPermission + ); + }); +} + +#[test] +fn set_max_supply_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let collection = nfts::create_collection(owner); + assert_ok!(NonFungibles::set_max_supply(signed(owner), collection, 10)); + (0..10).into_iter().for_each(|i| { + assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); + }); + assert_noop!( + Nfts::mint(signed(owner), collection, 42, owner, None), + NftsError::MaxSupplyReached + ); + }); +} + +#[test] +fn set_metadata_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + let value = BoundedVec::truncate_from("some metadata".as_bytes().to_vec()); + assert_ok!(NonFungibles::set_metadata(signed(ALICE), collection, item, value.clone())); + assert_eq!( + NonFungibles::read(ItemMetadata { collection, item }).encode(), + Some(value).encode() + ); + }); +} + +#[test] +fn clear_metadata_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_ok!(NonFungibles::set_metadata( + signed(ALICE), + collection, + item, + BoundedVec::truncate_from("some metadata".as_bytes().to_vec()) + )); + assert_ok!(NonFungibles::clear_metadata(signed(ALICE), collection, item)); + assert_eq!( + NonFungibles::read(ItemMetadata { collection, item }).encode(), + ReadResult::::ItemMetadata(None).encode() + ); + }); +} + +#[test] +fn clear_attribute_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let result: Option< + BoundedVec>>::ValueLimit>, + > = None; + assert_ok!(Nfts::set_attribute( + signed(ALICE), + collection, + Some(item), + AttributeNamespace::CollectionOwner, + attribute.clone(), + BoundedVec::truncate_from("some value".as_bytes().to_vec()) + )); + // Successfully clear an attribute. + assert_ok!(Nfts::clear_attribute( + signed(ALICE), + collection, + Some(item), + AttributeNamespace::CollectionOwner, + attribute.clone(), + )); + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item, + namespace: AttributeNamespace::CollectionOwner, + key: attribute + }) + .encode(), + result.encode() + ); + }); +} + +#[test] +fn approve_item_attribute_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); + // Successfully approve delegate to set attributes. + assert_ok!(Nfts::approve_item_attributes(signed(ALICE), collection, item, BOB)); + assert_ok!(Nfts::set_attribute( + signed(BOB), + collection, + Some(item), + AttributeNamespace::Account(BOB), + attribute.clone(), + value.clone() + )); + let result: Option< + BoundedVec>>::ValueLimit>, + > = Some(value); + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item, + namespace: AttributeNamespace::Account(BOB), + key: attribute + }) + .encode(), + result.encode() + ); + }); +} + +#[test] +fn cancel_item_attribute_approval_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId).encode(), Some(1).encode()); + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let value = BoundedVec::truncate_from("some value".as_bytes().to_vec()); + // Successfully approve delegate to set attributes. + assert_ok!(Nfts::approve_item_attributes(signed(ALICE), collection, item, BOB)); + assert_ok!(Nfts::set_attribute( + signed(BOB), + collection, + Some(item), + AttributeNamespace::Account(BOB), + attribute.clone(), + value.clone() + )); + assert_ok!(Nfts::cancel_item_attributes_approval( + signed(ALICE), + collection, + item, + BOB, + CancelAttributesApprovalWitness { account_attributes: 1 } + )); + assert_noop!( + Nfts::set_attribute( + signed(BOB), + collection, + Some(item), + AttributeNamespace::Account(BOB), + attribute.clone(), + value.clone() + ), + NftsError::NoPermission + ); + }); +} + +#[test] +fn create_works() { + new_test_ext().execute_with(|| { + let creator = ALICE; + let admin = ALICE; + let next_collection_id = NextCollectionIdOf::::get().unwrap_or_default(); + for origin in vec![root(), none()] { + assert_noop!( + NonFungibles::create( + origin, + admin, + CollectionConfig { + max_supply: None, + mint_settings: MintSettings::default(), + settings: CollectionSettings::all_enabled() + }, + ), + BadOrigin + ); + } + assert_ok!(NonFungibles::create( + signed(creator), + admin, + CollectionConfig { + max_supply: None, + mint_settings: MintSettings::default(), + settings: CollectionSettings::all_enabled() + }, + )); + assert_eq!(Nfts::collection_owner(next_collection_id), Some(creator)); + System::assert_last_event(Event::Created { id: next_collection_id, creator, admin }.into()); + }); +} + +#[test] +fn destroy_works() { + new_test_ext().execute_with(|| { + let collection = COLLECTION; + let witness = DestroyWitness { + item_metadatas: 0, + item_configs: 0, + item_holders: 0, + attributes: 0, + allowances: 0, + }; + // Check error works for `Nfts::destroy()`. + assert_noop!( + NonFungibles::destroy(signed(ALICE), collection, witness), + NftsError::UnknownCollection + ); + nfts::create_collection(ALICE); + assert_ok!(NonFungibles::destroy(signed(ALICE), collection, witness)); + assert_eq!(Nfts::collection_owner(collection), None); + }); +} + +#[test] +fn total_supply_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let collection = nfts::create_collection(owner); + assert_eq!(NonFungibles::read(TotalSupply(collection)), ReadResult::TotalSupply(0)); + (0..10).into_iter().for_each(|i| { + assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); + assert_eq!( + NonFungibles::read(TotalSupply(collection)), + ReadResult::TotalSupply((i + 1).into()) + ); + assert_eq!( + NonFungibles::read(TotalSupply(collection)).encode(), + (Nfts::collection_items(collection).unwrap_or_default() as u128).encode() + ); + }); + }); +} + +#[test] +fn balance_of_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let collection = nfts::create_collection(owner); + assert_eq!( + NonFungibles::read(BalanceOf { collection, owner }), + ReadResult::BalanceOf(Default::default()) + ); + (0..10).into_iter().for_each(|i| { + assert_ok!(Nfts::mint(signed(owner), collection, i, owner, None)); + assert_eq!( + NonFungibles::read(BalanceOf { collection, owner }), + ReadResult::BalanceOf(i + 1) + ); + assert_eq!( + NonFungibles::read(BalanceOf { collection, owner }).encode(), + AccountBalanceOf::::get(collection, owner).encode() + ); + }); + }); +} + +#[test] +fn allowance_works() { + new_test_ext().execute_with(|| { + let owner = ALICE; + let operator = BOB; + let (collection, item) = nfts::create_collection_mint_and_approve(owner, ITEM, operator); + assert_eq!( + NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }), + ReadResult::Allowance(true) + ); + assert_eq!( + NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }) + .encode(), + Nfts::check_allowance(&collection, &Some(item), &owner, &operator) + .is_ok() + .encode() + ); + }); +} + +#[test] +fn owner_of_works() { + new_test_ext().execute_with(|| { + assert_eq!( + NonFungibles::read(OwnerOf { collection: COLLECTION, item: ITEM }), + ReadResult::OwnerOf(None) + ); + nfts::create_collection_mint(ALICE, ITEM); + assert_eq!( + NonFungibles::read(OwnerOf { collection: COLLECTION, item: ITEM }), + ReadResult::OwnerOf(Some(ALICE)) + ); + assert_eq!( + NonFungibles::read(OwnerOf { collection: COLLECTION, item: ITEM }).encode(), + Nfts::owner(COLLECTION, ITEM).encode() + ); + }); +} + +#[test] +fn get_attribute_works() { + new_test_ext().execute_with(|| { + let (collection, item) = nfts::create_collection_mint(ALICE, ITEM); + let attribute = BoundedVec::truncate_from("some attribute".as_bytes().to_vec()); + let raw_value = "some value".as_bytes().to_vec(); + let value = BoundedVec::truncate_from(raw_value.clone()); + let namespace = AttributeNamespace::CollectionOwner; + // No attribute set. + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item, + namespace: namespace.clone(), + key: attribute.clone() + }), + ReadResult::GetAttribute(None) + ); + // Successfully get an existing attribute. + assert_ok!(Nfts::set_attribute( + signed(ALICE), + collection, + Some(item), + namespace.clone(), + attribute.clone(), + value, + )); + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item, + namespace: namespace.clone(), + key: attribute.clone() + }), + ReadResult::GetAttribute(Some(raw_value)) + ); + assert_eq!( + NonFungibles::read(GetAttribute { + collection, + item, + namespace: namespace.clone(), + key: attribute.clone() + }) + .encode(), + AttributeOf::::get((collection, Some(item), namespace, attribute)) + .map(|result| result.0) + .encode() + ); + }); +} + +#[test] +fn collection_works() { + new_test_ext().execute_with(|| { + assert_eq!(NonFungibles::read(Collection(COLLECTION)), ReadResult::Collection(None),); + nfts::create_collection_mint(ALICE, ITEM); + assert_eq!( + NonFungibles::read(Collection(COLLECTION)), + ReadResult::Collection(CollectionOf::::get(COLLECTION)), + ); + assert_eq!( + NonFungibles::read(Collection(COLLECTION)).encode(), + CollectionOf::::get(COLLECTION).encode(), + ); + }); +} + +#[test] +fn item_metadata_works() { + new_test_ext().execute_with(|| { + assert_eq!( + NonFungibles::read(ItemMetadata { collection: COLLECTION, item: ITEM }), + ReadResult::ItemMetadata(None) + ); + nfts::create_collection_mint(ALICE, ITEM); + let value = "some metadata".as_bytes().to_vec(); + assert_ok!(NonFungibles::set_metadata( + signed(ALICE), + COLLECTION, + ITEM, + BoundedVec::truncate_from(value.clone()) + )); + assert_eq!( + NonFungibles::read(ItemMetadata { collection: COLLECTION, item: ITEM }), + ReadResult::ItemMetadata(Some(value)) + ); + assert_eq!( + NonFungibles::read(ItemMetadata { collection: COLLECTION, item: ITEM }).encode(), + Nfts::item_metadata(COLLECTION, ITEM).encode() + ); + }); +} + +#[test] +fn next_collection_id_works() { + new_test_ext().execute_with(|| { + assert_eq!(NonFungibles::read(NextCollectionId), ReadResult::NextCollectionId(Some(0))); + nfts::create_collection_mint(ALICE, ITEM); + assert_eq!(NonFungibles::read(NextCollectionId), ReadResult::NextCollectionId(Some(1))); + assert_eq!( + NonFungibles::read(NextCollectionId).encode(), + Some(NextCollectionIdOf::::get().unwrap_or_default()).encode(), + ); + }); +} + +fn signed(account_id: AccountId) -> RuntimeOrigin { + RuntimeOrigin::signed(account_id) +} + +fn root() -> RuntimeOrigin { + RuntimeOrigin::root() +} + +fn none() -> RuntimeOrigin { + RuntimeOrigin::none() +} + +// Helper functions for interacting with pallet-nfts. +mod nfts { + use super::*; + + pub(super) fn create_collection_mint_and_approve( + owner: AccountId, + item: ItemIdOf, + operator: AccountId, + ) -> (u32, u32) { + let (collection, item) = create_collection_mint(owner, item); + assert_ok!(Nfts::approve_transfer(signed(owner), collection, Some(item), operator, None)); + (collection, item) + } + + pub(super) fn create_collection_mint(owner: AccountId, item: ItemIdOf) -> (u32, u32) { + let collection = create_collection(owner); + assert_ok!(Nfts::mint(signed(owner), collection, item, owner, None)); + (collection, item) + } + + pub(super) fn create_collection(owner: AccountId) -> u32 { + let next_id = NextCollectionIdOf::::get().unwrap_or_default(); + assert_ok!(Nfts::create( + signed(owner), + owner, + collection_config_with_all_settings_enabled() + )); + next_id + } + + pub(super) fn collection_config_with_all_settings_enabled( + ) -> CollectionConfig, CollectionIdOf> { + CollectionConfig { + settings: CollectionSettings::all_enabled(), + max_supply: None, + mint_settings: MintSettings::default(), + } + } +} + +mod read_weights { + use frame_support::weights::Weight; + + use super::*; + use crate::nonfungibles::{weights::WeightInfo, Config}; + + struct ReadWeightInfo { + total_supply: Weight, + balance_of: Weight, + allowance: Weight, + owner_of: Weight, + get_attribute: Weight, + collection: Weight, + next_collection_id: Weight, + item_metadata: Weight, + } + + impl ReadWeightInfo { + fn new() -> Self { + Self { + total_supply: NonFungibles::weight(&TotalSupply(COLLECTION)), + balance_of: NonFungibles::weight(&BalanceOf { + collection: COLLECTION, + owner: ALICE, + }), + allowance: NonFungibles::weight(&Allowance { + collection: COLLECTION, + item: Some(ITEM), + owner: ALICE, + operator: BOB, + }), + owner_of: NonFungibles::weight(&OwnerOf { collection: COLLECTION, item: ITEM }), + get_attribute: NonFungibles::weight(&GetAttribute { + collection: COLLECTION, + item: ITEM, + namespace: AttributeNamespace::CollectionOwner, + key: BoundedVec::default(), + }), + collection: NonFungibles::weight(&Collection(COLLECTION)), + next_collection_id: NonFungibles::weight(&NextCollectionId), + item_metadata: NonFungibles::weight(&ItemMetadata { + collection: COLLECTION, + item: ITEM, + }), + } + } + } + + #[test] + fn ensure_read_matches_benchmarks() { + let ReadWeightInfo { + allowance, + balance_of, + collection, + get_attribute, + item_metadata, + next_collection_id, + owner_of, + total_supply, + } = ReadWeightInfo::new(); + + assert_eq!(total_supply, ::WeightInfo::total_supply()); + assert_eq!(balance_of, ::WeightInfo::balance_of()); + assert_eq!(allowance, ::WeightInfo::allowance()); + assert_eq!(owner_of, ::WeightInfo::owner_of()); + assert_eq!(get_attribute, ::WeightInfo::get_attribute()); + assert_eq!(collection, ::WeightInfo::collection()); + assert_eq!(next_collection_id, ::WeightInfo::next_collection_id()); + assert_eq!(item_metadata, ::WeightInfo::item_metadata()); + } + + // These types read from the `Collection` storage. + #[test] + fn ensure_collection_variants_match() { + let ReadWeightInfo { total_supply, collection, .. } = ReadWeightInfo::new(); + + assert_eq!(total_supply, collection); + } + + // Proof size is based on `MaxEncodedLen`, not hardware. + // This test ensures that the data structure sizes do not change with upgrades. + #[test] + fn ensure_expected_proof_size_does_not_change() { + let ReadWeightInfo { + allowance, + balance_of, + collection, + get_attribute, + item_metadata, + next_collection_id, + owner_of, + total_supply, + } = ReadWeightInfo::new(); + + // These values come from `weights.rs`. + assert_eq!(total_supply.proof_size(), 3557); + assert_eq!(balance_of.proof_size(), 3529); + assert_eq!(allowance.proof_size(), 4326); + assert_eq!(owner_of.proof_size(), 4326); + assert_eq!(get_attribute.proof_size(), 3944); + assert_eq!(collection.proof_size(), 3557); + assert_eq!(next_collection_id.proof_size(), 1489); + assert_eq!(item_metadata.proof_size(), 3812); + } +} + +mod ensure_codec_indexes { + use super::{Encode, *}; + use crate::{mock::RuntimeCall::NonFungibles, nonfungibles}; + + #[test] + fn ensure_read_variant_indexes() { + [ + (TotalSupply::(Default::default()), 0u8, "TotalSupply"), + ( + BalanceOf:: { collection: Default::default(), owner: Default::default() }, + 1, + "BalanceOf", + ), + ( + Allowance:: { + collection: Default::default(), + item: Default::default(), + owner: Default::default(), + operator: Default::default(), + }, + 2, + "Allowance", + ), + ( + OwnerOf:: { collection: Default::default(), item: Default::default() }, + 5, + "OwnerOf", + ), + ( + GetAttribute:: { + collection: Default::default(), + item: Default::default(), + namespace: AttributeNamespace::CollectionOwner, + key: Default::default(), + }, + 6, + "GetAttribute", + ), + (Collection::(Default::default()), 9, "Collection"), + (NextCollectionId, 10, "NextCollectionId"), + ( + ItemMetadata { collection: Default::default(), item: Default::default() }, + 11, + "ItemMetadata", + ), + ] + .iter() + .for_each(|(variant, expected_index, name)| { + assert_eq!(variant.encode()[0], *expected_index, "{name} variant index changed"); + }) + } + + #[test] + fn ensure_dispatchable_indexes() { + use nonfungibles::Call::*; + + [ + ( + transfer { + collection: Default::default(), + item: Default::default(), + to: Default::default(), + }, + 3u8, + "transfer", + ), + ( + approve { + collection: Default::default(), + item: Default::default(), + operator: Default::default(), + approved: Default::default(), + }, + 4, + "approve", + ), + (create { admin: Default::default(), config: Default::default() }, 7, "create"), + ( + destroy { + collection: Default::default(), + witness: DestroyWitness { + item_metadatas: Default::default(), + item_configs: Default::default(), + item_holders: Default::default(), + attributes: Default::default(), + allowances: Default::default(), + }, + }, + 8, + "destroy", + ), + ( + set_attribute { + collection: Default::default(), + item: Default::default(), + namespace: AttributeNamespace::CollectionOwner, + key: Default::default(), + value: Default::default(), + }, + 12, + "set_attribute", + ), + ( + clear_attribute { + collection: Default::default(), + item: Default::default(), + namespace: AttributeNamespace::CollectionOwner, + key: Default::default(), + }, + 13, + "clear_attribute", + ), + ( + set_metadata { + collection: Default::default(), + item: Default::default(), + data: Default::default(), + }, + 14, + "set_metadata", + ), + ( + clear_metadata { collection: Default::default(), item: Default::default() }, + 15, + "clear_metadata", + ), + ( + approve_item_attributes { + collection: Default::default(), + item: Default::default(), + delegate: Default::default(), + }, + 16, + "approve_item_attributes", + ), + ( + cancel_item_attributes_approval { + collection: Default::default(), + item: Default::default(), + delegate: Default::default(), + witness: CancelAttributesApprovalWitness { + account_attributes: Default::default(), + }, + }, + 17, + "cancel_item_attributes_approval", + ), + ( + set_max_supply { collection: Default::default(), max_supply: Default::default() }, + 18, + "set_max_supply", + ), + ( + mint { + to: Default::default(), + collection: Default::default(), + item: Default::default(), + witness: MintWitness { + owned_item: Default::default(), + mint_price: Default::default(), + }, + }, + 19, + "mint", + ), + (burn { collection: Default::default(), item: Default::default() }, 20, "burn"), + ] + .iter() + .for_each(|(variant, expected_index, name)| { + assert_eq!( + NonFungibles(variant.to_owned()).encode()[1], + *expected_index, + "{name} dispatchable index changed" + ); + }) + } +} diff --git a/pallets/api/src/nonfungibles/weights.rs b/pallets/api/src/nonfungibles/weights.rs new file mode 100644 index 000000000..f0b8fa833 --- /dev/null +++ b/pallets/api/src/nonfungibles/weights.rs @@ -0,0 +1,217 @@ + +//! Autogenerated weights for `nonfungibles` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 40.0.0 +//! DATE: 2024-11-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `R0GUE`, CPU: `` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` + +// Executed Command: +// ./target/release/pop-node +// benchmark +// pallet +// --chain=dev +// --wasm-execution=compiled +// --pallet=nonfungibles +// --steps=50 +// --repeat=20 +// --json +// --template +// ./scripts/pallet-weights-template.hbs +// --output=./pallets/api/src/nonfungibles/weights.rs +// --extrinsic= + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +/// Weight functions needed for `nonfungibles`. +pub trait WeightInfo { + fn total_supply() -> Weight; + fn balance_of() -> Weight; + fn allowance() -> Weight; + fn owner_of() -> Weight; + fn get_attribute() -> Weight; + fn collection() -> Weight; + fn next_collection_id() -> Weight; + fn item_metadata() -> Weight; +} + +/// Weights for `nonfungibles` using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn total_supply() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + fn balance_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3529` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3529) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Allowances` (r:1 w:0) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn allowance() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(7_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn owner_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + fn get_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3944` + // Minimum execution time: 5_000_000 picoseconds. + Weight::from_parts(5_000_000, 3944) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn collection() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::NextCollectionId` (r:1 w:0) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn next_collection_id() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `1489` + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(1_000_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + fn item_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3812` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3812) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } +} + +// For backwards compatibility and tests. +impl WeightInfo for () { + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn total_supply() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + fn balance_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3529` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3529) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Allowances` (r:1 w:0) + /// Proof: `Nfts::Allowances` (`max_values`: None, `max_size`: Some(109), added: 2584, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn allowance() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(7_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + fn owner_of() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `4326` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) + fn get_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3944` + // Minimum execution time: 5_000_000 picoseconds. + Weight::from_parts(5_000_000, 3944) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(92), added: 2567, mode: `MaxEncodedLen`) + fn collection() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3557` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(2_000_000, 3557) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::NextCollectionId` (r:1 w:0) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn next_collection_id() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `1489` + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(1_000_000, 1489) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + fn item_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `3` + // Estimated: `3812` + // Minimum execution time: 2_000_000 picoseconds. + Weight::from_parts(3_000_000, 3812) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } +} + From 399695c73465507bd24eba4c3f373a02e3d6ffbe Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Tue, 19 Nov 2024 14:04:08 +0700 Subject: [PATCH 66/76] feat: add pallet-api/nonfungibles to runtime devnet --- runtime/devnet/src/config/api/mod.rs | 193 ++++++++++++++++++++++++--- runtime/devnet/src/config/assets.rs | 21 ++- runtime/devnet/src/config/proxy.rs | 38 +++--- runtime/devnet/src/lib.rs | 8 +- 4 files changed, 216 insertions(+), 44 deletions(-) diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs index 035a6014f..d96fd85bd 100644 --- a/runtime/devnet/src/config/api/mod.rs +++ b/runtime/devnet/src/config/api/mod.rs @@ -11,7 +11,8 @@ use sp_std::vec::Vec; use versioning::*; use crate::{ - config::assets::TrustBackedAssetsInstance, fungibles, Runtime, RuntimeCall, RuntimeEvent, + config::assets::{TrustBackedAssetsInstance, TrustBackedNftsInstance}, + fungibles, nonfungibles, Runtime, RuntimeCall, RuntimeEvent, }; mod versioning; @@ -32,6 +33,9 @@ pub enum RuntimeRead { /// Fungible token queries. #[codec(index = 150)] Fungibles(fungibles::Read), + /// Non-fungible token queries. + #[codec(index = 151)] + NonFungibles(nonfungibles::Read), } impl Readable for RuntimeRead { @@ -43,6 +47,7 @@ impl Readable for RuntimeRead { fn weight(&self) -> Weight { match self { RuntimeRead::Fungibles(key) => fungibles::Pallet::weight(key), + RuntimeRead::NonFungibles(key) => nonfungibles::Pallet::weight(key), } } @@ -50,16 +55,20 @@ impl Readable for RuntimeRead { fn read(self) -> Self::Result { match self { RuntimeRead::Fungibles(key) => RuntimeResult::Fungibles(fungibles::Pallet::read(key)), + RuntimeRead::NonFungibles(key) => + RuntimeResult::NonFungibles(nonfungibles::Pallet::read(key)), } } } /// The result of a runtime state read. #[derive(Debug)] -#[cfg_attr(test, derive(PartialEq, Clone))] +#[cfg_attr(feature = "std", derive(PartialEq, Clone))] pub enum RuntimeResult { /// Fungible token read results. Fungibles(fungibles::ReadResult), + /// Non-fungible token read results. + NonFungibles(nonfungibles::ReadResult), } impl RuntimeResult { @@ -67,6 +76,7 @@ impl RuntimeResult { fn encode(&self) -> Vec { match self { RuntimeResult::Fungibles(result) => result.encode(), + RuntimeResult::NonFungibles(result) => result.encode(), } } } @@ -77,6 +87,12 @@ impl fungibles::Config for Runtime { type WeightInfo = fungibles::weights::SubstrateWeight; } +impl nonfungibles::Config for Runtime { + type NftsInstance = TrustBackedNftsInstance; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); +} + #[derive(Default)] pub struct Config; impl pallet_api::extension::Config for Config { @@ -130,8 +146,8 @@ pub struct Filter(PhantomData); impl> Contains for Filter { fn contains(c: &RuntimeCall) -> bool { - use fungibles::Call::*; - T::BaseCallFilter::contains(c) && + let contain_fungibles: bool = { + use fungibles::Call::*; matches!( c, RuntimeCall::Fungibles( @@ -142,26 +158,63 @@ impl> Contains f create { .. } | set_metadata { .. } | start_destroy { .. } | clear_metadata { .. } | - mint { .. } | burn { .. } + mint { .. } | burn { .. }, + ) + ) + }; + + let contain_nonfungibles: bool = { + use nonfungibles::Call::*; + matches!( + c, + RuntimeCall::NonFungibles( + transfer { .. } | + approve { .. } | create { .. } | + destroy { .. } | set_metadata { .. } | + clear_metadata { .. } | + set_attribute { .. } | + clear_attribute { .. } | + approve_item_attributes { .. } | + cancel_item_attributes_approval { .. } | + mint { .. } | burn { .. } | + set_max_supply { .. }, ) ) + }; + + T::BaseCallFilter::contains(c) && contain_fungibles | contain_nonfungibles } } impl Contains for Filter { fn contains(r: &RuntimeRead) -> bool { - use fungibles::Read::*; - matches!( - r, - RuntimeRead::Fungibles( - TotalSupply(..) | - BalanceOf { .. } | - Allowance { .. } | - TokenName(..) | TokenSymbol(..) | - TokenDecimals(..) | - TokenExists(..) + let contain_fungibles: bool = { + use fungibles::Read::*; + matches!( + r, + RuntimeRead::Fungibles( + TotalSupply(..) | + BalanceOf { .. } | Allowance { .. } | + TokenName(..) | TokenSymbol(..) | + TokenDecimals(..) | TokenExists(..), + ) + ) + }; + let contain_nonfungibles: bool = { + use nonfungibles::Read::*; + matches!( + r, + RuntimeRead::NonFungibles( + TotalSupply(..) | + BalanceOf { .. } | Allowance { .. } | + OwnerOf { .. } | GetAttribute { .. } | + Collection { .. } | NextCollectionId | + ItemMetadata { .. }, + ) ) - ) + }; + + contain_fungibles | contain_nonfungibles } } @@ -169,8 +222,9 @@ impl Contains for Filter { mod tests { use codec::Encode; use pallet_api::fungibles::Call::*; - use sp_core::crypto::AccountId32; - use RuntimeCall::{Balances, Fungibles}; + use pallet_nfts::MintWitness; + use sp_core::{bounded_vec, crypto::AccountId32}; + use RuntimeCall::{Balances, Fungibles, NonFungibles}; use super::*; @@ -181,6 +235,10 @@ mod tests { let value = 1_000; let result = fungibles::ReadResult::::TotalSupply(value); assert_eq!(RuntimeResult::Fungibles(result).encode(), value.encode()); + + let value = 1_000; + let result = nonfungibles::ReadResult::::TotalSupply(value); + assert_eq!(RuntimeResult::NonFungibles(result).encode(), value.encode()); } #[test] @@ -228,6 +286,76 @@ mod tests { } } + #[test] + fn filter_allows_nonfungibles_calls() { + use pallet_api::nonfungibles::{ + Call::*, CollectionConfig, CollectionSettings, MintSettings, + }; + use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness}; + + for call in vec![ + NonFungibles(transfer { collection: 0, item: 0, to: ACCOUNT }), + NonFungibles(approve { + collection: 0, + item: Some(0), + operator: ACCOUNT, + approved: false, + }), + NonFungibles(create { + admin: ACCOUNT, + config: CollectionConfig { + max_supply: Some(0), + mint_settings: MintSettings::default(), + settings: CollectionSettings::all_enabled(), + }, + }), + NonFungibles(destroy { + collection: 0, + witness: DestroyWitness { + attributes: 0, + item_configs: 0, + item_metadatas: 0, + item_holders: 0, + allowances: 0, + }, + }), + NonFungibles(set_attribute { + collection: 0, + item: Some(0), + namespace: pallet_nfts::AttributeNamespace::Pallet, + key: bounded_vec![], + value: bounded_vec![], + }), + NonFungibles(clear_attribute { + collection: 0, + item: Some(0), + namespace: pallet_nfts::AttributeNamespace::Pallet, + key: bounded_vec![], + }), + NonFungibles(set_metadata { collection: 0, item: 0, data: bounded_vec![] }), + NonFungibles(clear_metadata { collection: 0, item: 0 }), + NonFungibles(approve_item_attributes { collection: 0, item: 0, delegate: ACCOUNT }), + NonFungibles(cancel_item_attributes_approval { + collection: 0, + item: 0, + delegate: ACCOUNT, + witness: CancelAttributesApprovalWitness { account_attributes: 0 }, + }), + NonFungibles(set_max_supply { collection: 0, max_supply: 0 }), + NonFungibles(mint { + to: ACCOUNT, + collection: 0, + item: 0, + witness: MintWitness { mint_price: None, owned_item: None }, + }), + NonFungibles(burn { collection: 0, item: 0 }), + ] + .iter() + { + assert!(Filter::::contains(call)) + } + } + #[test] fn filter_allows_fungibles_reads() { use super::{fungibles::Read::*, RuntimeRead::*}; @@ -245,4 +373,33 @@ mod tests { assert!(Filter::::contains(&read)) } } + + #[test] + fn filter_allows_nonfungibles_reads() { + use super::{nonfungibles::Read::*, RuntimeRead::*}; + + for read in vec![ + NonFungibles(TotalSupply(1)), + NonFungibles(BalanceOf { collection: 1, owner: ACCOUNT }), + NonFungibles(Allowance { + collection: 1, + item: None, + owner: ACCOUNT, + operator: ACCOUNT, + }), + NonFungibles(OwnerOf { collection: 1, item: 1 }), + NonFungibles(GetAttribute { + collection: 0, + item: 0, + namespace: pallet_nfts::AttributeNamespace::CollectionOwner, + key: bounded_vec![], + }), + NonFungibles(Collection(1)), + NonFungibles(NextCollectionId), + ] + .iter() + { + assert!(Filter::::contains(read)) + } + } } diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 326b7e594..65405ea46 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -6,7 +6,7 @@ use frame_support::{ use frame_system::{EnsureRoot, EnsureSigned}; use pallet_nfts::PalletFeatures; use parachains_common::{AssetIdForTrustBackedAssets, CollectionId, ItemId, Signature}; -use sp_runtime::traits::Verify; +use sp_runtime::traits::{Get, Verify}; use crate::{ deposit, AccountId, Assets, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, @@ -37,7 +37,18 @@ parameter_types! { pub const NftsMaxDeadlineDuration: BlockNumber = 12 * 30 * DAYS; } -impl pallet_nfts::Config for Runtime { +#[derive(Debug)] +#[cfg_attr(feature = "std", derive(PartialEq, Clone))] +pub struct KeyLimit; +impl Get for KeyLimit { + fn get() -> u32 { + N + } +} + +pub(crate) type TrustBackedNftsInstance = pallet_nfts::Instance1; +pub type TrustBackedNftsCall = pallet_nfts::Call; +impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ApprovalsLimit = ConstU32<20>; type AttributeDepositBase = NftsAttributeDepositBase; @@ -56,7 +67,7 @@ impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ItemId = ItemId; // TODO: source from primitives - type KeyLimit = ConstU32<64>; + type KeyLimit = KeyLimit<64>; type Locker = (); type MaxAttributesPerCall = ConstU32<10>; type MaxDeadlineDuration = NftsMaxDeadlineDuration; @@ -86,8 +97,8 @@ impl pallet_nft_fractionalization::Config for Runtime { type Deposit = AssetDeposit; type NewAssetName = NewAssetName; type NewAssetSymbol = NewAssetSymbol; - type NftCollectionId = ::CollectionId; - type NftId = ::ItemId; + type NftCollectionId = >::CollectionId; + type NftId = >::ItemId; type Nfts = Nfts; type PalletId = NftFractionalizationPalletId; type RuntimeEvent = RuntimeEvent; diff --git a/runtime/devnet/src/config/proxy.rs b/runtime/devnet/src/config/proxy.rs index ff70240e7..486530276 100644 --- a/runtime/devnet/src/config/proxy.rs +++ b/runtime/devnet/src/config/proxy.rs @@ -5,7 +5,7 @@ use pop_runtime_common::proxy::{ }; use sp_runtime::traits::BlakeTwo256; -use super::assets::TrustBackedAssetsCall; +use super::assets::{TrustBackedAssetsCall, TrustBackedNftsCall}; use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; impl InstanceFilter for ProxyType { @@ -45,13 +45,13 @@ impl InstanceFilter for ProxyType { RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::transfer_ownership { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_team { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_collection_max_supply { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_collection { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::create { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::destroy { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::redeposit { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::transfer_ownership { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_team { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_collection_max_supply { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_collection { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), @@ -66,17 +66,17 @@ impl InstanceFilter for ProxyType { RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_attributes_pre_signed { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_item_transfer { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::unlock_item_transfer { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_item_properties { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::clear_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_collection_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::clear_collection_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::force_mint { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::update_mint_settings { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::mint_pre_signed { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_attributes_pre_signed { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_item_transfer { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::unlock_item_transfer { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_item_properties { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::clear_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_collection_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::clear_collection_metadata { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index f539cbdee..736f0be73 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -39,7 +39,7 @@ use frame_system::{ limits::{BlockLength, BlockWeights}, EnsureRoot, }; -use pallet_api::fungibles; +use pallet_api::{fungibles, nonfungibles}; use pallet_balances::Call as BalancesCall; use pallet_ismp::mmr::{Leaf, Proof, ProofKeys}; use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; @@ -628,7 +628,7 @@ mod runtime { // Assets #[runtime::pallet_index(50)] - pub type Nfts = pallet_nfts::Pallet; + pub type Nfts = pallet_nfts::Pallet; #[runtime::pallet_index(51)] pub type NftFractionalization = pallet_nft_fractionalization::Pallet; #[runtime::pallet_index(52)] @@ -637,6 +637,8 @@ mod runtime { // Pop API #[runtime::pallet_index(150)] pub type Fungibles = fungibles::Pallet; + #[runtime::pallet_index(151)] + pub type NonFungibles = nonfungibles::Pallet; } #[cfg(feature = "runtime-benchmarks")] @@ -644,10 +646,12 @@ mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] [fungibles, Fungibles] + [nonfungibles, NonFungibles] [pallet_balances, Balances] [pallet_session, SessionBench::] [pallet_timestamp, Timestamp] [pallet_message_queue, MessageQueue] + [pallet_nfts, Nfts] [pallet_sudo, Sudo] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] From 37bb0a3682460ab6e7d230e6d2bf76a64afcc751 Mon Sep 17 00:00:00 2001 From: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> Date: Thu, 19 Dec 2024 11:56:09 +0100 Subject: [PATCH 67/76] refactor: sdk runtimes (#411) --- Cargo.lock | 499 +++++++++++++----- Cargo.toml | 16 +- integration-tests/Cargo.toml | 76 ++- .../src/chains/asset_hub/genesis.rs | 57 ++ integration-tests/src/chains/asset_hub/mod.rs | 42 ++ .../src/chains/asset_hub_paseo/genesis.rs | 60 --- .../src/chains/asset_hub_paseo/mod.rs | 38 -- integration-tests/src/chains/mod.rs | 4 +- integration-tests/src/chains/paseo/genesis.rs | 76 --- integration-tests/src/chains/paseo/mod.rs | 33 -- integration-tests/src/chains/relay/genesis.rs | 85 +++ integration-tests/src/chains/relay/mod.rs | 41 ++ integration-tests/src/lib.rs | 159 +++--- 13 files changed, 736 insertions(+), 450 deletions(-) create mode 100644 integration-tests/src/chains/asset_hub/genesis.rs create mode 100644 integration-tests/src/chains/asset_hub/mod.rs delete mode 100644 integration-tests/src/chains/asset_hub_paseo/genesis.rs delete mode 100644 integration-tests/src/chains/asset_hub_paseo/mod.rs delete mode 100644 integration-tests/src/chains/paseo/genesis.rs delete mode 100644 integration-tests/src/chains/paseo/mod.rs create mode 100644 integration-tests/src/chains/relay/genesis.rs create mode 100644 integration-tests/src/chains/relay/mod.rs diff --git a/Cargo.lock b/Cargo.lock index d2bf2acec..e31ca132e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -459,14 +459,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] -name = "asset-hub-polkadot-runtime" +name = "asset-hub-paseo-runtime" version = "1.0.0" -source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" +source = "git+https://github.com/paseo-network/runtimes/?tag=v1.3.3#871469acf97f0f233d0d50ebf80b414305a5c055" dependencies = [ "assets-common", - "bp-asset-hub-kusama", - "bp-asset-hub-polkadot", + "bp-asset-hub-paseo", "bp-bridge-hub-kusama", + "bp-bridge-hub-paseo", "bp-bridge-hub-polkadot", "collectives-polkadot-runtime-constants", "cumulus-pallet-aura-ext", @@ -486,7 +486,6 @@ dependencies = [ "frame-system-rpc-runtime-api", "frame-try-runtime", "hex-literal 0.4.1", - "kusama-runtime-constants", "log", "pallet-asset-conversion", "pallet-asset-conversion-tx-payment", @@ -501,6 +500,7 @@ dependencies = [ "pallet-nfts-runtime-api", "pallet-proxy", "pallet-session", + "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", @@ -512,10 +512,10 @@ dependencies = [ "pallet-xcm-bridge-hub-router", "parachains-common", "parity-scale-codec", + "paseo-runtime-constants", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-runtime-common", - "polkadot-runtime-constants", "primitive-types", "scale-info", "serde_json", @@ -524,6 +524,7 @@ dependencies = [ "sp-block-builder", "sp-consensus-aura", "sp-core", + "sp-debug-derive", "sp-genesis-builder", "sp-inherents", "sp-io", @@ -540,7 +541,91 @@ dependencies = [ "staging-xcm-builder", "staging-xcm-executor", "substrate-wasm-builder", - "system-parachains-constants", + "system-parachains-constants 1.0.0 (git+https://github.com/paseo-network/runtimes/?tag=v1.3.3)", + "xcm-runtime-apis", +] + +[[package]] +name = "asset-hub-westend-runtime" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09947ff9d035d5524a6b210e676ca932c58a262d3331f5cb871dde20a82548b4" +dependencies = [ + "assets-common", + "bp-asset-hub-rococo", + "bp-asset-hub-westend", + "bp-bridge-hub-rococo", + "bp-bridge-hub-westend", + "cumulus-pallet-aura-ext", + "cumulus-pallet-parachain-system", + "cumulus-pallet-session-benchmarking", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-aura", + "cumulus-primitives-core", + "cumulus-primitives-storage-weight-reclaim", + "cumulus-primitives-utility", + "frame-benchmarking", + "frame-executive", + "frame-metadata-hash-extension", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "hex-literal 0.4.1", + "log", + "pallet-asset-conversion", + "pallet-asset-conversion-ops", + "pallet-asset-conversion-tx-payment", + "pallet-assets", + "pallet-assets-freezer", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-collator-selection", + "pallet-message-queue", + "pallet-multisig", + "pallet-nft-fractionalization", + "pallet-nfts 30.0.0", + "pallet-nfts-runtime-api", + "pallet-proxy", + "pallet-session", + "pallet-state-trie-migration", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-uniques", + "pallet-utility", + "pallet-xcm", + "pallet-xcm-benchmarks", + "pallet-xcm-bridge-hub-router", + "parachains-common", + "parity-scale-codec", + "polkadot-parachain-primitives", + "polkadot-runtime-common", + "primitive-types", + "scale-info", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-genesis-builder", + "sp-inherents", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-storage", + "sp-transaction-pool", + "sp-version", + "staging-parachain-info", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "substrate-wasm-builder", + "testnet-parachains-constants", + "westend-runtime-constants", "xcm-runtime-apis", ] @@ -1130,9 +1215,9 @@ dependencies = [ ] [[package]] -name = "bp-asset-hub-kusama" +name = "bp-asset-hub-paseo" version = "1.0.0" -source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" +source = "git+https://github.com/paseo-network/runtimes/?tag=v1.3.3#871469acf97f0f233d0d50ebf80b414305a5c055" dependencies = [ "bp-xcm-bridge-hub-router", "frame-support", @@ -1140,21 +1225,31 @@ dependencies = [ "scale-info", "sp-std", "staging-xcm", - "system-parachains-constants", + "system-parachains-constants 1.0.0 (git+https://github.com/paseo-network/runtimes/?tag=v1.3.3)", ] [[package]] -name = "bp-asset-hub-polkadot" -version = "1.0.0" -source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" +name = "bp-asset-hub-rococo" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f44a24eebc53fdb071a4111bc3a8727be57b8a5f368a809f0dd142bd7dc374c" +dependencies = [ + "bp-xcm-bridge-hub-router", + "frame-support", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "bp-asset-hub-westend" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af585d00509b3723819189c34410a2ed332fe6c2cc5c7876f64f79818c346f13" dependencies = [ "bp-xcm-bridge-hub-router", "frame-support", "parity-scale-codec", "scale-info", - "sp-std", - "staging-xcm", - "system-parachains-constants", ] [[package]] @@ -1176,7 +1271,7 @@ dependencies = [ [[package]] name = "bp-bridge-hub-kusama" version = "1.0.0" -source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" +source = "git+https://github.com/polkadot-fellows/runtimes?tag=v1.3.3#55bd514d60311b67cb11400a545cb64ce7a87c0e" dependencies = [ "bp-bridge-hub-cumulus", "bp-messages", @@ -1187,13 +1282,33 @@ dependencies = [ "sp-api", "sp-runtime", "sp-std", - "system-parachains-constants", + "system-parachains-constants 1.0.0 (git+https://github.com/polkadot-fellows/runtimes?tag=v1.3.3)", +] + +[[package]] +name = "bp-bridge-hub-paseo" +version = "1.0.0" +source = "git+https://github.com/paseo-network/runtimes/?tag=v1.3.3#871469acf97f0f233d0d50ebf80b414305a5c055" +dependencies = [ + "bp-bridge-hub-cumulus", + "bp-messages", + "bp-polkadot-bulletin", + "bp-runtime", + "frame-support", + "kusama-runtime-constants", + "paseo-runtime-constants", + "snowbridge-core", + "sp-api", + "sp-runtime", + "sp-std", + "staging-xcm", + "system-parachains-constants 1.0.0 (git+https://github.com/paseo-network/runtimes/?tag=v1.3.3)", ] [[package]] name = "bp-bridge-hub-polkadot" version = "1.0.0" -source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" +source = "git+https://github.com/polkadot-fellows/runtimes?tag=v1.3.3#55bd514d60311b67cb11400a545cb64ce7a87c0e" dependencies = [ "bp-bridge-hub-cumulus", "bp-messages", @@ -1207,7 +1322,37 @@ dependencies = [ "sp-runtime", "sp-std", "staging-xcm", - "system-parachains-constants", + "system-parachains-constants 1.0.0 (git+https://github.com/polkadot-fellows/runtimes?tag=v1.3.3)", +] + +[[package]] +name = "bp-bridge-hub-rococo" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89228837ee3b9673a8bc0b6c2eab73b85e2f466cb100ace0f779f733bddb56c" +dependencies = [ + "bp-bridge-hub-cumulus", + "bp-messages", + "bp-runtime", + "frame-support", + "sp-api", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "bp-bridge-hub-westend" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b32c6051deb0f147081ebc5bf1d0d327cbfbc8e8af6d14c9f336167122c9cf5" +dependencies = [ + "bp-bridge-hub-cumulus", + "bp-messages", + "bp-runtime", + "frame-support", + "sp-api", + "sp-runtime", + "sp-std", ] [[package]] @@ -1772,7 +1917,7 @@ dependencies = [ [[package]] name = "collectives-polkadot-runtime-constants" version = "1.0.0" -source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" +source = "git+https://github.com/polkadot-fellows/runtimes?tag=v1.3.3#55bd514d60311b67cb11400a545cb64ce7a87c0e" [[package]] name = "color-print" @@ -5208,7 +5353,8 @@ dependencies = [ name = "integration-tests" version = "0.0.0" dependencies = [ - "asset-hub-polkadot-runtime", + "asset-hub-paseo-runtime", + "asset-hub-westend-runtime", "asset-test-utils", "cumulus-primitives-core", "emulated-integration-tests-common", @@ -5218,9 +5364,9 @@ dependencies = [ "pallet-message-queue", "pallet-xcm", "parity-scale-codec", + "paseo-runtime", + "paseo-runtime-constants", "polkadot-primitives", - "polkadot-runtime", - "polkadot-runtime-constants", "polkadot-runtime-parachains", "pop-runtime-common", "pop-runtime-devnet", @@ -5235,6 +5381,8 @@ dependencies = [ "staging-xcm", "staging-xcm-executor", "tracing-subscriber 0.3.18", + "westend-runtime", + "westend-runtime-constants", ] [[package]] @@ -5596,7 +5744,7 @@ checksum = "c33070833c9ee02266356de0c43f723152bd38bd96ddf52c82b3af10c9138b28" [[package]] name = "kusama-runtime-constants" version = "1.0.0" -source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" +source = "git+https://github.com/polkadot-fellows/runtimes?tag=v1.3.3#55bd514d60311b67cb11400a545cb64ce7a87c0e" dependencies = [ "frame-support", "polkadot-primitives", @@ -7395,6 +7543,26 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-asset-conversion-ops" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffad613243bdac3426f8db5e4adb674f068fca3d76254f58d648cbc03d3ffce" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-asset-conversion", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-asset-conversion-tx-payment" version = "18.0.0" @@ -7464,6 +7632,22 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-assets-freezer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a98488bba3ba1b9877ed2fb8a8739f07a3e19389d5011549ce7b78f62466ff8" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-assets", + "parity-scale-codec", + "scale-info", + "sp-runtime", +] + [[package]] name = "pallet-aura" version = "35.0.0" @@ -9160,6 +9344,123 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7924d1d0ad836f665c9065e26d016c673ece3993f30d340068b16f282afc1156" +[[package]] +name = "paseo-runtime" +version = "1.3.3" +source = "git+https://github.com/paseo-network/runtimes/?tag=v1.3.3#871469acf97f0f233d0d50ebf80b414305a5c055" +dependencies = [ + "binary-merkle-tree", + "frame-benchmarking", + "frame-election-provider-support", + "frame-executive", + "frame-metadata-hash-extension", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "hex-literal 0.4.1", + "log", + "pallet-asset-rate", + "pallet-authority-discovery", + "pallet-authorship", + "pallet-babe", + "pallet-bags-list", + "pallet-balances", + "pallet-beefy", + "pallet-beefy-mmr", + "pallet-bounties", + "pallet-broker", + "pallet-child-bounties", + "pallet-conviction-voting", + "pallet-election-provider-multi-phase", + "pallet-election-provider-support-benchmarking", + "pallet-fast-unstake", + "pallet-grandpa", + "pallet-im-online", + "pallet-indices", + "pallet-message-queue", + "pallet-mmr", + "pallet-multisig", + "pallet-nomination-pools", + "pallet-nomination-pools-benchmarking", + "pallet-nomination-pools-runtime-api", + "pallet-offences", + "pallet-offences-benchmarking", + "pallet-parameters", + "pallet-preimage", + "pallet-proxy", + "pallet-referenda", + "pallet-scheduler", + "pallet-session", + "pallet-session-benchmarking", + "pallet-staking", + "pallet-staking-reward-curve", + "pallet-staking-reward-fn", + "pallet-staking-runtime-api", + "pallet-state-trie-migration", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-treasury", + "pallet-utility", + "pallet-vesting", + "pallet-whitelist", + "pallet-xcm", + "pallet-xcm-benchmarks", + "parity-scale-codec", + "paseo-runtime-constants", + "polkadot-parachain-primitives", + "polkadot-primitives", + "polkadot-runtime-common", + "polkadot-runtime-parachains", + "relay-common", + "scale-info", + "serde_json", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-authority-discovery", + "sp-block-builder", + "sp-consensus-babe", + "sp-consensus-beefy", + "sp-core", + "sp-debug-derive", + "sp-genesis-builder", + "sp-inherents", + "sp-io", + "sp-npos-elections", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std", + "sp-storage", + "sp-transaction-pool", + "sp-version", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "substrate-wasm-builder", + "xcm-runtime-apis", +] + +[[package]] +name = "paseo-runtime-constants" +version = "1.0.0" +source = "git+https://github.com/paseo-network/runtimes/?tag=v1.3.3#871469acf97f0f233d0d50ebf80b414305a5c055" +dependencies = [ + "frame-support", + "polkadot-primitives", + "polkadot-runtime-common", + "smallvec", + "sp-core", + "sp-runtime", + "sp-weights", + "staging-xcm-builder", +] + [[package]] name = "password-hash" version = "0.5.0" @@ -10180,104 +10481,6 @@ dependencies = [ "substrate-state-trie-migration-rpc", ] -[[package]] -name = "polkadot-runtime" -version = "1.0.0" -source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" -dependencies = [ - "binary-merkle-tree", - "frame-benchmarking", - "frame-election-provider-support", - "frame-executive", - "frame-metadata-hash-extension", - "frame-support", - "frame-system", - "frame-system-benchmarking", - "frame-system-rpc-runtime-api", - "frame-try-runtime", - "log", - "pallet-asset-rate", - "pallet-authority-discovery", - "pallet-authorship", - "pallet-babe", - "pallet-bags-list", - "pallet-balances", - "pallet-beefy", - "pallet-beefy-mmr", - "pallet-bounties", - "pallet-broker", - "pallet-child-bounties", - "pallet-conviction-voting", - "pallet-election-provider-multi-phase", - "pallet-election-provider-support-benchmarking", - "pallet-fast-unstake", - "pallet-grandpa", - "pallet-im-online", - "pallet-indices", - "pallet-message-queue", - "pallet-mmr", - "pallet-multisig", - "pallet-nomination-pools", - "pallet-nomination-pools-benchmarking", - "pallet-nomination-pools-runtime-api", - "pallet-offences", - "pallet-offences-benchmarking", - "pallet-preimage", - "pallet-proxy", - "pallet-referenda", - "pallet-scheduler", - "pallet-session", - "pallet-session-benchmarking", - "pallet-staking", - "pallet-staking-reward-curve", - "pallet-staking-reward-fn", - "pallet-staking-runtime-api", - "pallet-state-trie-migration", - "pallet-timestamp", - "pallet-transaction-payment", - "pallet-transaction-payment-rpc-runtime-api", - "pallet-treasury", - "pallet-utility", - "pallet-vesting", - "pallet-whitelist", - "pallet-xcm", - "pallet-xcm-benchmarks", - "parity-scale-codec", - "polkadot-parachain-primitives", - "polkadot-primitives", - "polkadot-runtime-common", - "polkadot-runtime-constants", - "polkadot-runtime-parachains", - "scale-info", - "serde_json", - "sp-api", - "sp-application-crypto", - "sp-arithmetic", - "sp-authority-discovery", - "sp-block-builder", - "sp-consensus-babe", - "sp-consensus-beefy", - "sp-core", - "sp-debug-derive", - "sp-genesis-builder", - "sp-inherents", - "sp-io", - "sp-npos-elections", - "sp-offchain", - "sp-runtime", - "sp-session", - "sp-staking", - "sp-std", - "sp-storage", - "sp-transaction-pool", - "sp-version", - "staging-xcm", - "staging-xcm-builder", - "staging-xcm-executor", - "substrate-wasm-builder", - "xcm-runtime-apis", -] - [[package]] name = "polkadot-runtime-common" version = "15.0.0" @@ -10333,7 +10536,7 @@ dependencies = [ [[package]] name = "polkadot-runtime-constants" version = "1.0.0" -source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" +source = "git+https://github.com/polkadot-fellows/runtimes?tag=v1.3.3#55bd514d60311b67cb11400a545cb64ce7a87c0e" dependencies = [ "frame-support", "polkadot-primitives", @@ -11768,6 +11971,19 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "relay-common" +version = "1.0.0" +source = "git+https://github.com/paseo-network/runtimes/?tag=v1.3.3#871469acf97f0f233d0d50ebf80b414305a5c055" +dependencies = [ + "pallet-staking-reward-fn", + "parity-scale-codec", + "polkadot-primitives", + "scale-info", + "sp-api", + "sp-runtime", +] + [[package]] name = "resolv-conf" version = "0.7.0" @@ -15629,7 +15845,24 @@ dependencies = [ [[package]] name = "system-parachains-constants" version = "1.0.0" -source = "git+https://github.com/polkadot-fellows/runtimes#f42acab60edf4d6ded4d9e99b1a8fbacded85669" +source = "git+https://github.com/paseo-network/runtimes/?tag=v1.3.3#871469acf97f0f233d0d50ebf80b414305a5c055" +dependencies = [ + "frame-support", + "parachains-common", + "paseo-runtime-constants", + "polkadot-core-primitives", + "polkadot-primitives", + "smallvec", + "sp-core", + "sp-runtime", + "sp-std", + "staging-xcm", +] + +[[package]] +name = "system-parachains-constants" +version = "1.0.0" +source = "git+https://github.com/polkadot-fellows/runtimes?tag=v1.3.3#55bd514d60311b67cb11400a545cb64ce7a87c0e" dependencies = [ "frame-support", "kusama-runtime-constants", @@ -15703,6 +15936,22 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" +[[package]] +name = "testnet-parachains-constants" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad78d2dae5b039af1b1dc70ee765fb2d98d64c5e2a8bf1dc00d25c930a62f01d" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "polkadot-core-primitives", + "rococo-runtime-constants", + "smallvec", + "sp-runtime", + "staging-xcm", + "westend-runtime-constants", +] + [[package]] name = "thiserror" version = "1.0.61" diff --git a/Cargo.toml b/Cargo.toml index 0c73e23f7..2e0efe9bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -181,15 +181,13 @@ pallet-collator-selection = { version = "17.0.0", default-features = false } parachain-info = { version = "0.15.0", package = "staging-parachain-info", default-features = false } parachains-common = { version = "15.0.0", default-features = false } -# TODO: Paseo (note: using polkadot as stopgap until paseo updated to polkadot sdk v1.14.0) -asset-hub-paseo-runtime = { git = "https://github.com/polkadot-fellows/runtimes", default-features = false, package = "asset-hub-polkadot-runtime" } -paseo-runtime = { git = "https://github.com/polkadot-fellows/runtimes", default-features = false, package = "polkadot-runtime" } -paseo-runtime-constants = { git = "https://github.com/polkadot-fellows/runtimes", default-features = false, package = "polkadot-runtime-constants" } - -# Paseo -# asset-hub-paseo-runtime = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.2.5-system-chains", default-features = false } -# paseo-runtime = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.2.5-system-chains", default-features = false } -# paseo-runtime-constants = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.2.5-system-chains", default-features = false } +# Runtimes +asset-hub-paseo-runtime = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.3.3", default-features = false } +asset-hub-westend-runtime = { version = "0.23.0", default-features = false } +paseo-runtime = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.3.3", default-features = false } +paseo-runtime-constants = { git = "https://github.com/paseo-network/runtimes/", tag = "v1.3.3", default-features = false } +westend-runtime = { version = "15.0.0", default-features = false } +westend-runtime-constants = { version = "15.0.0", default-features = false } ismp = { git = "https://github.com/r0gue-io/ismp", branch = "polkadot-v1.14.0", default-features = false } ismp-parachain = { git = "https://github.com/r0gue-io/ismp", branch = "polkadot-v1.14.0", default-features = false } diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 0bbdc053c..9c34b5817 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -6,7 +6,7 @@ license.workspace = true name = "integration-tests" repository.workspace = true -[dev-dependencies] +[dependencies] codec.workspace = true tracing-subscriber = { workspace = true, features = [ "env-filter", @@ -40,10 +40,13 @@ asset-test-utils.workspace = true cumulus-primitives-core.workspace = true emulated-integration-tests-common.workspace = true -# Paseo -asset-hub-paseo-runtime.workspace = true -paseo-runtime.workspace = true -paseo-runtime-constants.workspace = true +# Runtimes +asset-hub-paseo-runtime = { workspace = true, optional = true } +asset-hub-westend-runtime = { workspace = true, optional = true } +paseo-runtime = { workspace = true, optional = true } +paseo-runtime-constants = { workspace = true, optional = true } +westend-runtime = { workspace = true, optional = true } +westend-runtime-constants = { workspace = true, optional = true } # Local pop-runtime-common.workspace = true @@ -51,18 +54,42 @@ pop-runtime-devnet.workspace = true pop-runtime-mainnet.workspace = true [features] -default = [ "std" ] +default = [ "westend" ] mainnet = [ "pop-runtime-mainnet/default" ] +paseo = [ + "asset-hub-paseo-runtime", + "paseo-runtime", + "paseo-runtime-constants", + "std", +] +runtime-benchmarks = [ + "asset-hub-paseo-runtime?/runtime-benchmarks", + "asset-hub-westend-runtime?/runtime-benchmarks", + "cumulus-primitives-core/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-message-queue/runtime-benchmarks", + "paseo-runtime?/runtime-benchmarks", + "polkadot-primitives/runtime-benchmarks", + "pop-runtime-common/runtime-benchmarks", + "pop-runtime-devnet/runtime-benchmarks", + "pop-runtime-mainnet/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "westend-runtime?/runtime-benchmarks", + "xcm-executor/runtime-benchmarks", +] std = [ - "asset-hub-paseo-runtime/std", + "asset-hub-paseo-runtime?/std", + "asset-hub-westend-runtime?/std", "cumulus-primitives-core/std", "frame-support/std", "pallet-assets/std", "pallet-balances/std", "pallet-message-queue/std", "pallet-xcm/std", - "paseo-runtime-constants/std", - "paseo-runtime/std", + "paseo-runtime-constants?/std", + "paseo-runtime?/std", "polkadot-primitives/std", "polkadot-runtime-parachains/std", "pop-runtime-common/std", @@ -75,34 +102,27 @@ std = [ "sp-consensus-grandpa/std", "sp-core/std", "sp-runtime/std", + "westend-runtime-constants?/std", + "westend-runtime?/std", "xcm-executor/std", "xcm/std", ] - -runtime-benchmarks = [ - "asset-hub-paseo-runtime/runtime-benchmarks", - "cumulus-primitives-core/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "pallet-assets/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-message-queue/runtime-benchmarks", - "paseo-runtime/runtime-benchmarks", - "polkadot-primitives/runtime-benchmarks", - "pop-runtime-common/runtime-benchmarks", - "pop-runtime-devnet/runtime-benchmarks", - "pop-runtime-mainnet/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-executor/runtime-benchmarks", -] - try-runtime = [ - "asset-hub-paseo-runtime/try-runtime", + "asset-hub-paseo-runtime?/try-runtime", + "asset-hub-westend-runtime?/try-runtime", "frame-support/try-runtime", "pallet-assets/try-runtime", "pallet-balances/std", "pallet-message-queue/try-runtime", - "paseo-runtime/try-runtime", + "paseo-runtime?/try-runtime", "pop-runtime-devnet/try-runtime", "pop-runtime-mainnet/try-runtime", "sp-runtime/try-runtime", + "westend-runtime?/try-runtime", +] +westend = [ + "asset-hub-westend-runtime", + "std", + "westend-runtime", + "westend-runtime-constants", ] diff --git a/integration-tests/src/chains/asset_hub/genesis.rs b/integration-tests/src/chains/asset_hub/genesis.rs new file mode 100644 index 000000000..e6269c8de --- /dev/null +++ b/integration-tests/src/chains/asset_hub/genesis.rs @@ -0,0 +1,57 @@ +use cumulus_primitives_core::relay_chain::Balance; +use emulated_integration_tests_common::{ + accounts, build_genesis_storage, collators::invulnerables, SAFE_XCM_VERSION, +}; +use sp_core::storage::Storage; + +use crate::chains::asset_hub::{ + constants::currency::EXISTENTIAL_DEPOSIT, + runtime::{ + BalancesConfig, CollatorSelectionConfig, ParachainInfoConfig, PolkadotXcmConfig, + RuntimeGenesisConfig, SessionConfig, SessionKeys, SystemConfig, WASM_BINARY, + }, +}; + +pub(crate) const ED: Balance = EXISTENTIAL_DEPOSIT; +pub(crate) const PARA_ID: u32 = 1000; + +pub(crate) fn genesis() -> Storage { + let genesis_config = RuntimeGenesisConfig { + system: SystemConfig::default(), + balances: BalancesConfig { + balances: accounts::init_balances() + .iter() + .cloned() + .map(|k| (k, ED * 4096 * 4096)) + .collect(), + }, + parachain_info: ParachainInfoConfig { parachain_id: PARA_ID.into(), ..Default::default() }, + collator_selection: CollatorSelectionConfig { + invulnerables: invulnerables().iter().cloned().map(|(acc, _)| acc).collect(), + candidacy_bond: ED * 16, + ..Default::default() + }, + session: SessionConfig { + keys: invulnerables() + .into_iter() + .map(|(acc, aura)| { + ( + acc.clone(), // account id + acc, // validator id + SessionKeys { aura }, // session keys + ) + }) + .collect(), + }, + polkadot_xcm: PolkadotXcmConfig { + safe_xcm_version: Some(SAFE_XCM_VERSION), + ..Default::default() + }, + ..Default::default() + }; + + build_genesis_storage( + &genesis_config, + WASM_BINARY.expect("WASM binary was not built, please build it!"), + ) +} diff --git a/integration-tests/src/chains/asset_hub/mod.rs b/integration-tests/src/chains/asset_hub/mod.rs new file mode 100644 index 000000000..13d086b76 --- /dev/null +++ b/integration-tests/src/chains/asset_hub/mod.rs @@ -0,0 +1,42 @@ +use emulated_integration_tests_common::{ + impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain, + impl_assets_helpers_for_parachain, impl_foreign_assets_helpers_for_parachain, + impl_xcm_helpers_for_parachain, impls::Parachain, xcm_emulator::decl_test_parachains, +}; +use frame_support::traits::OnInitialize; +#[cfg(feature = "paseo")] +pub(crate) use {asset_hub_paseo_runtime as runtime, paseo_runtime_constants as constants}; +#[cfg(feature = "westend")] +pub(crate) use {asset_hub_westend_runtime as runtime, westend_runtime_constants as constants}; + +pub(crate) mod genesis; + +// AssetHub Parachain declaration. +decl_test_parachains! { + pub struct AssetHub { + genesis = genesis::genesis(), + on_init = { + runtime::AuraExt::on_initialize(1); + }, + runtime = runtime, + core = { + XcmpMessageHandler: runtime::XcmpQueue, + LocationToAccountId: runtime::xcm_config::LocationToAccountId, + ParachainInfo: runtime::ParachainInfo, + MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin, + }, + pallets = { + PolkadotXcm: runtime::PolkadotXcm, + Assets: runtime::Assets, + ForeignAssets: runtime::ForeignAssets, + Balances: runtime::Balances, + } + }, +} + +// AssetHub implementation. +impl_accounts_helpers_for_parachain!(AssetHub); +impl_assert_events_helpers_for_parachain!(AssetHub); +impl_assets_helpers_for_parachain!(AssetHub); +impl_foreign_assets_helpers_for_parachain!(AssetHub, xcm::v3::Location); +impl_xcm_helpers_for_parachain!(AssetHub); diff --git a/integration-tests/src/chains/asset_hub_paseo/genesis.rs b/integration-tests/src/chains/asset_hub_paseo/genesis.rs deleted file mode 100644 index 5d73eb3b6..000000000 --- a/integration-tests/src/chains/asset_hub_paseo/genesis.rs +++ /dev/null @@ -1,60 +0,0 @@ -use emulated_integration_tests_common::{ - accounts, build_genesis_storage, get_account_id_from_seed, get_from_seed, SAFE_XCM_VERSION, -}; -use polkadot_primitives::{AccountId, Balance}; -use sp_core::{sr25519, storage::Storage}; - -pub(crate) const PARA_ID: u32 = 1000; -pub(crate) const ED: Balance = paseo_runtime_constants::currency::EXISTENTIAL_DEPOSIT / 10; - -pub(crate) fn genesis() -> Storage { - let genesis_config = asset_hub_paseo_runtime::RuntimeGenesisConfig { - system: asset_hub_paseo_runtime::SystemConfig::default(), - balances: asset_hub_paseo_runtime::BalancesConfig { - balances: accounts::init_balances() - .iter() - .cloned() - .map(|k| (k, ED * 4096 * 4096)) - .collect(), - }, - parachain_info: asset_hub_paseo_runtime::ParachainInfoConfig { - parachain_id: PARA_ID.into(), - ..Default::default() - }, - collator_selection: asset_hub_paseo_runtime::CollatorSelectionConfig { - invulnerables: invulnerables().iter().cloned().map(|(acc, _)| acc).collect(), - candidacy_bond: ED * 16, - ..Default::default() - }, - session: asset_hub_paseo_runtime::SessionConfig { - keys: invulnerables() - .into_iter() - .map(|(acc, aura)| { - ( - acc.clone(), // account id - acc, // validator id - asset_hub_paseo_runtime::SessionKeys { aura }, // session keys - ) - }) - .collect(), - }, - polkadot_xcm: asset_hub_paseo_runtime::PolkadotXcmConfig { - safe_xcm_version: Some(SAFE_XCM_VERSION), - ..Default::default() - }, - ..Default::default() - }; - - build_genesis_storage( - &genesis_config, - asset_hub_paseo_runtime::WASM_BINARY.expect("WASM binary was not built, please build it!"), - ) -} - -type AuraId = sp_consensus_aura::ed25519::AuthorityId; -pub fn invulnerables() -> Vec<(AccountId, AuraId)> { - vec![ - (get_account_id_from_seed::("Alice"), get_from_seed::("Alice")), - (get_account_id_from_seed::("Bob"), get_from_seed::("Bob")), - ] -} diff --git a/integration-tests/src/chains/asset_hub_paseo/mod.rs b/integration-tests/src/chains/asset_hub_paseo/mod.rs deleted file mode 100644 index 0a9620e31..000000000 --- a/integration-tests/src/chains/asset_hub_paseo/mod.rs +++ /dev/null @@ -1,38 +0,0 @@ -pub(crate) mod genesis; - -use emulated_integration_tests_common::{ - impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain, - impl_assets_helpers_for_parachain, impl_foreign_assets_helpers_for_parachain, - impl_xcm_helpers_for_parachain, impls::Parachain, xcm_emulator::decl_test_parachains, -}; -use frame_support::traits::OnInitialize; - -// AssetHubPaseo Parachain declaration -decl_test_parachains! { - pub struct AssetHubPaseo { - genesis = genesis::genesis(), - on_init = { - asset_hub_paseo_runtime::AuraExt::on_initialize(1); - }, - runtime = asset_hub_paseo_runtime, - core = { - XcmpMessageHandler: asset_hub_paseo_runtime::XcmpQueue, - LocationToAccountId: asset_hub_paseo_runtime::xcm_config::LocationToAccountId, - ParachainInfo: asset_hub_paseo_runtime::ParachainInfo, - MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin, - }, - pallets = { - PolkadotXcm: asset_hub_paseo_runtime::PolkadotXcm, - Assets: asset_hub_paseo_runtime::Assets, - ForeignAssets: asset_hub_paseo_runtime::ForeignAssets, - Balances: asset_hub_paseo_runtime::Balances, - } - }, -} - -// AssetHubPaseo implementation -impl_accounts_helpers_for_parachain!(AssetHubPaseo); -impl_assert_events_helpers_for_parachain!(AssetHubPaseo); -impl_assets_helpers_for_parachain!(AssetHubPaseo); -impl_foreign_assets_helpers_for_parachain!(AssetHubPaseo, xcm::v3::Location); -impl_xcm_helpers_for_parachain!(AssetHubPaseo); diff --git a/integration-tests/src/chains/mod.rs b/integration-tests/src/chains/mod.rs index 429c66913..604bbeef0 100644 --- a/integration-tests/src/chains/mod.rs +++ b/integration-tests/src/chains/mod.rs @@ -1,3 +1,3 @@ -pub(crate) mod asset_hub_paseo; -pub(crate) mod paseo; +pub(crate) mod asset_hub; pub(crate) mod pop_network; +pub(crate) mod relay; diff --git a/integration-tests/src/chains/paseo/genesis.rs b/integration-tests/src/chains/paseo/genesis.rs deleted file mode 100644 index 0ecdb1ff8..000000000 --- a/integration-tests/src/chains/paseo/genesis.rs +++ /dev/null @@ -1,76 +0,0 @@ -use emulated_integration_tests_common::{ - accounts, build_genesis_storage, get_from_seed, get_host_config, validators, -}; -use paseo_runtime_constants::currency::UNITS as PAS; -use polkadot_primitives::{AssignmentId, Balance, ValidatorId}; -use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; -use sp_consensus_babe::AuthorityId as BabeId; -use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId; -use sp_consensus_grandpa::AuthorityId as GrandpaId; -use sp_core::storage::Storage; - -pub(crate) const ED: Balance = paseo_runtime_constants::currency::EXISTENTIAL_DEPOSIT; -const ENDOWMENT: u128 = 1_000_000 * PAS; - -fn session_keys( - babe: BabeId, - grandpa: GrandpaId, - para_validator: ValidatorId, - para_assignment: AssignmentId, - authority_discovery: AuthorityDiscoveryId, - beefy: BeefyId, -) -> paseo_runtime::SessionKeys { - paseo_runtime::SessionKeys { - babe, - grandpa, - para_validator, - para_assignment, - authority_discovery, - beefy, - } -} - -pub(crate) fn genesis() -> Storage { - let genesis_config = paseo_runtime::RuntimeGenesisConfig { - system: paseo_runtime::SystemConfig::default(), - balances: paseo_runtime::BalancesConfig { - balances: accounts::init_balances().iter().map(|k| (k.clone(), ENDOWMENT)).collect(), - }, - session: paseo_runtime::SessionConfig { - keys: validators::initial_authorities() - .iter() - .map(|x| { - ( - x.0.clone(), - x.0.clone(), - session_keys( - x.2.clone(), - x.3.clone(), - x.4.clone(), - x.5.clone(), - x.6.clone(), - get_from_seed::("Alice"), - ), - ) - }) - .collect::>(), - }, - babe: paseo_runtime::BabeConfig { - authorities: Default::default(), - epoch_config: paseo_runtime::BABE_GENESIS_EPOCH_CONFIG, - ..Default::default() - }, - // TODO: sudo pallet is not configured in polkadot runtime - // sudo: runtime::SudoConfig { - // key: Some(get_account_id_from_seed::("Alice")), - // }, - configuration: paseo_runtime::ConfigurationConfig { config: get_host_config() }, - registrar: paseo_runtime::RegistrarConfig { - next_free_para_id: polkadot_primitives::LOWEST_PUBLIC_ID, - ..Default::default() - }, - ..Default::default() - }; - - build_genesis_storage(&genesis_config, paseo_runtime::WASM_BINARY.unwrap()) -} diff --git a/integration-tests/src/chains/paseo/mod.rs b/integration-tests/src/chains/paseo/mod.rs deleted file mode 100644 index 4df1d2afd..000000000 --- a/integration-tests/src/chains/paseo/mod.rs +++ /dev/null @@ -1,33 +0,0 @@ -pub(crate) mod genesis; - -use emulated_integration_tests_common::{ - impl_accounts_helpers_for_relay_chain, impl_assert_events_helpers_for_relay_chain, - impl_hrmp_channels_helpers_for_relay_chain, impl_send_transact_helpers_for_relay_chain, - xcm_emulator::decl_test_relay_chains, -}; - -// Paseo declaration -decl_test_relay_chains! { - #[api_version(11)] - pub struct Paseo { - genesis = genesis::genesis(), - on_init = (), - runtime = paseo_runtime, - core = { - SovereignAccountOf: paseo_runtime::xcm_config::SovereignAccountOf, - }, - pallets = { - XcmPallet: paseo_runtime::XcmPallet, - // TODO: sudo pallet is not configured in polkadot runtime - // Sudo: paseo_runtime::Sudo, - Balances: paseo_runtime::Balances, - Hrmp: paseo_runtime::Hrmp, - } - }, -} - -// Paseo implementation -impl_accounts_helpers_for_relay_chain!(Paseo); -impl_assert_events_helpers_for_relay_chain!(Paseo); -impl_hrmp_channels_helpers_for_relay_chain!(Paseo); -impl_send_transact_helpers_for_relay_chain!(Paseo); diff --git a/integration-tests/src/chains/relay/genesis.rs b/integration-tests/src/chains/relay/genesis.rs new file mode 100644 index 000000000..2db07b5a4 --- /dev/null +++ b/integration-tests/src/chains/relay/genesis.rs @@ -0,0 +1,85 @@ +use emulated_integration_tests_common::{ + accounts, build_genesis_storage, get_from_seed, get_host_config, validators, +}; +use polkadot_primitives::{AssignmentId, Balance, ValidatorId, LOWEST_PUBLIC_ID}; +use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; +use sp_consensus_babe::AuthorityId as BabeId; +use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId; +use sp_consensus_grandpa::AuthorityId as GrandpaId; +use sp_core::storage::Storage; + +use crate::chains::relay::{ + constants::currency::{EXISTENTIAL_DEPOSIT, UNITS}, + runtime::{ + BabeConfig, BalancesConfig, ConfigurationConfig, RegistrarConfig, RuntimeGenesisConfig, + SessionConfig, SessionKeys, SystemConfig, BABE_GENESIS_EPOCH_CONFIG, WASM_BINARY, + }, +}; + +pub(crate) const ED: Balance = EXISTENTIAL_DEPOSIT; +const ENDOWMENT: u128 = 1_000_000 * UNITS; + +pub(crate) fn genesis() -> Storage { + let genesis_config = RuntimeGenesisConfig { + system: SystemConfig::default(), + balances: BalancesConfig { + balances: accounts::init_balances().iter().map(|k| (k.clone(), ENDOWMENT)).collect(), + }, + session: SessionConfig { + keys: validators::initial_authorities() + .iter() + .map(|x| { + ( + x.0.clone(), + x.0.clone(), + session_keys( + x.2.clone(), + x.3.clone(), + x.4.clone(), + x.5.clone(), + x.6.clone(), + get_from_seed::("Alice"), + ), + ) + }) + .collect::>(), + }, + babe: BabeConfig { + authorities: Default::default(), + epoch_config: BABE_GENESIS_EPOCH_CONFIG, + ..Default::default() + }, + configuration: ConfigurationConfig { config: get_host_config() }, + registrar: RegistrarConfig { next_free_para_id: LOWEST_PUBLIC_ID, ..Default::default() }, + ..Default::default() + }; + + build_genesis_storage(&genesis_config, WASM_BINARY.unwrap()) +} + +fn session_keys( + babe: BabeId, + grandpa: GrandpaId, + para_validator: ValidatorId, + para_assignment: AssignmentId, + authority_discovery: AuthorityDiscoveryId, + beefy: BeefyId, +) -> SessionKeys { + SessionKeys { babe, grandpa, para_validator, para_assignment, authority_discovery, beefy } +} + +// In case we want to add Polkadot in the future, the following change in `invulnerables` is +// required. +// +// #[cfg(feature = "polkadot")] +// use emulated_integration_tests_common::{get_account_id_from_seed, get_from_seed}; +// use sp_core::sr25519; +// use polkadot_primitives::{AccountId, Balance}; +// +// type AuraId = sp_consensus_aura::ed25519::AuthorityId; +// pub fn invulnerables() -> Vec<(AccountId, AuraId)> { +// vec![ +// (get_account_id_from_seed::("Alice"), get_from_seed::("Alice")), +// (get_account_id_from_seed::("Bob"), get_from_seed::("Bob")), +// ] +// } diff --git a/integration-tests/src/chains/relay/mod.rs b/integration-tests/src/chains/relay/mod.rs new file mode 100644 index 000000000..708406666 --- /dev/null +++ b/integration-tests/src/chains/relay/mod.rs @@ -0,0 +1,41 @@ +use emulated_integration_tests_common::{ + impl_accounts_helpers_for_relay_chain, impl_assert_events_helpers_for_relay_chain, + impl_hrmp_channels_helpers_for_relay_chain, impl_send_transact_helpers_for_relay_chain, + xcm_emulator::decl_test_relay_chains, +}; +#[cfg(feature = "paseo")] +pub(crate) use { + paseo_runtime::{self as runtime, xcm_config::SovereignAccountOf}, + paseo_runtime_constants as constants, +}; +#[cfg(feature = "westend")] +pub(crate) use { + westend_runtime::{self as runtime, xcm_config::LocationConverter as SovereignAccountOf}, + westend_runtime_constants as constants, +}; + +pub(crate) mod genesis; + +// Relay declaration. +decl_test_relay_chains! { + #[api_version(11)] + pub struct Relay { + genesis = genesis::genesis(), + on_init = (), + runtime = runtime, + core = { + SovereignAccountOf: SovereignAccountOf, + }, + pallets = { + XcmPallet: runtime::XcmPallet, + Balances: runtime::Balances, + Hrmp: runtime::Hrmp, + } + }, +} + +// Relay implementation. +impl_accounts_helpers_for_relay_chain!(Relay); +impl_assert_events_helpers_for_relay_chain!(Relay); +impl_hrmp_channels_helpers_for_relay_chain!(Relay); +impl_send_transact_helpers_for_relay_chain!(Relay); diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index 50513a3e1..fba1eddf0 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -1,36 +1,38 @@ #![cfg(test)] -use asset_hub_paseo_runtime::xcm_config::XcmConfig as AssetHubPaseoXcmConfig; use asset_test_utils::xcm_helpers; -use chains::{asset_hub_paseo::AssetHubPaseo, paseo::Paseo, pop_network::PopNetwork}; +use chains::{ + asset_hub::{ + genesis::ED as ASSET_HUB_ED, runtime::xcm_config::XcmConfig as AssetHubXcmConfig, AssetHub, + AssetHubParaPallet, + }, + pop_network::{PopNetwork, PopNetworkParaPallet}, + relay::{ + genesis::ED as RELAY_ED, runtime::xcm_config::XcmConfig as RelayXcmConfig, Relay, + RelayRelayPallet as RelayPallet, + }, +}; use emulated_integration_tests_common::{ accounts::{ALICE, BOB}, xcm_emulator::{ assert_expected_events, bx, decl_test_networks, - decl_test_sender_receiver_accounts_parameter_types, Chain, Parachain as Para, - RelayChain as Relay, Test, TestArgs, TestContext, TestExt, + decl_test_sender_receiver_accounts_parameter_types, Chain, Parachain as Para, RelayChain, + Test, TestArgs, TestContext, TestExt, }, }; use frame_support::{pallet_prelude::Weight, sp_runtime::DispatchResult}; -use paseo_runtime::xcm_config::XcmConfig as PaseoXcmConfig; use pop_runtime_common::Balance; use pop_runtime_devnet::config::xcm::XcmConfig as PopNetworkXcmConfig; use xcm::prelude::*; -use crate::chains::{ - asset_hub_paseo::{genesis::ED as ASSET_HUB_PASEO_ED, AssetHubPaseoParaPallet}, - paseo::{genesis::ED as PASEO_ED, PaseoRelayPallet}, - pop_network::PopNetworkParaPallet, -}; - mod chains; decl_test_networks! { // `pub` mandatory for the macro - pub struct PaseoMockNet { - relay_chain = Paseo, + pub struct MockNet { + relay_chain = Relay, parachains = vec![ - AssetHubPaseo, + AssetHub, PopNetwork, ], bridge = () @@ -38,28 +40,28 @@ decl_test_networks! { } decl_test_sender_receiver_accounts_parameter_types! { - PaseoRelay { sender: ALICE, receiver: BOB }, - AssetHubPaseoPara { sender: ALICE, receiver: BOB }, + RelayRelay { sender: ALICE, receiver: BOB }, + AssetHubPara { sender: ALICE, receiver: BOB }, PopNetworkPara { sender: ALICE, receiver: BOB} } -type RelayToParaTest = Test; -type SystemParaToParaTest = Test; -type ParaToSystemParaTest = Test; -type ParaToRelayTest = Test; +type RelayToParaTest = Test; +type SystemParaToParaTest = Test; +type ParaToSystemParaTest = Test; +type ParaToRelayTest = Test; fn relay_to_para_sender_assertions(t: RelayToParaTest) { - type RuntimeEvent = ::RuntimeEvent; - PaseoRelay::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8_799))); + type RuntimeEvent = ::RuntimeEvent; + RelayRelay::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8_799))); assert_expected_events!( - PaseoRelay, + RelayRelay, vec![ // Amount to reserve transfer is transferred to Parachain's Sovereign account RuntimeEvent::Balances( pallet_balances::Event::Transfer { from, to, amount } ) => { from: *from == t.sender.account_id, - to: *to == PaseoRelay::sovereign_account_id_of( + to: *to == RelayRelay::sovereign_account_id_of( t.args.dest.clone() ), amount: *amount == t.args.amount, @@ -69,20 +71,20 @@ fn relay_to_para_sender_assertions(t: RelayToParaTest) { } fn system_para_to_para_sender_assertions(t: SystemParaToParaTest) { - type RuntimeEvent = ::RuntimeEvent; - AssetHubPaseoPara::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts( + type RuntimeEvent = ::RuntimeEvent; + AssetHubPara::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts( 864_610_000, 8_799, ))); assert_expected_events!( - AssetHubPaseoPara, + AssetHubPara, vec![ // Amount to reserve transfer is transferred to Parachain's Sovereign account RuntimeEvent::Balances( pallet_balances::Event::Transfer { from, to, amount } ) => { from: *from == t.sender.account_id, - to: *to == AssetHubPaseoPara::sovereign_account_id_of( + to: *to == AssetHubPara::sovereign_account_id_of( t.args.dest.clone() ), amount: *amount == t.args.amount, @@ -141,12 +143,12 @@ fn para_to_relay_sender_assertions(t: ParaToRelayTest) { } fn para_to_system_para_receiver_assertions(t: ParaToSystemParaTest) { - type RuntimeEvent = ::RuntimeEvent; - let sov_pop_net_on_ahr = AssetHubPaseoPara::sovereign_account_id_of( - AssetHubPaseoPara::sibling_location_of(PopNetworkPara::para_id()), + type RuntimeEvent = ::RuntimeEvent; + let sov_pop_net_on_ahr = AssetHubPara::sovereign_account_id_of( + AssetHubPara::sibling_location_of(PopNetworkPara::para_id()), ); assert_expected_events!( - AssetHubPaseoPara, + AssetHubPara, vec![ // Amount to reserve transfer is withdrawn from Parachain's Sovereign account RuntimeEvent::Balances( @@ -164,12 +166,12 @@ fn para_to_system_para_receiver_assertions(t: ParaToSystemParaTest) { } fn para_to_relay_receiver_assertions(t: ParaToRelayTest) { - type RuntimeEvent = ::RuntimeEvent; - let sov_pop_net_on_relay = PaseoRelay::sovereign_account_id_of(PaseoRelay::child_location_of( + type RuntimeEvent = ::RuntimeEvent; + let sov_pop_net_on_relay = RelayRelay::sovereign_account_id_of(RelayRelay::child_location_of( PopNetworkPara::para_id(), )); assert_expected_events!( - PaseoRelay, + RelayRelay, vec![ // Amount to reserve transfer is withdrawn from Parachain's Sovereign account RuntimeEvent::Balances( @@ -187,7 +189,7 @@ fn para_to_relay_receiver_assertions(t: ParaToRelayTest) { } fn relay_to_para_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult { - ::XcmPallet::limited_reserve_transfer_assets( + ::XcmPallet::limited_reserve_transfer_assets( t.signed_origin, bx!(t.args.dest.into()), bx!(t.args.beneficiary.into()), @@ -198,7 +200,7 @@ fn relay_to_para_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult { } fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult { - ::PolkadotXcm::limited_reserve_transfer_assets( + ::PolkadotXcm::limited_reserve_transfer_assets( t.signed_origin, bx!(t.args.dest.into()), bx!(t.args.beneficiary.into()), @@ -236,7 +238,7 @@ fn fund_pop_from_relay( amount_to_send: Balance, beneficiary: sp_runtime::AccountId32, ) { - let destination = PaseoRelay::child_location_of(PopNetworkPara::para_id()); + let destination = RelayRelay::child_location_of(PopNetworkPara::para_id()); let test_args = TestContext { sender, receiver: beneficiary.clone(), @@ -244,7 +246,7 @@ fn fund_pop_from_relay( }; let mut test = RelayToParaTest::new(test_args); - test.set_dispatchable::(relay_to_para_reserve_transfer_assets); + test.set_dispatchable::(relay_to_para_reserve_transfer_assets); test.assert(); } @@ -255,7 +257,7 @@ fn fund_pop_from_system_para( beneficiary: sp_runtime::AccountId32, assets: Assets, ) { - let destination = AssetHubPaseoPara::sibling_location_of(PopNetworkPara::para_id()); + let destination = AssetHubPara::sibling_location_of(PopNetworkPara::para_id()); let test_args = TestContext { sender, receiver: beneficiary.clone(), @@ -263,7 +265,7 @@ fn fund_pop_from_system_para( }; let mut test = SystemParaToParaTest::new(test_args); - test.set_dispatchable::(system_para_to_para_reserve_transfer_assets); + test.set_dispatchable::(system_para_to_para_reserve_transfer_assets); test.assert(); } @@ -273,12 +275,12 @@ fn reserve_transfer_native_asset_from_relay_to_para() { init_tracing(); // Init values for Relay - let destination = PaseoRelay::child_location_of(PopNetworkPara::para_id()); + let destination = RelayRelay::child_location_of(PopNetworkPara::para_id()); let beneficiary_id = PopNetworkParaReceiver::get(); - let amount_to_send: Balance = PASEO_ED * 1000; + let amount_to_send: Balance = RELAY_ED * 1000; let test_args = TestContext { - sender: PaseoRelaySender::get(), + sender: RelayRelaySender::get(), receiver: PopNetworkParaReceiver::get(), args: TestArgs::new_relay(destination, beneficiary_id, amount_to_send), }; @@ -288,14 +290,14 @@ fn reserve_transfer_native_asset_from_relay_to_para() { let sender_balance_before = test.sender.balance; let receiver_balance_before = test.receiver.balance; - test.set_assertion::(relay_to_para_sender_assertions); + test.set_assertion::(relay_to_para_sender_assertions); test.set_assertion::(para_receiver_assertions); - test.set_dispatchable::(relay_to_para_reserve_transfer_assets); + test.set_dispatchable::(relay_to_para_reserve_transfer_assets); test.assert(); - let delivery_fees = PaseoRelay::execute_with(|| { + let delivery_fees = RelayRelay::execute_with(|| { xcm_helpers::teleport_assets_delivery_fees::< - ::XcmSender, + ::XcmSender, >( test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest ) @@ -321,18 +323,18 @@ fn reserve_transfer_native_asset_from_para_to_relay() { // Setup: reserve transfer from relay to Pop, so that sovereign account accurate for return // transfer - let amount_to_send: Balance = PASEO_ED * 1_000; - fund_pop_from_relay(PaseoRelaySender::get(), amount_to_send, PopNetworkParaReceiver::get()); // alice on relay > bob on pop + let amount_to_send: Balance = RELAY_ED * 1_000; + fund_pop_from_relay(RelayRelaySender::get(), amount_to_send, PopNetworkParaReceiver::get()); // alice on relay > bob on pop // Init values for Pop Network Parachain let destination = PopNetworkPara::parent_location(); // relay - let beneficiary_id = PaseoRelayReceiver::get(); // bob on relay + let beneficiary_id = RelayRelayReceiver::get(); // bob on relay let amount_to_send = PopNetworkPara::account_data_of(PopNetworkParaReceiver::get()).free; // bob on pop balance let assets = (Parent, amount_to_send).into(); let test_args = TestContext { sender: PopNetworkParaReceiver::get(), // bob on pop - receiver: PaseoRelayReceiver::get(), // bob on relay + receiver: RelayRelayReceiver::get(), // bob on relay args: TestArgs::new_para(destination, beneficiary_id, amount_to_send, assets, None, 0), }; @@ -342,7 +344,7 @@ fn reserve_transfer_native_asset_from_para_to_relay() { let receiver_balance_before = test.receiver.balance; test.set_assertion::(para_to_relay_sender_assertions); - test.set_assertion::(para_to_relay_receiver_assertions); + test.set_assertion::(para_to_relay_receiver_assertions); test.set_dispatchable::(para_to_relay_reserve_transfer_assets); test.assert(); @@ -373,13 +375,13 @@ fn reserve_transfer_native_asset_from_system_para_to_para() { init_tracing(); // Init values for System Parachain - let destination = AssetHubPaseoPara::sibling_location_of(PopNetworkPara::para_id()); + let destination = AssetHubPara::sibling_location_of(PopNetworkPara::para_id()); let beneficiary_id = PopNetworkParaReceiver::get(); - let amount_to_send: Balance = ASSET_HUB_PASEO_ED * 1000; + let amount_to_send: Balance = ASSET_HUB_ED * 1000; let assets = (Parent, amount_to_send).into(); let test_args = TestContext { - sender: AssetHubPaseoParaSender::get(), + sender: AssetHubParaSender::get(), receiver: PopNetworkParaReceiver::get(), args: TestArgs::new_para(destination, beneficiary_id, amount_to_send, assets, None, 0), }; @@ -389,17 +391,17 @@ fn reserve_transfer_native_asset_from_system_para_to_para() { let sender_balance_before = test.sender.balance; let receiver_balance_before = test.receiver.balance; - test.set_assertion::(system_para_to_para_sender_assertions); + test.set_assertion::(system_para_to_para_sender_assertions); test.set_assertion::(para_receiver_assertions); - test.set_dispatchable::(system_para_to_para_reserve_transfer_assets); + test.set_dispatchable::(system_para_to_para_reserve_transfer_assets); test.assert(); let sender_balance_after = test.sender.balance; let receiver_balance_after = test.receiver.balance; - let delivery_fees = AssetHubPaseoPara::execute_with(|| { + let delivery_fees = AssetHubPara::execute_with(|| { xcm_helpers::teleport_assets_delivery_fees::< - ::XcmSender, + ::XcmSender, >( test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest ) @@ -422,23 +424,23 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { // Setup: reserve transfer from AH to Pop, so that sovereign account accurate for return // transfer - let amount_to_send: Balance = ASSET_HUB_PASEO_ED * 1000; + let amount_to_send: Balance = ASSET_HUB_ED * 1000; fund_pop_from_system_para( - AssetHubPaseoParaSender::get(), + AssetHubParaSender::get(), amount_to_send, PopNetworkParaReceiver::get(), (Parent, amount_to_send).into(), ); // alice on asset hub > bob on pop // Init values for Pop Network Parachain - let destination = PopNetworkPara::sibling_location_of(AssetHubPaseoPara::para_id()); - let beneficiary_id = AssetHubPaseoParaReceiver::get(); // bob on asset hub + let destination = PopNetworkPara::sibling_location_of(AssetHubPara::para_id()); + let beneficiary_id = AssetHubParaReceiver::get(); // bob on asset hub let amount_to_send = PopNetworkPara::account_data_of(PopNetworkParaReceiver::get()).free; // bob on pop balance let assets = (Parent, amount_to_send).into(); let test_args = TestContext { - sender: PopNetworkParaReceiver::get(), // bob on pop - receiver: AssetHubPaseoParaReceiver::get(), // bob on asset hub + sender: PopNetworkParaReceiver::get(), // bob on pop + receiver: AssetHubParaReceiver::get(), // bob on asset hub args: TestArgs::new_para(destination, beneficiary_id, amount_to_send, assets, None, 0), }; @@ -448,15 +450,14 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { let receiver_balance_before = test.receiver.balance; let pop_net_location_as_seen_by_ahr = - AssetHubPaseoPara::sibling_location_of(PopNetworkPara::para_id()); - let sov_pop_net_on_ahr = - AssetHubPaseoPara::sovereign_account_id_of(pop_net_location_as_seen_by_ahr); + AssetHubPara::sibling_location_of(PopNetworkPara::para_id()); + let sov_pop_net_on_ahr = AssetHubPara::sovereign_account_id_of(pop_net_location_as_seen_by_ahr); // fund Pop Network's SA on AHR with the native tokens held in reserve - AssetHubPaseoPara::fund_accounts(vec![(sov_pop_net_on_ahr.into(), amount_to_send * 2)]); + AssetHubPara::fund_accounts(vec![(sov_pop_net_on_ahr.into(), amount_to_send * 2)]); test.set_assertion::(para_to_system_para_sender_assertions); - test.set_assertion::(para_to_system_para_receiver_assertions); + test.set_assertion::(para_to_system_para_receiver_assertions); test.set_dispatchable::(para_to_system_para_reserve_transfer_assets); test.assert(); @@ -490,15 +491,15 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { // // // Setup: reserve transfer from relay to Pop, so that sovereign account accurate for return // transfer let amount_to_send: Balance = pop_runtime::UNIT * 1000; -// fund_pop_from_relay(PaseoRelaySender::get(), amount_to_send, beneficiary.clone()); +// fund_pop_from_relay(RelayRelaySender::get(), amount_to_send, beneficiary.clone()); // // let message = { // let assets: Asset = (Here, 10 * pop_runtime::UNIT).into(); // let beneficiary = AccountId32 { id: beneficiary.clone().into(), network: None }.into(); -// let spot_order = ::RuntimeCall::OnDemandAssignmentProvider( -// assigner_on_demand::Call::<::Runtime>::place_order_keep_alive { +// let spot_order = ::RuntimeCall::OnDemandAssignmentProvider( +// assigner_on_demand::Call::<::Runtime>::place_order_keep_alive { // max_amount: 1 * pop_runtime::UNIT, -// para_id: AssetHubPaseoPara::para_id().into(), +// para_id: AssetHubPara::para_id().into(), // }, // ); // @@ -521,7 +522,7 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { // spot_order.encode().into(), // ) // .report_transact_status(QueryResponseInfo { -// destination: PaseoRelay::child_location_of(PopNetworkPara::para_id()), +// destination: RelayRelay::child_location_of(PopNetworkPara::para_id()), // query_id, // max_weight: Weight::from_parts(250_000_000, 10_000), // }) @@ -554,10 +555,10 @@ fn reserve_transfer_native_asset_from_para_to_system_para() { // ); // }); // -// PaseoRelay::execute_with(|| { -// type RuntimeEvent = ::RuntimeEvent; +// RelayRelay::execute_with(|| { +// type RuntimeEvent = ::RuntimeEvent; // assert_expected_events!( -// PaseoRelay, +// RelayRelay, // vec![ // // We currently only check that the message was processed successfully // RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true, .. }) => From c6ad12689e85fc62e22b40bc6d929b608dfccf63 Mon Sep 17 00:00:00 2001 From: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> Date: Thu, 19 Dec 2024 16:33:04 +0100 Subject: [PATCH 68/76] chore: ink v5.1 (#409) --- pop-api/Cargo.toml | 2 +- pop-api/examples/fungibles/Cargo.toml | 2 +- pop-api/examples/fungibles/tests.rs | 1 - .../contracts/create_token_in_constructor/Cargo.toml | 2 +- pop-api/integration-tests/contracts/fungibles/Cargo.toml | 2 +- pop-api/src/v0/fungibles/errors.rs | 2 +- 6 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index 4caf8eaad..cb491fef1 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -6,7 +6,7 @@ name = "pop-api" version = "0.0.0" [dependencies] -ink = { version = "5.0.0", default-features = false } +ink = { version = "5.1.0", default-features = false } pop-primitives = { path = "../primitives", default-features = false } sp-io = { version = "37.0.0", default-features = false, features = [ "disable_allocator", diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index 1882a8792..668e97eef 100644 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -5,7 +5,7 @@ name = "fungibles" version = "0.1.0" [dependencies] -ink = { version = "=5.0.0", default-features = false, features = [ "ink-debug" ] } +ink = { version = "5.1.0", default-features = false, features = [ "ink-debug" ] } pop-api = { path = "../../../pop-api", default-features = false, features = [ "fungibles", ] } diff --git a/pop-api/examples/fungibles/tests.rs b/pop-api/examples/fungibles/tests.rs index fee1204e6..b41f177d2 100644 --- a/pop-api/examples/fungibles/tests.rs +++ b/pop-api/examples/fungibles/tests.rs @@ -13,7 +13,6 @@ use drink::{ session::Session, AssetsAPI, TestExternalities, NO_SALT, }; -use ink::scale::Encode; use pop_api::{ primitives::TokenId, v0::fungibles::events::{Approval, Created, Transfer}, diff --git a/pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.toml b/pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.toml index a1517cddf..42736b394 100755 --- a/pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.toml +++ b/pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.toml @@ -4,7 +4,7 @@ name = "create_token_in_constructor" version = "0.1.0" [dependencies] -ink = { version = "5.0.0", default-features = false } +ink = { version = "5.1.0", default-features = false } pop-api = { path = "../../..", default-features = false, features = [ "fungibles" ] } [lib] diff --git a/pop-api/integration-tests/contracts/fungibles/Cargo.toml b/pop-api/integration-tests/contracts/fungibles/Cargo.toml index dce9b2570..62dab3e03 100755 --- a/pop-api/integration-tests/contracts/fungibles/Cargo.toml +++ b/pop-api/integration-tests/contracts/fungibles/Cargo.toml @@ -4,7 +4,7 @@ name = "fungibles" version = "0.1.0" [dependencies] -ink = { version = "5.0.0", default-features = false } +ink = { version = "5.1.0", default-features = false } pop-api = { path = "../../../../pop-api", default-features = false, features = [ "fungibles" ] } [lib] diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 3080a2c4c..1df32d4e6 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -3,7 +3,6 @@ use ink::{ prelude::string::{String, ToString}, - scale::{Decode, Encode}, }; use super::*; @@ -130,6 +129,7 @@ mod tests { }, StatusCode, }; + use ink::scale::{Decode, Encode}; fn error_into_status_code(error: Error) -> StatusCode { let mut encoded_error = error.encode(); From 72a5a6301fb5bd0a2904a4e398aa849f8581f12a Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 23 Dec 2024 15:59:04 +0700 Subject: [PATCH 69/76] chore: rebase --- pallets/api/src/nonfungibles/mod.rs | 26 +------- .../integration-tests/src/nonfungibles/mod.rs | 62 +++++-------------- .../src/nonfungibles/utils.rs | 11 +--- pop-api/src/v0/nonfungibles/types.rs | 10 --- runtime/devnet/src/config/assets.rs | 2 +- 5 files changed, 21 insertions(+), 90 deletions(-) diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index d10d9770d..7ee400594 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -11,7 +11,8 @@ pub use pallet_nfts::{ CollectionSetting, CollectionSettings, DestroyWitness, ItemDeposit, ItemDetails, ItemMetadata, ItemSetting, MintSettings, MintType, MintWitness, }; -use sp_runtime::traits::StaticLookup; +use sp_runtime::{traits::StaticLookup, BoundedVec}; +use types::*; use weights::WeightInfo; #[cfg(feature = "runtime-benchmarks")] @@ -19,30 +20,9 @@ mod benchmarking; mod impls; #[cfg(test)] mod tests; +pub mod types; pub mod weights; -type AccountIdOf = ::AccountId; -type NftsOf = pallet_nfts::Pallet>; -type NftsErrorOf = pallet_nfts::Error>; -type NftsWeightInfoOf = >>::WeightInfo; -type NftsInstanceOf = ::NftsInstance; -type BalanceOf = <>>::Currency as Currency< - ::AccountId, ->>::Balance; -type CollectionIdOf = - as Inspect<::AccountId>>::CollectionId; -type ItemIdOf = as Inspect<::AccountId>>::ItemId; -type ItemPriceOf = BalanceOf; -type CollectionDetailsFor = CollectionDetails, BalanceOf>; -type AttributeNamespaceOf = AttributeNamespace>; -type CollectionConfigFor = - CollectionConfig, BlockNumberFor, CollectionIdOf>; -// Type aliases for pallet-nfts storage items. -pub(super) type AccountBalanceOf = pallet_nfts::AccountBalance>; -pub(super) type AttributeOf = pallet_nfts::Attribute>; -pub(super) type NextCollectionIdOf = pallet_nfts::NextCollectionId>; -pub(super) type CollectionOf = pallet_nfts::Collection>; - #[frame_support::pallet] pub mod pallet { use frame_support::{ diff --git a/pop-api/integration-tests/src/nonfungibles/mod.rs b/pop-api/integration-tests/src/nonfungibles/mod.rs index 5c236f9f5..bcf9eb9f7 100644 --- a/pop-api/integration-tests/src/nonfungibles/mod.rs +++ b/pop-api/integration-tests/src/nonfungibles/mod.rs @@ -3,8 +3,8 @@ use pallet_api::nonfungibles::types::*; use pop_api::{ nonfungibles::{ events::{Approval, AttributeSet, Transfer}, - AttributeNamespace, CancelAttributesApprovalWitness, CollectionConfig, CollectionDetails, - CollectionId, CollectionSettings, DestroyWitness, ItemId, MintSettings, MintWitness, + AttributeNamespace, CancelAttributesApprovalWitness, CollectionConfig, CollectionId, + CollectionSettings, DestroyWitness, ItemId, MintSettings, MintWitness, }, primitives::BlockNumber, }; @@ -64,7 +64,7 @@ fn allowance_works() { // No collection item is created. assert_eq!( allowance(&addr.clone(), COLLECTION, None, addr.clone(), ALICE), - Ok(!Nfts::check_allowance(&COLLECTION, &None, &addr, &ALICE).is_err()), + Ok(!Nfts::check_approval(&COLLECTION, &None, &addr, &ALICE).is_err()), ); assert_eq!(allowance(&addr.clone(), COLLECTION, None, addr.clone(), ALICE), Ok(false)); @@ -72,7 +72,7 @@ fn allowance_works() { let (_, item) = nfts::create_collection_mint_and_approve(&addr, &addr, ITEM, &addr, &ALICE); assert_eq!( allowance(&addr.clone(), COLLECTION, Some(item), addr.clone(), ALICE), - Ok(Nfts::check_allowance(&COLLECTION, &Some(item), &addr.clone(), &ALICE).is_ok()), + Ok(Nfts::check_approval(&COLLECTION, &Some(item), &addr.clone(), &ALICE).is_ok()), ); assert_eq!(allowance(&addr.clone(), COLLECTION, Some(item), addr.clone(), ALICE), Ok(true)); }); @@ -83,10 +83,10 @@ fn transfer_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - // Collection item does not exist. + // Collection item does not exist. Throws error `UnknownItem`. assert_eq!( transfer(&addr, COLLECTION, ITEM, ALICE), - Err(Module { index: 50, error: [1, 0] }) + Err(Module { index: 50, error: [20, 0] }) ); // Create a collection and mint to a contract address. let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); @@ -129,7 +129,7 @@ fn approve_item_transfer_works() { // Successful approvals. let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); assert_ok!(approve(&addr, collection, Some(item), ALICE, true)); - assert!(Nfts::check_allowance(&collection, &Some(item), &addr.clone(), &ALICE).is_ok()); + assert!(Nfts::check_approval(&collection, &Some(item), &addr.clone(), &ALICE).is_ok()); // Successfully emit event. let owner = account_id_from_slice(addr.as_ref()); let operator = account_id_from_slice(ALICE.as_ref()); @@ -137,7 +137,7 @@ fn approve_item_transfer_works() { assert_eq!(last_contract_event(), expected.as_slice()); // New value overrides old value. assert_ok!(approve(&addr, collection, Some(item), ALICE, false)); - assert!(Nfts::check_allowance(&collection, &Some(item), &addr.clone(), &ALICE).is_err()); + assert!(Nfts::check_approval(&collection, &Some(item), &addr.clone(), &ALICE).is_err()); }); } @@ -146,15 +146,15 @@ fn approve_collection_transfer_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - // Collection does not exist. + // Account ownes zero items in the collection. assert_eq!( approve(&addr, COLLECTION, None, ALICE, true), - Err(Module { index: 50, error: [1, 0] }) + Err(Module { index: 50, error: [45, 0] }) ); // Successful approvals. let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); assert_ok!(approve(&addr, collection, None, ALICE, true)); - assert!(Nfts::check_allowance(&collection, &None, &addr.clone(), &ALICE).is_ok()); + assert!(Nfts::check_approval(&collection, &None, &addr.clone(), &ALICE).is_ok()); // Successfully emit event. let owner = account_id_from_slice(addr.as_ref()); let operator = account_id_from_slice(ALICE.as_ref()); @@ -162,7 +162,7 @@ fn approve_collection_transfer_works() { assert_eq!(last_contract_event(), expected.as_slice()); // New value overrides old value. assert_ok!(approve(&addr, collection, None, ALICE, false)); - assert!(Nfts::check_allowance(&collection, &None, &addr.clone(), &ALICE).is_err()); + assert!(Nfts::check_approval(&collection, &None, &addr.clone(), &ALICE).is_err()); }); } @@ -394,19 +394,7 @@ fn create_works() { settings: CollectionSettings::all_enabled(), } )); - assert_eq!( - CollectionOf::::get(collection), - Some(pallet_nfts::CollectionDetails { - owner: addr.clone(), - owner_deposit: 100000000000, - items: 0, - item_metadatas: 0, - item_configs: 0, - attributes: 0, - item_holders: 0, - allowances: 0 - }) - ); + // TODO: check the collection owner after creaton. }); } @@ -420,13 +408,7 @@ fn destroy_works() { destroy( &addr.clone(), COLLECTION, - DestroyWitness { - item_metadatas: 0, - item_configs: 0, - attributes: 0, - item_holders: 0, - allowances: 0 - } + DestroyWitness { item_metadatas: 0, item_configs: 0, attributes: 0 } ), Err(Module { index: 50, error: [1, 0] }) ); @@ -436,13 +418,7 @@ fn destroy_works() { destroy( &addr.clone(), collection, - DestroyWitness { - item_metadatas: 0, - item_configs: 0, - attributes: 0, - item_holders: 0, - allowances: 0 - } + DestroyWitness { item_metadatas: 0, item_configs: 0, attributes: 0 } ), Err(Module { index: 50, error: [0, 0] }) ); @@ -451,13 +427,7 @@ fn destroy_works() { assert_ok!(destroy( &addr.clone(), collection, - DestroyWitness { - item_metadatas: 0, - item_configs: 0, - attributes: 0, - item_holders: 0, - allowances: 0 - } + DestroyWitness { item_metadatas: 0, item_configs: 0, attributes: 0 } )); assert_eq!(CollectionOf::::get(collection), None); }); diff --git a/pop-api/integration-tests/src/nonfungibles/utils.rs b/pop-api/integration-tests/src/nonfungibles/utils.rs index 48d4dbaae..76420e27a 100644 --- a/pop-api/integration-tests/src/nonfungibles/utils.rs +++ b/pop-api/integration-tests/src/nonfungibles/utils.rs @@ -109,15 +109,6 @@ pub(super) fn destroy( .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) } -pub(super) fn collection( - addr: &AccountId32, - collection: CollectionId, -) -> Result, Error> { - let result = do_bare_call("collection", &addr, collection.encode()); - decoded::, Error>>(result.clone()) - .unwrap_or_else(|_| panic!("Contract reverted: {:?}", result)) -} - pub(super) fn set_attribute( addr: &AccountId32, collection: CollectionId, @@ -272,7 +263,7 @@ pub(super) mod nfts { assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(to.clone()), collection, - Some(item), + item, operator.clone().into(), None )); diff --git a/pop-api/src/v0/nonfungibles/types.rs b/pop-api/src/v0/nonfungibles/types.rs index 5cd725ae5..c630f04b9 100644 --- a/pop-api/src/v0/nonfungibles/types.rs +++ b/pop-api/src/v0/nonfungibles/types.rs @@ -22,12 +22,8 @@ pub struct CollectionDetails { pub item_metadatas: u32, /// The total number of outstanding item configs of this collection. pub item_configs: u32, - /// The total number of accounts that hold items of the collection. - pub item_holders: u32, /// The total number of attributes for this collection. pub attributes: u32, - /// The total number of allowances to spend all items within collections. - pub allowances: u32, } /// Attribute namespaces for non-fungible tokens. @@ -73,15 +69,9 @@ pub struct DestroyWitness { /// The total number of outstanding item configs of this collection. #[codec(compact)] pub item_configs: u32, - /// The total number of accounts that hold items of the collection. - #[codec(compact)] - pub item_holders: u32, /// The total number of attributes for this collection. #[codec(compact)] pub attributes: u32, - /// The total number of allowances to spend all items within collections. - #[codec(compact)] - pub allowances: u32, } /// Witness data for items mint transactions. diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index dc9dd01ca..76a339186 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -41,7 +41,7 @@ parameter_types! { #[derive(Debug)] #[cfg_attr(feature = "std", derive(PartialEq, Clone))] -struct KeyLimit; +pub struct KeyLimit; impl Get for KeyLimit { fn get() -> u32 { N From 8f82806ee6bfa4207b87336fd34762509fa867f1 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Mon, 23 Dec 2024 16:59:09 +0700 Subject: [PATCH 70/76] chore: comments --- pop-api/integration-tests/src/nonfungibles/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pop-api/integration-tests/src/nonfungibles/mod.rs b/pop-api/integration-tests/src/nonfungibles/mod.rs index bcf9eb9f7..ed258e5be 100644 --- a/pop-api/integration-tests/src/nonfungibles/mod.rs +++ b/pop-api/integration-tests/src/nonfungibles/mod.rs @@ -61,6 +61,7 @@ fn balance_of_works() { fn allowance_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); + // No collection item is created. assert_eq!( allowance(&addr.clone(), COLLECTION, None, addr.clone(), ALICE), @@ -83,7 +84,7 @@ fn transfer_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - // Collection item does not exist. Throws error `UnknownItem`. + // Collection item does not exist, throws module error `UnknownItem`. assert_eq!( transfer(&addr, COLLECTION, ITEM, ALICE), Err(Module { index: 50, error: [20, 0] }) @@ -121,7 +122,7 @@ fn approve_item_transfer_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - // Collection item does not exist. + // Collection does not exist, throws module error `UnknownItem`. assert_eq!( approve(&addr, COLLECTION, Some(ITEM), ALICE, true), Err(Module { index: 50, error: [20, 0] }) @@ -146,7 +147,7 @@ fn approve_collection_transfer_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - // Account ownes zero items in the collection. + // Collection does not exist, throws module error `NoItemOwned`. assert_eq!( approve(&addr, COLLECTION, None, ALICE, true), Err(Module { index: 50, error: [45, 0] }) From 96913264d87006c10ebba125e0ceff5b75fbebbf Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 27 Dec 2024 14:50:35 +0700 Subject: [PATCH 71/76] chore: rebase --- pop-api/integration-tests/src/nonfungibles/utils.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pop-api/integration-tests/src/nonfungibles/utils.rs b/pop-api/integration-tests/src/nonfungibles/utils.rs index 76420e27a..423f71062 100644 --- a/pop-api/integration-tests/src/nonfungibles/utils.rs +++ b/pop-api/integration-tests/src/nonfungibles/utils.rs @@ -322,6 +322,8 @@ pub(super) mod nfts { pub(crate) fn balance_of(collection: CollectionId, owner: AccountId32) -> u32 { AccountBalanceOf::::get(collection, owner) + .map(|(balance, _)| balance) + .unwrap_or_default() } pub(crate) fn max_supply(collection: CollectionId) -> Option { From 93a29f696fbeb785d9dc5e918bfa217ef14cb7e6 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Fri, 27 Dec 2024 15:07:14 +0700 Subject: [PATCH 72/76] chore: update tests --- pop-api/integration-tests/src/nonfungibles/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pop-api/integration-tests/src/nonfungibles/mod.rs b/pop-api/integration-tests/src/nonfungibles/mod.rs index ed258e5be..6281285e8 100644 --- a/pop-api/integration-tests/src/nonfungibles/mod.rs +++ b/pop-api/integration-tests/src/nonfungibles/mod.rs @@ -15,8 +15,8 @@ use super::*; mod utils; -const COLLECTION: CollectionId = 0; const ITEM: ItemId = 0; +const COLLECTION: CollectionId = 0; const CONTRACT: &str = "contracts/nonfungibles/target/ink/nonfungibles.wasm"; #[test] @@ -384,8 +384,6 @@ fn clear_metadata_works() { fn create_works() { new_test_ext().execute_with(|| { let addr = instantiate(CONTRACT, INIT_VALUE, vec![]); - - let collection = nfts::next_collection_id(); assert_ok!(create( &addr.clone(), addr.clone(), @@ -395,7 +393,7 @@ fn create_works() { settings: CollectionSettings::all_enabled(), } )); - // TODO: check the collection owner after creaton. + assert_eq!(Nfts::collection_owner(COLLECTION), Some(addr.clone())); }); } From 8fb843fa7bba93885369fd733fa1531715bdb01e Mon Sep 17 00:00:00 2001 From: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> Date: Wed, 15 Jan 2025 08:37:04 +0200 Subject: [PATCH 73/76] fix: remove old dependencies and include Cargo.lock in VCS (#424) --- .github/workflows/ci.yml | 6 +- .gitignore | 3 - extension/contract/Cargo.lock | 1637 ++++ extension/contract/Cargo.toml | 2 +- pop-api/.gitignore | 4 - pop-api/Cargo.lock | 3323 +++++++ pop-api/examples/fungibles/Cargo.toml | 6 - pop-api/integration-tests/Cargo.lock | 7669 +++++++++++++++++ pop-api/integration-tests/Cargo.toml | 6 +- .../create_token_in_constructor/Cargo.lock | 3331 +++++++ .../contracts/fungibles/Cargo.lock | 3331 +++++++ pop-api/src/v0/fungibles/errors.rs | 7 +- 12 files changed, 19299 insertions(+), 26 deletions(-) create mode 100644 extension/contract/Cargo.lock create mode 100644 pop-api/Cargo.lock create mode 100644 pop-api/integration-tests/Cargo.lock create mode 100644 pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.lock create mode 100644 pop-api/integration-tests/contracts/fungibles/Cargo.lock diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index faef3232a..9704588b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -123,7 +123,7 @@ jobs: - name: Run tests working-directory: pop-api - run: cargo test --release --all-features + run: cargo test --release --locked --all-features api-integration-tests-devnet: runs-on: ubuntu-latest @@ -134,7 +134,7 @@ jobs: - name: Run integration tests working-directory: pop-api/integration-tests - run: cargo test --release --features devnet + run: cargo test --release --locked --features devnet api-integration-tests-testnet: runs-on: ubuntu-latest @@ -145,7 +145,7 @@ jobs: - name: Run integration tests working-directory: pop-api/integration-tests - run: cargo test --release --features testnet + run: cargo test --release --locked --features testnet coverage: needs: lint diff --git a/.gitignore b/.gitignore index b99b862b6..d15af847e 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,3 @@ # Binaries **/bin/ - -# Cargo.lock -**/Cargo.lock \ No newline at end of file diff --git a/extension/contract/Cargo.lock b/extension/contract/Cargo.lock new file mode 100644 index 000000000..0080544fb --- /dev/null +++ b/extension/contract/Cargo.lock @@ -0,0 +1,1637 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "array-bytes" +version = "6.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5dde061bd34119e902bbb2d9b90c5692635cf59fb91d582c2b68043f1b8293" + +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bounded-collections" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d077619e9c237a5d1875166f5e8033e8f6bff0c96f8caf81e1c2d7738c431bf" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "common-path" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" + +[[package]] +name = "const_env" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e9e4f72c6e3398ca6da372abd9affd8f89781fe728869bbf986206e9af9627e" +dependencies = [ + "const_env_impl", +] + +[[package]] +name = "const_env_impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4f51209740b5e1589e702b3044cdd4562cef41b6da404904192ffffb852d62" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive-syn-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "docify" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a772b62b1837c8f060432ddcc10b17aae1453ef17617a99bc07789252d2a5896" +dependencies = [ + "docify_macros", +] + +[[package]] +name = "docify_macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60e6be249b0a462a14784a99b19bf35a667bb5e09de611738bb7362fa4c95ff7" +dependencies = [ + "common-path", + "derive-syn-parse", + "once_cell", + "proc-macro2", + "quote", + "regex", + "syn 2.0.90", + "termcolor", + "toml", + "walkdir", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "environmental" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom_or_panic" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" +dependencies = [ + "rand", + "rand_core", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "ink" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15d7438a13d38fa8f4eebea8d1e7c2931058eafd0336c79f4141d4ed0162a412" +dependencies = [ + "derive_more 1.0.0", + "ink_env", + "ink_macro", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage", + "pallet-contracts-uapi", + "parity-scale-codec", + "scale-info", + "staging-xcm", +] + +[[package]] +name = "ink_allocator" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ec348ce75d284bc2e698187dc01da416a52dfa2d685e2a57d04e9e580447df0" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_codegen" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2238f147295746f1fee4cf7dcdee6378c94e61fbf7b9f9f4bb2a7f918530801b" +dependencies = [ + "blake2", + "derive_more 1.0.0", + "either", + "heck", + "impl-serde", + "ink_ir", + "ink_primitives", + "itertools", + "parity-scale-codec", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn 2.0.90", +] + +[[package]] +name = "ink_engine" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273f2aa983d04a6476d3c5ac76ddbef07555664b88f923996e7465e261dda48" +dependencies = [ + "blake2", + "derive_more 1.0.0", + "ink_primitives", + "pallet-contracts-uapi", + "parity-scale-codec", + "secp256k1", + "sha2", + "sha3", +] + +[[package]] +name = "ink_env" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9ee6089a1836c2e92d00be97d42308b7fb2c2b51ff6150b1130166a58107092" +dependencies = [ + "blake2", + "cfg-if", + "const_env", + "derive_more 1.0.0", + "ink_allocator", + "ink_engine", + "ink_prelude", + "ink_primitives", + "ink_storage_traits", + "num-traits", + "pallet-contracts-uapi", + "parity-scale-codec", + "paste", + "rlibc", + "scale-decode", + "scale-encode", + "scale-info", + "schnorrkel", + "secp256k1", + "sha2", + "sha3", + "staging-xcm", + "static_assertions", +] + +[[package]] +name = "ink_ir" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e201688fb27ff97496a4231a393dd4befcc5a9c092d6bf231f0f5d409ef44f34" +dependencies = [ + "blake2", + "either", + "impl-serde", + "ink_prelude", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "ink_macro" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce9465553d3066a8e28bd94a94880289084c4ff12f1852312553e902fa1ffdd" +dependencies = [ + "ink_codegen", + "ink_ir", + "ink_primitives", + "parity-scale-codec", + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + +[[package]] +name = "ink_metadata" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27135c651274087ba0578d2c07866c31d8dd481ae8de5bb7295fe3931491aa80" +dependencies = [ + "derive_more 1.0.0", + "impl-serde", + "ink_prelude", + "ink_primitives", + "linkme", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", +] + +[[package]] +name = "ink_prelude" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b29c9b7f686f4305f523bca5e2ae6f22a09531ec2bf0a9498cdc877959f70ad0" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_primitives" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a530c1b352a53176ea718f3a65f15003e54e0474ec12353ea0e0e5bb60b25741" +dependencies = [ + "derive_more 1.0.0", + "ink_prelude", + "parity-scale-codec", + "scale-decode", + "scale-encode", + "scale-info", + "xxhash-rust", +] + +[[package]] +name = "ink_storage" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bed602a974481b194084b93957917f27e724c7561fd0de9b6f3c171590c839b" +dependencies = [ + "array-init", + "cfg-if", + "derive_more 1.0.0", + "ink_env", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage_traits", + "pallet-contracts-uapi", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "ink_storage_traits" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde9b3f4a1e355682e5d13fd5639e5da4d0a2029537292e05a4255ea1169663e" +dependencies = [ + "ink_metadata", + "ink_prelude", + "ink_primitives", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "linkme" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "566336154b9e58a4f055f6dd4cbab62c7dc0826ce3c0a04e63b2d2ecd784cdae" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edbe595006d355eaf9ae11db92707d4338cd2384d16866131cc1afdbdd35d8d9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core", + "zeroize", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "pallet-contracts-uapi" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7a51646d9ff1d91abd0186d2c074f0dfd3b1a2d55f08a229a2f2e4bc6d1e49" +dependencies = [ + "bitflags", + "paste", + "polkavm-derive", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "polkavm-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9428a5cfcc85c5d7b9fc4b6a18c4b802d0173d768182a51cc7751640f08b92" + +[[package]] +name = "polkavm-derive" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8c4bea6f3e11cd89bb18bcdddac10bd9a24015399bd1c485ad68a985a19606" +dependencies = [ + "polkavm-derive-impl-macro", +] + +[[package]] +name = "polkavm-derive-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" +dependencies = [ + "polkavm-common", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "polkavm-derive-impl-macro" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" +dependencies = [ + "polkavm-derive-impl", + "syn 2.0.90", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit 0.22.22", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proxy" +version = "0.1.0" +dependencies = [ + "ink", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rlibc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scale-bits" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "662d10dcd57b1c2a3c41c9cf68f71fb09747ada1ea932ad961aca7e2ca28315f" +dependencies = [ + "parity-scale-codec", + "scale-type-resolver", +] + +[[package]] +name = "scale-decode" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc79ba56a1c742f5aeeed1f1801f3edf51f7e818f0a54582cac6f131364ea7b" +dependencies = [ + "derive_more 0.99.18", + "parity-scale-codec", + "scale-bits", + "scale-decode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-decode-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5398fdb3c7bea3cb419bac4983aadacae93fe1a7b5f693f4ebd98c3821aad7a5" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-encode" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628800925a33794fb5387781b883b5e14d130fece9af5a63613867b8de07c5c7" +dependencies = [ + "derive_more 0.99.18", + "parity-scale-codec", + "scale-encode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-encode-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a304e1af7cdfbe7a24e08b012721456cc8cecdedadc14b3d10513eada63233c" +dependencies = [ + "darling", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-info" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more 1.0.0", + "parity-scale-codec", + "scale-info-derive", + "schemars", + "serde", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "scale-type-resolver" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10b800069bfd43374e0f96f653e0d46882a2cb16d6d961ac43bea80f26c76843" +dependencies = [ + "smallvec", +] + +[[package]] +name = "schemars" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.90", +] + +[[package]] +name = "schnorrkel" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de18f6d8ba0aad7045f5feae07ec29899c1112584a38509a84ad7b04451eaa0" +dependencies = [ + "aead", + "arrayref", + "arrayvec", + "curve25519-dalek", + "getrandom_or_panic", + "merlin", + "rand_core", + "serde_bytes", + "sha2", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", +] + +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" + +[[package]] +name = "serde" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "sp-arithmetic" +version = "26.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46d0d0a4c591c421d3231ddd5e27d828618c24456d51445d21a1f79fcee97c23" +dependencies = [ + "docify", + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std", + "static_assertions", +] + +[[package]] +name = "sp-debug-derive" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sp-std" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8ee986414b0a9ad741776762f4083cd3a5128449b982a3919c4df36874834" + +[[package]] +name = "sp-weights" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93cdaf72a1dad537bbb130ba4d47307ebe5170405280ed1aa31fa712718a400e" +dependencies = [ + "bounded-collections", + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-debug-derive", +] + +[[package]] +name = "staging-xcm" +version = "11.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aded0292274ad473250c22ed3deaf2d9ed47d15786d700e9e83ab7c1cad2ad44" +dependencies = [ + "array-bytes", + "bounded-collections", + "derivative", + "environmental", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-weights", + "xcm-procedural", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.22", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.20", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "xcm-procedural" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4717a97970a9cda70d7db53cf50d2615c2f6f6b7c857445325b4a39ea7aa2cd" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "xxhash-rust" +version = "0.8.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08fd76779ae1883bbf1e46c2c46a75a0c4e37c445e68a24b01479d438f26ae6" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] diff --git a/extension/contract/Cargo.toml b/extension/contract/Cargo.toml index 52c56f663..286c00707 100755 --- a/extension/contract/Cargo.toml +++ b/extension/contract/Cargo.toml @@ -6,7 +6,7 @@ name = "proxy" version = "0.1.0" [dependencies] -ink = { version = "5.0.0", default-features = false } +ink = { version = "5.1.0", default-features = false } [lib] path = "lib.rs" diff --git a/pop-api/.gitignore b/pop-api/.gitignore index 9170f5913..e4fa8cd88 100644 --- a/pop-api/.gitignore +++ b/pop-api/.gitignore @@ -4,10 +4,6 @@ debug/ target/ -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -Cargo.lock - # These are backup files generated by rustfmt **/*.rs.bk diff --git a/pop-api/Cargo.lock b/pop-api/Cargo.lock new file mode 100644 index 000000000..2acc212f7 --- /dev/null +++ b/pop-api/Cargo.lock @@ -0,0 +1,3323 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "anyhow" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" + +[[package]] +name = "ark-bls12-377" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb00293ba84f51ce3bd026bd0de55899c4e68f0a39a5728cebae3a73ffdc0a4f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "array-bytes" +version = "6.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5dde061bd34119e902bbb2d9b90c5692635cf59fb91d582c2b68043f1b8293" + +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "hex-conservative", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bounded-collections" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d077619e9c237a5d1875166f5e8033e8f6bff0c96f8caf81e1c2d7738c431bf" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "cc" +version = "1.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "common-path" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const_env" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e9e4f72c6e3398ca6da372abd9affd8f89781fe728869bbf986206e9af9627e" +dependencies = [ + "const_env_impl", +] + +[[package]] +name = "const_env_impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4f51209740b5e1589e702b3044cdd4562cef41b6da404904192ffffb852d62" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "constcat" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7e35aee659887cbfb97aaf227ac12cad1a9d7c71e55ff3376839ed4e282d08" + +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive-syn-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "docify" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a772b62b1837c8f060432ddcc10b17aae1453ef17617a99bc07789252d2a5896" +dependencies = [ + "docify_macros", +] + +[[package]] +name = "docify_macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60e6be249b0a462a14784a99b19bf35a667bb5e09de611738bb7362fa4c95ff7" +dependencies = [ + "common-path", + "derive-syn-parse", + "once_cell", + "proc-macro2", + "quote", + "regex", + "syn 2.0.90", + "termcolor", + "toml", + "walkdir", +] + +[[package]] +name = "dyn-clonable" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +dependencies = [ + "dyn-clonable-impl", + "dyn-clone", +] + +[[package]] +name = "dyn-clonable-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "serdect", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "ed25519-zebra" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "hashbrown 0.14.5", + "hex", + "rand_core", + "sha2 0.10.8", + "zeroize", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "environmental" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "expander" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2c470c71d91ecbd179935b24170459e926382eaaa86b590b78814e180d8a8e2" +dependencies = [ + "blake2", + "file-guard", + "fs-err", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "file-guard" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21ef72acf95ec3d7dbf61275be556299490a245f017cf084bd23b4f68cf9407c" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fs-err" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom_or_panic" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" +dependencies = [ + "rand", + "rand_core", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hash-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac 0.8.1", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "ink" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15d7438a13d38fa8f4eebea8d1e7c2931058eafd0336c79f4141d4ed0162a412" +dependencies = [ + "derive_more 1.0.0", + "ink_env", + "ink_macro", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage", + "pallet-contracts-uapi", + "parity-scale-codec", + "scale-info", + "staging-xcm", +] + +[[package]] +name = "ink_allocator" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ec348ce75d284bc2e698187dc01da416a52dfa2d685e2a57d04e9e580447df0" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_codegen" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2238f147295746f1fee4cf7dcdee6378c94e61fbf7b9f9f4bb2a7f918530801b" +dependencies = [ + "blake2", + "derive_more 1.0.0", + "either", + "heck", + "impl-serde", + "ink_ir", + "ink_primitives", + "itertools 0.12.1", + "parity-scale-codec", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn 2.0.90", +] + +[[package]] +name = "ink_engine" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273f2aa983d04a6476d3c5ac76ddbef07555664b88f923996e7465e261dda48" +dependencies = [ + "blake2", + "derive_more 1.0.0", + "ink_primitives", + "pallet-contracts-uapi", + "parity-scale-codec", + "secp256k1", + "sha2 0.10.8", + "sha3", +] + +[[package]] +name = "ink_env" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9ee6089a1836c2e92d00be97d42308b7fb2c2b51ff6150b1130166a58107092" +dependencies = [ + "blake2", + "cfg-if", + "const_env", + "derive_more 1.0.0", + "ink_allocator", + "ink_engine", + "ink_prelude", + "ink_primitives", + "ink_storage_traits", + "num-traits", + "pallet-contracts-uapi", + "parity-scale-codec", + "paste", + "rlibc", + "scale-decode", + "scale-encode", + "scale-info", + "schnorrkel", + "secp256k1", + "sha2 0.10.8", + "sha3", + "staging-xcm", + "static_assertions", +] + +[[package]] +name = "ink_ir" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e201688fb27ff97496a4231a393dd4befcc5a9c092d6bf231f0f5d409ef44f34" +dependencies = [ + "blake2", + "either", + "impl-serde", + "ink_prelude", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "ink_macro" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce9465553d3066a8e28bd94a94880289084c4ff12f1852312553e902fa1ffdd" +dependencies = [ + "ink_codegen", + "ink_ir", + "ink_primitives", + "parity-scale-codec", + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + +[[package]] +name = "ink_metadata" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27135c651274087ba0578d2c07866c31d8dd481ae8de5bb7295fe3931491aa80" +dependencies = [ + "derive_more 1.0.0", + "impl-serde", + "ink_prelude", + "ink_primitives", + "linkme", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", +] + +[[package]] +name = "ink_prelude" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b29c9b7f686f4305f523bca5e2ae6f22a09531ec2bf0a9498cdc877959f70ad0" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_primitives" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a530c1b352a53176ea718f3a65f15003e54e0474ec12353ea0e0e5bb60b25741" +dependencies = [ + "derive_more 1.0.0", + "ink_prelude", + "parity-scale-codec", + "scale-decode", + "scale-encode", + "scale-info", + "xxhash-rust", +] + +[[package]] +name = "ink_storage" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bed602a974481b194084b93957917f27e724c7561fd0de9b6f3c171590c839b" +dependencies = [ + "array-init", + "cfg-if", + "derive_more 1.0.0", + "ink_env", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage_traits", + "pallet-contracts-uapi", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "ink_storage_traits" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde9b3f4a1e355682e5d13fd5639e5da4d0a2029537292e05a4255ea1169663e" +dependencies = [ + "ink_metadata", + "ink_prelude", + "ink_primitives", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "serdect", + "sha2 0.10.8", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.168" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "linkme" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "566336154b9e58a4f055f6dd4cbab62c7dc0826ce3c0a04e63b2d2ecd784cdae" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edbe595006d355eaf9ae11db92707d4338cd2384d16866131cc1afdbdd35d8d9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memory-db" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +dependencies = [ + "hash-db", +] + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core", + "zeroize", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec", + "itoa", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "pallet-contracts-uapi" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7a51646d9ff1d91abd0186d2c074f0dfd3b1a2d55f08a229a2f2e4bc6d1e49" +dependencies = [ + "bitflags 1.3.2", + "paste", + "polkavm-derive", +] + +[[package]] +name = "parity-bip39" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" +dependencies = [ + "bitcoin_hashes", + "rand", + "rand_core", + "serde", + "unicode-normalization", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", + "password-hash", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "polkavm-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9428a5cfcc85c5d7b9fc4b6a18c4b802d0173d768182a51cc7751640f08b92" + +[[package]] +name = "polkavm-derive" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8c4bea6f3e11cd89bb18bcdddac10bd9a24015399bd1c485ad68a985a19606" +dependencies = [ + "polkavm-derive-impl-macro", +] + +[[package]] +name = "polkavm-derive-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" +dependencies = [ + "polkavm-common", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "polkavm-derive-impl-macro" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" +dependencies = [ + "polkavm-derive-impl", + "syn 2.0.90", +] + +[[package]] +name = "pop-api" +version = "0.0.0" +dependencies = [ + "ink", + "pop-primitives", + "sp-io", +] + +[[package]] +name = "pop-primitives" +version = "0.0.0" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +dependencies = [ + "proc-macro2", + "syn 2.0.90", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-serde", + "scale-info", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit 0.22.22", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + +[[package]] +name = "rlibc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scale-bits" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "662d10dcd57b1c2a3c41c9cf68f71fb09747ada1ea932ad961aca7e2ca28315f" +dependencies = [ + "parity-scale-codec", + "scale-type-resolver", +] + +[[package]] +name = "scale-decode" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc79ba56a1c742f5aeeed1f1801f3edf51f7e818f0a54582cac6f131364ea7b" +dependencies = [ + "derive_more 0.99.18", + "parity-scale-codec", + "scale-bits", + "scale-decode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-decode-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5398fdb3c7bea3cb419bac4983aadacae93fe1a7b5f693f4ebd98c3821aad7a5" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-encode" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628800925a33794fb5387781b883b5e14d130fece9af5a63613867b8de07c5c7" +dependencies = [ + "derive_more 0.99.18", + "parity-scale-codec", + "scale-encode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-encode-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a304e1af7cdfbe7a24e08b012721456cc8cecdedadc14b3d10513eada63233c" +dependencies = [ + "darling", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-info" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more 1.0.0", + "parity-scale-codec", + "scale-info-derive", + "schemars", + "serde", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "scale-type-resolver" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10b800069bfd43374e0f96f653e0d46882a2cb16d6d961ac43bea80f26c76843" +dependencies = [ + "smallvec", +] + +[[package]] +name = "schemars" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.90", +] + +[[package]] +name = "schnellru" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" +dependencies = [ + "ahash", + "cfg-if", + "hashbrown 0.13.2", +] + +[[package]] +name = "schnorrkel" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de18f6d8ba0aad7045f5feae07ec29899c1112584a38509a84ad7b04451eaa0" +dependencies = [ + "aead", + "arrayref", + "arrayvec", + "curve25519-dalek", + "getrandom_or_panic", + "merlin", + "rand_core", + "serde_bytes", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" + +[[package]] +name = "serde" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "sp-arithmetic" +version = "26.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46d0d0a4c591c421d3231ddd5e27d828618c24456d51445d21a1f79fcee97c23" +dependencies = [ + "docify", + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std", + "static_assertions", +] + +[[package]] +name = "sp-core" +version = "34.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c961a5e33fb2962fa775c044ceba43df9c6f917e2c35d63bfe23738468fa76a7" +dependencies = [ + "array-bytes", + "bitflags 1.3.2", + "blake2", + "bounded-collections", + "bs58", + "dyn-clonable", + "ed25519-zebra", + "futures", + "hash-db", + "hash256-std-hasher", + "impl-serde", + "itertools 0.11.0", + "k256", + "libsecp256k1", + "log", + "merlin", + "parity-bip39", + "parity-scale-codec", + "parking_lot", + "paste", + "primitive-types", + "rand", + "scale-info", + "schnorrkel", + "secp256k1", + "secrecy", + "serde", + "sp-crypto-hashing", + "sp-debug-derive", + "sp-externalities", + "sp-runtime-interface", + "sp-std", + "sp-storage", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tracing", + "w3f-bls", + "zeroize", +] + +[[package]] +name = "sp-crypto-hashing" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9927a7f81334ed5b8a98a4a978c81324d12bd9713ec76b5c68fd410174c5eb" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.7", + "sha2 0.10.8", + "sha3", + "twox-hash", +] + +[[package]] +name = "sp-debug-derive" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sp-externalities" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a904407d61cb94228c71b55a9d3708e9d6558991f9e83bd42bd91df37a159d30" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-storage", +] + +[[package]] +name = "sp-io" +version = "37.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5036cad2e48d41f5caf6785226c8be1a7db15bec14a9fd7aa6cca84f34cf689f" +dependencies = [ + "bytes", + "ed25519-dalek", + "libsecp256k1", + "log", + "parity-scale-codec", + "polkavm-derive", + "rustversion", + "secp256k1", + "sp-core", + "sp-crypto-hashing", + "sp-externalities", + "sp-keystore", + "sp-runtime-interface", + "sp-state-machine", + "sp-std", + "sp-tracing", + "sp-trie", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-keystore" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0248b4d784cb4a01472276928977121fa39d977a5bb24793b6b15e64b046df42" +dependencies = [ + "parity-scale-codec", + "parking_lot", + "sp-core", + "sp-externalities", +] + +[[package]] +name = "sp-panic-handler" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f5a17a0a11de029a8b811cb6e8b32ce7e02183cc04a3e965c383246798c416" +dependencies = [ + "backtrace", + "lazy_static", + "regex", +] + +[[package]] +name = "sp-runtime-interface" +version = "28.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985eb981f40c689c6a0012c937b68ed58dabb4341d06f2dfe4dfd5ed72fa4017" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "polkavm-derive", + "primitive-types", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0195f32c628fee3ce1dfbbf2e7e52a30ea85f3589da9fe62a8b816d70fc06294" +dependencies = [ + "Inflector", + "expander", + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sp-state-machine" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "211e528aa6e902261a343f7b40840aa3d66fe4ad3aadbd04a035f10baf96dbc5" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "parking_lot", + "rand", + "smallvec", + "sp-core", + "sp-externalities", + "sp-panic-handler", + "sp-trie", + "thiserror", + "tracing", + "trie-db", +] + +[[package]] +name = "sp-std" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8ee986414b0a9ad741776762f4083cd3a5128449b982a3919c4df36874834" + +[[package]] +name = "sp-storage" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99c82989b3a4979a7e1ad848aad9f5d0b4388f1f454cc131766526601ab9e8f8" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive", +] + +[[package]] +name = "sp-tracing" +version = "17.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf641a1d17268c8fcfdb8e0fa51a79c2d4222f4cfda5f3944dbdbc384dced8d5" +dependencies = [ + "parity-scale-codec", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sp-trie" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d717c0f465f5371569e6fdc25b6f32d47c15d6e4c92b3b779e1c9b18b951d" +dependencies = [ + "ahash", + "hash-db", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot", + "rand", + "scale-info", + "schnellru", + "sp-core", + "sp-externalities", + "thiserror", + "tracing", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-wasm-interface" +version = "21.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b066baa6d57951600b14ffe1243f54c47f9c23dd89c262e17ca00ae8dca58be9" +dependencies = [ + "anyhow", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", +] + +[[package]] +name = "sp-weights" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93cdaf72a1dad537bbb130ba4d47307ebe5170405280ed1aa31fa712718a400e" +dependencies = [ + "bounded-collections", + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-debug-derive", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "ss58-registry" +version = "1.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19409f13998e55816d1c728395af0b52ec066206341d939e22e7766df9b494b8" +dependencies = [ + "Inflector", + "num-format", + "proc-macro2", + "quote", + "serde", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "staging-xcm" +version = "11.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aded0292274ad473250c22ed3deaf2d9ed47d15786d700e9e83ab7c1cad2ad44" +dependencies = [ + "array-bytes", + "bounded-collections", + "derivative", + "environmental", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-weights", + "xcm-procedural", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "substrate-bip39" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca58ffd742f693dc13d69bdbb2e642ae239e0053f6aab3b104252892f856700a" +dependencies = [ + "hmac 0.12.1", + "pbkdf2", + "schnorrkel", + "sha2 0.10.8", + "zeroize", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.22", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.20", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "time", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "trie-db" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c992b4f40c234a074d48a757efeabb1a6be88af84c0c23f7ca158950cb0ae7f" +dependencies = [ + "hash-db", + "log", + "rustc-hex", + "smallvec", +] + +[[package]] +name = "trie-root" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +dependencies = [ + "hash-db", +] + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "digest 0.10.7", + "rand", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "w3f-bls" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a3028804c8bbae2a97a15b71ffc0e308c4b01a520994aafa77d56e94e19024" +dependencies = [ + "ark-bls12-377", + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-serialize-derive", + "arrayref", + "constcat", + "digest 0.10.7", + "rand", + "rand_chacha", + "rand_core", + "sha2 0.10.8", + "sha3", + "thiserror", + "zeroize", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "xcm-procedural" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4717a97970a9cda70d7db53cf50d2615c2f6f6b7c857445325b4a39ea7aa2cd" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "xxhash-rust" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] diff --git a/pop-api/examples/fungibles/Cargo.toml b/pop-api/examples/fungibles/Cargo.toml index 668e97eef..b636d1234 100644 --- a/pop-api/examples/fungibles/Cargo.toml +++ b/pop-api/examples/fungibles/Cargo.toml @@ -15,12 +15,6 @@ drink = { package = "pop-drink", git = "https://github.com/r0gue-io/pop-drink" } env_logger = { version = "0.11.3" } serde_json = "1.0.114" -# TODO: due to compilation issues caused by `sp-runtime`, `frame-support-procedural` and `staging-xcm` this dependency -# (with specific version) has to be added. Will be tackled by #348, please ignore for now. -frame-support-procedural = { version = "=30.0.1", default-features = false } -sp-runtime = { version = "=38.0.0", default-features = false } -staging-xcm = { version = "=14.1.0", default-features = false } - [lib] path = "lib.rs" diff --git a/pop-api/integration-tests/Cargo.lock b/pop-api/integration-tests/Cargo.lock new file mode 100644 index 000000000..a69358a20 --- /dev/null +++ b/pop-api/integration-tests/Cargo.lock @@ -0,0 +1,7669 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli 0.31.1", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "aquamarine" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21cc1548309245035eb18aa7f0967da6bc65587005170c56e6ef2788a4cf3f4e" +dependencies = [ + "include_dir", + "itertools 0.10.5", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "ark-bls12-377" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb00293ba84f51ce3bd026bd0de55899c4e68f0a39a5728cebae3a73ffdc0a4f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "array-bytes" +version = "6.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5dde061bd34119e902bbb2d9b90c5692635cf59fb91d582c2b68043f1b8293" + +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object 0.36.5", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "hex-conservative", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "serde", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bollard" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aed08d3adb6ebe0eff737115056652670ae290f177759aac19c30456135f94c" +dependencies = [ + "base64 0.22.1", + "bollard-stubs", + "bytes", + "futures-core", + "futures-util", + "hex", + "http", + "http-body-util", + "hyper", + "hyper-named-pipe", + "hyper-util", + "hyperlocal-next", + "log", + "pin-project-lite", + "serde", + "serde_derive", + "serde_json", + "serde_repr", + "serde_urlencoded", + "thiserror", + "tokio", + "tokio-util", + "tower-service", + "url", + "winapi", +] + +[[package]] +name = "bollard-stubs" +version = "1.44.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709d9aa1c37abb89d40f19f5d0ad6f0d88cb1581264e571c9350fc5bb89cf1c5" +dependencies = [ + "serde", + "serde_repr", + "serde_with", +] + +[[package]] +name = "bounded-collections" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d077619e9c237a5d1875166f5e8033e8f6bff0c96f8caf81e1c2d7738c431bf" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "bp-xcm-bridge-hub-router" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7dae4d1ec894ee920195dd39070b279ef3c1d4d078c3fcf7336c93a1d502a9d" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "build-helper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdce191bf3fa4995ce948c8c83b4640a1745457a149e73c6db75b4ffe36aad5f" +dependencies = [ + "semver 0.6.0", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "bytemuck" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.24", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.24", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cc" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets 0.52.6", +] + +[[package]] +name = "ckb-merkle-mountain-range" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ccb671c5921be8a84686e6212ca184cb1d7c51cadcdbfcbd1cc3f042f5dfb8" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "clap" +version = "4.5.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.1", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width 0.1.14", +] + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "colored" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" +dependencies = [ + "lazy_static", + "windows-sys 0.59.0", +] + +[[package]] +name = "common-path" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" + +[[package]] +name = "console" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width 0.2.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "const_env" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e9e4f72c6e3398ca6da372abd9affd8f89781fe728869bbf986206e9af9627e" +dependencies = [ + "const_env_impl", +] + +[[package]] +name = "const_env_impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4f51209740b5e1589e702b3044cdd4562cef41b6da404904192ffffb852d62" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "constcat" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7e35aee659887cbfb97aaf227ac12cad1a9d7c71e55ff3376839ed4e282d08" + +[[package]] +name = "contract-build" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c49937fb19dcb29219ce081292d820d7297560754e29ded0a9f5e7bb8ed64cd" +dependencies = [ + "anyhow", + "blake2", + "bollard", + "cargo_metadata 0.18.1", + "clap", + "colored", + "contract-metadata", + "crossterm", + "duct", + "heck 0.5.0", + "hex", + "impl-serde", + "parity-scale-codec", + "parity-wasm", + "regex", + "rustc_version", + "semver 1.0.24", + "serde", + "serde_json", + "strum 0.26.3", + "tempfile", + "term_size", + "tokio", + "tokio-stream", + "toml", + "tracing", + "url", + "uzers", + "walkdir", + "wasm-opt", + "which", + "zip", +] + +[[package]] +name = "contract-metadata" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "141ae20807af6bfde6aa4ae2027f6b74713ca0ce0777191b8d45941de6a91365" +dependencies = [ + "anyhow", + "impl-serde", + "semver 1.0.24", + "serde", + "serde_json", + "url", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crossterm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +dependencies = [ + "bitflags 2.6.0", + "crossterm_winapi", + "libc", + "mio 0.8.11", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "cumulus-pallet-aura-ext" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e8af48090936c45483d489ee681acb54277763586b53fa3dbd17173aa474fc" +dependencies = [ + "cumulus-pallet-parachain-system", + "frame-support", + "frame-system", + "pallet-aura", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-application-crypto", + "sp-consensus-aura", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "cumulus-pallet-parachain-system" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300d5509bd8ac95bafe158fa475278315175a4eb0422c2cd82e08e8b9dde035c" +dependencies = [ + "bytes", + "cumulus-pallet-parachain-system-proc-macro", + "cumulus-primitives-core", + "cumulus-primitives-parachain-inherent", + "cumulus-primitives-proof-size-hostfunction", + "environmental", + "frame-benchmarking", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "pallet-message-queue", + "parity-scale-codec", + "polkadot-parachain-primitives", + "polkadot-runtime-common", + "polkadot-runtime-parachains", + "scale-info", + "sp-core", + "sp-externalities", + "sp-inherents", + "sp-io", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-trie", + "sp-version", + "staging-xcm 14.1.0", + "staging-xcm-builder", + "trie-db", +] + +[[package]] +name = "cumulus-pallet-parachain-system-proc-macro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "befbaf3a1ce23ac8476481484fef5f4d500cbd15b4dad6380ce1d28134b0c1f7" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "cumulus-pallet-session-benchmarking" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "506daacefa861aa2909b64f26e76495ce029227fd8355b97e074cc1d5dc54ab2" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-session", + "parity-scale-codec", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "cumulus-pallet-xcm" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5224285f60e5159bab549f458079d606a7f95ef779def8b89f1a244dc7cf81" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm 14.1.0", +] + +[[package]] +name = "cumulus-pallet-xcmp-queue" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0adf5409618b21e754fef0ac70f257878d22d61c48fdeefcab666835dcb8e0f0" +dependencies = [ + "bounded-collections", + "bp-xcm-bridge-hub-router", + "cumulus-primitives-core", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-message-queue", + "parity-scale-codec", + "polkadot-runtime-common", + "polkadot-runtime-parachains", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm 14.1.0", + "staging-xcm-builder", + "staging-xcm-executor", +] + +[[package]] +name = "cumulus-primitives-aura" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e7977947ad43a4cbc532ca33abcde136ae3deffdc7168b2ae253d73ccd371e4" +dependencies = [ + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-primitives", + "sp-api", + "sp-consensus-aura", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "cumulus-primitives-core" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "751e64b89a839d5cfabebc1c797936e5eee791d0fa2322d91e86f8440a743ddb" +dependencies = [ + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "polkadot-primitives", + "scale-info", + "sp-api", + "sp-runtime", + "sp-std", + "sp-trie", + "staging-xcm 14.1.0", +] + +[[package]] +name = "cumulus-primitives-parachain-inherent" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df521e13b48278b86d02c61d6e44036d6d263deb5aaec4838b1751da8988d3d2" +dependencies = [ + "async-trait", + "cumulus-primitives-core", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-inherents", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-trie", +] + +[[package]] +name = "cumulus-primitives-proof-size-hostfunction" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f973d2a7262c90e48dcd42062bcb1e0fbf48bbcdac4ea6df3d85212d8d8be5d" +dependencies = [ + "sp-externalities", + "sp-runtime-interface", + "sp-trie", +] + +[[package]] +name = "cumulus-primitives-storage-weight-reclaim" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29a7e13063f593f21534a7b64c96f311c40cd4d3c72649e0bd063a34506fdd70" +dependencies = [ + "cumulus-primitives-core", + "cumulus-primitives-proof-size-hostfunction", + "docify", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "cumulus-primitives-utility" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05742c520065e3870d419683113ed7f6d35de66f0c80af6828e7878d1bb0ea94" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "log", + "pallet-asset-conversion", + "parity-scale-codec", + "polkadot-runtime-common", + "polkadot-runtime-parachains", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm 14.1.0", + "staging-xcm-builder", + "staging-xcm-executor", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "cxx" +version = "1.0.135" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d44ff199ff93242c3afe480ab588d544dd08d72e92885e152ffebc670f076ad" +dependencies = [ + "cc", + "cxxbridge-cmd", + "cxxbridge-flags", + "cxxbridge-macro", + "foldhash", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.135" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fd8f17ad454fc1e4f4ab83abffcc88a532e90350d3ffddcb73030220fcbd52" +dependencies = [ + "cc", + "codespan-reporting", + "proc-macro2", + "quote", + "scratch", + "syn 2.0.90", +] + +[[package]] +name = "cxxbridge-cmd" +version = "1.0.135" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4717c9c806a9e07fdcb34c84965a414ea40fafe57667187052cf1eb7f5e8a8a9" +dependencies = [ + "clap", + "codespan-reporting", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.135" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f6515329bf3d98f4073101c7866ff2bec4e635a13acb82e3f3753fff0bf43cb" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.135" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb93e6a7ce8ec985c02bbb758237a31598b340acbbc3c19c5a4fa6adaaac92ab" +dependencies = [ + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.90", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive-syn-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.90", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "docify" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a772b62b1837c8f060432ddcc10b17aae1453ef17617a99bc07789252d2a5896" +dependencies = [ + "docify_macros", +] + +[[package]] +name = "docify_macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60e6be249b0a462a14784a99b19bf35a667bb5e09de611738bb7362fa4c95ff7" +dependencies = [ + "common-path", + "derive-syn-parse", + "once_cell", + "proc-macro2", + "quote", + "regex", + "syn 2.0.90", + "termcolor", + "toml", + "walkdir", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "duct" +version = "0.13.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c" +dependencies = [ + "libc", + "once_cell", + "os_pipe", + "shared_child", +] + +[[package]] +name = "dyn-clonable" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +dependencies = [ + "dyn-clonable-impl", + "dyn-clone", +] + +[[package]] +name = "dyn-clonable-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "serdect", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "ed25519-zebra" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "hashbrown 0.14.5", + "hex", + "rand_core", + "sha2 0.10.8", + "zeroize", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "enumflags2" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" +dependencies = [ + "enumflags2_derive", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "enumn" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "environmental" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "expander" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2c470c71d91ecbd179935b24170459e926382eaaa86b590b78814e180d8a8e2" +dependencies = [ + "blake2", + "file-guard", + "fs-err", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "file-guard" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21ef72acf95ec3d7dbf61275be556299490a245f017cf084bd23b4f68cf9407c" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fortuples" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87630a8087e9cac4b7edfb6ee5e250ddca9112b57b6b17d8f5107375a3a8eace" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "frame-benchmarking" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709b26657ebbba53dc7bb616577375ca462b20fef1b00e8d9b20d2435e87f7bc" +dependencies = [ + "frame-support", + "frame-support-procedural", + "frame-system", + "linregress", + "log", + "parity-scale-codec", + "paste", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-core", + "sp-io", + "sp-runtime", + "sp-runtime-interface", + "sp-std", + "sp-storage", + "static_assertions", +] + +[[package]] +name = "frame-election-provider-solution-type" +version = "14.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8156f209055d352994ecd49e19658c6b469d7c6de923bd79868957d0dcfb6f71" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "frame-election-provider-support" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1ec289ebad5e601bb165cf7eb6ec2179ae34280ee310d0710a3111d4f8f8f94" +dependencies = [ + "frame-election-provider-solution-type", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-npos-elections", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "frame-executive" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d878830330eaa9e8b886279c338556b05702d0059989cb51cfb226b70bf3fa4" +dependencies = [ + "aquamarine", + "frame-support", + "frame-system", + "frame-try-runtime", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-tracing", +] + +[[package]] +name = "frame-metadata" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cf1549fba25a6fcac22785b61698317d958e96cac72a59102ea45b9ae64692" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "frame-metadata-hash-extension" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf37fc730bf4b51e82a34c6357eebe32c04dbacf6525e0a7b9726f6a17ec9427" +dependencies = [ + "array-bytes", + "docify", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", +] + +[[package]] +name = "frame-support" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512b517645f29d76c79e4c97bf8b0f4dcb6708a2af3be24b1956085dcdcf6ce5" +dependencies = [ + "aquamarine", + "array-bytes", + "bitflags 1.3.2", + "docify", + "environmental", + "frame-metadata", + "frame-support-procedural", + "impl-trait-for-tuples", + "k256", + "log", + "macro_magic", + "parity-scale-codec", + "paste", + "scale-info", + "serde", + "serde_json", + "smallvec", + "sp-api", + "sp-arithmetic", + "sp-core", + "sp-crypto-hashing-proc-macro", + "sp-debug-derive", + "sp-genesis-builder", + "sp-inherents", + "sp-io", + "sp-metadata-ir", + "sp-runtime", + "sp-staking", + "sp-state-machine", + "sp-std", + "sp-tracing", + "sp-weights", + "static_assertions", + "tt-call", +] + +[[package]] +name = "frame-support-procedural" +version = "30.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd94af68373e179c32c360b3c280497a9cf0f45a4f47f0ee6539a6c6c9cf2343" +dependencies = [ + "Inflector", + "cfg-expr", + "derive-syn-parse", + "expander", + "frame-support-procedural-tools", + "itertools 0.11.0", + "macro_magic", + "proc-macro-warning", + "proc-macro2", + "quote", + "sp-crypto-hashing", + "syn 2.0.90", +] + +[[package]] +name = "frame-support-procedural-tools" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bead15a320be1764cdd50458c4cfacb23e0cee65f64f500f8e34136a94c7eeca" +dependencies = [ + "frame-support-procedural-tools-derive", + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "frame-support-procedural-tools-derive" +version = "12.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed971c6435503a099bdac99fe4c5bea08981709e5b5a0a8535a1856f48561191" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "frame-system" +version = "36.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d6a0e7bb6503facdcc6f8e19c83cd0bfc8bbbd268522b1a50e107dfc6b972d" +dependencies = [ + "cfg-if", + "docify", + "frame-support", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-version", + "sp-weights", +] + +[[package]] +name = "frame-system-benchmarking" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15afc91c7780e18274dcea58ed1edb700c48d10e086a9785e3f6708099cd3250" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "frame-system-rpc-runtime-api" +version = "33.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e9e2b7b85e451e367f4fb85ff3295bd039e17f64de1906154d3976e2638ee8" +dependencies = [ + "parity-scale-codec", + "sp-api", +] + +[[package]] +name = "frame-try-runtime" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae6ba8b36a52775ad39ccfb45ff4ad814c3cb45ec74d0a4271889e00bd791c6c" +dependencies = [ + "frame-support", + "parity-scale-codec", + "sp-api", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "fs-err" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom_or_panic" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" +dependencies = [ + "rand", + "rand_core", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +dependencies = [ + "fallible-iterator", + "stable_deref_trait", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hash-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac 0.8.1", +] + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "http" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-named-pipe" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" +dependencies = [ + "hex", + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", + "winapi", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "hyperlocal-next" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acf569d43fa9848e510358c07b80f4adf34084ddc28c6a4a651ee8474c070dcc" +dependencies = [ + "hex", + "http-body-util", + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "include_dir" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" +dependencies = [ + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", + "serde", +] + +[[package]] +name = "indexmap-nostd" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" + +[[package]] +name = "ink" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15d7438a13d38fa8f4eebea8d1e7c2931058eafd0336c79f4141d4ed0162a412" +dependencies = [ + "derive_more 1.0.0", + "ink_env", + "ink_macro", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage", + "pallet-contracts-uapi 9.0.0", + "parity-scale-codec", + "scale-info", + "staging-xcm 11.0.0", +] + +[[package]] +name = "ink_allocator" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ec348ce75d284bc2e698187dc01da416a52dfa2d685e2a57d04e9e580447df0" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_codegen" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2238f147295746f1fee4cf7dcdee6378c94e61fbf7b9f9f4bb2a7f918530801b" +dependencies = [ + "blake2", + "derive_more 1.0.0", + "either", + "heck 0.5.0", + "impl-serde", + "ink_ir", + "ink_primitives", + "itertools 0.12.1", + "parity-scale-codec", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn 2.0.90", +] + +[[package]] +name = "ink_engine" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273f2aa983d04a6476d3c5ac76ddbef07555664b88f923996e7465e261dda48" +dependencies = [ + "blake2", + "derive_more 1.0.0", + "ink_primitives", + "pallet-contracts-uapi 9.0.0", + "parity-scale-codec", + "secp256k1", + "sha2 0.10.8", + "sha3", +] + +[[package]] +name = "ink_env" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9ee6089a1836c2e92d00be97d42308b7fb2c2b51ff6150b1130166a58107092" +dependencies = [ + "blake2", + "cfg-if", + "const_env", + "derive_more 1.0.0", + "ink_allocator", + "ink_engine", + "ink_prelude", + "ink_primitives", + "ink_storage_traits", + "num-traits", + "pallet-contracts-uapi 9.0.0", + "parity-scale-codec", + "paste", + "rlibc", + "scale-decode", + "scale-encode", + "scale-info", + "schnorrkel", + "secp256k1", + "sha2 0.10.8", + "sha3", + "staging-xcm 11.0.0", + "static_assertions", +] + +[[package]] +name = "ink_ir" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e201688fb27ff97496a4231a393dd4befcc5a9c092d6bf231f0f5d409ef44f34" +dependencies = [ + "blake2", + "either", + "impl-serde", + "ink_prelude", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "ink_macro" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce9465553d3066a8e28bd94a94880289084c4ff12f1852312553e902fa1ffdd" +dependencies = [ + "ink_codegen", + "ink_ir", + "ink_primitives", + "parity-scale-codec", + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + +[[package]] +name = "ink_metadata" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27135c651274087ba0578d2c07866c31d8dd481ae8de5bb7295fe3931491aa80" +dependencies = [ + "derive_more 1.0.0", + "impl-serde", + "ink_prelude", + "ink_primitives", + "linkme", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", +] + +[[package]] +name = "ink_prelude" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b29c9b7f686f4305f523bca5e2ae6f22a09531ec2bf0a9498cdc877959f70ad0" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_primitives" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a530c1b352a53176ea718f3a65f15003e54e0474ec12353ea0e0e5bb60b25741" +dependencies = [ + "derive_more 1.0.0", + "ink_prelude", + "parity-scale-codec", + "scale-decode", + "scale-encode", + "scale-info", + "xxhash-rust", +] + +[[package]] +name = "ink_storage" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bed602a974481b194084b93957917f27e724c7561fd0de9b6f3c171590c839b" +dependencies = [ + "array-init", + "cfg-if", + "derive_more 1.0.0", + "ink_env", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage_traits", + "pallet-contracts-uapi 9.0.0", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "ink_storage_traits" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde9b3f4a1e355682e5d13fd5639e5da4d0a2029537292e05a4255ea1169663e" +dependencies = [ + "ink_metadata", + "ink_prelude", + "ink_primitives", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + +[[package]] +name = "integration-tests" +version = "0.1.0" +dependencies = [ + "contract-build", + "env_logger", + "frame-support", + "frame-system", + "log", + "pallet-assets", + "pallet-balances", + "pallet-contracts", + "parity-scale-codec", + "pop-api", + "pop-primitives", + "pop-runtime-devnet", + "pop-runtime-testnet", + "sp-io", + "sp-runtime", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "ismp" +version = "0.2.0" +source = "git+https://github.com/r0gue-io/ismp?branch=polkadot-v1.14.0#f95ee188c3b73ca3c4d6319ab85cff12fe757c4c" +dependencies = [ + "anyhow", + "derive_more 0.99.18", + "hex", + "parity-scale-codec", + "primitive-types", + "scale-info", + "serde", + "serde-utils", + "serde_json", +] + +[[package]] +name = "ismp-parachain" +version = "1.15.0" +source = "git+https://github.com/r0gue-io/ismp?branch=polkadot-v1.14.0#f95ee188c3b73ca3c4d6319ab85cff12fe757c4c" +dependencies = [ + "cumulus-pallet-parachain-system", + "cumulus-primitives-core", + "frame-support", + "frame-system", + "hex-literal", + "ismp", + "log", + "pallet-ismp", + "parity-scale-codec", + "primitive-types", + "scale-info", + "serde", + "sp-consensus-aura", + "sp-inherents", + "sp-io", + "sp-runtime", + "sp-trie", + "substrate-state-machine", +] + +[[package]] +name = "ismp-parachain-runtime-api" +version = "1.15.0" +source = "git+https://github.com/r0gue-io/ismp?branch=polkadot-v1.14.0#f95ee188c3b73ca3c4d6319ab85cff12fe757c4c" +dependencies = [ + "cumulus-pallet-parachain-system", + "sp-api", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "serdect", + "sha2 0.10.8", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall", +] + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64 0.13.1", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "link-cplusplus" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" +dependencies = [ + "cc", +] + +[[package]] +name = "linkme" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "566336154b9e58a4f055f6dd4cbab62c7dc0826ce3c0a04e63b2d2ecd784cdae" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edbe595006d355eaf9ae11db92707d4338cd2384d16866131cc1afdbdd35d8d9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "linregress" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9eda9dcf4f2a99787827661f312ac3219292549c2ee992bf9a6248ffb066bf7" +dependencies = [ + "nalgebra", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "macro_magic" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc33f9f0351468d26fbc53d9ce00a096c8522ecb42f19b50f34f2c422f76d21d" +dependencies = [ + "macro_magic_core", + "macro_magic_macros", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "macro_magic_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1687dc887e42f352865a393acae7cf79d98fab6351cde1f58e9e057da89bf150" +dependencies = [ + "const-random", + "derive-syn-parse", + "macro_magic_core_macros", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "macro_magic_core_macros" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "macro_magic_macros" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" +dependencies = [ + "macro_magic_core", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "matrixmultiply" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +dependencies = [ + "autocfg", + "rawpointer", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memory-db" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +dependencies = [ + "hash-db", +] + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core", + "zeroize", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "mmr-primitives" +version = "1.15.0" +source = "git+https://github.com/r0gue-io/ismp?branch=polkadot-v1.14.0#f95ee188c3b73ca3c4d6319ab85cff12fe757c4c" +dependencies = [ + "ckb-merkle-mountain-range", + "frame-system", + "ismp", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-mmr-primitives", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "multi-stash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685a9ac4b61f4e728e1d2c6a7844609c16527aeb5e6c865915c08e619c16410f" + +[[package]] +name = "nalgebra" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b" +dependencies = [ + "approx", + "matrixmultiply", + "num-complex", + "num-rational", + "num-traits", + "simba", + "typenum", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec", + "itoa", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "os_pipe" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "pallet-api" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-assets", + "parity-scale-codec", + "pop-chain-extension", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-asset-conversion" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f726ebb59401c1844a4a8703047bdafcd99a1827cd5d8b2c82abeb8948a7f25b" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-asset-rate" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e806842bec955190ec64f8b2179f74f5355137c4cadf04f3269e6196cd19caf9" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-asset-tx-payment" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "100a180dfbf30a1c872100ec2dae8a61c0f5e8b3f2d3a5cbb34093826293e2ab" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-transaction-payment", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-assets" +version = "37.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79ef6a7763fc08177f014052469ee12aefcdad0d99a747372360c2f648d2cc4" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-aura" +version = "35.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0861b2a1ad6526948567bb59a3fdc4c7f02ee79b07be8b931a544350ec35ab0c" +dependencies = [ + "frame-support", + "frame-system", + "log", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-application-crypto", + "sp-consensus-aura", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-authority-discovery" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2c3666a476132f5846fe4d5e1961a923a58a0f54d873d84566f24ffaa3684f" +dependencies = [ + "frame-support", + "frame-system", + "pallet-session", + "parity-scale-codec", + "scale-info", + "sp-application-crypto", + "sp-authority-discovery", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-authorship" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38885846dbcf03b025fdbd7edb3649046dbc68fa0b419ffe8837ef853a10d31f" +dependencies = [ + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-babe" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b23d2d814e3cb793659fcf84533f66fdf0ed9cccb66cb2225851f482843ed096" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-authorship", + "pallet-session", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-application-crypto", + "sp-consensus-babe", + "sp-core", + "sp-io", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std", +] + +[[package]] +name = "pallet-balances" +version = "37.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6878e240962d3887f0e0654ac343a18845adb95ad493c9d4d5e803c015d4a4c3" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-broker" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0d652c399b6ed776ee3322e60f40e323f86b413719d7696eddb8f64c368ac0" +dependencies = [ + "bitvec", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-arithmetic", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-collator-selection" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f660cc09f2f277a3976da2eef856b5c725ab7ad1192902ef7f4e4bafd992f04f" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-authorship", + "pallet-balances", + "pallet-session", + "parity-scale-codec", + "rand", + "scale-info", + "sp-runtime", + "sp-staking", + "sp-std", +] + +[[package]] +name = "pallet-contracts" +version = "35.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e6989ac82690f981959b0d38ac6d6d52fc06bf00a035548d62b9a2e9c220376" +dependencies = [ + "bitflags 1.3.2", + "environmental", + "frame-benchmarking", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "pallet-balances", + "pallet-contracts-proc-macro", + "pallet-contracts-uapi 11.0.0", + "parity-scale-codec", + "paste", + "rand", + "scale-info", + "serde", + "smallvec", + "sp-api", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm 14.1.0", + "staging-xcm-builder", + "wasm-instrument", + "wasmi", +] + +[[package]] +name = "pallet-contracts-proc-macro" +version = "23.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94226cbd48516b7c310eb5dae8d50798c1ce73a7421dc0977c55b7fc2237a283" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "pallet-contracts-uapi" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7a51646d9ff1d91abd0186d2c074f0dfd3b1a2d55f08a229a2f2e4bc6d1e49" +dependencies = [ + "bitflags 1.3.2", + "paste", + "polkavm-derive", +] + +[[package]] +name = "pallet-contracts-uapi" +version = "11.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1330375dcced95509e3cca7ef6b1c3fac648df995b86d39467d082ba981dc46" +dependencies = [ + "bitflags 1.3.2", + "parity-scale-codec", + "paste", + "polkavm-derive", + "scale-info", +] + +[[package]] +name = "pallet-election-provider-multi-phase" +version = "35.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd1090fdc6ccdd8ff08c60000c970428baaaf0b33e7a6b01a91ec8b697a650a3" +dependencies = [ + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "log", + "pallet-election-provider-support-benchmarking", + "parity-scale-codec", + "rand", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-npos-elections", + "sp-runtime", + "sp-std", + "strum 0.26.3", +] + +[[package]] +name = "pallet-election-provider-support-benchmarking" +version = "35.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93475989d2f6900caf8f1c847a55d909295c156525a7510c5f1dde176ec7c714" +dependencies = [ + "frame-benchmarking", + "frame-election-provider-support", + "frame-system", + "parity-scale-codec", + "sp-npos-elections", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-fast-unstake" +version = "35.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9155f4f762513e0287320411415c76a647152799ad33db1785c9b71c36a14575" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-std", +] + +[[package]] +name = "pallet-identity" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4555795a3e0e3aa49ea432b7afecb9c71a7db8793a99c68bd8dd3a52a12571f3" +dependencies = [ + "enumflags2", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-ismp" +version = "1.15.0" +source = "git+https://github.com/r0gue-io/ismp?branch=polkadot-v1.14.0#f95ee188c3b73ca3c4d6319ab85cff12fe757c4c" +dependencies = [ + "fortuples", + "frame-benchmarking", + "frame-support", + "frame-system", + "ismp", + "log", + "mmr-primitives", + "parity-scale-codec", + "scale-info", + "serde", + "sp-api", + "sp-core", + "sp-io", + "sp-mmr-primitives", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-ismp-runtime-api" +version = "1.15.0" +source = "git+https://github.com/r0gue-io/ismp?branch=polkadot-v1.14.0#f95ee188c3b73ca3c4d6319ab85cff12fe757c4c" +dependencies = [ + "ismp", + "pallet-ismp", + "parity-scale-codec", + "primitive-types", + "serde", + "sp-api", + "sp-mmr-primitives", +] + +[[package]] +name = "pallet-message-queue" +version = "39.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e565e64035684e8768e00e54aaa4a0c8e69c83703899d74e8de57ed5fde399da" +dependencies = [ + "environmental", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", +] + +[[package]] +name = "pallet-multisig" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be58483d827602eb8353ecf36aed65c857f0974db5d27981831e5ebf853040bd" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-nft-fractionalization" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcaa330221f60feaf3b23d495cccc3bf2a3d6254c596b3c032273c2b46d4078" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-assets", + "pallet-nfts 30.0.0", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-nfts" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e1cd476809de3840e19091a083d5a79178af1f108ad489706e1f9e04c8836a4" +dependencies = [ + "enumflags2", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-nfts" +version = "31.0.0" +dependencies = [ + "enumflags2", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", +] + +[[package]] +name = "pallet-nfts-runtime-api" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0ca7a0446d2d3c27f726a016c6366218df2e0bfef9ed35886b252cfa9757f6c" +dependencies = [ + "pallet-nfts 30.0.0", + "parity-scale-codec", + "sp-api", + "sp-std", +] + +[[package]] +name = "pallet-preimage" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ac726abc5b1bcd6c8f783514b8e1a48be32c7d15e0b263e4bc28cc1e4e7763" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-proxy" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4e12680e176607815a78a0cd10a52af50790292cb950404f30a885e2a7229e9" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-scheduler" +version = "37.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b170d6aa191197d3f50b1193925546972ffc394376ead4d2739eb40909b73c85" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", +] + +[[package]] +name = "pallet-session" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c92b24c911c2cfa5351616edc7f2f93427ea6f4f95efdb13f0f5d51997939c3" +dependencies = [ + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-state-machine", + "sp-std", + "sp-trie", +] + +[[package]] +name = "pallet-staking" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbebdb060417654f215fc6f03675e5f44cfc83837d9e523e1b8fd9a4a2e1bdc2" +dependencies = [ + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "log", + "pallet-authorship", + "pallet-session", + "parity-scale-codec", + "scale-info", + "serde", + "sp-application-crypto", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-std", +] + +[[package]] +name = "pallet-staking-reward-fn" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "988a7ebeacc84d4bdb0b12409681e956ffe35438447d8f8bc78db547cffb6ebc" +dependencies = [ + "log", + "sp-arithmetic", +] + +[[package]] +name = "pallet-sudo" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd2a8797c1bb3d3897b4f87a7716111da5eeb8561345277b6e6d70349ec8b35" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-timestamp" +version = "35.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae789d344be857679b0b98b28a67c747119724847f81d704d3fd03ee13fb6841" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-inherents", + "sp-io", + "sp-runtime", + "sp-std", + "sp-storage", + "sp-timestamp", +] + +[[package]] +name = "pallet-transaction-payment" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74fb6114223c8d967c3c2f21cbc845e8ea604ff7e21a8e59d119d5a9257ba886" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-transaction-payment-rpc-runtime-api" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4bad1700ad7eb5ab254189e1df894d1d16b3626a3c4b9c45259ec4d9efc262c" +dependencies = [ + "pallet-transaction-payment", + "parity-scale-codec", + "sp-api", + "sp-runtime", + "sp-weights", +] + +[[package]] +name = "pallet-treasury" +version = "35.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c502615bb4fdd02856a131cb2a612ad40c26435ec938f65f11cae4ff230812b" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-utility" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3238fe6ad00da6a137be115904c39cab97eb5c7f03da0bb1a20de1bef03f0c71" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-vesting" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78f7f0f4fe5e1d851e85d81e5e73b6f929f0c35af786ce8be9c9e3363717c136" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-xcm" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe7409458b7fedc5c7d46459da154ccc2dc22a843ce08e8ab6c1743ef5cf972c" +dependencies = [ + "bounded-collections", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm 14.1.0", + "staging-xcm-builder", + "staging-xcm-executor", + "xcm-runtime-apis", +] + +[[package]] +name = "parachains-common" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9319e656eebdf161666e54a4d8e24f73137f702f01600247f7be650bc4d46167" +dependencies = [ + "cumulus-primitives-core", + "cumulus-primitives-utility", + "frame-support", + "frame-system", + "log", + "pallet-asset-tx-payment", + "pallet-assets", + "pallet-authorship", + "pallet-balances", + "pallet-collator-selection", + "pallet-message-queue", + "pallet-xcm", + "parity-scale-codec", + "polkadot-primitives", + "scale-info", + "sp-consensus-aura", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-parachain-info", + "staging-xcm 14.1.0", + "staging-xcm-executor", + "substrate-wasm-builder", +] + +[[package]] +name = "parity-bip39" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" +dependencies = [ + "bitcoin_hashes", + "rand", + "rand_core", + "serde", + "unicode-normalization", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parity-wasm" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", + "password-hash", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "polkadot-ckb-merkle-mountain-range" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b44320e5f7ce2c18227537a3032ae5b2c476a7e8eddba45333e1011fc31b92" +dependencies = [ + "cfg-if", + "itertools 0.10.5", +] + +[[package]] +name = "polkadot-core-primitives" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17c72ee63bcf920f963cd7ac066759b0b649350c8ab3781a85a6aac87b1488f2" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "polkadot-parachain-primitives" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f61070d0ff28f596890def0e0d03c231860796130b2a43e293106fa86a50c9a9" +dependencies = [ + "bounded-collections", + "derive_more 0.99.18", + "parity-scale-codec", + "polkadot-core-primitives", + "scale-info", + "serde", + "sp-core", + "sp-runtime", + "sp-std", + "sp-weights", +] + +[[package]] +name = "polkadot-primitives" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a4879609f4340138930c3c7313256941104a3ff6f7ecb2569d15223da9b35b2" +dependencies = [ + "bitvec", + "hex-literal", + "log", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-authority-discovery", + "sp-consensus-slots", + "sp-core", + "sp-inherents", + "sp-io", + "sp-keystore", + "sp-runtime", + "sp-staking", + "sp-std", +] + +[[package]] +name = "polkadot-runtime-common" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28fdcb41bb21c7b14d0341a9a17364ccc04ad34de05d41e7938cb03acbc11066" +dependencies = [ + "bitvec", + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "libsecp256k1", + "log", + "pallet-asset-rate", + "pallet-authorship", + "pallet-balances", + "pallet-broker", + "pallet-election-provider-multi-phase", + "pallet-fast-unstake", + "pallet-identity", + "pallet-session", + "pallet-staking", + "pallet-staking-reward-fn", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-treasury", + "pallet-vesting", + "parity-scale-codec", + "polkadot-primitives", + "polkadot-runtime-parachains", + "rustc-hex", + "scale-info", + "serde", + "serde_derive", + "slot-range-helper", + "sp-api", + "sp-core", + "sp-inherents", + "sp-io", + "sp-npos-elections", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std", + "staging-xcm 14.1.0", + "staging-xcm-builder", + "staging-xcm-executor", + "static_assertions", +] + +[[package]] +name = "polkadot-runtime-metrics" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac75b3fea8464e5681b44733ed11cf09e22ff1e956f6703b918b637bd40e7427" +dependencies = [ + "bs58", + "frame-benchmarking", + "parity-scale-codec", + "polkadot-primitives", + "sp-std", + "sp-tracing", +] + +[[package]] +name = "polkadot-runtime-parachains" +version = "15.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7e68cb26f9025daaad694d8192fd0e63e92c8761c45a339dd7a5b7925a3cb6" +dependencies = [ + "bitflags 1.3.2", + "bitvec", + "derive_more 0.99.18", + "frame-benchmarking", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "pallet-authority-discovery", + "pallet-authorship", + "pallet-babe", + "pallet-balances", + "pallet-broker", + "pallet-message-queue", + "pallet-session", + "pallet-staking", + "pallet-timestamp", + "pallet-vesting", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "polkadot-primitives", + "polkadot-runtime-metrics", + "rand", + "rand_chacha", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-inherents", + "sp-io", + "sp-keystore", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std", + "staging-xcm 14.1.0", + "staging-xcm-executor", +] + +[[package]] +name = "polkavm-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9428a5cfcc85c5d7b9fc4b6a18c4b802d0173d768182a51cc7751640f08b92" + +[[package]] +name = "polkavm-derive" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8c4bea6f3e11cd89bb18bcdddac10bd9a24015399bd1c485ad68a985a19606" +dependencies = [ + "polkavm-derive-impl-macro", +] + +[[package]] +name = "polkavm-derive-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" +dependencies = [ + "polkavm-common", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "polkavm-derive-impl-macro" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" +dependencies = [ + "polkavm-derive-impl", + "syn 2.0.90", +] + +[[package]] +name = "polkavm-linker" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c7be503e60cf56c0eb785f90aaba4b583b36bff00e93997d93fef97f9553c39" +dependencies = [ + "gimli 0.28.1", + "hashbrown 0.14.5", + "log", + "object 0.32.2", + "polkavm-common", + "regalloc2", + "rustc-demangle", +] + +[[package]] +name = "pop-api" +version = "0.0.0" +dependencies = [ + "ink", + "pop-primitives", + "sp-io", +] + +[[package]] +name = "pop-chain-extension" +version = "0.1.0" +dependencies = [ + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "pallet-contracts", + "parity-scale-codec", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pop-primitives" +version = "0.0.0" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "pop-runtime-common" +version = "0.0.0" +dependencies = [ + "frame-support", + "parachains-common", + "parity-scale-codec", + "polkadot-primitives", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pop-runtime-devnet" +version = "0.1.0" +dependencies = [ + "cumulus-pallet-aura-ext", + "cumulus-pallet-parachain-system", + "cumulus-pallet-session-benchmarking", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-aura", + "cumulus-primitives-core", + "cumulus-primitives-storage-weight-reclaim", + "cumulus-primitives-utility", + "frame-benchmarking", + "frame-executive", + "frame-metadata-hash-extension", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "hex-literal", + "ismp", + "ismp-parachain", + "ismp-parachain-runtime-api", + "log", + "pallet-api", + "pallet-assets", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-collator-selection", + "pallet-contracts", + "pallet-ismp", + "pallet-ismp-runtime-api", + "pallet-message-queue", + "pallet-multisig", + "pallet-nft-fractionalization", + "pallet-nfts 31.0.0", + "pallet-nfts-runtime-api", + "pallet-preimage", + "pallet-proxy", + "pallet-scheduler", + "pallet-session", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-utility", + "pallet-xcm", + "parachains-common", + "parity-scale-codec", + "polkadot-parachain-primitives", + "polkadot-runtime-common", + "pop-chain-extension", + "pop-primitives", + "pop-runtime-common", + "scale-info", + "smallvec", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-genesis-builder", + "sp-inherents", + "sp-io", + "sp-mmr-primitives", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "staging-parachain-info", + "staging-xcm 14.1.0", + "staging-xcm-builder", + "staging-xcm-executor", + "substrate-wasm-builder", +] + +[[package]] +name = "pop-runtime-testnet" +version = "0.4.2" +dependencies = [ + "cumulus-pallet-aura-ext", + "cumulus-pallet-parachain-system", + "cumulus-pallet-session-benchmarking", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-aura", + "cumulus-primitives-core", + "cumulus-primitives-storage-weight-reclaim", + "cumulus-primitives-utility", + "frame-benchmarking", + "frame-executive", + "frame-metadata-hash-extension", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "hex-literal", + "log", + "pallet-api", + "pallet-assets", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-collator-selection", + "pallet-contracts", + "pallet-message-queue", + "pallet-multisig", + "pallet-nft-fractionalization", + "pallet-nfts 31.0.0", + "pallet-nfts-runtime-api", + "pallet-preimage", + "pallet-proxy", + "pallet-scheduler", + "pallet-session", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-utility", + "pallet-xcm", + "parachains-common", + "parity-scale-codec", + "polkadot-parachain-primitives", + "polkadot-runtime-common", + "pop-chain-extension", + "pop-primitives", + "pop-runtime-common", + "scale-info", + "smallvec", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-genesis-builder", + "sp-inherents", + "sp-io", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "staging-parachain-info", + "staging-xcm 14.1.0", + "staging-xcm-builder", + "staging-xcm-executor", + "substrate-wasm-builder", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +dependencies = [ + "proc-macro2", + "syn 2.0.90", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-serde", + "scale-info", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit 0.22.22", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-warning" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "834da187cfe638ae8abb0203f0b33e5ccdb02a28e7199f2f47b3e2754f50edca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "regalloc2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" +dependencies = [ + "hashbrown 0.13.2", + "log", + "rustc-hash", + "slice-group-by", + "smallvec", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + +[[package]] +name = "rlibc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.24", +] + +[[package]] +name = "rustix" +version = "0.38.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "safe_arch" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3460605018fdc9612bce72735cba0d27efbcd9904780d44c7e3a9948f96148a" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scale-bits" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "662d10dcd57b1c2a3c41c9cf68f71fb09747ada1ea932ad961aca7e2ca28315f" +dependencies = [ + "parity-scale-codec", + "scale-type-resolver", +] + +[[package]] +name = "scale-decode" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc79ba56a1c742f5aeeed1f1801f3edf51f7e818f0a54582cac6f131364ea7b" +dependencies = [ + "derive_more 0.99.18", + "parity-scale-codec", + "scale-bits", + "scale-decode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-decode-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5398fdb3c7bea3cb419bac4983aadacae93fe1a7b5f693f4ebd98c3821aad7a5" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-encode" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628800925a33794fb5387781b883b5e14d130fece9af5a63613867b8de07c5c7" +dependencies = [ + "derive_more 0.99.18", + "parity-scale-codec", + "scale-encode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-encode-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a304e1af7cdfbe7a24e08b012721456cc8cecdedadc14b3d10513eada63233c" +dependencies = [ + "darling", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-info" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more 1.0.0", + "parity-scale-codec", + "scale-info-derive", + "schemars", + "serde", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "scale-type-resolver" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10b800069bfd43374e0f96f653e0d46882a2cb16d6d961ac43bea80f26c76843" +dependencies = [ + "smallvec", +] + +[[package]] +name = "schemars" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.90", +] + +[[package]] +name = "schnellru" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" +dependencies = [ + "ahash", + "cfg-if", + "hashbrown 0.13.2", +] + +[[package]] +name = "schnorrkel" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de18f6d8ba0aad7045f5feae07ec29899c1112584a38509a84ad7b04451eaa0" +dependencies = [ + "aead", + "arrayref", + "arrayvec", + "curve25519-dalek", + "getrandom_or_panic", + "merlin", + "rand_core", + "serde_bytes", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scratch" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "semver" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" +dependencies = [ + "serde", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-utils" +version = "0.1.0" +source = "git+https://github.com/r0gue-io/ismp?branch=polkadot-v1.14.0#f95ee188c3b73ca3c4d6319ab85cff12fe757c4c" +dependencies = [ + "anyhow", + "hex", + "serde", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.7.0", + "serde", + "serde_derive", + "serde_json", + "time", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shared_child" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09fa9338aed9a1df411814a5b2252f7cd206c55ae9bf2fa763f8de84603aa60c" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +dependencies = [ + "libc", + "mio 0.8.11", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + +[[package]] +name = "simba" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa" +dependencies = [ + "approx", + "num-complex", + "num-traits", + "paste", + "wide", +] + +[[package]] +name = "simple-mermaid" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "620a1d43d70e142b1d46a929af51d44f383db9c7a2ec122de2cd992ccfcf3c18" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + +[[package]] +name = "slot-range-helper" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4d67aa9b1ccfd746c8529754c4ce06445b1d48e189567402ef856340a3a6b14" +dependencies = [ + "enumn", + "parity-scale-codec", + "paste", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "sp-api" +version = "33.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e43fbf034e9dbaa8ffc6a238a22808777eb38c580f66fc6736d8511631789e" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "scale-info", + "sp-api-proc-macro", + "sp-core", + "sp-externalities", + "sp-metadata-ir", + "sp-runtime", + "sp-runtime-interface", + "sp-state-machine", + "sp-std", + "sp-trie", + "sp-version", + "thiserror", +] + +[[package]] +name = "sp-api-proc-macro" +version = "20.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9aadf9e97e694f0e343978aa632938c5de309cbcc8afed4136cb71596737278" +dependencies = [ + "Inflector", + "blake2", + "expander", + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sp-application-crypto" +version = "37.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d96d1fc0f1c741bbcbd0dd5470eff7b66f011708cc1942b088ebf0d4efb3d93" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-std", +] + +[[package]] +name = "sp-arithmetic" +version = "26.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46d0d0a4c591c421d3231ddd5e27d828618c24456d51445d21a1f79fcee97c23" +dependencies = [ + "docify", + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std", + "static_assertions", +] + +[[package]] +name = "sp-authority-discovery" +version = "33.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a4a1e45abc3277f18484ee0b0f9808e4206eb696ad38500c892c72f33480d69" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-application-crypto", + "sp-runtime", +] + +[[package]] +name = "sp-block-builder" +version = "33.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cf199dc4f9f77abd3fd91c409759118159ce6ffcd8bc90b229b684ccc8c981f" +dependencies = [ + "sp-api", + "sp-inherents", + "sp-runtime", +] + +[[package]] +name = "sp-consensus-aura" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ebb90bf00f331b898eb729a1f707251846c1d5582d7467f083884799a69b89" +dependencies = [ + "async-trait", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-application-crypto", + "sp-consensus-slots", + "sp-inherents", + "sp-runtime", + "sp-timestamp", +] + +[[package]] +name = "sp-consensus-babe" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3aa2de4c7100a3279658d8dd4affd8f92487528deae5cb4b40322717b9175ed5" +dependencies = [ + "async-trait", + "parity-scale-codec", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-consensus-slots", + "sp-core", + "sp-inherents", + "sp-runtime", + "sp-timestamp", +] + +[[package]] +name = "sp-consensus-slots" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ca60d713f8ddb03bbebcc755d5e6463fdc0b6259fabfc4221b20a5f1e428fd" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-timestamp", +] + +[[package]] +name = "sp-core" +version = "34.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c961a5e33fb2962fa775c044ceba43df9c6f917e2c35d63bfe23738468fa76a7" +dependencies = [ + "array-bytes", + "bitflags 1.3.2", + "blake2", + "bounded-collections", + "bs58", + "dyn-clonable", + "ed25519-zebra", + "futures", + "hash-db", + "hash256-std-hasher", + "impl-serde", + "itertools 0.11.0", + "k256", + "libsecp256k1", + "log", + "merlin", + "parity-bip39", + "parity-scale-codec", + "parking_lot", + "paste", + "primitive-types", + "rand", + "scale-info", + "schnorrkel", + "secp256k1", + "secrecy", + "serde", + "sp-crypto-hashing", + "sp-debug-derive", + "sp-externalities", + "sp-runtime-interface", + "sp-std", + "sp-storage", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tracing", + "w3f-bls", + "zeroize", +] + +[[package]] +name = "sp-crypto-hashing" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9927a7f81334ed5b8a98a4a978c81324d12bd9713ec76b5c68fd410174c5eb" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.7", + "sha2 0.10.8", + "sha3", + "twox-hash", +] + +[[package]] +name = "sp-crypto-hashing-proc-macro" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b85d0f1f1e44bd8617eb2a48203ee854981229e3e79e6f468c7175d5fd37489b" +dependencies = [ + "quote", + "sp-crypto-hashing", + "syn 2.0.90", +] + +[[package]] +name = "sp-debug-derive" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sp-externalities" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a904407d61cb94228c71b55a9d3708e9d6558991f9e83bd42bd91df37a159d30" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-storage", +] + +[[package]] +name = "sp-genesis-builder" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcd065854d96fd81521c103d0aaa287d4f08b9b15c9fae2a3bfb208b0812bf44" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde_json", + "sp-api", + "sp-runtime", +] + +[[package]] +name = "sp-inherents" +version = "33.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53407ba38ec22ca4a16381722c4bd0b559a0428bc1713079b0d5163ada63186a" +dependencies = [ + "async-trait", + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "sp-io" +version = "37.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5036cad2e48d41f5caf6785226c8be1a7db15bec14a9fd7aa6cca84f34cf689f" +dependencies = [ + "bytes", + "ed25519-dalek", + "libsecp256k1", + "log", + "parity-scale-codec", + "polkavm-derive", + "rustversion", + "secp256k1", + "sp-core", + "sp-crypto-hashing", + "sp-externalities", + "sp-keystore", + "sp-runtime-interface", + "sp-state-machine", + "sp-std", + "sp-tracing", + "sp-trie", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-keystore" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0248b4d784cb4a01472276928977121fa39d977a5bb24793b6b15e64b046df42" +dependencies = [ + "parity-scale-codec", + "parking_lot", + "sp-core", + "sp-externalities", +] + +[[package]] +name = "sp-maybe-compressed-blob" +version = "11.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c768c11afbe698a090386876911da4236af199cd38a5866748df4d8628aeff" +dependencies = [ + "thiserror", + "zstd", +] + +[[package]] +name = "sp-metadata-ir" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a616fa51350b35326682a472ee8e6ba742fdacb18babac38ecd46b3e05ead869" +dependencies = [ + "frame-metadata", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "sp-mmr-primitives" +version = "33.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47412a2d2e988430d5f59d7fec1473f229e1ef5ce24c1ea4f601b4b3679cac52" +dependencies = [ + "log", + "parity-scale-codec", + "polkadot-ckb-merkle-mountain-range", + "scale-info", + "serde", + "sp-api", + "sp-core", + "sp-debug-derive", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "sp-npos-elections" +version = "33.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b0c51a7b60cd663f2661e6949069eb316b092f22c239691d5272a4d0cfca0fb" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-arithmetic", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "sp-offchain" +version = "33.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbe721c367760bddf10fcfa24fb48edd64c442f71db971f043c8ac73f51aa6e9" +dependencies = [ + "sp-api", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "sp-panic-handler" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f5a17a0a11de029a8b811cb6e8b32ce7e02183cc04a3e965c383246798c416" +dependencies = [ + "backtrace", + "lazy_static", + "regex", +] + +[[package]] +name = "sp-runtime" +version = "38.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ef409c414546b655ec1e94aaea178e4a97e21284a91b24c762aebf836d3b49" +dependencies = [ + "docify", + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log", + "num-traits", + "parity-scale-codec", + "paste", + "rand", + "scale-info", + "serde", + "simple-mermaid", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-std", + "sp-weights", +] + +[[package]] +name = "sp-runtime-interface" +version = "28.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985eb981f40c689c6a0012c937b68ed58dabb4341d06f2dfe4dfd5ed72fa4017" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "polkavm-derive", + "primitive-types", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0195f32c628fee3ce1dfbbf2e7e52a30ea85f3589da9fe62a8b816d70fc06294" +dependencies = [ + "Inflector", + "expander", + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sp-session" +version = "34.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4daf2e40ffc7e7e8de08efb860eb9534faf614a49c53dc282f430faedb4aed13" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-core", + "sp-keystore", + "sp-runtime", + "sp-staking", +] + +[[package]] +name = "sp-staking" +version = "33.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a0b7abfe66c07a3b6eb99e1286dfa9b6f3b057b0e986e7da2ccbf707f6c781a" +dependencies = [ + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "sp-state-machine" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "211e528aa6e902261a343f7b40840aa3d66fe4ad3aadbd04a035f10baf96dbc5" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "parking_lot", + "rand", + "smallvec", + "sp-core", + "sp-externalities", + "sp-panic-handler", + "sp-trie", + "thiserror", + "tracing", + "trie-db", +] + +[[package]] +name = "sp-std" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8ee986414b0a9ad741776762f4083cd3a5128449b982a3919c4df36874834" + +[[package]] +name = "sp-storage" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99c82989b3a4979a7e1ad848aad9f5d0b4388f1f454cc131766526601ab9e8f8" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive", +] + +[[package]] +name = "sp-timestamp" +version = "33.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78becf144a76f6fd108dfe94a90e20a185b38c0b310dc5482328196143c8266b" +dependencies = [ + "async-trait", + "parity-scale-codec", + "sp-inherents", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "sp-tracing" +version = "17.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf641a1d17268c8fcfdb8e0fa51a79c2d4222f4cfda5f3944dbdbc384dced8d5" +dependencies = [ + "parity-scale-codec", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sp-transaction-pool" +version = "33.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3c9d1604aadc15b70e95f4388d0b1aa380215520b7ddfd372531a6d8262269c" +dependencies = [ + "sp-api", + "sp-runtime", +] + +[[package]] +name = "sp-trie" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d717c0f465f5371569e6fdc25b6f32d47c15d6e4c92b3b779e1c9b18b951d" +dependencies = [ + "ahash", + "hash-db", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot", + "rand", + "scale-info", + "schnellru", + "sp-core", + "sp-externalities", + "thiserror", + "tracing", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-version" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bccf96fefae339dee7c4453f91be64eb28cce4c2fe82130445cf096b18b2c081" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "parity-wasm", + "scale-info", + "serde", + "sp-crypto-hashing-proc-macro", + "sp-runtime", + "sp-std", + "sp-version-proc-macro", + "thiserror", +] + +[[package]] +name = "sp-version-proc-macro" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aee8f6730641a65fcf0c8f9b1e448af4b3bb083d08058b47528188bccc7b7a7" +dependencies = [ + "parity-scale-codec", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sp-wasm-interface" +version = "21.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b066baa6d57951600b14ffe1243f54c47f9c23dd89c262e17ca00ae8dca58be9" +dependencies = [ + "anyhow", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", +] + +[[package]] +name = "sp-weights" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93cdaf72a1dad537bbb130ba4d47307ebe5170405280ed1aa31fa712718a400e" +dependencies = [ + "bounded-collections", + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-debug-derive", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "ss58-registry" +version = "1.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19409f13998e55816d1c728395af0b52ec066206341d939e22e7766df9b494b8" +dependencies = [ + "Inflector", + "num-format", + "proc-macro2", + "quote", + "serde", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "staging-parachain-info" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd00d586b0dac4f42736bdd0ad52213a891b240e011ea82b38938263dd821c25" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "staging-xcm" +version = "11.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aded0292274ad473250c22ed3deaf2d9ed47d15786d700e9e83ab7c1cad2ad44" +dependencies = [ + "array-bytes", + "bounded-collections", + "derivative", + "environmental", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-weights", + "xcm-procedural 8.0.0", +] + +[[package]] +name = "staging-xcm" +version = "14.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b7b5f531c6bf9629514ef8e5fda0e9e80dd84516957f710940d0e01d3fb36c" +dependencies = [ + "array-bytes", + "bounded-collections", + "derivative", + "environmental", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-weights", + "xcm-procedural 10.1.0", +] + +[[package]] +name = "staging-xcm-builder" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "847fa2afe1bed2751eaabf7b91fa4043037947f17653d7cc59ea202cc44c6bb8" +dependencies = [ + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "pallet-transaction-payment", + "parity-scale-codec", + "polkadot-parachain-primitives", + "scale-info", + "sp-arithmetic", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", + "staging-xcm 14.1.0", + "staging-xcm-executor", +] + +[[package]] +name = "staging-xcm-executor" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b98d8219449eaf02e71a7edf1a14b14d4c713dd01d9df66fde1ce30dba4d6d" +dependencies = [ + "environmental", + "frame-benchmarking", + "frame-support", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", + "staging-xcm 14.1.0", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "string-interner" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c6a0d765f5807e98a091107bae0a56ea3799f66a5de47b2c84c94a39c09974e" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "serde", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", +] + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.109", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.90", +] + +[[package]] +name = "substrate-bip39" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca58ffd742f693dc13d69bdbb2e642ae239e0053f6aab3b104252892f856700a" +dependencies = [ + "hmac 0.12.1", + "pbkdf2", + "schnorrkel", + "sha2 0.10.8", + "zeroize", +] + +[[package]] +name = "substrate-state-machine" +version = "1.15.0" +source = "git+https://github.com/r0gue-io/ismp?branch=polkadot-v1.14.0#f95ee188c3b73ca3c4d6319ab85cff12fe757c4c" +dependencies = [ + "frame-support", + "hash-db", + "ismp", + "pallet-ismp", + "parity-scale-codec", + "primitive-types", + "scale-info", + "serde", + "sp-consensus-aura", + "sp-runtime", + "sp-trie", +] + +[[package]] +name = "substrate-wasm-builder" +version = "23.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dc993ad871b63fbba60362f3ea86583f5e7e1256e8fdcb3b5b249c9ead354bf" +dependencies = [ + "build-helper", + "cargo_metadata 0.15.4", + "console", + "filetime", + "parity-wasm", + "polkavm-linker", + "sp-maybe-compressed-blob", + "strum 0.26.3", + "tempfile", + "toml", + "walkdir", + "wasm-opt", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "term_size" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio 1.0.3", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.22", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.7.0", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.7.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.20", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "time", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "trie-db" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c992b4f40c234a074d48a757efeabb1a6be88af84c0c23f7ca158950cb0ae7f" +dependencies = [ + "hash-db", + "log", + "rustc-hex", + "smallvec", +] + +[[package]] +name = "trie-root" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +dependencies = [ + "hash-db", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "tt-call" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f195fd851901624eee5a58c4bb2b4f06399148fcd0ed336e6f1cb60a9881df" + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "digest 0.10.7", + "rand", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uzers" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d283dc7e8c901e79e32d077866eaf599156cbf427fffa8289aecc52c5c3f63" +dependencies = [ + "libc", + "log", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "w3f-bls" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a3028804c8bbae2a97a15b71ffc0e308c4b01a520994aafa77d56e94e19024" +dependencies = [ + "ark-bls12-377", + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-serialize-derive", + "arrayref", + "constcat", + "digest 0.10.7", + "rand", + "rand_chacha", + "rand_core", + "sha2 0.10.8", + "sha3", + "thiserror", + "zeroize", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.90", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" + +[[package]] +name = "wasm-instrument" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a47ecb37b9734d1085eaa5ae1a81e60801fd8c28d4cabdd8aedb982021918bc" +dependencies = [ + "parity-wasm", +] + +[[package]] +name = "wasm-opt" +version = "0.116.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd87a4c135535ffed86123b6fb0f0a5a0bc89e50416c942c5f0662c645f679c" +dependencies = [ + "anyhow", + "libc", + "strum 0.24.1", + "strum_macros 0.24.3", + "tempfile", + "thiserror", + "wasm-opt-cxx-sys", + "wasm-opt-sys", +] + +[[package]] +name = "wasm-opt-cxx-sys" +version = "0.116.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c57b28207aa724318fcec6575fe74803c23f6f266fce10cbc9f3f116762f12e" +dependencies = [ + "anyhow", + "cxx", + "cxx-build", + "wasm-opt-sys", +] + +[[package]] +name = "wasm-opt-sys" +version = "0.116.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a1cce564dc768dacbdb718fc29df2dba80bd21cb47d8f77ae7e3d95ceb98cbe" +dependencies = [ + "anyhow", + "cc", + "cxx", + "cxx-build", +] + +[[package]] +name = "wasmi" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50386c99b9c32bd2ed71a55b6dd4040af2580530fae8bdb9a6576571a80d0cca" +dependencies = [ + "arrayvec", + "multi-stash", + "num-derive", + "num-traits", + "smallvec", + "spin", + "wasmi_collections", + "wasmi_core", + "wasmparser-nostd", +] + +[[package]] +name = "wasmi_collections" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c128c039340ffd50d4195c3f8ce31aac357f06804cfc494c8b9508d4b30dca4" +dependencies = [ + "ahash", + "hashbrown 0.14.5", + "string-interner", +] + +[[package]] +name = "wasmi_core" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23b3a7f6c8c3ceeec6b83531ee61f0013c56e51cbf2b14b0f213548b23a4b41" +dependencies = [ + "downcast-rs", + "libm", + "num-traits", + "paste", +] + +[[package]] +name = "wasmparser-nostd" +version = "0.100.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5a015fe95f3504a94bb1462c717aae75253e39b9dd6c3fb1062c934535c64aa" +dependencies = [ + "indexmap-nostd", +] + +[[package]] +name = "which" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +dependencies = [ + "either", + "home", + "rustix", + "winsafe", +] + +[[package]] +name = "wide" +version = "0.7.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58e6db2670d2be78525979e9a5f9c69d296fd7d670549fe9ebf70f8708cb5019" +dependencies = [ + "bytemuck", + "safe_arch", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "xcm-procedural" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4717a97970a9cda70d7db53cf50d2615c2f6f6b7c857445325b4a39ea7aa2cd" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "xcm-procedural" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87fb4f14094d65c500a59bcf540cf42b99ee82c706edd6226a92e769ad60563e" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "xcm-runtime-apis" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30fffcd9128a46abd836c37dd001c2cbe122aeb8904cd7b9bac8358564fb7b56" +dependencies = [ + "frame-support", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-std", + "sp-weights", + "staging-xcm 14.1.0", + "staging-xcm-executor", +] + +[[package]] +name = "xxhash-rust" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "byteorder", + "crc32fast", + "crossbeam-utils", +] + +[[package]] +name = "zstd" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a27595e173641171fc74a1232b7b1c7a7cb6e18222c11e9dfb9888fa424c53c" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "6.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee98ffd0b48ee95e6c5168188e44a54550b1564d9d530ee21d5f0eaed1069581" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.13+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/pop-api/integration-tests/Cargo.toml b/pop-api/integration-tests/Cargo.toml index 482a214f7..23a299947 100644 --- a/pop-api/integration-tests/Cargo.toml +++ b/pop-api/integration-tests/Cargo.toml @@ -10,7 +10,6 @@ contract-build = "4.1.1" [dev-dependencies] env_logger = "0.11.2" frame-support = { version = "36.0.0", default-features = false } -frame-support-procedural = { version = "=30.0.1", default-features = false } frame-system = { version = "36.1.0", default-features = false } log = "0.4.22" pallet-assets = { version = "37.0.0", default-features = false } @@ -26,9 +25,7 @@ scale = { package = "parity-scale-codec", version = "3.6.12", default-features = "derive", ] } sp-io = { version = "37.0.0", default-features = false } -sp-runtime = { version = "=38.0.0", default-features = false } -# TODO: Requires to resolve a dependency version issue. See more at: https://github.com/r0gue-io/pop-node/issues/313. -staging-xcm = { version = "=14.1.0", default-features = false } +sp-runtime = { version = "38.0.0", default-features = false } [features] default = [ "std" ] @@ -46,6 +43,5 @@ std = [ "scale/std", "sp-io/std", "sp-runtime/std", - "staging-xcm/std", ] testnet = [ ] diff --git a/pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.lock b/pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.lock new file mode 100644 index 000000000..11b547f55 --- /dev/null +++ b/pop-api/integration-tests/contracts/create_token_in_constructor/Cargo.lock @@ -0,0 +1,3331 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "anyhow" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" + +[[package]] +name = "ark-bls12-377" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb00293ba84f51ce3bd026bd0de55899c4e68f0a39a5728cebae3a73ffdc0a4f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "array-bytes" +version = "6.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5dde061bd34119e902bbb2d9b90c5692635cf59fb91d582c2b68043f1b8293" + +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "hex-conservative", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bounded-collections" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d077619e9c237a5d1875166f5e8033e8f6bff0c96f8caf81e1c2d7738c431bf" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "cc" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "common-path" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const_env" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e9e4f72c6e3398ca6da372abd9affd8f89781fe728869bbf986206e9af9627e" +dependencies = [ + "const_env_impl", +] + +[[package]] +name = "const_env_impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4f51209740b5e1589e702b3044cdd4562cef41b6da404904192ffffb852d62" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "constcat" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7e35aee659887cbfb97aaf227ac12cad1a9d7c71e55ff3376839ed4e282d08" + +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + +[[package]] +name = "create_token_in_constructor" +version = "0.1.0" +dependencies = [ + "ink", + "pop-api", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive-syn-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "docify" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a772b62b1837c8f060432ddcc10b17aae1453ef17617a99bc07789252d2a5896" +dependencies = [ + "docify_macros", +] + +[[package]] +name = "docify_macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60e6be249b0a462a14784a99b19bf35a667bb5e09de611738bb7362fa4c95ff7" +dependencies = [ + "common-path", + "derive-syn-parse", + "once_cell", + "proc-macro2", + "quote", + "regex", + "syn 2.0.90", + "termcolor", + "toml", + "walkdir", +] + +[[package]] +name = "dyn-clonable" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +dependencies = [ + "dyn-clonable-impl", + "dyn-clone", +] + +[[package]] +name = "dyn-clonable-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "serdect", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "ed25519-zebra" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "hashbrown 0.14.5", + "hex", + "rand_core", + "sha2 0.10.8", + "zeroize", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "environmental" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "expander" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2c470c71d91ecbd179935b24170459e926382eaaa86b590b78814e180d8a8e2" +dependencies = [ + "blake2", + "file-guard", + "fs-err", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "file-guard" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21ef72acf95ec3d7dbf61275be556299490a245f017cf084bd23b4f68cf9407c" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fs-err" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom_or_panic" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" +dependencies = [ + "rand", + "rand_core", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hash-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac 0.8.1", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "ink" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15d7438a13d38fa8f4eebea8d1e7c2931058eafd0336c79f4141d4ed0162a412" +dependencies = [ + "derive_more 1.0.0", + "ink_env", + "ink_macro", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage", + "pallet-contracts-uapi", + "parity-scale-codec", + "scale-info", + "staging-xcm", +] + +[[package]] +name = "ink_allocator" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ec348ce75d284bc2e698187dc01da416a52dfa2d685e2a57d04e9e580447df0" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_codegen" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2238f147295746f1fee4cf7dcdee6378c94e61fbf7b9f9f4bb2a7f918530801b" +dependencies = [ + "blake2", + "derive_more 1.0.0", + "either", + "heck", + "impl-serde", + "ink_ir", + "ink_primitives", + "itertools 0.12.1", + "parity-scale-codec", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn 2.0.90", +] + +[[package]] +name = "ink_engine" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273f2aa983d04a6476d3c5ac76ddbef07555664b88f923996e7465e261dda48" +dependencies = [ + "blake2", + "derive_more 1.0.0", + "ink_primitives", + "pallet-contracts-uapi", + "parity-scale-codec", + "secp256k1", + "sha2 0.10.8", + "sha3", +] + +[[package]] +name = "ink_env" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9ee6089a1836c2e92d00be97d42308b7fb2c2b51ff6150b1130166a58107092" +dependencies = [ + "blake2", + "cfg-if", + "const_env", + "derive_more 1.0.0", + "ink_allocator", + "ink_engine", + "ink_prelude", + "ink_primitives", + "ink_storage_traits", + "num-traits", + "pallet-contracts-uapi", + "parity-scale-codec", + "paste", + "rlibc", + "scale-decode", + "scale-encode", + "scale-info", + "schnorrkel", + "secp256k1", + "sha2 0.10.8", + "sha3", + "staging-xcm", + "static_assertions", +] + +[[package]] +name = "ink_ir" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e201688fb27ff97496a4231a393dd4befcc5a9c092d6bf231f0f5d409ef44f34" +dependencies = [ + "blake2", + "either", + "impl-serde", + "ink_prelude", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "ink_macro" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce9465553d3066a8e28bd94a94880289084c4ff12f1852312553e902fa1ffdd" +dependencies = [ + "ink_codegen", + "ink_ir", + "ink_primitives", + "parity-scale-codec", + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + +[[package]] +name = "ink_metadata" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27135c651274087ba0578d2c07866c31d8dd481ae8de5bb7295fe3931491aa80" +dependencies = [ + "derive_more 1.0.0", + "impl-serde", + "ink_prelude", + "ink_primitives", + "linkme", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", +] + +[[package]] +name = "ink_prelude" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b29c9b7f686f4305f523bca5e2ae6f22a09531ec2bf0a9498cdc877959f70ad0" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_primitives" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a530c1b352a53176ea718f3a65f15003e54e0474ec12353ea0e0e5bb60b25741" +dependencies = [ + "derive_more 1.0.0", + "ink_prelude", + "parity-scale-codec", + "scale-decode", + "scale-encode", + "scale-info", + "xxhash-rust", +] + +[[package]] +name = "ink_storage" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bed602a974481b194084b93957917f27e724c7561fd0de9b6f3c171590c839b" +dependencies = [ + "array-init", + "cfg-if", + "derive_more 1.0.0", + "ink_env", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage_traits", + "pallet-contracts-uapi", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "ink_storage_traits" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde9b3f4a1e355682e5d13fd5639e5da4d0a2029537292e05a4255ea1169663e" +dependencies = [ + "ink_metadata", + "ink_prelude", + "ink_primitives", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "serdect", + "sha2 0.10.8", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "linkme" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "566336154b9e58a4f055f6dd4cbab62c7dc0826ce3c0a04e63b2d2ecd784cdae" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edbe595006d355eaf9ae11db92707d4338cd2384d16866131cc1afdbdd35d8d9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memory-db" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +dependencies = [ + "hash-db", +] + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core", + "zeroize", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" +dependencies = [ + "adler2", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec", + "itoa", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "pallet-contracts-uapi" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7a51646d9ff1d91abd0186d2c074f0dfd3b1a2d55f08a229a2f2e4bc6d1e49" +dependencies = [ + "bitflags 1.3.2", + "paste", + "polkavm-derive", +] + +[[package]] +name = "parity-bip39" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" +dependencies = [ + "bitcoin_hashes", + "rand", + "rand_core", + "serde", + "unicode-normalization", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", + "password-hash", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "polkavm-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9428a5cfcc85c5d7b9fc4b6a18c4b802d0173d768182a51cc7751640f08b92" + +[[package]] +name = "polkavm-derive" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8c4bea6f3e11cd89bb18bcdddac10bd9a24015399bd1c485ad68a985a19606" +dependencies = [ + "polkavm-derive-impl-macro", +] + +[[package]] +name = "polkavm-derive-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" +dependencies = [ + "polkavm-common", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "polkavm-derive-impl-macro" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" +dependencies = [ + "polkavm-derive-impl", + "syn 2.0.90", +] + +[[package]] +name = "pop-api" +version = "0.0.0" +dependencies = [ + "ink", + "pop-primitives", + "sp-io", +] + +[[package]] +name = "pop-primitives" +version = "0.0.0" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +dependencies = [ + "proc-macro2", + "syn 2.0.90", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-serde", + "scale-info", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit 0.22.22", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + +[[package]] +name = "rlibc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scale-bits" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "662d10dcd57b1c2a3c41c9cf68f71fb09747ada1ea932ad961aca7e2ca28315f" +dependencies = [ + "parity-scale-codec", + "scale-type-resolver", +] + +[[package]] +name = "scale-decode" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc79ba56a1c742f5aeeed1f1801f3edf51f7e818f0a54582cac6f131364ea7b" +dependencies = [ + "derive_more 0.99.18", + "parity-scale-codec", + "scale-bits", + "scale-decode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-decode-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5398fdb3c7bea3cb419bac4983aadacae93fe1a7b5f693f4ebd98c3821aad7a5" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-encode" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628800925a33794fb5387781b883b5e14d130fece9af5a63613867b8de07c5c7" +dependencies = [ + "derive_more 0.99.18", + "parity-scale-codec", + "scale-encode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-encode-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a304e1af7cdfbe7a24e08b012721456cc8cecdedadc14b3d10513eada63233c" +dependencies = [ + "darling", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-info" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more 1.0.0", + "parity-scale-codec", + "scale-info-derive", + "schemars", + "serde", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "scale-type-resolver" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10b800069bfd43374e0f96f653e0d46882a2cb16d6d961ac43bea80f26c76843" +dependencies = [ + "smallvec", +] + +[[package]] +name = "schemars" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.90", +] + +[[package]] +name = "schnellru" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" +dependencies = [ + "ahash", + "cfg-if", + "hashbrown 0.13.2", +] + +[[package]] +name = "schnorrkel" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de18f6d8ba0aad7045f5feae07ec29899c1112584a38509a84ad7b04451eaa0" +dependencies = [ + "aead", + "arrayref", + "arrayvec", + "curve25519-dalek", + "getrandom_or_panic", + "merlin", + "rand_core", + "serde_bytes", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" + +[[package]] +name = "serde" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "sp-arithmetic" +version = "26.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46d0d0a4c591c421d3231ddd5e27d828618c24456d51445d21a1f79fcee97c23" +dependencies = [ + "docify", + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std", + "static_assertions", +] + +[[package]] +name = "sp-core" +version = "34.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c961a5e33fb2962fa775c044ceba43df9c6f917e2c35d63bfe23738468fa76a7" +dependencies = [ + "array-bytes", + "bitflags 1.3.2", + "blake2", + "bounded-collections", + "bs58", + "dyn-clonable", + "ed25519-zebra", + "futures", + "hash-db", + "hash256-std-hasher", + "impl-serde", + "itertools 0.11.0", + "k256", + "libsecp256k1", + "log", + "merlin", + "parity-bip39", + "parity-scale-codec", + "parking_lot", + "paste", + "primitive-types", + "rand", + "scale-info", + "schnorrkel", + "secp256k1", + "secrecy", + "serde", + "sp-crypto-hashing", + "sp-debug-derive", + "sp-externalities", + "sp-runtime-interface", + "sp-std", + "sp-storage", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tracing", + "w3f-bls", + "zeroize", +] + +[[package]] +name = "sp-crypto-hashing" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9927a7f81334ed5b8a98a4a978c81324d12bd9713ec76b5c68fd410174c5eb" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.7", + "sha2 0.10.8", + "sha3", + "twox-hash", +] + +[[package]] +name = "sp-debug-derive" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sp-externalities" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a904407d61cb94228c71b55a9d3708e9d6558991f9e83bd42bd91df37a159d30" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-storage", +] + +[[package]] +name = "sp-io" +version = "37.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5036cad2e48d41f5caf6785226c8be1a7db15bec14a9fd7aa6cca84f34cf689f" +dependencies = [ + "bytes", + "ed25519-dalek", + "libsecp256k1", + "log", + "parity-scale-codec", + "polkavm-derive", + "rustversion", + "secp256k1", + "sp-core", + "sp-crypto-hashing", + "sp-externalities", + "sp-keystore", + "sp-runtime-interface", + "sp-state-machine", + "sp-std", + "sp-tracing", + "sp-trie", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-keystore" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0248b4d784cb4a01472276928977121fa39d977a5bb24793b6b15e64b046df42" +dependencies = [ + "parity-scale-codec", + "parking_lot", + "sp-core", + "sp-externalities", +] + +[[package]] +name = "sp-panic-handler" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f5a17a0a11de029a8b811cb6e8b32ce7e02183cc04a3e965c383246798c416" +dependencies = [ + "backtrace", + "lazy_static", + "regex", +] + +[[package]] +name = "sp-runtime-interface" +version = "28.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985eb981f40c689c6a0012c937b68ed58dabb4341d06f2dfe4dfd5ed72fa4017" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "polkavm-derive", + "primitive-types", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0195f32c628fee3ce1dfbbf2e7e52a30ea85f3589da9fe62a8b816d70fc06294" +dependencies = [ + "Inflector", + "expander", + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sp-state-machine" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "211e528aa6e902261a343f7b40840aa3d66fe4ad3aadbd04a035f10baf96dbc5" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "parking_lot", + "rand", + "smallvec", + "sp-core", + "sp-externalities", + "sp-panic-handler", + "sp-trie", + "thiserror", + "tracing", + "trie-db", +] + +[[package]] +name = "sp-std" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8ee986414b0a9ad741776762f4083cd3a5128449b982a3919c4df36874834" + +[[package]] +name = "sp-storage" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99c82989b3a4979a7e1ad848aad9f5d0b4388f1f454cc131766526601ab9e8f8" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive", +] + +[[package]] +name = "sp-tracing" +version = "17.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf641a1d17268c8fcfdb8e0fa51a79c2d4222f4cfda5f3944dbdbc384dced8d5" +dependencies = [ + "parity-scale-codec", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sp-trie" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d717c0f465f5371569e6fdc25b6f32d47c15d6e4c92b3b779e1c9b18b951d" +dependencies = [ + "ahash", + "hash-db", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot", + "rand", + "scale-info", + "schnellru", + "sp-core", + "sp-externalities", + "thiserror", + "tracing", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-wasm-interface" +version = "21.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b066baa6d57951600b14ffe1243f54c47f9c23dd89c262e17ca00ae8dca58be9" +dependencies = [ + "anyhow", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", +] + +[[package]] +name = "sp-weights" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93cdaf72a1dad537bbb130ba4d47307ebe5170405280ed1aa31fa712718a400e" +dependencies = [ + "bounded-collections", + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-debug-derive", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "ss58-registry" +version = "1.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19409f13998e55816d1c728395af0b52ec066206341d939e22e7766df9b494b8" +dependencies = [ + "Inflector", + "num-format", + "proc-macro2", + "quote", + "serde", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "staging-xcm" +version = "11.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aded0292274ad473250c22ed3deaf2d9ed47d15786d700e9e83ab7c1cad2ad44" +dependencies = [ + "array-bytes", + "bounded-collections", + "derivative", + "environmental", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-weights", + "xcm-procedural", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "substrate-bip39" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca58ffd742f693dc13d69bdbb2e642ae239e0053f6aab3b104252892f856700a" +dependencies = [ + "hmac 0.12.1", + "pbkdf2", + "schnorrkel", + "sha2 0.10.8", + "zeroize", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.22", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.20", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "time", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "trie-db" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c992b4f40c234a074d48a757efeabb1a6be88af84c0c23f7ca158950cb0ae7f" +dependencies = [ + "hash-db", + "log", + "rustc-hex", + "smallvec", +] + +[[package]] +name = "trie-root" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +dependencies = [ + "hash-db", +] + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "digest 0.10.7", + "rand", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "w3f-bls" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a3028804c8bbae2a97a15b71ffc0e308c4b01a520994aafa77d56e94e19024" +dependencies = [ + "ark-bls12-377", + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-serialize-derive", + "arrayref", + "constcat", + "digest 0.10.7", + "rand", + "rand_chacha", + "rand_core", + "sha2 0.10.8", + "sha3", + "thiserror", + "zeroize", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "xcm-procedural" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4717a97970a9cda70d7db53cf50d2615c2f6f6b7c857445325b4a39ea7aa2cd" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "xxhash-rust" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] diff --git a/pop-api/integration-tests/contracts/fungibles/Cargo.lock b/pop-api/integration-tests/contracts/fungibles/Cargo.lock new file mode 100644 index 000000000..fd95f6c02 --- /dev/null +++ b/pop-api/integration-tests/contracts/fungibles/Cargo.lock @@ -0,0 +1,3331 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "anyhow" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" + +[[package]] +name = "ark-bls12-377" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb00293ba84f51ce3bd026bd0de55899c4e68f0a39a5728cebae3a73ffdc0a4f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "array-bytes" +version = "6.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5dde061bd34119e902bbb2d9b90c5692635cf59fb91d582c2b68043f1b8293" + +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "hex-conservative", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bounded-collections" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d077619e9c237a5d1875166f5e8033e8f6bff0c96f8caf81e1c2d7738c431bf" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "cc" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "common-path" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const_env" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e9e4f72c6e3398ca6da372abd9affd8f89781fe728869bbf986206e9af9627e" +dependencies = [ + "const_env_impl", +] + +[[package]] +name = "const_env_impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4f51209740b5e1589e702b3044cdd4562cef41b6da404904192ffffb852d62" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "constcat" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7e35aee659887cbfb97aaf227ac12cad1a9d7c71e55ff3376839ed4e282d08" + +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive-syn-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "docify" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a772b62b1837c8f060432ddcc10b17aae1453ef17617a99bc07789252d2a5896" +dependencies = [ + "docify_macros", +] + +[[package]] +name = "docify_macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60e6be249b0a462a14784a99b19bf35a667bb5e09de611738bb7362fa4c95ff7" +dependencies = [ + "common-path", + "derive-syn-parse", + "once_cell", + "proc-macro2", + "quote", + "regex", + "syn 2.0.90", + "termcolor", + "toml", + "walkdir", +] + +[[package]] +name = "dyn-clonable" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +dependencies = [ + "dyn-clonable-impl", + "dyn-clone", +] + +[[package]] +name = "dyn-clonable-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "serdect", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "ed25519-zebra" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "hashbrown 0.14.5", + "hex", + "rand_core", + "sha2 0.10.8", + "zeroize", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "environmental" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "expander" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2c470c71d91ecbd179935b24170459e926382eaaa86b590b78814e180d8a8e2" +dependencies = [ + "blake2", + "file-guard", + "fs-err", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "file-guard" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21ef72acf95ec3d7dbf61275be556299490a245f017cf084bd23b4f68cf9407c" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fs-err" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] + +[[package]] +name = "fungibles" +version = "0.1.0" +dependencies = [ + "ink", + "pop-api", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom_or_panic" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" +dependencies = [ + "rand", + "rand_core", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hash-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac 0.8.1", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "ink" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15d7438a13d38fa8f4eebea8d1e7c2931058eafd0336c79f4141d4ed0162a412" +dependencies = [ + "derive_more 1.0.0", + "ink_env", + "ink_macro", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage", + "pallet-contracts-uapi", + "parity-scale-codec", + "scale-info", + "staging-xcm", +] + +[[package]] +name = "ink_allocator" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ec348ce75d284bc2e698187dc01da416a52dfa2d685e2a57d04e9e580447df0" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_codegen" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2238f147295746f1fee4cf7dcdee6378c94e61fbf7b9f9f4bb2a7f918530801b" +dependencies = [ + "blake2", + "derive_more 1.0.0", + "either", + "heck", + "impl-serde", + "ink_ir", + "ink_primitives", + "itertools 0.12.1", + "parity-scale-codec", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn 2.0.90", +] + +[[package]] +name = "ink_engine" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273f2aa983d04a6476d3c5ac76ddbef07555664b88f923996e7465e261dda48" +dependencies = [ + "blake2", + "derive_more 1.0.0", + "ink_primitives", + "pallet-contracts-uapi", + "parity-scale-codec", + "secp256k1", + "sha2 0.10.8", + "sha3", +] + +[[package]] +name = "ink_env" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9ee6089a1836c2e92d00be97d42308b7fb2c2b51ff6150b1130166a58107092" +dependencies = [ + "blake2", + "cfg-if", + "const_env", + "derive_more 1.0.0", + "ink_allocator", + "ink_engine", + "ink_prelude", + "ink_primitives", + "ink_storage_traits", + "num-traits", + "pallet-contracts-uapi", + "parity-scale-codec", + "paste", + "rlibc", + "scale-decode", + "scale-encode", + "scale-info", + "schnorrkel", + "secp256k1", + "sha2 0.10.8", + "sha3", + "staging-xcm", + "static_assertions", +] + +[[package]] +name = "ink_ir" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e201688fb27ff97496a4231a393dd4befcc5a9c092d6bf231f0f5d409ef44f34" +dependencies = [ + "blake2", + "either", + "impl-serde", + "ink_prelude", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "ink_macro" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce9465553d3066a8e28bd94a94880289084c4ff12f1852312553e902fa1ffdd" +dependencies = [ + "ink_codegen", + "ink_ir", + "ink_primitives", + "parity-scale-codec", + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + +[[package]] +name = "ink_metadata" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27135c651274087ba0578d2c07866c31d8dd481ae8de5bb7295fe3931491aa80" +dependencies = [ + "derive_more 1.0.0", + "impl-serde", + "ink_prelude", + "ink_primitives", + "linkme", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", +] + +[[package]] +name = "ink_prelude" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b29c9b7f686f4305f523bca5e2ae6f22a09531ec2bf0a9498cdc877959f70ad0" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_primitives" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a530c1b352a53176ea718f3a65f15003e54e0474ec12353ea0e0e5bb60b25741" +dependencies = [ + "derive_more 1.0.0", + "ink_prelude", + "parity-scale-codec", + "scale-decode", + "scale-encode", + "scale-info", + "xxhash-rust", +] + +[[package]] +name = "ink_storage" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bed602a974481b194084b93957917f27e724c7561fd0de9b6f3c171590c839b" +dependencies = [ + "array-init", + "cfg-if", + "derive_more 1.0.0", + "ink_env", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage_traits", + "pallet-contracts-uapi", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "ink_storage_traits" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde9b3f4a1e355682e5d13fd5639e5da4d0a2029537292e05a4255ea1169663e" +dependencies = [ + "ink_metadata", + "ink_prelude", + "ink_primitives", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "serdect", + "sha2 0.10.8", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "linkme" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "566336154b9e58a4f055f6dd4cbab62c7dc0826ce3c0a04e63b2d2ecd784cdae" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edbe595006d355eaf9ae11db92707d4338cd2384d16866131cc1afdbdd35d8d9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memory-db" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +dependencies = [ + "hash-db", +] + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core", + "zeroize", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" +dependencies = [ + "adler2", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec", + "itoa", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "pallet-contracts-uapi" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7a51646d9ff1d91abd0186d2c074f0dfd3b1a2d55f08a229a2f2e4bc6d1e49" +dependencies = [ + "bitflags 1.3.2", + "paste", + "polkavm-derive", +] + +[[package]] +name = "parity-bip39" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" +dependencies = [ + "bitcoin_hashes", + "rand", + "rand_core", + "serde", + "unicode-normalization", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", + "password-hash", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "polkavm-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9428a5cfcc85c5d7b9fc4b6a18c4b802d0173d768182a51cc7751640f08b92" + +[[package]] +name = "polkavm-derive" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8c4bea6f3e11cd89bb18bcdddac10bd9a24015399bd1c485ad68a985a19606" +dependencies = [ + "polkavm-derive-impl-macro", +] + +[[package]] +name = "polkavm-derive-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" +dependencies = [ + "polkavm-common", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "polkavm-derive-impl-macro" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" +dependencies = [ + "polkavm-derive-impl", + "syn 2.0.90", +] + +[[package]] +name = "pop-api" +version = "0.0.0" +dependencies = [ + "ink", + "pop-primitives", + "sp-io", +] + +[[package]] +name = "pop-primitives" +version = "0.0.0" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +dependencies = [ + "proc-macro2", + "syn 2.0.90", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-serde", + "scale-info", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit 0.22.22", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + +[[package]] +name = "rlibc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scale-bits" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "662d10dcd57b1c2a3c41c9cf68f71fb09747ada1ea932ad961aca7e2ca28315f" +dependencies = [ + "parity-scale-codec", + "scale-type-resolver", +] + +[[package]] +name = "scale-decode" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc79ba56a1c742f5aeeed1f1801f3edf51f7e818f0a54582cac6f131364ea7b" +dependencies = [ + "derive_more 0.99.18", + "parity-scale-codec", + "scale-bits", + "scale-decode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-decode-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5398fdb3c7bea3cb419bac4983aadacae93fe1a7b5f693f4ebd98c3821aad7a5" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-encode" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628800925a33794fb5387781b883b5e14d130fece9af5a63613867b8de07c5c7" +dependencies = [ + "derive_more 0.99.18", + "parity-scale-codec", + "scale-encode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-encode-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a304e1af7cdfbe7a24e08b012721456cc8cecdedadc14b3d10513eada63233c" +dependencies = [ + "darling", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-info" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more 1.0.0", + "parity-scale-codec", + "scale-info-derive", + "schemars", + "serde", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "scale-type-resolver" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10b800069bfd43374e0f96f653e0d46882a2cb16d6d961ac43bea80f26c76843" +dependencies = [ + "smallvec", +] + +[[package]] +name = "schemars" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.90", +] + +[[package]] +name = "schnellru" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" +dependencies = [ + "ahash", + "cfg-if", + "hashbrown 0.13.2", +] + +[[package]] +name = "schnorrkel" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de18f6d8ba0aad7045f5feae07ec29899c1112584a38509a84ad7b04451eaa0" +dependencies = [ + "aead", + "arrayref", + "arrayvec", + "curve25519-dalek", + "getrandom_or_panic", + "merlin", + "rand_core", + "serde_bytes", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" + +[[package]] +name = "serde" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.216" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "sp-arithmetic" +version = "26.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46d0d0a4c591c421d3231ddd5e27d828618c24456d51445d21a1f79fcee97c23" +dependencies = [ + "docify", + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std", + "static_assertions", +] + +[[package]] +name = "sp-core" +version = "34.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c961a5e33fb2962fa775c044ceba43df9c6f917e2c35d63bfe23738468fa76a7" +dependencies = [ + "array-bytes", + "bitflags 1.3.2", + "blake2", + "bounded-collections", + "bs58", + "dyn-clonable", + "ed25519-zebra", + "futures", + "hash-db", + "hash256-std-hasher", + "impl-serde", + "itertools 0.11.0", + "k256", + "libsecp256k1", + "log", + "merlin", + "parity-bip39", + "parity-scale-codec", + "parking_lot", + "paste", + "primitive-types", + "rand", + "scale-info", + "schnorrkel", + "secp256k1", + "secrecy", + "serde", + "sp-crypto-hashing", + "sp-debug-derive", + "sp-externalities", + "sp-runtime-interface", + "sp-std", + "sp-storage", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tracing", + "w3f-bls", + "zeroize", +] + +[[package]] +name = "sp-crypto-hashing" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9927a7f81334ed5b8a98a4a978c81324d12bd9713ec76b5c68fd410174c5eb" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.7", + "sha2 0.10.8", + "sha3", + "twox-hash", +] + +[[package]] +name = "sp-debug-derive" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sp-externalities" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a904407d61cb94228c71b55a9d3708e9d6558991f9e83bd42bd91df37a159d30" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-storage", +] + +[[package]] +name = "sp-io" +version = "37.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5036cad2e48d41f5caf6785226c8be1a7db15bec14a9fd7aa6cca84f34cf689f" +dependencies = [ + "bytes", + "ed25519-dalek", + "libsecp256k1", + "log", + "parity-scale-codec", + "polkavm-derive", + "rustversion", + "secp256k1", + "sp-core", + "sp-crypto-hashing", + "sp-externalities", + "sp-keystore", + "sp-runtime-interface", + "sp-state-machine", + "sp-std", + "sp-tracing", + "sp-trie", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-keystore" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0248b4d784cb4a01472276928977121fa39d977a5bb24793b6b15e64b046df42" +dependencies = [ + "parity-scale-codec", + "parking_lot", + "sp-core", + "sp-externalities", +] + +[[package]] +name = "sp-panic-handler" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f5a17a0a11de029a8b811cb6e8b32ce7e02183cc04a3e965c383246798c416" +dependencies = [ + "backtrace", + "lazy_static", + "regex", +] + +[[package]] +name = "sp-runtime-interface" +version = "28.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985eb981f40c689c6a0012c937b68ed58dabb4341d06f2dfe4dfd5ed72fa4017" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "polkavm-derive", + "primitive-types", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0195f32c628fee3ce1dfbbf2e7e52a30ea85f3589da9fe62a8b816d70fc06294" +dependencies = [ + "Inflector", + "expander", + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sp-state-machine" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "211e528aa6e902261a343f7b40840aa3d66fe4ad3aadbd04a035f10baf96dbc5" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "parking_lot", + "rand", + "smallvec", + "sp-core", + "sp-externalities", + "sp-panic-handler", + "sp-trie", + "thiserror", + "tracing", + "trie-db", +] + +[[package]] +name = "sp-std" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8ee986414b0a9ad741776762f4083cd3a5128449b982a3919c4df36874834" + +[[package]] +name = "sp-storage" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99c82989b3a4979a7e1ad848aad9f5d0b4388f1f454cc131766526601ab9e8f8" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive", +] + +[[package]] +name = "sp-tracing" +version = "17.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf641a1d17268c8fcfdb8e0fa51a79c2d4222f4cfda5f3944dbdbc384dced8d5" +dependencies = [ + "parity-scale-codec", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sp-trie" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d717c0f465f5371569e6fdc25b6f32d47c15d6e4c92b3b779e1c9b18b951d" +dependencies = [ + "ahash", + "hash-db", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot", + "rand", + "scale-info", + "schnellru", + "sp-core", + "sp-externalities", + "thiserror", + "tracing", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-wasm-interface" +version = "21.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b066baa6d57951600b14ffe1243f54c47f9c23dd89c262e17ca00ae8dca58be9" +dependencies = [ + "anyhow", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", +] + +[[package]] +name = "sp-weights" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93cdaf72a1dad537bbb130ba4d47307ebe5170405280ed1aa31fa712718a400e" +dependencies = [ + "bounded-collections", + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-debug-derive", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "ss58-registry" +version = "1.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19409f13998e55816d1c728395af0b52ec066206341d939e22e7766df9b494b8" +dependencies = [ + "Inflector", + "num-format", + "proc-macro2", + "quote", + "serde", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "staging-xcm" +version = "11.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aded0292274ad473250c22ed3deaf2d9ed47d15786d700e9e83ab7c1cad2ad44" +dependencies = [ + "array-bytes", + "bounded-collections", + "derivative", + "environmental", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-weights", + "xcm-procedural", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "substrate-bip39" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca58ffd742f693dc13d69bdbb2e642ae239e0053f6aab3b104252892f856700a" +dependencies = [ + "hmac 0.12.1", + "pbkdf2", + "schnorrkel", + "sha2 0.10.8", + "zeroize", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.22", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.20", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "time", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "trie-db" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c992b4f40c234a074d48a757efeabb1a6be88af84c0c23f7ca158950cb0ae7f" +dependencies = [ + "hash-db", + "log", + "rustc-hex", + "smallvec", +] + +[[package]] +name = "trie-root" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +dependencies = [ + "hash-db", +] + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "digest 0.10.7", + "rand", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "w3f-bls" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a3028804c8bbae2a97a15b71ffc0e308c4b01a520994aafa77d56e94e19024" +dependencies = [ + "ark-bls12-377", + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-serialize-derive", + "arrayref", + "constcat", + "digest 0.10.7", + "rand", + "rand_chacha", + "rand_core", + "sha2 0.10.8", + "sha3", + "thiserror", + "zeroize", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "xcm-procedural" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4717a97970a9cda70d7db53cf50d2615c2f6f6b7c857445325b4a39ea7aa2cd" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "xxhash-rust" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] diff --git a/pop-api/src/v0/fungibles/errors.rs b/pop-api/src/v0/fungibles/errors.rs index 1df32d4e6..2a7b962cb 100644 --- a/pop-api/src/v0/fungibles/errors.rs +++ b/pop-api/src/v0/fungibles/errors.rs @@ -1,9 +1,7 @@ //! A set of errors for use in smart contracts that interact with the fungibles api. This includes //! errors compliant to standards. -use ink::{ - prelude::string::{String, ToString}, -}; +use ink::prelude::string::{String, ToString}; use super::*; @@ -118,6 +116,8 @@ impl From for Psp22Error { #[cfg(test)] mod tests { + use ink::scale::{Decode, Encode}; + use super::*; use crate::{ constants::{ASSETS, BALANCES}, @@ -129,7 +129,6 @@ mod tests { }, StatusCode, }; - use ink::scale::{Decode, Encode}; fn error_into_status_code(error: Error) -> StatusCode { let mut encoded_error = error.encode(); From f92bbb9a18120c0fc1138ee8aee131003a43a0a5 Mon Sep 17 00:00:00 2001 From: Tin Chung <56880684+chungquantin@users.noreply.github.com> Date: Wed, 15 Jan 2025 17:48:50 +0700 Subject: [PATCH 74/76] feat(nfts): add `CollectionApprovals` and `AccountBalance` storages, and general improvements (#387) Co-authored-by: Daan van der Plas <93204684+Daanvdplas@users.noreply.github.com> Co-authored-by: Frank Bell --- pallets/nfts/README.md | 6 + pallets/nfts/src/benchmarking.rs | 107 +- pallets/nfts/src/common_functions.rs | 155 +- pallets/nfts/src/features/approvals.rs | 215 ++- pallets/nfts/src/features/atomic_swap.rs | 16 +- pallets/nfts/src/features/buy_sell.rs | 2 +- .../src/features/create_delete_collection.rs | 6 + .../nfts/src/features/create_delete_item.rs | 30 +- pallets/nfts/src/features/transfer.rs | 17 + pallets/nfts/src/impl_nonfungibles.rs | 6 +- pallets/nfts/src/lib.rs | 290 +++- pallets/nfts/src/mock.rs | 2 + pallets/nfts/src/tests.rs | 1523 ++++++++++++++++- pallets/nfts/src/types.rs | 3 + pallets/nfts/src/weights.rs | 877 ++++++---- runtime/devnet/src/config/assets.rs | 31 + runtime/devnet/src/lib.rs | 1 + runtime/testnet/src/config/assets.rs | 31 + 18 files changed, 2897 insertions(+), 421 deletions(-) diff --git a/pallets/nfts/README.md b/pallets/nfts/README.md index 93ccf2949..dcd036285 100644 --- a/pallets/nfts/README.md +++ b/pallets/nfts/README.md @@ -51,7 +51,9 @@ The NFTs pallet in Substrate is designed to make the following possible: * `transfer`: Send an item to a new owner. * `redeposit`: Update the deposit amount of an item, potentially freeing funds. * `approve_transfer`: Name a delegate who may authorize a transfer. +* `approve_collection_transfer`: Name a delegate who may authorize a transfer of all collection items owned by the account. * `cancel_approval`: Revert the effects of a previous `approve_transfer`. +* `cancel_collection_approval`: Revert the effects of a previous `approve_collection_transfer`. * `approve_item_attributes`: Name a delegate who may change item's attributes within a namespace. * `cancel_item_attributes_approval`: Revert the effects of a previous `approve_item_attributes`. * `set_price`: Set the price for an item. @@ -70,6 +72,7 @@ The NFTs pallet in Substrate is designed to make the following possible: * `lock_item_transfer`: Prevent an individual item from being transferred. * `unlock_item_transfer`: Revert the effects of a previous `lock_item_transfer`. * `clear_all_transfer_approvals`: Clears all transfer approvals set by calling the `approve_transfer`. +* `clear_collection_approvals`: Clears collection approvals set by calling the `approve_collection_transfer`. * `lock_collection`: Prevent all items within a collection from being transferred (making them all `soul bound`). * `lock_item_properties`: Lock item's metadata or attributes. * `transfer_ownership`: Alter the owner of a collection, moving all associated deposits. (Ownership of individual items @@ -95,6 +98,9 @@ The NFTs pallet in Substrate is designed to make the following possible: * `force_collection_owner`: Change collection's owner. * `force_collection_config`: Change collection's config. * `force_set_attribute`: Set an attribute. +* `force_approve_collection_transfer`: Name a delegate who may authorize a transfer of all collection items owned by the specified account. +* `force_cancel_collection_approval`: Revert the effects of a previous `approve_collection_transfer`. +* `force_clear_collection_approvals`: Revert the effects of all previous `approve_collection_transfer` calls for the collection. Please refer to the [`Call`](https://paritytech.github.io/substrate/master/pallet_nfts/pallet/enum.Call.html) enum and its associated variants for documentation on each function. diff --git a/pallets/nfts/src/benchmarking.rs b/pallets/nfts/src/benchmarking.rs index bc25602c5..4b680f606 100644 --- a/pallets/nfts/src/benchmarking.rs +++ b/pallets/nfts/src/benchmarking.rs @@ -274,6 +274,7 @@ benchmarks_instance_pallet! { mint { let (collection, caller, caller_lookup) = create_collection::(); let item = T::Helper::item(0); + T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance() + T::CollectionDeposit::get() + T::CollectionBalanceDeposit::get()); }: _(SystemOrigin::Signed(caller.clone()), collection, item, caller_lookup, None) verify { assert_last_event::(Event::Issued { collection, item, owner: caller }.into()); @@ -282,6 +283,7 @@ benchmarks_instance_pallet! { force_mint { let (collection, caller, caller_lookup) = create_collection::(); let item = T::Helper::item(0); + T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance() + T::CollectionDeposit::get() + T::CollectionBalanceDeposit::get()); }: _(SystemOrigin::Signed(caller.clone()), collection, item, caller_lookup, default_item_config()) verify { assert_last_event::(Event::Issued { collection, item, owner: caller }.into()); @@ -296,13 +298,15 @@ benchmarks_instance_pallet! { } transfer { - let (collection, caller, _) = create_collection::(); - let (item, ..) = mint_item::(0); - + let (collection, ..) = create_collection::(); + let (item, caller, _) = mint_item::(0); + let delegate: T::AccountId = account("delegate", 0, SEED); + let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let target: T::AccountId = account("target", 0, SEED); let target_lookup = T::Lookup::unlookup(target.clone()); - T::Currency::make_free_balance_be(&target, T::Currency::minimum_balance()); - }: _(SystemOrigin::Signed(caller.clone()), collection, item, target_lookup) + let origin = SystemOrigin::Signed(caller.clone()).into(); + Nfts::::approve_transfer(origin, collection, item, delegate_lookup, None)?; + }: _(SystemOrigin::Signed(delegate), collection, item, target_lookup) verify { assert_last_event::(Event::Transferred { collection, item, from: caller, to: target }.into()); } @@ -578,7 +582,7 @@ benchmarks_instance_pallet! { let deadline = BlockNumberFor::::max_value(); }: _(SystemOrigin::Signed(caller.clone()), collection, item, delegate_lookup, Some(deadline)) verify { - assert_last_event::(Event::TransferApproved { collection, item, owner: caller, delegate, deadline: Some(deadline) }.into()); + assert_last_event::(Event::TransferApproved { collection, item: Some(item), owner: caller, delegate, deadline: Some(deadline) }.into()); } cancel_approval { @@ -591,7 +595,7 @@ benchmarks_instance_pallet! { Nfts::::approve_transfer(origin, collection, item, delegate_lookup.clone(), Some(deadline))?; }: _(SystemOrigin::Signed(caller.clone()), collection, item, delegate_lookup) verify { - assert_last_event::(Event::ApprovalCancelled { collection, item, owner: caller, delegate }.into()); + assert_last_event::(Event::ApprovalCancelled { collection, item: Some(item), owner: caller, delegate }.into()); } clear_all_transfer_approvals { @@ -667,7 +671,7 @@ benchmarks_instance_pallet! { let price = ItemPrice::::from(0u32); let origin = SystemOrigin::Signed(seller.clone()).into(); Nfts::::set_price(origin, collection, item, Some(price), Some(buyer_lookup))?; - T::Currency::make_free_balance_be(&buyer, DepositBalanceOf::::max_value()); + T::Currency::make_free_balance_be(&buyer, T::Currency::minimum_balance() + price + T::CollectionBalanceDeposit::get()); }: _(SystemOrigin::Signed(buyer.clone()), collection, item, price) verify { assert_last_event::(Event::ItemBought { @@ -757,7 +761,7 @@ benchmarks_instance_pallet! { let duration = T::MaxDeadlineDuration::get(); let target: T::AccountId = account("target", 0, SEED); let target_lookup = T::Lookup::unlookup(target.clone()); - T::Currency::make_free_balance_be(&target, T::Currency::minimum_balance()); + T::Currency::make_free_balance_be(&target, T::Currency::minimum_balance() + T::CollectionBalanceDeposit::get()); let origin = SystemOrigin::Signed(caller.clone()); frame_system::Pallet::::set_block_number(One::one()); Nfts::::transfer(origin.clone().into(), collection, item2, target_lookup)?; @@ -876,5 +880,90 @@ benchmarks_instance_pallet! { ); } + approve_collection_transfer { + let (collection, caller, _) = create_collection::(); + mint_item::(0); + let delegate: T::AccountId = account("delegate", 0, SEED); + let delegate_lookup = T::Lookup::unlookup(delegate.clone()); + let deadline = BlockNumberFor::::max_value(); + }: _(SystemOrigin::Signed(caller.clone()), collection, delegate_lookup, Some(deadline)) + verify { + assert_last_event::(Event::TransferApproved { collection, item: None, owner: caller, delegate, deadline: Some(deadline) }.into()); + } + + force_approve_collection_transfer { + let (collection, caller, caller_lookup) = create_collection::(); + mint_item::(0); + let delegate: T::AccountId = account("delegate", 0, SEED); + let delegate_lookup = T::Lookup::unlookup(delegate.clone()); + let deadline = BlockNumberFor::::max_value(); + }: _(SystemOrigin::Root, caller_lookup, collection, delegate_lookup, Some(deadline)) + verify { + assert_last_event::(Event::TransferApproved { collection, item: None, owner: caller, delegate, deadline: Some(deadline) }.into()); + } + + cancel_collection_approval { + let (collection, caller, _) = create_collection::(); + mint_item::(0); + let delegate: T::AccountId = account("delegate", 0, SEED); + let delegate_lookup = T::Lookup::unlookup(delegate.clone()); + let origin = SystemOrigin::Signed(caller.clone()).into(); + let deadline = BlockNumberFor::::max_value(); + Nfts::::approve_collection_transfer(origin, collection, delegate_lookup.clone(), Some(deadline))?; + }: _(SystemOrigin::Signed(caller.clone()), collection, delegate_lookup) + verify { + assert_last_event::(Event::ApprovalCancelled { collection, item: None, owner: caller, delegate }.into()); + } + + force_cancel_collection_approval { + let (collection, caller, caller_lookup) = create_collection::(); + mint_item::(0); + let delegate: T::AccountId = account("delegate", 0, SEED); + let delegate_lookup = T::Lookup::unlookup(delegate.clone()); + let deadline = BlockNumberFor::::max_value(); + Nfts::::approve_collection_transfer(SystemOrigin::Signed(caller.clone()).into(), collection, delegate_lookup.clone(), Some(deadline))?; + }: _(SystemOrigin::Root, caller_lookup, collection, delegate_lookup) + verify { + assert_last_event::(Event::ApprovalCancelled { collection, item: None, owner: caller, delegate }.into()); + } + + clear_collection_approvals { + let n in 1 .. 1_000; + let (collection, caller, _) = create_collection::(); + mint_item::(0); + for i in 0 .. n { + let delegate: T::AccountId = account("delegate", i, SEED); + Nfts::::approve_collection_transfer( + SystemOrigin::Signed(caller.clone()).into(), + collection, + T::Lookup::unlookup(delegate), + Some(BlockNumberFor::::max_value()), + )?; + } + }: _(SystemOrigin::Signed(caller.clone()), collection, n) + verify { + assert_last_event::(Event::ApprovalsCancelled {collection, owner: caller.clone(), approvals: n}.into()); + assert!(CollectionApprovals::::iter_prefix((collection, caller,)).take(1).next().is_none()); + } + + force_clear_collection_approvals { + let n in 1 .. 1_000; + let (collection, caller, caller_lookup) = create_collection::(); + mint_item::(0); + for i in 0 .. n { + let delegate: T::AccountId = account("delegate", i, SEED); + Nfts::::approve_collection_transfer( + SystemOrigin::Signed(caller.clone()).into(), + collection, + T::Lookup::unlookup(delegate), + Some(BlockNumberFor::::max_value()), + )?; + } + }: _(SystemOrigin::Root, caller_lookup, collection, n) + verify { + assert_last_event::(Event::ApprovalsCancelled {collection, owner: caller.clone(), approvals: n}.into()); + assert!(CollectionApprovals::::iter_prefix((collection, caller,)).take(1).next().is_none()); + } + impl_benchmark_test_suite!(Nfts, crate::mock::new_test_ext(), crate::mock::Test); } diff --git a/pallets/nfts/src/common_functions.rs b/pallets/nfts/src/common_functions.rs index f9224046f..f27a90290 100644 --- a/pallets/nfts/src/common_functions.rs +++ b/pallets/nfts/src/common_functions.rs @@ -19,21 +19,44 @@ use alloc::vec::Vec; -use frame_support::pallet_prelude::*; +use frame_support::{pallet_prelude::*, sp_runtime::ArithmeticError}; use crate::*; impl, I: 'static> Pallet { /// Get the owner of the item, if the item exists. + /// + /// - `collection`: The identifier of the collection. + /// - `item`: The identifier of the collection item. pub fn owner(collection: T::CollectionId, item: T::ItemId) -> Option { Item::::get(collection, item).map(|i| i.owner) } /// Get the owner of the collection, if the collection exists. + /// + /// - `collection`: The identifier of the collection. pub fn collection_owner(collection: T::CollectionId) -> Option { Collection::::get(collection).map(|i| i.owner) } + /// Get the total number of items in the collection, if the collection exists. + /// + /// - `collection`: The identifier of the collection. + pub fn collection_items(collection: T::CollectionId) -> Option { + Collection::::get(collection).map(|i| i.items) + } + + /// Get the metadata of the collection item. + /// + /// - `collection`: The identifier of the collection. + /// - `item`: The identifier of the collection item. + pub fn item_metadata( + collection: T::CollectionId, + item: T::ItemId, + ) -> Option> { + ItemMetadataOf::::get(collection, item).map(|metadata| metadata.data) + } + /// Validates the signature of the given data with the provided signer's account ID. /// /// # Errors @@ -69,6 +92,52 @@ impl, I: 'static> Pallet { Self::deposit_event(Event::NextCollectionIdIncremented { next_id }); } + /// Increment the number of items in the `collection` owned by the `owner`. If no entry exists + /// for the `owner` in `AccountBalance`, create a new record and reserve `deposit_amount` from + /// the `deposit_account`. + pub(crate) fn increment_account_balance( + collection: T::CollectionId, + owner: &T::AccountId, + (deposit_account, deposit_amount): (&T::AccountId, DepositBalanceOf), + ) -> DispatchResult { + AccountBalance::::mutate(collection, owner, |maybe_balance| -> DispatchResult { + match maybe_balance { + None => { + T::Currency::reserve(deposit_account, deposit_amount)?; + *maybe_balance = Some((1, (deposit_account.clone(), deposit_amount))); + }, + Some((balance, _deposit)) => { + balance.saturating_inc(); + }, + } + Ok(()) + }) + } + + /// Decrement the number of `collection` items owned by the `owner`. If the `owner`'s item + /// count reaches zero after the reduction, remove the `AccountBalance` record and unreserve + /// the deposited funds. + pub(crate) fn decrement_account_balance( + collection: T::CollectionId, + owner: &T::AccountId, + ) -> DispatchResult { + AccountBalance::::try_mutate_exists( + collection, + owner, + |maybe_balance| -> DispatchResult { + let (balance, (deposit_account, deposit_amount)) = + maybe_balance.as_mut().ok_or(Error::::NoItemOwned)?; + + *balance = balance.checked_sub(1).ok_or(ArithmeticError::Underflow)?; + if balance.is_zero() { + T::Currency::unreserve(deposit_account, *deposit_amount); + *maybe_balance = None; + } + Ok(()) + }, + ) + } + #[allow(missing_docs)] #[cfg(any(test, feature = "runtime-benchmarks"))] pub fn set_next_id(id: T::CollectionId) { @@ -82,3 +151,87 @@ impl, I: 'static> Pallet { .expect("Failed to get next collection ID") } } + +#[cfg(test)] +mod tests { + use crate::{mock::*, tests::*, Currency, Error, ReservableCurrency}; + + #[test] + fn increment_account_balance_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let deposit_account = account(1); + let deposit_amount = balance_deposit(); + let owner = account(2); + assert_noop!( + Nfts::increment_account_balance( + collection_id, + &owner, + (&deposit_account, deposit_amount) + ), + BalancesError::::InsufficientBalance + ); + Balances::make_free_balance_be(&deposit_account, 100); + // Initialize `AccountBalance` and increase the collection item count for the new + // account. + assert_ok!(Nfts::increment_account_balance( + collection_id, + &owner, + (&deposit_account, deposit_amount) + )); + assert_eq!(Balances::reserved_balance(&deposit_account), deposit_amount); + assert_eq!( + AccountBalance::get(collection_id, &owner), + Some((1, (deposit_account.clone(), deposit_amount))) + ); + // Increment the balance of a non-zero balance account. No additional reserves. + assert_ok!(Nfts::increment_account_balance( + collection_id, + &owner, + (&deposit_account, deposit_amount) + )); + assert_eq!(Balances::reserved_balance(&deposit_account), deposit_amount); + assert_eq!( + AccountBalance::get(collection_id, &owner), + Some((2, (deposit_account.clone(), deposit_amount))) + ); + }); + } + + #[test] + fn decrement_account_balance_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let balance = 2u32; + let deposit_account = account(1); + let deposit_amount = balance_deposit(); + let owner = account(2); + + Balances::make_free_balance_be(&deposit_account, 100); + // Decrement non-existing `AccountBalance` record. + assert_noop!( + Nfts::decrement_account_balance(collection_id, &deposit_account), + Error::::NoItemOwned + ); + // Set account balance and reserve `DepositBalance`. + AccountBalance::insert( + collection_id, + &owner, + (&balance, (&deposit_account, deposit_amount)), + ); + Balances::reserve(&deposit_account, deposit_amount).expect("should work"); + // Successfully decrement the value of the `AccountBalance` entry. + assert_ok!(Nfts::decrement_account_balance(collection_id, &owner)); + assert_eq!( + AccountBalance::get(collection_id, &owner), + Some((balance - 1, (deposit_account.clone(), deposit_amount))) + ); + assert_eq!(Balances::reserved_balance(&deposit_account), deposit_amount); + // `AccountBalance` record is deleted, and the depositor's funds are unreserved if + // the `AccountBalance` value reaches zero after decrementing. + assert_ok!(Nfts::decrement_account_balance(collection_id, &owner)); + assert_eq!(Balances::reserved_balance(&deposit_account), 0); + assert!(!AccountBalance::contains_key(collection_id, &owner)); + }); + } +} diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index 5ffaeea72..f7db22a74 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -20,6 +20,7 @@ //! to have the functionality defined in this module. use frame_support::pallet_prelude::*; +use frame_system::pallet_prelude::BlockNumberFor; use crate::*; @@ -47,7 +48,7 @@ impl, I: 'static> Pallet { collection: T::CollectionId, item: T::ItemId, delegate: T::AccountId, - maybe_deadline: Option>, + maybe_deadline: Option>, ) -> DispatchResult { ensure!( Self::is_pallet_feature_enabled(PalletFeature::Approvals), @@ -65,8 +66,8 @@ impl, I: 'static> Pallet { ensure!(check_origin == details.owner, Error::::NoPermission); } - let now = frame_system::Pallet::::block_number(); - let deadline = maybe_deadline.map(|d| d.saturating_add(now)); + let deadline = + maybe_deadline.map(|d| d.saturating_add(frame_system::Pallet::::block_number())); details .approvals @@ -76,12 +77,11 @@ impl, I: 'static> Pallet { Self::deposit_event(Event::TransferApproved { collection, - item, + item: Some(item), owner: details.owner, delegate, deadline, }); - Ok(()) } @@ -122,12 +122,19 @@ impl, I: 'static> Pallet { } } + // Cannot revoke approval for a specific collection item if the delegate has + // permission to transfer all collection items owned by the origin. + ensure!( + !CollectionApprovals::::contains_key((collection, &details.owner, &delegate)), + Error::::DelegateApprovalConflict + ); + details.approvals.remove(&delegate); Item::::insert(collection, item, &details); Self::deposit_event(Event::ApprovalCancelled { collection, - item, + item: Some(item), owner: details.owner, delegate, }); @@ -146,7 +153,7 @@ impl, I: 'static> Pallet { /// - `maybe_check_origin`: The optional account that is required to be the owner of the item, /// granting permission to clear all transfer approvals. If `None`, no permission check is /// performed. - /// - `collection`: The collection ID containing the item. + /// - `collection`: The identifier of the collection. /// - `item`: The item ID for which transfer approvals will be cleared. pub(crate) fn do_clear_all_transfer_approvals( maybe_check_origin: Option, @@ -157,6 +164,15 @@ impl, I: 'static> Pallet { Item::::get(collection, item).ok_or(Error::::UnknownCollection)?; if let Some(check_origin) = maybe_check_origin { + // Cannot revoke approvals for individual items when there are existing approvals to + // transfer all items in the collection owned by the origin. + ensure!( + CollectionApprovals::::iter_prefix((collection, &check_origin)) + .take(1) + .next() + .is_none(), + Error::::DelegateApprovalConflict + ); ensure!(check_origin == details.owner, Error::::NoPermission); } @@ -171,4 +187,189 @@ impl, I: 'static> Pallet { Ok(()) } + + /// Approves the transfer of all collection items of `owner` to a `delegate`. + /// + /// This function is used to approve the transfer of all (current and future) collection items + /// of `owner` to a `delegate`. The `delegate` account will be allowed to take control of the + /// items. Optionally, a `deadline` can be specified to set a time limit for the approval. The + /// `deadline` is expressed in block numbers and is added to the current block number to + /// determine the absolute deadline for the approval. After approving the transfer, the + /// function emits the `TransferApproved` event. + /// + /// This function reserves the necessary deposit from the owner account. If an approval already + /// exists, additional funds are reserved only if the updated deposit exceeds the currently + /// reserved amount. The existing approval's deadline is also updated. + /// + /// - `owner`: The owner of the collection items. + /// - `collection`: The identifier of the collection. + /// - `delegate`: The account that will be approved to take control of the collection items. + /// - `deposit`: The reserved amount for granting a collection approval. + /// - `maybe_deadline`: The optional deadline (in block numbers) specifying the time limit for + /// the approval. + pub(crate) fn do_approve_collection_transfer( + owner: T::AccountId, + collection: T::CollectionId, + delegate: T::AccountId, + deposit: DepositBalanceOf, + maybe_deadline: Option>, + ) -> DispatchResult { + ensure!( + Self::is_pallet_feature_enabled(PalletFeature::Approvals), + Error::::MethodDisabled + ); + ensure!( + AccountBalance::::get(collection, &owner) + .filter(|(balance, _)| !balance.is_zero()) + .is_some(), + Error::::NoItemOwned + ); + + let collection_config = Self::get_collection_config(&collection)?; + ensure!( + collection_config.is_setting_enabled(CollectionSetting::TransferableItems), + Error::::ItemsNonTransferable + ); + let deadline = + maybe_deadline.map(|d| d.saturating_add(frame_system::Pallet::::block_number())); + + CollectionApprovals::::try_mutate_exists( + (&collection, &owner, &delegate), + |maybe_approval| -> DispatchResult { + let current_deposit = + maybe_approval.map(|(_, deposit)| deposit).unwrap_or_default(); + T::Currency::reserve(&owner, deposit.saturating_sub(current_deposit))?; + *maybe_approval = Some((deadline, deposit)); + Ok(()) + }, + )?; + + Self::deposit_event(Event::TransferApproved { + collection, + item: None, + owner, + delegate, + deadline, + }); + + Ok(()) + } + + /// Cancels the transfer of all `collection` items of `owner` to a `delegate`. + /// + /// This function is used to cancel the approval for the transfer of the collection items of + /// `owner` to a `delegate`. After canceling the approval, the deposit is returned to the + /// `owner` account and the `ApprovalCancelled` event is emitted. + /// + /// - `owner`: The owner of the collection items. + /// - `collection`: The identifier of the collection. + /// - `delegate`: The account that had permission to transfer collection items. + pub(crate) fn do_cancel_collection_approval( + owner: T::AccountId, + collection: T::CollectionId, + delegate: T::AccountId, + ) -> DispatchResult { + let (_, deposit) = CollectionApprovals::::take((&collection, &owner, &delegate)) + .ok_or(Error::::NotDelegate)?; + + T::Currency::unreserve(&owner, deposit); + + Self::deposit_event(Event::ApprovalCancelled { collection, owner, item: None, delegate }); + + Ok(()) + } + + /// Clears all collection approvals. + /// + /// This function is used to clear `limit` collection approvals for the + /// collection items of `owner`. After clearing the approvals, the deposit of each collection + /// approval is returned to the `owner` account and the `ApprovalsCancelled` event is + /// emitted. + /// + /// - `owner`: The owner of the collection items. + /// - `collection`: The identifier of the collection. + /// - `limit`: The amount of collection approvals that will be cleared. + pub(crate) fn do_clear_collection_approvals( + owner: T::AccountId, + collection: T::CollectionId, + limit: u32, + ) -> Result { + if limit == 0 { + return Ok(0); + } + let mut removed_approvals: u32 = 0; + let mut deposits: BalanceOf = Zero::zero(); + // Iterate and remove each collection approval, returning the deposit back to the `owner`. + for (_, (_, deposit)) in + CollectionApprovals::::drain_prefix((collection, &owner)).take(limit as usize) + { + deposits.saturating_accrue(deposit); + removed_approvals.saturating_inc(); + } + + T::Currency::unreserve(&owner, deposits); + Self::deposit_event(Event::ApprovalsCancelled { + collection, + owner, + approvals: removed_approvals, + }); + Ok(removed_approvals) + } + + /// Checks whether the `delegate` has permission to transfer collection items of `owner`. + /// + /// - `collection`: The identifier of the collection. + /// - `owner`: The owner of the collection items. + /// - `delegate`: The account to check for permission to transfer collection items of `owner`. + fn check_collection_approval_permission( + collection: &T::CollectionId, + owner: &T::AccountId, + delegate: &T::AccountId, + ) -> DispatchResult { + let (maybe_deadline, _) = + CollectionApprovals::::get((&collection, &owner, &delegate)) + .ok_or(Error::::NoPermission)?; + if let Some(deadline) = maybe_deadline { + let block_number = frame_system::Pallet::::block_number(); + ensure!(block_number <= deadline, Error::::ApprovalExpired); + } + Ok(()) + } + + /// Checks whether the `delegate` has permission to transfer `owner`'s collection item(s). + /// If the `delegate` has permission to transfer all `owner`'s collection items, they can + /// transfer any item without needing explicit approval for each individual item. + /// + /// - `collection`: The identifier of the collection. + /// - `maybe_item`: The optional item of the collection that the delegated account has + /// permission to transfer. If not provided, permission to transfer all `owner`'s collection + /// items will be checked. + /// - `owner`: The owner of the specified collection item. + /// - `delegate`: The account to check for permission to transfer collection item(s) from the + /// owner. + pub fn check_approval_permission( + collection: &T::CollectionId, + maybe_item: &Option, + owner: &T::AccountId, + delegate: &T::AccountId, + ) -> DispatchResult { + // Check if `delegate` has permission to transfer `owner`'s collection items. + let Err(error) = Self::check_collection_approval_permission(collection, owner, delegate) + else { + return Ok(()); + }; + + // Check if a `delegate` has permission to transfer the given collection item. + if let Some(item) = maybe_item { + let details = Item::::get(collection, item).ok_or(Error::::UnknownItem)?; + let maybe_deadline = + details.approvals.get(delegate).ok_or(Error::::NoPermission)?; + if let Some(deadline) = maybe_deadline { + let block_number = frame_system::Pallet::::block_number(); + ensure!(block_number <= *deadline, Error::::ApprovalExpired); + } + return Ok(()); + }; + Err(error) + } } diff --git a/pallets/nfts/src/features/atomic_swap.rs b/pallets/nfts/src/features/atomic_swap.rs index 6c15f15ae..1ffd6dce4 100644 --- a/pallets/nfts/src/features/atomic_swap.rs +++ b/pallets/nfts/src/features/atomic_swap.rs @@ -77,8 +77,7 @@ impl, I: 'static> Pallet { ), }; - let now = frame_system::Pallet::::block_number(); - let deadline = duration.saturating_add(now); + let deadline = duration.saturating_add(frame_system::Pallet::::block_number()); PendingSwapOf::::insert( offered_collection_id, @@ -210,13 +209,20 @@ impl, I: 'static> Pallet { } // This also removes the swap. - Self::do_transfer(send_collection_id, send_item_id, receive_item.owner.clone(), |_, _| { - Ok(()) - })?; + Self::do_transfer( + send_collection_id, + send_item_id, + receive_item.owner.clone(), + Some(&receive_item.owner), + |_, _| Ok(()), + )?; + // Owner of `send_item` is responsible for the deposit if the collection balance + // went to zero due to the previous transfer. Self::do_transfer( receive_collection_id, receive_item_id, send_item.owner.clone(), + Some(&send_item.owner), |_, _| Ok(()), )?; diff --git a/pallets/nfts/src/features/buy_sell.rs b/pallets/nfts/src/features/buy_sell.rs index 476053ee0..2b4d2967c 100644 --- a/pallets/nfts/src/features/buy_sell.rs +++ b/pallets/nfts/src/features/buy_sell.rs @@ -158,7 +158,7 @@ impl, I: 'static> Pallet { let old_owner = details.owner.clone(); - Self::do_transfer(collection, item, buyer.clone(), |_, _| Ok(()))?; + Self::do_transfer(collection, item, buyer.clone(), Some(&buyer), |_, _| Ok(()))?; Self::deposit_event(Event::ItemBought { collection, diff --git a/pallets/nfts/src/features/create_delete_collection.rs b/pallets/nfts/src/features/create_delete_collection.rs index 60286d701..4a8bed33c 100644 --- a/pallets/nfts/src/features/create_delete_collection.rs +++ b/pallets/nfts/src/features/create_delete_collection.rs @@ -96,6 +96,8 @@ impl, I: 'static> Pallet { /// ([`NoPermission`](crate::Error::NoPermission)). /// - If the collection is not empty (contains items) /// ([`CollectionNotEmpty`](crate::Error::CollectionNotEmpty)). + /// - If there are collection approvals + /// ([`CollectionApprovalsExist`](crate::Error::CollectionApprovalsExist)). /// - If the `witness` does not match the actual collection details /// ([`BadWitness`](crate::Error::BadWitness)). pub fn do_destroy_collection( @@ -110,6 +112,10 @@ impl, I: 'static> Pallet { ensure!(collection_details.owner == check_owner, Error::::NoPermission); } ensure!(collection_details.items == 0, Error::::CollectionNotEmpty); + ensure!( + CollectionApprovals::::iter_prefix((collection,)).take(1).next().is_none(), + Error::::CollectionApprovalsExist + ); ensure!(collection_details.attributes == witness.attributes, Error::::BadWitness); ensure!( collection_details.item_metadatas == witness.item_metadatas, diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index 7a69de9ea..5c687d427 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -69,15 +69,19 @@ impl, I: 'static> Pallet { collection_details.items.saturating_inc(); let collection_config = Self::get_collection_config(&collection)?; - let deposit_amount = - match collection_config.is_setting_enabled(CollectionSetting::DepositRequired) { - true => T::ItemDeposit::get(), - false => Zero::zero(), - }; - let deposit_account = match maybe_depositor { - None => collection_details.owner.clone(), - Some(depositor) => depositor, - }; + let deposit_required = + collection_config.is_setting_enabled(CollectionSetting::DepositRequired); + let deposit_account = + maybe_depositor.unwrap_or_else(|| collection_details.owner.clone()); + + let balance_deposit = deposit_required + .then_some(T::CollectionBalanceDeposit::get()) + .unwrap_or_default(); + Self::increment_account_balance( + collection, + &mint_to, + (&deposit_account, balance_deposit), + )?; let item_owner = mint_to.clone(); Account::::insert((&item_owner, &collection, &item), ()); @@ -89,9 +93,11 @@ impl, I: 'static> Pallet { collection_details.item_configs.saturating_inc(); } - T::Currency::reserve(&deposit_account, deposit_amount)?; + let item_deposit = + deposit_required.then_some(T::ItemDeposit::get()).unwrap_or_default(); + T::Currency::reserve(&deposit_account, item_deposit)?; - let deposit = ItemDeposit { account: deposit_account, amount: deposit_amount }; + let deposit = ItemDeposit { account: deposit_account, amount: item_deposit }; let details = ItemDetails { owner: item_owner, approvals: ApprovalsOf::::default(), @@ -260,6 +266,8 @@ impl, I: 'static> Pallet { PendingSwapOf::::remove(collection, item); ItemAttributesApprovalsOf::::remove(collection, item); + Self::decrement_account_balance(collection, &owner)?; + if remove_config { ItemConfigOf::::remove(collection, item); } diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index e0ae770ab..9f5dc77b4 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -28,6 +28,8 @@ impl, I: 'static> Pallet { /// - `collection`: The ID of the collection to which the NFT belongs. /// - `item`: The ID of the NFT to transfer. /// - `dest`: The destination account to which the NFT will be transferred. + /// - `depositor`: The account reserving the `CollectionBalanceDeposit` from if `dest` holds no + /// items in the collection. /// - `with_details`: A closure that provides access to the collection and item details, /// allowing customization of the transfer process. /// @@ -48,6 +50,7 @@ impl, I: 'static> Pallet { collection: T::CollectionId, item: T::ItemId, dest: T::AccountId, + depositor: Option<&T::AccountId>, with_details: impl FnOnce( &CollectionDetailsFor, &mut ItemDetailsFor, @@ -86,6 +89,20 @@ impl, I: 'static> Pallet { // Perform the transfer with custom details using the provided closure. with_details(&collection_details, &mut details)?; + // Update account balance of the owner. + Self::decrement_account_balance(collection, &details.owner)?; + + let deposit_amount = collection_config + .is_setting_enabled(CollectionSetting::DepositRequired) + .then_some(T::CollectionBalanceDeposit::get()) + .unwrap_or_default(); + // Reserve `CollectionBalanceDeposit` from the depositor if provided. Otherwise, reserve + // from the item's owner. + let deposit_account = depositor.unwrap_or(&details.owner); + + // Update account balance of the destination account. + Self::increment_account_balance(collection, &dest, (deposit_account, deposit_amount))?; + // Update account ownership information. Account::::remove((&details.owner, &collection, &item)); Account::::insert((&dest, &collection, &item), ()); diff --git a/pallets/nfts/src/impl_nonfungibles.rs b/pallets/nfts/src/impl_nonfungibles.rs index b014e3ed4..e8fa4457a 100644 --- a/pallets/nfts/src/impl_nonfungibles.rs +++ b/pallets/nfts/src/impl_nonfungibles.rs @@ -411,7 +411,11 @@ impl, I: 'static> Transfer for Pallet { item: &Self::ItemId, destination: &T::AccountId, ) -> DispatchResult { - Self::do_transfer(*collection, *item, destination.clone(), |_, _| Ok(())) + // The item's owner pays for the deposit of `AccountBalance` if the `dest` holds no items + // in `collection`. If `dest` paid the deposit, a malicious actor could transfer NFTs to + // reserve involuntary deposits for `dest` . The deposit amount can be accounted for in the + // off chain price of the NFT. + Self::do_transfer(*collection, *item, destination.clone(), None, |_, _| Ok(())) } fn disable_transfer(collection: &Self::CollectionId, item: &Self::ItemId) -> DispatchResult { diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index 90d2a6224..8d9c77fad 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -56,9 +56,12 @@ use alloc::{boxed::Box, vec, vec::Vec}; use core::cmp::Ordering; use codec::{Decode, Encode}; -use frame_support::traits::{ - tokens::Locker, BalanceStatus::Reserved, Currency, EnsureOriginWithArg, Incrementable, - ReservableCurrency, +use frame_support::{ + dispatch::WithPostDispatchInfo, + traits::{ + tokens::Locker, BalanceStatus::Reserved, Currency, EnsureOriginWithArg, Incrementable, + ReservableCurrency, + }, }; use frame_system::Config as SystemConfig; pub use pallet::*; @@ -250,6 +253,18 @@ pub mod pallet { /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; + + /// The basic amount of funds that must be reserved for a collection approval. + // Key: `sizeof((CollectionId, AccountId, AccountId))` bytes. + // Value: `sizeof((Option, Balance))` bytes. + #[pallet::constant] + type CollectionApprovalDeposit: Get>; + + /// The basic amount of funds that must be reversed for an account's collection balance. + // Key: `sizeof((CollectionId, AccountId))` bytes. + // Value: `sizeof((u32, Some(AccountId, Balance)))` bytes. + #[pallet::constant] + type CollectionBalanceDeposit: Get>; } /// Details of a collection. @@ -418,6 +433,36 @@ pub mod pallet { OptionQuery, >; + /// Number of collection items owned by an account. + #[pallet::storage] + pub type AccountBalance, I: 'static = ()> = StorageDoubleMap< + _, + Blake2_128Concat, + T::CollectionId, + Blake2_128Concat, + T::AccountId, + // (Account's collection items, Deposit details). + (u32, AccountDepositOf), + >; + + /// Permission for a delegate to transfer all owner's collection items. + #[pallet::storage] + pub type CollectionApprovals, I: 'static = ()> = StorageNMap< + _, + ( + NMapKey, + NMapKey, // owner + NMapKey, // delegate + ), + ( + // The optional deadline for the approval. If specified, the approval is valid on or + // before the given block number. + Option>, + // The balance to be deposited. + DepositBalanceOf, + ), + >; + #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] #[allow(missing_docs)] @@ -461,24 +506,26 @@ pub mod pallet { admin: Option, freezer: Option, }, - /// An `item` of a `collection` has been approved by the `owner` for transfer by - /// a `delegate`. + /// A provided `item` of a `collection`, or if no `item` is provided, all items in the + /// `collection` owned by the `owner` have been approved by the `owner` for transfer by a + /// `delegate`. TransferApproved { collection: T::CollectionId, - item: T::ItemId, + item: Option, owner: T::AccountId, delegate: T::AccountId, deadline: Option>, }, - /// An approval for a `delegate` account to transfer the `item` of an item - /// `collection` was cancelled by its `owner`. + /// An approval for a `delegate` account to transfer a specific `item` in a `collection`, + /// or if no `item` is provided, all collection items owned by the `owner` have been + /// cancelled by the `owner`. ApprovalCancelled { collection: T::CollectionId, - item: T::ItemId, + item: Option, owner: T::AccountId, delegate: T::AccountId, }, - /// All approvals of an item got cancelled. + /// All approvals of an item were cancelled. AllApprovalsCancelled { collection: T::CollectionId, item: T::ItemId, owner: T::AccountId }, /// A `collection` has had its config changed by the `Force` origin. CollectionConfigChanged { collection: T::CollectionId }, @@ -599,13 +646,15 @@ pub mod pallet { attribute: PalletAttributes, value: BoundedVec, }, + /// Multiple approvals of a collection were cancelled. + ApprovalsCancelled { collection: T::CollectionId, owner: T::AccountId, approvals: u32 }, } #[pallet::error] pub enum Error { /// The signing account has no permission to do the operation. NoPermission, - /// The given item ID is unknown. + /// The given collection ID is unknown. UnknownCollection, /// The item ID has already been used for an item. AlreadyExists, @@ -623,8 +672,6 @@ pub mod pallet { NotDelegate, /// The delegate turned out to be different to what was expected. WrongDelegate, - /// No approval exists that would allow the transfer. - Unapproved, /// The named owner has not signed ownership acceptance of the collection. Unaccepted, /// The item is locked (non-transferable). @@ -693,6 +740,24 @@ pub mod pallet { CollectionNotEmpty, /// The witness data should be provided. WitnessRequired, + /// The account owns zero items in the collection. + NoItemOwned, + /// The collection has existing approvals. + CollectionApprovalsExist, + /// Collection and item approval conflicts. + DelegateApprovalConflict, + } + + #[pallet::hooks] + impl, I: 'static> Hooks> for Pallet { + #[cfg(any(feature = "std", test))] + fn integrity_test() { + use core::any::TypeId; + assert!( + TypeId::of::<>::ItemId>() != TypeId::of::() && + TypeId::of::<>::ItemId>() != TypeId::of::() + ); + } } #[pallet::call] @@ -792,7 +857,7 @@ pub mod pallet { /// The origin must conform to `ForceOrigin` or must be `Signed` and the sender must be the /// owner of the `collection`. /// - /// NOTE: The collection must have 0 items to be destroyed. + /// NOTE: The collection must have 0 items and 0 approvals to be destroyed. /// /// - `collection`: The identifier of the collection to be destroyed. /// - `witness`: Information on the items minted in the collection. This must be @@ -1033,14 +1098,18 @@ pub mod pallet { let origin = ensure_signed(origin)?; let dest = T::Lookup::lookup(dest)?; - Self::do_transfer(collection, item, dest, |_, details| { + // The item's owner pays for the deposit of `AccountBalance` if the `dest` holds no + // items in `collection`. A malicious actor could have a deposit reserved from `dest` + // without them knowing about the transfer. The deposit amount can be accounted for + // in the off chain price of the NFT. + Self::do_transfer(collection, item, dest, None, |_, details| { if details.owner != origin { - let deadline = - details.approvals.get(&origin).ok_or(Error::::NoPermission)?; - if let Some(d) = deadline { - let block_number = frame_system::Pallet::::block_number(); - ensure!(block_number <= *d, Error::::ApprovalExpired); - } + Self::check_approval_permission( + &collection, + &Some(item), + &details.owner, + &origin, + )?; } Ok(()) }) @@ -1289,7 +1358,7 @@ pub mod pallet { /// - `item`: The item to be approved for delegated transfer. /// - `delegate`: The account to delegate permission to transfer the item. /// - `maybe_deadline`: Optional deadline for the approval. Specified by providing the - /// number of blocks after which the approval will expire + /// number of blocks after which the approval will expire. /// /// Emits `TransferApproved` on success. /// @@ -1325,7 +1394,7 @@ pub mod pallet { /// Arguments: /// - `collection`: The collection of the item of whose approval will be cancelled. /// - `item`: The item of the collection of whose approval will be cancelled. - /// - `delegate`: The account that is going to loose their approval. + /// - `delegate`: The account that is going to lose their approval. /// /// Emits `ApprovalCancelled` on success. /// @@ -1938,6 +2007,181 @@ pub mod pallet { Self::validate_signature(&Encode::encode(&data), &signature, &signer)?; Self::do_set_attributes_pre_signed(origin, data, signer) } + + /// Approve collection items owned by the origin to be transferred by a delegated + /// third-party account. This function reserves the required deposit + /// `CollectionApprovalDeposit` from the `origin` account. + /// + /// Origin must be Signed. + /// + /// - `collection`: The collection of the items to be approved for delegated transfer. + /// - `delegate`: The account to delegate permission to transfer collection items owned by + /// the origin. + /// - `maybe_deadline`: Optional deadline for the approval. Specified by providing the + /// number of blocks after which the approval will expire + /// + /// Emits `TransferApproved` on success. + /// + /// Weight: `O(1)` + #[pallet::call_index(50)] + #[pallet::weight(T::WeightInfo::approve_collection_transfer())] + pub fn approve_collection_transfer( + origin: OriginFor, + collection: T::CollectionId, + delegate: AccountIdLookupOf, + maybe_deadline: Option>, + ) -> DispatchResult { + let origin = ensure_signed(origin)?; + let delegate = T::Lookup::lookup(delegate)?; + Self::do_approve_collection_transfer( + origin, + collection, + delegate, + T::CollectionApprovalDeposit::get(), + maybe_deadline, + ) + } + + /// Force-approve collection items owned by the `owner` to be transferred by a delegated + /// third-party account. + /// + /// Origin must be the `ForceOrigin`. + /// + /// Any deposit is left alone. + /// + /// - `owner`: The owner of the collection items to be force-approved by the `origin`. + /// - `collection`: The collection of the items to be approved for delegated transfer. + /// - `delegate`: The account to delegate permission to transfer collection items owned by + /// the `owner`. + /// - `maybe_deadline`: Optional deadline for the approval. Specified by providing the + /// number of blocks after which the approval will expire. + /// + /// Emits `TransferApproved` on success. + /// + /// Weight: `O(1)` + #[pallet::call_index(51)] + #[pallet::weight(T::WeightInfo::force_approve_collection_transfer())] + pub fn force_approve_collection_transfer( + origin: OriginFor, + owner: AccountIdLookupOf, + collection: T::CollectionId, + delegate: AccountIdLookupOf, + maybe_deadline: Option>, + ) -> DispatchResult { + T::ForceOrigin::ensure_origin(origin)?; + let delegate = T::Lookup::lookup(delegate)?; + let owner = T::Lookup::lookup(owner)?; + Self::do_approve_collection_transfer( + owner, + collection, + delegate, + Zero::zero(), + maybe_deadline, + ) + } + + /// Cancel a collection approval. + /// + /// Origin must be Signed. + /// + /// Arguments: + /// - `collection`: The collection whose approval will be cancelled. + /// - `delegate`: The account that is going to lose their approval. + /// + /// Emits `ApprovalCancelled` on success. + /// + /// Weight: `O(1)` + #[pallet::call_index(52)] + #[pallet::weight(T::WeightInfo::cancel_collection_approval())] + pub fn cancel_collection_approval( + origin: OriginFor, + collection: T::CollectionId, + delegate: AccountIdLookupOf, + ) -> DispatchResult { + let origin = ensure_signed(origin)?; + let delegate = T::Lookup::lookup(delegate)?; + Self::do_cancel_collection_approval(origin, collection, delegate) + } + + /// Force-cancel a collection approval granted by `owner` account. + /// + /// Origin must be `ForceOrigin`. + /// + /// Arguments: + /// - `owner`: The owner of the approval to be force-cancelled by the `origin`. + /// - `collection`: The collection whose approval will be cancelled. + /// - `delegate`: The account that is going to lose their approval. + /// + /// Emits `ApprovalCancelled` on success. + /// + /// Weight: `O(1)` + #[pallet::call_index(53)] + #[pallet::weight(T::WeightInfo::force_cancel_collection_approval())] + pub fn force_cancel_collection_approval( + origin: OriginFor, + owner: AccountIdLookupOf, + collection: T::CollectionId, + delegate: AccountIdLookupOf, + ) -> DispatchResult { + T::ForceOrigin::ensure_origin(origin)?; + let delegate = T::Lookup::lookup(delegate)?; + let owner = T::Lookup::lookup(owner)?; + Self::do_cancel_collection_approval(owner, collection, delegate) + } + + /// Cancel all collection approvals, up to a specified limit. + /// + /// Origin must be Signed. + /// + /// Arguments: + /// - `collection`: The collection whose approvals will be cleared. + /// - `limit`: The amount of collection approvals that will be cleared. + /// + /// Emits `ApprovalsCancelled` on success. + /// + /// Weight: `O(n)` where: + /// - `n = limit` + #[pallet::call_index(54)] + #[pallet::weight(T::WeightInfo::clear_collection_approvals(*limit))] + pub fn clear_collection_approvals( + origin: OriginFor, + collection: T::CollectionId, + limit: u32, + ) -> DispatchResultWithPostInfo { + let origin = ensure_signed(origin) + .map_err(|e| e.with_weight(T::WeightInfo::clear_collection_approvals(0)))?; + let removed_approvals = Self::do_clear_collection_approvals(origin, collection, limit)?; + Ok(Some(T::WeightInfo::clear_collection_approvals(removed_approvals)).into()) + } + + /// Force-cancel all collection approvals granted by `owner` account, up to a specified + /// limit. + /// + /// Origin must be `ForceOrigin`. + /// + /// Arguments: + /// - `owner`: The owner of the approvals to be force-cancelled by the `origin`. + /// - `collection`: The collection whose approvals will be cleared. + /// - `limit`: The amount of collection approvals that will be cleared. + /// + /// Emits `ApprovalsCancelled` on success. + /// + /// Weight: `O(n)` where: + /// - `n = limit` + #[pallet::call_index(55)] + #[pallet::weight(T::WeightInfo::force_clear_collection_approvals(*limit))] + pub fn force_clear_collection_approvals( + origin: OriginFor, + owner: AccountIdLookupOf, + collection: T::CollectionId, + limit: u32, + ) -> DispatchResultWithPostInfo { + T::ForceOrigin::ensure_origin(origin) + .map_err(|e| e.with_weight(T::WeightInfo::clear_collection_approvals(0)))?; + let owner = T::Lookup::lookup(owner)?; + let removed_approvals = Self::do_clear_collection_approvals(owner, collection, limit)?; + Ok(Some(T::WeightInfo::clear_collection_approvals(removed_approvals)).into()) + } } } diff --git a/pallets/nfts/src/mock.rs b/pallets/nfts/src/mock.rs index 5532be8f4..efd72722f 100644 --- a/pallets/nfts/src/mock.rs +++ b/pallets/nfts/src/mock.rs @@ -65,6 +65,8 @@ parameter_types! { impl Config for Test { type ApprovalsLimit = ConstU32<10>; type AttributeDepositBase = ConstU64<1>; + type CollectionApprovalDeposit = ConstU64<1>; + type CollectionBalanceDeposit = ConstU64<1>; type CollectionDeposit = ConstU64<2>; type CollectionId = u32; type CreateOrigin = AsEnsureOriginWithArg>; diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 44f2f32ae..d0c6bff9d 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -18,28 +18,39 @@ //! Tests for Nfts pallet. use enumflags2::BitFlags; -use frame_support::{ +pub(crate) use frame_support::{ assert_noop, assert_ok, + dispatch::WithPostDispatchInfo, traits::{ tokens::nonfungibles_v2::{Create, Destroy, Inspect, Mutate}, Currency, Get, }, }; -use pallet_balances::Error as BalancesError; +use frame_system::pallet_prelude::BlockNumberFor; +pub(crate) use pallet_balances::Error as BalancesError; use sp_core::{bounded::BoundedVec, Pair}; use sp_runtime::{ traits::{Dispatchable, IdentifyAccount}, + DispatchError::BadOrigin, MultiSignature, MultiSigner, }; use crate::{mock::*, Event, SystemConfig, *}; type AccountIdOf = ::AccountId; +pub(crate) type AccountBalance = crate::AccountBalance; +type CollectionApprovals = crate::CollectionApprovals; +type CollectionApprovalDeposit = ::CollectionApprovalDeposit; +type WeightOf = ::WeightInfo; -fn account(id: u8) -> AccountIdOf { +pub(crate) fn account(id: u8) -> AccountIdOf { [id; 32].into() } +fn none() -> RuntimeOrigin { + RuntimeOrigin::none() +} + fn items() -> Vec<(AccountIdOf, u32, u32)> { let mut r: Vec<_> = Account::::iter().map(|x| x.0).collect(); r.sort(); @@ -147,6 +158,14 @@ fn item_config_from_disabled_settings(settings: BitFlags) -> ItemCo ItemConfig { settings: ItemSettings::from_disabled(settings) } } +pub(crate) fn balance_deposit() -> DepositBalanceOf { + <::CollectionBalanceDeposit>::get() +} + +pub(crate) fn item_deposit() -> DepositBalanceOf { + <::ItemDeposit>::get() +} + #[test] fn basic_setup_works() { new_test_ext().execute_with(|| { @@ -180,6 +199,8 @@ fn basic_minting_should_work() { #[test] fn lifecycle_should_work() { new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + Balances::make_free_balance_be(&account(1), 100); Balances::make_free_balance_be(&account(2), 100); assert_ok!(Nfts::create( @@ -204,7 +225,7 @@ fn lifecycle_should_work() { account(10), default_item_config() )); - assert_eq!(Balances::reserved_balance(&account(1)), 6); + assert_eq!(Balances::reserved_balance(&account(1)), 6 + balance_deposit); assert_ok!(Nfts::force_mint( RuntimeOrigin::signed(account(1)), 0, @@ -212,23 +233,23 @@ fn lifecycle_should_work() { account(20), default_item_config() )); - assert_eq!(Balances::reserved_balance(&account(1)), 7); + assert_eq!(Balances::reserved_balance(&account(1)), 7 + 2 * balance_deposit); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 70, account(1), None)); assert_eq!(items(), vec![(account(1), 0, 70), (account(10), 0, 42), (account(20), 0, 69)]); assert_eq!(Collection::::get(0).unwrap().items, 3); assert_eq!(Collection::::get(0).unwrap().item_metadatas, 0); assert_eq!(Collection::::get(0).unwrap().item_configs, 3); - assert_eq!(Balances::reserved_balance(&account(1)), 8); + assert_eq!(Balances::reserved_balance(&account(1)), 8 + 3 * balance_deposit); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 70, account(2))); - assert_eq!(Balances::reserved_balance(&account(1)), 8); + assert_eq!(Balances::reserved_balance(&account(1)), 8 + 3 * balance_deposit); assert_eq!(Balances::reserved_balance(&account(2)), 0); assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![42, 42])); - assert_eq!(Balances::reserved_balance(&account(1)), 11); + assert_eq!(Balances::reserved_balance(&account(1)), 11 + 3 * balance_deposit); assert!(ItemMetadataOf::::contains_key(0, 42)); assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 69, bvec![69, 69])); - assert_eq!(Balances::reserved_balance(&account(1)), 14); + assert_eq!(Balances::reserved_balance(&account(1)), 14 + 3 * balance_deposit); assert!(ItemMetadataOf::::contains_key(0, 69)); assert!(ItemConfigOf::::contains_key(0, 69)); let w = Nfts::get_destroy_witness(&0).unwrap(); @@ -328,6 +349,52 @@ fn destroy_should_work() { }); } +#[test] +fn destroy_ensures_no_active_collection_approval() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let collection_owner = account(1); + let delegate = account(3); + let item_id = 42; + let item_owner = account(2); + + Balances::make_free_balance_be(&collection_owner, 100); + assert_ok!(Nfts::create( + RuntimeOrigin::signed(collection_owner.clone()), + collection_owner.clone(), + collection_config_with_all_settings_enabled() + )); + + CollectionApprovals::set( + (collection_id, item_owner.clone(), delegate.clone()), + Some((None, 0)), + ); + // Throws error `CollectionApprovalsExist`. + assert_noop!( + Nfts::destroy( + RuntimeOrigin::signed(collection_owner.clone()), + collection_id, + Nfts::get_destroy_witness(&collection_id).unwrap() + ), + Error::::CollectionApprovalsExist + ); + assert_ok!(Nfts::cancel_collection_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate + )); + + // Successfully destroy the collection. + assert_ok!(Nfts::destroy( + RuntimeOrigin::signed(collection_owner.clone()), + collection_id, + Nfts::get_destroy_witness(&collection_id).unwrap() + )); + assert!(!ItemConfigOf::::contains_key(collection_id, item_id)); + assert_eq!(ItemConfigOf::::iter_prefix(collection_id).count() as u32, collection_id); + }); +} + #[test] fn mint_should_work() { new_test_ext().execute_with(|| { @@ -461,6 +528,51 @@ fn mint_should_work() { }); } +#[test] +fn mint_should_update_account_balance_works() { + new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + let collection_id = 0; + let dest = account(1); + let owner = account(2); + + Balances::make_free_balance_be(&owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + owner.clone(), + collection_config_with_all_settings_enabled() + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(owner.clone()), + collection_id, + 42, + dest.clone(), + None + )); + // Minting reserves a deposit because `dest` doesn't have an item in the collection yet and + // thus a storage item has to be created. + assert_eq!( + AccountBalance::get(collection_id, dest.clone()), + Some((1, (owner.clone(), balance_deposit))) + ); + assert_eq!(Balances::reserved_balance(&owner), item_deposit() + balance_deposit); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(owner.clone()), + collection_id, + 43, + dest.clone(), + None + )); + // `dest` already has an item in the collection so no extra deposit is reserved. + assert_eq!( + AccountBalance::get(collection_id, &dest), + Some((2, (owner.clone(), balance_deposit))) + ); + assert_eq!(Balances::reserved_balance(&owner), (2 * item_deposit()) + balance_deposit); + assert_eq!(Balances::reserved_balance(&dest), 0); + }); +} + #[test] fn transfer_should_work() { new_test_ext().execute_with(|| { @@ -518,9 +630,75 @@ fn transfer_should_work() { }); } +#[test] +fn transfer_should_update_account_balance_works() { + new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + let collection_id = 0; + let delegate = account(1); + let dest = account(2); + let item_id = 42; + let owner = account(3); + + Balances::make_free_balance_be(&owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + owner.clone(), + collection_config_with_all_settings_enabled() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(owner.clone()), + collection_id, + item_id, + owner.clone(), + default_item_config() + )); + assert_ok!(Nfts::transfer( + RuntimeOrigin::signed(owner.clone()), + collection_id, + item_id, + dest.clone() + )); + assert!(!AccountBalance::contains_key(collection_id, &owner)); + assert_eq!( + AccountBalance::get(collection_id, &dest), + Some((1, (owner.clone(), balance_deposit))) + ); + // Reserve funds from `owner` when transferring to `dest`. + assert_eq!(Balances::reserved_balance(&owner), item_deposit() + balance_deposit); + assert_eq!(Balances::reserved_balance(&dest), 0); + + // Approve `delegate` for approved transfer case. + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(dest.clone()), + collection_id, + item_id, + delegate.clone(), + None + )); + Balances::make_free_balance_be(&dest, Balances::minimum_balance() + balance_deposit); + assert_ok!(Nfts::transfer( + RuntimeOrigin::signed(delegate.clone()), + collection_id, + item_id, + owner.clone() + )); + assert_eq!( + AccountBalance::get(collection_id, &owner), + Some((1, (dest.clone(), balance_deposit))) + ); + // Reserve funds from `dest` during a delegated transfer initiated by the + // `delegate` back to `owner`. + assert_eq!(Balances::reserved_balance(&owner), item_deposit()); + assert_eq!(Balances::reserved_balance(&delegate), 0); + assert_eq!(Balances::reserved_balance(&dest), balance_deposit); + }); +} + #[test] fn locking_transfer_should_work() { new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&account(1), 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), account(1), @@ -607,6 +785,8 @@ fn origin_guards_should_work() { #[test] fn transfer_owner_should_work() { new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + Balances::make_free_balance_be(&account(1), 100); Balances::make_free_balance_be(&account(2), 100); Balances::make_free_balance_be(&account(3), 100); @@ -647,7 +827,7 @@ fn transfer_owner_should_work() { bvec![0u8; 20], )); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); - assert_eq!(Balances::reserved_balance(&account(1)), 1); + assert_eq!(Balances::reserved_balance(&account(1)), 1 + balance_deposit); assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0u8; 20])); assert_ok!(Nfts::set_accept_ownership(RuntimeOrigin::signed(account(3)), Some(0))); assert_ok!(Nfts::transfer_ownership(RuntimeOrigin::signed(account(2)), 0, account(3))); @@ -658,8 +838,9 @@ fn transfer_owner_should_work() { assert_eq!(Balances::reserved_balance(&account(3)), 44); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 42, account(2))); - // reserved_balance of accounts 1 & 2 should be unchanged: - assert_eq!(Balances::reserved_balance(&account(1)), 1); + // The reserved balance of account 1 is incremented to create a new storage record for the + // account 2. + assert_eq!(Balances::reserved_balance(&account(1)), 1 + balance_deposit); assert_eq!(Balances::reserved_balance(&account(2)), 0); // 2's acceptance from before is reset when it became an owner, so it cannot be transferred @@ -835,6 +1016,8 @@ fn set_collection_metadata_should_work() { #[test] fn set_item_metadata_should_work() { new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + Balances::make_free_balance_be(&account(1), 30); // Cannot add metadata to unknown item @@ -852,7 +1035,7 @@ fn set_item_metadata_should_work() { // Successfully add metadata and take deposit assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0u8; 20])); - assert_eq!(Balances::free_balance(&account(1)), 8); + assert_eq!(Balances::free_balance(&account(1)), 8 - balance_deposit); assert!(ItemMetadataOf::::contains_key(0, 42)); // Force origin works, too. @@ -860,9 +1043,9 @@ fn set_item_metadata_should_work() { // Update deposit assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0u8; 15])); - assert_eq!(Balances::free_balance(&account(1)), 13); + assert_eq!(Balances::free_balance(&account(1)), 13 - balance_deposit); assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0u8; 25])); - assert_eq!(Balances::free_balance(&account(1)), 3); + assert_eq!(Balances::free_balance(&account(1)), 3 - balance_deposit); // Cannot over-reserve assert_noop!( @@ -906,6 +1089,8 @@ fn set_item_metadata_should_work() { #[test] fn set_collection_owner_attributes_should_work() { new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + Balances::make_free_balance_be(&account(1), 100); assert_ok!(Nfts::force_create( @@ -947,7 +1132,7 @@ fn set_collection_owner_attributes_should_work() { (Some(0), AttributeNamespace::CollectionOwner, bvec![1], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(account(1)), 10); + assert_eq!(Balances::reserved_balance(account(1)), 10 + balance_deposit); assert_eq!(Collection::::get(0).unwrap().owner_deposit, 9); assert_ok!(Nfts::set_attribute( @@ -966,7 +1151,7 @@ fn set_collection_owner_attributes_should_work() { (Some(0), AttributeNamespace::CollectionOwner, bvec![1], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(account(1)), 19); + assert_eq!(Balances::reserved_balance(account(1)), 19 + balance_deposit); assert_eq!(Collection::::get(0).unwrap().owner_deposit, 18); assert_ok!(Nfts::clear_attribute( @@ -983,7 +1168,7 @@ fn set_collection_owner_attributes_should_work() { (Some(0), AttributeNamespace::CollectionOwner, bvec![0], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(account(1)), 16); + assert_eq!(Balances::reserved_balance(account(1)), 16 + balance_deposit); assert_ok!(Nfts::burn(RuntimeOrigin::root(), 0, 0)); let w = Nfts::get_destroy_witness(&0).unwrap(); @@ -1227,7 +1412,7 @@ fn set_item_owner_attributes_should_work() { Attribute::::get((0, Some(0), AttributeNamespace::ItemOwner, &key)).unwrap(); assert_eq!(deposit.account, Some(account(3))); assert_eq!(deposit.amount, 13); - assert_eq!(Balances::reserved_balance(account(2)), 3); + assert_eq!(Balances::reserved_balance(account(2)), 3 + balance_deposit()); assert_eq!(Balances::reserved_balance(account(3)), 13); // validate attributes on item deletion @@ -1477,7 +1662,7 @@ fn set_attribute_should_respect_lock() { (Some(1), AttributeNamespace::CollectionOwner, bvec![0], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(account(1)), 11); + assert_eq!(Balances::reserved_balance(account(1)), 11 + balance_deposit()); assert_ok!(Nfts::set_collection_metadata(RuntimeOrigin::signed(account(1)), 0, bvec![])); assert_ok!(Nfts::lock_collection( @@ -1596,6 +1781,8 @@ fn preserve_config_for_frozen_items() { #[test] fn force_update_collection_should_work() { new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + Balances::make_free_balance_be(&account(1), 100); assert_ok!(Nfts::force_create( @@ -1618,7 +1805,7 @@ fn force_update_collection_should_work() { )); assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0; 20])); assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 69, bvec![0; 20])); - assert_eq!(Balances::reserved_balance(account(1)), 65); + assert_eq!(Balances::reserved_balance(account(1)), 65 + 2 * balance_deposit); // force item status to be free holding assert_ok!(Nfts::force_collection_config( @@ -1647,7 +1834,7 @@ fn force_update_collection_should_work() { Some(account(4)), )); assert_eq!(collections(), vec![(account(5), 0)]); - assert_eq!(Balances::reserved_balance(account(1)), 2); + assert_eq!(Balances::reserved_balance(account(1)), 2 + 2 * balance_deposit); assert_eq!(Balances::reserved_balance(account(5)), 63); assert_ok!(Nfts::redeposit( @@ -1655,7 +1842,7 @@ fn force_update_collection_should_work() { 0, bvec![0, 42, 50, 69, 100] )); - assert_eq!(Balances::reserved_balance(account(1)), 0); + assert_eq!(Balances::reserved_balance(account(1)), 2 * balance_deposit); assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(5)), 0, 42, bvec![0; 20])); assert_eq!(Balances::reserved_balance(account(5)), 42); @@ -1713,6 +1900,8 @@ fn force_update_collection_should_work() { #[test] fn burn_works() { new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + Balances::make_free_balance_be(&account(1), 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), @@ -1746,7 +1935,7 @@ fn burn_works() { account(5), default_item_config() )); - assert_eq!(Balances::reserved_balance(account(1)), 2); + assert_eq!(Balances::reserved_balance(account(1)), 2 + balance_deposit); assert_noop!( Nfts::burn(RuntimeOrigin::signed(account(0)), 0, 42), @@ -1759,6 +1948,46 @@ fn burn_works() { }); } +#[test] +fn burn_should_update_account_balance_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let owner = account(1); + + Balances::make_free_balance_be(&owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + owner.clone(), + collection_config_with_all_settings_enabled() + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(owner.clone()), + collection_id, + 42, + owner.clone(), + None, + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(owner.clone()), + collection_id, + 43, + owner.clone(), + None, + )); + + assert_ok!(Nfts::burn(RuntimeOrigin::signed(owner.clone()), collection_id, 42)); + assert_eq!( + AccountBalance::get(collection_id, &owner), + Some((1, (owner.clone(), balance_deposit()))) + ); + assert_eq!(Balances::reserved_balance(&owner), item_deposit() + balance_deposit()); + + assert_ok!(Nfts::burn(RuntimeOrigin::signed(owner.clone()), collection_id, 43)); + assert!(!AccountBalance::contains_key(collection_id, &owner)); + assert_eq!(Balances::reserved_balance(&owner), 0); + }); +} + #[test] fn approval_lifecycle_works() { new_test_ext().execute_with(|| { @@ -1869,6 +2098,12 @@ fn cancel_approval_works() { ); assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); + assert!(events().contains(&Event::::ApprovalCancelled { + collection: 0, + item: Some(42), + owner: account(2), + delegate: account(3) + })); assert_noop!( Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3)), Error::::NotDelegate @@ -1903,6 +2138,64 @@ fn cancel_approval_works() { }); } +#[test] +fn cancel_approval_ensures_no_active_collection_approval() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let delegate = account(3); + let item_id = 42; + let owner = account(1); + + Balances::make_free_balance_be(&owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + owner.clone(), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + collection_id, + item_id, + owner.clone(), + default_item_config() + )); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(owner.clone()), + collection_id, + item_id, + delegate.clone(), + None + )); + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(owner.clone()), + collection_id, + delegate.clone(), + None + )); + // Delegate has an active collection approval. + assert_noop!( + Nfts::cancel_approval( + RuntimeOrigin::signed(owner.clone()), + collection_id, + item_id, + delegate.clone() + ), + Error::::DelegateApprovalConflict + ); + assert_ok!(Nfts::cancel_collection_approval( + RuntimeOrigin::signed(owner.clone()), + collection_id, + delegate.clone() + )); + assert_ok!(Nfts::cancel_approval( + RuntimeOrigin::signed(owner), + collection_id, + item_id, + delegate + )); + }); +} + #[test] fn approving_multiple_accounts_works() { new_test_ext().execute_with(|| { @@ -1942,6 +2235,32 @@ fn approving_multiple_accounts_works() { account(5), Some(2) )); + assert_eq!( + events().last_chunk::<3>(), + Some(&[ + Event::TransferApproved { + collection: 0, + item: Some(42), + owner: account(2), + delegate: account(3), + deadline: None + }, + Event::TransferApproved { + collection: 0, + item: Some(42), + owner: account(2), + delegate: account(4), + deadline: None + }, + Event::TransferApproved { + collection: 0, + item: Some(42), + owner: account(2), + delegate: account(5), + deadline: Some(current_block + 2) + } + ]) + ); assert_eq!( approvals(0, 42), vec![(account(3), None), (account(4), None), (account(5), Some(current_block + 2))] @@ -2081,6 +2400,13 @@ fn cancel_approval_works_with_admin() { ); assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); + assert!(events().contains(&Event::::ApprovalCancelled { + collection: 0, + item: Some(42), + owner: account(2), + delegate: account(3) + })); + assert_noop!( Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(1)), Error::::NotDelegate @@ -2125,6 +2451,12 @@ fn cancel_approval_works_with_force() { ); assert_ok!(Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, account(3))); + assert!(events().contains(&Event::::ApprovalCancelled { + collection: 0, + item: Some(42), + owner: account(2), + delegate: account(3) + })); assert_noop!( Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, account(1)), Error::::NotDelegate @@ -2188,6 +2520,62 @@ fn clear_all_transfer_approvals_works() { }); } +#[test] +fn clear_all_transfer_approvals_ensures_no_active_collection_approval() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let delegate = account(3); + let item_id = 42; + let owner = account(1); + + Balances::make_free_balance_be(&owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + owner.clone(), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(owner.clone()), + collection_id, + item_id, + owner.clone(), + default_item_config() + )); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(owner.clone()), + collection_id, + item_id, + delegate.clone(), + None + )); + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(owner.clone()), + collection_id, + delegate.clone(), + None + )); + // Delegate has an active collection approval. + assert_noop!( + Nfts::clear_all_transfer_approvals( + RuntimeOrigin::signed(owner.clone()), + collection_id, + item_id + ), + Error::::DelegateApprovalConflict + ); + assert_ok!(Nfts::cancel_collection_approval( + RuntimeOrigin::signed(owner.clone()), + collection_id, + delegate + )); + assert_ok!(Nfts::clear_all_transfer_approvals( + RuntimeOrigin::signed(owner), + collection_id, + item_id + )); + }); +} + #[test] fn max_supply_should_work() { new_test_ext().execute_with(|| { @@ -2622,6 +3010,54 @@ fn buy_item_should_work() { }); } +#[test] +fn buy_item_should_update_account_balance_works() { + new_test_ext().execute_with(|| { + let user_1 = account(1); + let user_2 = account(2); + let collection_id = 0; + let item = 1; + let price = 20; + + Balances::make_free_balance_be(&user_1, 100); + Balances::make_free_balance_be( + &user_2, + Balances::minimum_balance() + price + balance_deposit(), + ); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + user_1.clone(), + collection_config_with_all_settings_enabled() + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(user_1.clone()), + collection_id, + item, + user_1.clone(), + None + )); + assert_ok!(Nfts::set_price( + RuntimeOrigin::signed(user_1.clone()), + collection_id, + item, + Some(price), + None, + )); + assert_ok!(Nfts::buy_item( + RuntimeOrigin::signed(user_2.clone()), + collection_id, + item, + price, + )); + assert!(!AccountBalance::contains_key(collection_id, &user_1)); + assert_eq!( + AccountBalance::get(collection_id, &user_2), + Some((1, (user_2.clone(), balance_deposit()))) + ); + assert_eq!(Balances::reserved_balance(&user_2), balance_deposit()); + }); +} + #[test] fn pay_tips_should_work() { new_test_ext().execute_with(|| { @@ -3041,24 +3477,97 @@ fn claim_swap_should_work() { } #[test] -fn various_collection_settings() { +fn claim_swap_should_update_account_balance_works() { new_test_ext().execute_with(|| { - // when we set only one value it's required to call .into() on it - let config = - collection_config_from_disabled_settings(CollectionSetting::TransferableItems.into()); - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), account(1), config)); - - let config = CollectionConfigOf::::get(0).unwrap(); - assert!(!config.is_setting_enabled(CollectionSetting::TransferableItems)); - assert!(config.is_setting_enabled(CollectionSetting::UnlockedMetadata)); + System::set_block_number(1); + let user_1 = account(1); + let user_2 = account(2); + let collection_id = 0; + let item_1 = 1; + let item_2 = 2; + let price = 100; + let price_with_direction = + PriceWithDirection { amount: price, direction: PriceDirection::Receive.clone() }; - // no need to call .into() for multiple values - let config = collection_config_from_disabled_settings( - CollectionSetting::UnlockedMetadata | CollectionSetting::TransferableItems, + Balances::make_free_balance_be(&user_1, 1000); + Balances::make_free_balance_be( + &user_2, + Balances::minimum_balance() + balance_deposit() + price, ); - assert_ok!(Nfts::force_create(RuntimeOrigin::root(), account(1), config)); - - let config = CollectionConfigOf::::get(1).unwrap(); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + user_1.clone(), + collection_config_with_all_settings_enabled() + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(user_1.clone()), + collection_id, + item_1, + user_1.clone(), + None, + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(user_1.clone()), + collection_id, + item_2, + user_2.clone(), + None, + )); + assert_eq!( + Balances::reserved_balance(&user_1), + (2 * item_deposit()) + (2 * balance_deposit()) + ); + assert_ok!(Nfts::create_swap( + RuntimeOrigin::signed(user_1.clone()), + collection_id, + item_1, + collection_id, + Some(item_2), + Some(price_with_direction.clone()), + 2 + )); + assert_ok!(Nfts::claim_swap( + RuntimeOrigin::signed(user_2.clone()), + collection_id, + item_2, + collection_id, + item_1, + Some(price_with_direction), + )); + assert_eq!( + AccountBalance::get(collection_id, &user_1), + Some((1, (user_1.clone(), balance_deposit()))) + ); + assert_eq!( + AccountBalance::get(collection_id, &user_2), + Some((1, (user_2.clone(), balance_deposit()))) + ); + assert_eq!(Balances::reserved_balance(&user_1), (2 * item_deposit()) + balance_deposit()); + // User pays for its own deposit (previously paid by the account who signed the mint + // transaction). + assert_eq!(Balances::reserved_balance(&user_2), balance_deposit()); + }); +} + +#[test] +fn various_collection_settings() { + new_test_ext().execute_with(|| { + // when we set only one value it's required to call .into() on it + let config = + collection_config_from_disabled_settings(CollectionSetting::TransferableItems.into()); + assert_ok!(Nfts::force_create(RuntimeOrigin::root(), account(1), config)); + + let config = CollectionConfigOf::::get(0).unwrap(); + assert!(!config.is_setting_enabled(CollectionSetting::TransferableItems)); + assert!(config.is_setting_enabled(CollectionSetting::UnlockedMetadata)); + + // no need to call .into() for multiple values + let config = collection_config_from_disabled_settings( + CollectionSetting::UnlockedMetadata | CollectionSetting::TransferableItems, + ); + assert_ok!(Nfts::force_create(RuntimeOrigin::root(), account(1), config)); + + let config = CollectionConfigOf::::get(1).unwrap(); assert!(!config.is_setting_enabled(CollectionSetting::TransferableItems)); assert!(!config.is_setting_enabled(CollectionSetting::UnlockedMetadata)); @@ -3380,7 +3889,7 @@ fn pre_signed_mints_should_work() { assert_eq!(deposit.amount, 3); assert_eq!(Balances::free_balance(&user_0), 100 - 2 + 10); // 2 - collection deposit, 10 - mint price - assert_eq!(Balances::free_balance(&user_2), 100 - 1 - 3 - 6 - 10); // 1 - item deposit, 3 - metadata, 6 - attributes, 10 - mint price + assert_eq!(Balances::free_balance(&user_2), 100 - balance_deposit() - 1 - 3 - 6 - 10); // 1 - item deposit, 3 - metadata, 6 - attributes, 10 - mint price assert_noop!( Nfts::mint_pre_signed( @@ -3555,7 +4064,7 @@ fn pre_signed_attributes_should_work() { assert_eq!(deposit.account, Some(user_2.clone())); assert_eq!(deposit.amount, 3); - assert_eq!(Balances::free_balance(&user_1), 100 - 2 - 1); // 2 - collection deposit, 1 - item deposit + assert_eq!(Balances::free_balance(&user_1), 100 - 2 - 1 - balance_deposit()); // 2 - collection deposit, 1 - item deposit assert_eq!(Balances::free_balance(&user_2), 100 - 6); // 6 - attributes // validate the deposit gets returned on attribute update from collection's owner @@ -3876,3 +4385,935 @@ fn clear_collection_metadata_works() { assert_eq!(Balances::reserved_balance(&account(1)), 10); }); } + +#[test] +fn collection_item_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let total_items = 10; + let user_id = account(1); + + // No collection. + assert_eq!(Nfts::collection_items(collection_id), None); + + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + user_id.clone(), + default_collection_config() + )); + + // Mint items and validate the total supply. + (0..total_items).into_iter().for_each(|i| { + assert_ok!(Nfts::force_mint( + RuntimeOrigin::root(), + collection_id, + i, + user_id.clone(), + ItemConfig::default() + )); + }); + assert_eq!(Nfts::collection_items(collection_id), Some(total_items)); + }); +} + +#[test] +fn clear_collection_approvals_works() { + new_test_ext().execute_with(|| { + let balance = 100; + let collection_id = 0; + let item_id = 42; + let item_owner = account(1); + let delegates = 10..20; + + for origin in [RuntimeOrigin::root(), none()] { + assert_noop!( + Nfts::clear_collection_approvals(origin, collection_id, 0), + BadOrigin.with_weight(WeightOf::clear_collection_approvals(0)) + ); + } + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + item_owner.clone(), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + item_id, + item_owner.clone(), + default_item_config() + )); + Balances::make_free_balance_be(&item_owner, balance); + // Approve delegates. + let mut approvals = 0u32; + for i in delegates.clone() { + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + account(i), + None + )); + approvals.saturating_inc(); + } + + // Remove zero collection approvals. + assert_eq!( + Nfts::clear_collection_approvals( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + 0 + ), + Ok(Some(WeightOf::clear_collection_approvals(0)).into()) + ); + assert_eq!(Balances::free_balance(&item_owner), balance - approvals as u64); + assert_eq!( + CollectionApprovals::iter_prefix((collection_id, &item_owner)).count(), + approvals as usize + ); + assert!(!events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner.clone(), + approvals + })); + + // Partially remove collection approvals. + let limit = 1; + assert_eq!( + Nfts::clear_collection_approvals( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + limit + ), + Ok(Some(WeightOf::clear_collection_approvals(limit)).into()) + ); + approvals = approvals - limit; + assert_eq!(Balances::free_balance(&item_owner), balance - approvals as u64); + assert_eq!( + CollectionApprovals::iter_prefix((collection_id, item_owner.clone())).count(), + approvals as usize + ); + assert!(events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner.clone(), + approvals: limit + })); + + // Successfully remove all collection approvals. Only charges post-dispatch weight for + // the removed approvals. + assert_eq!( + Nfts::clear_collection_approvals( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + 10 + ), + Ok(Some(WeightOf::clear_collection_approvals(approvals)).into()) + ); + assert_eq!(Balances::free_balance(&item_owner), balance); + assert!(CollectionApprovals::iter_prefix((collection_id, item_owner.clone())) + .count() + .is_zero()); + assert!(events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner.clone(), + approvals, + })); + + // Remove collection approvals while there are none. + assert_eq!( + Nfts::force_clear_collection_approvals( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + 10 + ), + Ok(Some(WeightOf::clear_collection_approvals(0)).into()) + ); + assert_eq!(Balances::free_balance(&item_owner), balance); + assert!(events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner, + approvals: 0 + })); + + // Ensure delegates are not able to transfer. + for i in delegates.clone() { + assert_noop!( + Nfts::transfer( + RuntimeOrigin::signed(account(i)), + collection_id, + item_id, + account(5) + ), + Error::::NoPermission + ); + } + }); +} + +#[test] +fn force_clear_collection_approvals_works() { + new_test_ext().execute_with(|| { + let balance = 100; + let collection_id = 0; + let item_id = 42; + let item_owner = account(1); + let delegates = 10..20; + + for origin in [RuntimeOrigin::signed(item_owner.clone()), none()] { + assert_noop!( + Nfts::force_clear_collection_approvals( + origin, + item_owner.clone(), + collection_id, + 0 + ), + BadOrigin.with_weight(WeightOf::clear_collection_approvals(0)) + ); + } + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + item_owner.clone(), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + item_id, + item_owner.clone(), + default_item_config() + )); + Balances::make_free_balance_be(&item_owner, balance); + // Approve delegates. + let mut approvals = 0u32; + for i in delegates.clone() { + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + account(i), + None + )); + approvals.saturating_inc(); + } + + // Remove zero collection approvals. + assert_eq!( + Nfts::force_clear_collection_approvals( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + 0 + ), + Ok(Some(WeightOf::clear_collection_approvals(0)).into()) + ); + assert_eq!(Balances::free_balance(&item_owner), balance - approvals as u64); + assert_eq!( + CollectionApprovals::iter_prefix((collection_id, &item_owner)).count(), + approvals as usize + ); + assert!(!events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner.clone(), + approvals + })); + + // Partially remove collection approvals. + let limit = 1; + assert_eq!( + Nfts::force_clear_collection_approvals( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + limit + ), + Ok(Some(WeightOf::clear_collection_approvals(limit)).into()) + ); + approvals = approvals - limit; + assert_eq!(Balances::free_balance(&item_owner), balance - approvals as u64); + assert_eq!( + CollectionApprovals::iter_prefix((collection_id, item_owner.clone())).count(), + approvals as usize + ); + assert!(events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner.clone(), + approvals: limit + })); + + // Successfully remove all collection approvals. Only charges post-dispatch weight for + // the removed approvals. + assert_eq!( + Nfts::force_clear_collection_approvals( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + 10 + ), + Ok(Some(WeightOf::clear_collection_approvals(approvals)).into()) + ); + assert_eq!(Balances::free_balance(&item_owner), balance); + assert!(CollectionApprovals::iter_prefix((collection_id, item_owner.clone())) + .count() + .is_zero()); + assert!(events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner.clone(), + approvals, + })); + + // Remove collection approvals while there are none. + assert_eq!( + Nfts::force_clear_collection_approvals( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + 10 + ), + Ok(Some(WeightOf::clear_collection_approvals(0)).into()) + ); + assert_eq!(Balances::free_balance(&item_owner), balance); + assert!(events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner, + approvals: 0 + })); + + // Ensure delegates are not able to transfer. + for i in delegates.clone() { + assert_noop!( + Nfts::transfer( + RuntimeOrigin::signed(account(i)), + collection_id, + item_id, + account(5) + ), + Error::::NoPermission + ); + } + }); +} + +#[test] +fn approve_collection_transfer_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let collection_owner = account(1); + let deadline: BlockNumberFor = 20; + let delegate = account(3); + let deposit = CollectionApprovalDeposit::get(); + let item_id = 42; + let item_owner = account(2); + + for origin in [RuntimeOrigin::root(), none()] { + assert_noop!( + Nfts::approve_collection_transfer(origin, collection_id, delegate.clone(), None), + BadOrigin + ); + } + // Approve unknown collection. + assert_noop!( + Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + None + ), + Error::::NoItemOwned + ); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + collection_owner.clone(), + default_collection_config() + )); + // Approve collection without items. + assert_noop!( + Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + None + ), + Error::::NoItemOwned + ); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(collection_owner.clone()), + collection_id, + item_id, + item_owner.clone(), + default_item_config() + )); + // Approve collection without balance. + assert_noop!( + Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + None + ), + BalancesError::::InsufficientBalance, + ); + + Balances::make_free_balance_be(&item_owner, 100); + // Approving a collection to a delegate with: + // 1. no deadline. + // 2. no deadline, again. + // 3. deadline. + // 3. equal deadline. + // 4. larger deadline. + // 5. smaller deadline. + // 6. no deadline, again. + // + // This tests all cases of approving the same delegate. + for deadline in + [None, None, Some(deadline), Some(deadline), Some(deadline * 2), Some(deadline), None] + { + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + deadline, + )); + let deadline = deadline.map(|d| d + 1); + System::assert_last_event( + Event::::TransferApproved { + collection: collection_id, + item: None, + owner: item_owner.clone(), + delegate: delegate.clone(), + deadline, + } + .into(), + ); + assert_eq!(Balances::reserved_balance(&item_owner), deposit); + assert_eq!( + CollectionApprovals::get((collection_id, &item_owner, &delegate)), + Some((deadline, deposit)) + ); + } + + // Set collection settings to non transferable. + assert_ok!(Nfts::lock_collection( + RuntimeOrigin::signed(collection_owner), + collection_id, + CollectionSettings::from_disabled(CollectionSetting::TransferableItems.into()) + )); + assert_noop!( + Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner), + collection_id, + delegate, + None + ), + Error::::ItemsNonTransferable + ); + }); +} + +#[test] +fn force_approve_collection_transfer_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let collection_owner = account(1); + let deadline: BlockNumberFor = 20; + let delegate = account(3); + let item_id = 42; + let item_owner = account(2); + + for origin in [RuntimeOrigin::signed(item_owner.clone()), none()] { + assert_noop!( + Nfts::force_approve_collection_transfer( + origin, + item_owner.clone(), + collection_id, + delegate.clone(), + None + ), + BadOrigin + ); + } + // Approve unknown collection. + assert_noop!( + Nfts::force_approve_collection_transfer( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + delegate.clone(), + None + ), + Error::::NoItemOwned + ); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + collection_owner.clone(), + default_collection_config() + )); + // Approve collection without items. + assert_noop!( + Nfts::force_approve_collection_transfer( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + delegate.clone(), + None + ), + Error::::NoItemOwned + ); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(collection_owner.clone()), + collection_id, + item_id, + item_owner.clone(), + default_item_config() + )); + // Approve collection without balance. + assert_ok!(Nfts::force_approve_collection_transfer( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + delegate.clone(), + None + )); + + Balances::make_free_balance_be(&item_owner, 100); + // Approving a collection to a delegate with: + // 1. no deadline. + // 2. no deadline, again. + // 3. deadline. + // 3. equal deadline. + // 4. larger deadline. + // 5. smaller deadline. + // 6. no deadline, again. + // + // This tests all cases of approving the same delegate. + for deadline in + [None, None, Some(deadline), Some(deadline), Some(deadline * 2), Some(deadline), None] + { + assert_ok!(Nfts::force_approve_collection_transfer( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + delegate.clone(), + deadline, + )); + let deadline = deadline.map(|d| d + 1); + System::assert_last_event( + Event::::TransferApproved { + collection: collection_id, + item: None, + owner: item_owner.clone(), + delegate: delegate.clone(), + deadline, + } + .into(), + ); + assert_eq!(Balances::reserved_balance(&item_owner), 0); + assert_eq!( + CollectionApprovals::get((collection_id, &item_owner, &delegate)), + Some((deadline, 0)) + ); + } + + // Set collection settings to non transferable. + assert_ok!(Nfts::lock_collection( + RuntimeOrigin::signed(collection_owner), + collection_id, + CollectionSettings::from_disabled(CollectionSetting::TransferableItems.into()) + )); + assert_noop!( + Nfts::force_approve_collection_transfer( + RuntimeOrigin::root(), + item_owner, + collection_id, + delegate, + None + ), + Error::::ItemsNonTransferable + ); + }); +} + +#[test] +fn cancel_collection_approval_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let collection_owner = account(1); + let delegate = account(3); + let item_id = 42; + let item_owner = account(2); + + for origin in [RuntimeOrigin::root(), none()] { + assert_noop!( + Nfts::cancel_collection_approval(origin, collection_id, delegate.clone()), + BadOrigin + ); + } + Balances::make_free_balance_be(&item_owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + collection_owner.clone(), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(collection_owner), + collection_id, + item_id, + item_owner.clone(), + default_item_config() + )); + // Cancel an approval for a non existing collection. + assert_noop!( + Nfts::cancel_collection_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone() + ), + Error::::NotDelegate + ); + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + None + )); + // Cancel an unapproved delegate. + assert_noop!( + Nfts::cancel_collection_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + account(69) + ), + Error::::NotDelegate + ); + // Successfully cancel a collection approval. + assert_ok!(Nfts::cancel_collection_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone() + )); + assert_eq!(Balances::reserved_balance(&item_owner), 0); + assert!(!CollectionApprovals::contains_key((collection_id, &item_owner, &delegate))); + System::assert_last_event( + Event::::ApprovalCancelled { + collection: collection_id, + item: None, + owner: item_owner, + delegate, + } + .into(), + ); + }); +} + +#[test] +fn force_cancel_collection_approval_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let collection_owner = account(1); + let delegate = account(3); + let item_id = 42; + let item_owner = account(2); + + for origin in [RuntimeOrigin::signed(item_owner.clone()), none()] { + assert_noop!( + Nfts::force_cancel_collection_approval( + origin, + item_owner.clone(), + collection_id, + delegate.clone() + ), + BadOrigin + ); + } + Balances::make_free_balance_be(&item_owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + collection_owner.clone(), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(collection_owner), + collection_id, + item_id, + item_owner.clone(), + default_item_config() + )); + // Cancel an approval for a non existing collection. + assert_noop!( + Nfts::force_cancel_collection_approval( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + delegate.clone() + ), + Error::::NotDelegate + ); + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + None + )); + // Cancel an unapproved delegate. + assert_noop!( + Nfts::force_cancel_collection_approval( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + account(69) + ), + Error::::NotDelegate + ); + // Successfully cancel a collection approval. + assert_ok!(Nfts::force_cancel_collection_approval( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + delegate.clone() + )); + assert_eq!(Balances::reserved_balance(&item_owner), 0); + assert!(!CollectionApprovals::contains_key((collection_id, &item_owner, &delegate))); + System::assert_last_event( + Event::::ApprovalCancelled { + collection: collection_id, + item: None, + owner: item_owner, + delegate, + } + .into(), + ); + }); +} + +#[test] +fn check_approval_permission_without_deadline_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let collection_owner = account(1); + let delegate = account(3); + let item_id = 42; + let item_owner = account(2); + + Balances::make_free_balance_be(&item_owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + collection_owner.clone(), + default_collection_config() + )); + // Item doesn't exist. + assert_noop!( + Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate), + Error::::NoPermission + ); + assert_noop!( + Nfts::check_approval_permission(&collection_id, &Some(item_id), &item_owner, &delegate), + Error::::UnknownItem + ); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(collection_owner.clone()), + collection_id, + item_id, + item_owner.clone(), + default_item_config() + )); + // No approval. + assert_noop!( + Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate), + Error::::NoPermission + ); + assert_noop!( + Nfts::check_approval_permission(&collection_id, &Some(item_id), &item_owner, &delegate), + Error::::NoPermission + ); + + // Approve collection without deadline. + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + None + )); + assert_ok!(Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate)); + assert_ok!(Nfts::check_approval_permission( + &collection_id, + &Some(item_id), + &item_owner, + &delegate + )); + assert_ok!(Nfts::cancel_collection_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone() + )); + + // Approve item without deadline. + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + item_id, + delegate.clone(), + None + )); + assert_noop!( + Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate), + Error::::NoPermission + ); + assert_ok!(Nfts::check_approval_permission( + &collection_id, + &Some(item_id), + &item_owner, + &delegate + )); + assert_ok!(Nfts::cancel_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + item_id, + delegate.clone() + )); + + // Approve collection and item without deadline. + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + item_id, + delegate.clone(), + None + )); + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + None + )); + assert_ok!(Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate)); + assert_ok!(Nfts::check_approval_permission( + &collection_id, + &Some(item_id), + &item_owner, + &delegate + )); + }); +} + +#[test] +fn check_approval_permission_with_deadline_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let collection_owner = account(1); + let delegate = account(3); + let item_id = 42; + let item_owner = account(2); + + Balances::make_free_balance_be(&item_owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + collection_owner.clone(), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(collection_owner.clone()), + collection_id, + item_id, + item_owner.clone(), + default_item_config() + )); + + // Approve collection with deadline. + let deadline: BlockNumberFor = 10; + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + Some(deadline), + )); + assert_ok!(Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate)); + assert_ok!(Nfts::check_approval_permission( + &collection_id, + &Some(item_id), + &item_owner, + &delegate + )); + // Expire approval. + System::set_block_number(deadline + System::block_number() + 1); + assert_noop!( + Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate), + Error::::ApprovalExpired + ); + assert_noop!( + Nfts::check_approval_permission(&collection_id, &Some(item_id), &item_owner, &delegate), + Error::::NoPermission + ); + assert_ok!(Nfts::cancel_collection_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + )); + + // Approve item with deadline. + let deadline: BlockNumberFor = 20; + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + item_id, + delegate.clone(), + Some(deadline), + )); + assert_noop!( + Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate), + Error::::NoPermission + ); + assert_ok!(Nfts::check_approval_permission( + &collection_id, + &Some(item_id), + &item_owner, + &delegate + )); + // Expire approval. + System::set_block_number(deadline + System::block_number() + 1); + assert_noop!( + Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate), + Error::::NoPermission + ); + assert_noop!( + Nfts::check_approval_permission(&collection_id, &Some(item_id), &item_owner, &delegate), + Error::::ApprovalExpired + ); + assert_ok!(Nfts::cancel_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + item_id, + delegate.clone(), + )); + + // Approve collection and item with deadline. + let deadline: BlockNumberFor = 30; + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + item_id, + delegate.clone(), + Some(deadline) + )); + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + Some(deadline) + )); + assert_ok!(Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate)); + assert_ok!(Nfts::check_approval_permission( + &collection_id, + &Some(item_id), + &item_owner, + &delegate + )); + // Expire approvals. + System::set_block_number(deadline + System::block_number() + 1); + assert_noop!( + Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate), + Error::::ApprovalExpired + ); + assert_noop!( + Nfts::check_approval_permission(&collection_id, &Some(item_id), &item_owner, &delegate), + Error::::ApprovalExpired + ); + }); +} diff --git a/pallets/nfts/src/types.rs b/pallets/nfts/src/types.rs index f08f1d097..135702b00 100644 --- a/pallets/nfts/src/types.rs +++ b/pallets/nfts/src/types.rs @@ -89,6 +89,9 @@ pub(super) type PreSignedAttributesOf = PreSignedAttributes< ::AccountId, BlockNumberFor, >; +/// A type alias for the depositor account and its associated deposited amount. +pub(super) type AccountDepositOf = + (::AccountId, DepositBalanceOf); /// Information about a collection. #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] diff --git a/pallets/nfts/src/weights.rs b/pallets/nfts/src/weights.rs index c5fb60a22..34e2d5408 100644 --- a/pallets/nfts/src/weights.rs +++ b/pallets/nfts/src/weights.rs @@ -17,14 +17,14 @@ //! Autogenerated weights for `pallet_nfts` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-04-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 40.0.0 +//! DATE: 2025-01-14, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `R0GUE`, CPU: `` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// ./target/production/pop-node // benchmark // pallet // --chain=dev @@ -34,12 +34,11 @@ // --no-storage-info // --no-median-slopes // --no-min-squares -// --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./substrate/frame/nfts/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --output=./pallets/nfts/src/weights.rs +// --template=./scripts/pallet-weights-template.hbs +// --extrinsic= #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -90,6 +89,12 @@ pub trait WeightInfo { fn claim_swap() -> Weight; fn mint_pre_signed(n: u32, ) -> Weight; fn set_attributes_pre_signed(n: u32, ) -> Weight; + fn approve_collection_transfer() -> Weight; + fn force_approve_collection_transfer() -> Weight; + fn cancel_collection_approval() -> Weight; + fn force_cancel_collection_approval() -> Weight; + fn clear_collection_approvals(n: u32, ) -> Weight; + fn force_clear_collection_approvals(n: u32, ) -> Weight; } /// Weights for `pallet_nfts` using the Substrate node and recommended hardware. @@ -107,10 +112,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: - // Measured: `216` + // Measured: `105` // Estimated: `3549` - // Minimum execution time: 34_863_000 picoseconds. - Weight::from_parts(36_679_000, 3549) + // Minimum execution time: 20_000_000 picoseconds. + Weight::from_parts(21_000_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -126,15 +131,17 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_create() -> Weight { // Proof Size summary in bytes: - // Measured: `76` + // Measured: `3` // Estimated: `3549` - // Minimum execution time: 19_631_000 picoseconds. - Weight::from_parts(20_384_000, 3549) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionApprovals` (r:1 w:0) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) @@ -152,15 +159,19 @@ impl WeightInfo for SubstrateWeight { /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. - fn destroy(_m: u32, _c: u32, a: u32, ) -> Weight { + fn destroy(m: u32, c: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32204 + a * (366 ±0)` + // Measured: `32137 + a * (366 ±0)` // Estimated: `2523990 + a * (2954 ±0)` - // Minimum execution time: 1_282_083_000 picoseconds. - Weight::from_parts(1_249_191_963, 2523990) - // Standard Error: 4_719 - .saturating_add(Weight::from_parts(6_470_227, 0).saturating_mul(a.into())) - .saturating_add(T::DbWeight::get().reads(1004_u64)) + // Minimum execution time: 902_000_000 picoseconds. + Weight::from_parts(786_614_356, 2523990) + // Standard Error: 18_860 + .saturating_add(Weight::from_parts(85_114, 0).saturating_mul(m.into())) + // Standard Error: 18_860 + .saturating_add(Weight::from_parts(52_018, 0).saturating_mul(c.into())) + // Standard Error: 18_860 + .saturating_add(Weight::from_parts(4_806_613, 0).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(1005_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(1005_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) @@ -174,18 +185,20 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: - // Measured: `455` + // Measured: `382` // Estimated: `4326` - // Minimum execution time: 49_055_000 picoseconds. - Weight::from_parts(50_592_000, 4326) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + // Minimum execution time: 36_000_000 picoseconds. + Weight::from_parts(38_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -195,18 +208,20 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn force_mint() -> Weight { // Proof Size summary in bytes: - // Measured: `455` + // Measured: `382` // Estimated: `4326` - // Minimum execution time: 47_102_000 picoseconds. - Weight::from_parts(48_772_000, 4326) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(4_u64)) + // Minimum execution time: 35_000_000 picoseconds. + Weight::from_parts(36_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) @@ -218,22 +233,24 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:0 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: - // Measured: `564` + // Measured: `634` // Estimated: `4326` - // Minimum execution time: 52_968_000 picoseconds. - Weight::from_parts(55_136_000, 4326) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) + // Minimum execution time: 39_000_000 picoseconds. + Weight::from_parts(41_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) @@ -245,6 +262,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionApprovals` (r:1 w:0) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:2) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) @@ -253,12 +274,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `593` - // Estimated: `4326` - // Minimum execution time: 41_140_000 picoseconds. - Weight::from_parts(43_288_000, 4326) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + // Measured: `696` + // Estimated: `6180` + // Minimum execution time: 45_000_000 picoseconds. + Weight::from_parts(52_000_000, 6180) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) @@ -269,12 +290,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `763 + i * (108 ±0)` + // Measured: `690 + i * (108 ±0)` // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 14_433_000 picoseconds. - Weight::from_parts(14_664_000, 3549) - // Standard Error: 23_078 - .saturating_add(Weight::from_parts(15_911_377, 0).saturating_mul(i.into())) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 3549) + // Standard Error: 24_440 + .saturating_add(Weight::from_parts(12_497_458, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -286,10 +307,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 18_307_000 picoseconds. - Weight::from_parts(18_966_000, 3534) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -299,10 +320,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn unlock_item_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 18_078_000 picoseconds. - Weight::from_parts(18_593_000, 3534) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -312,10 +333,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn lock_collection() -> Weight { // Proof Size summary in bytes: - // Measured: `340` + // Measured: `267` // Estimated: `3549` - // Minimum execution time: 15_175_000 picoseconds. - Weight::from_parts(15_762_000, 3549) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -329,10 +350,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `562` + // Measured: `417` // Estimated: `3593` - // Minimum execution time: 26_164_000 picoseconds. - Weight::from_parts(27_117_000, 3593) + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(16_000_000, 3593) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -342,10 +363,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: - // Measured: `369` + // Measured: `296` // Estimated: `6078` - // Minimum execution time: 38_523_000 picoseconds. - Weight::from_parts(39_486_000, 6078) + // Minimum execution time: 26_000_000 picoseconds. + Weight::from_parts(68_000_000, 6078) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -355,10 +376,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: - // Measured: `311` + // Measured: `238` // Estimated: `3549` - // Minimum execution time: 15_733_000 picoseconds. - Weight::from_parts(16_227_000, 3549) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 3549) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -368,10 +389,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn force_collection_config() -> Weight { // Proof Size summary in bytes: - // Measured: `276` + // Measured: `203` // Estimated: `3549` - // Minimum execution time: 12_042_000 picoseconds. - Weight::from_parts(12_690_000, 3549) + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(8_000_000, 3549) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -381,10 +402,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_properties() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 17_165_000 picoseconds. - Weight::from_parts(17_769_000, 3534) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(13_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -400,10 +421,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `499` // Estimated: `3944` - // Minimum execution time: 48_862_000 picoseconds. - Weight::from_parts(50_584_000, 3944) + // Minimum execution time: 29_000_000 picoseconds. + Weight::from_parts(31_000_000, 3944) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -413,10 +434,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `344` + // Measured: `271` // Estimated: `3944` - // Minimum execution time: 24_665_000 picoseconds. - Weight::from_parts(25_465_000, 3944) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(15_000_000, 3944) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -430,30 +451,30 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `983` + // Measured: `943` // Estimated: `3944` - // Minimum execution time: 44_617_000 picoseconds. - Weight::from_parts(46_458_000, 3944) + // Minimum execution time: 27_000_000 picoseconds. + Weight::from_parts(28_000_000, 3944) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) fn approve_item_attributes() -> Weight { // Proof Size summary in bytes: - // Measured: `381` - // Estimated: `4326` - // Minimum execution time: 15_710_000 picoseconds. - Weight::from_parts(16_191_000, 4326) + // Measured: `308` + // Estimated: `4466` + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(12_000_000, 4466) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1001 w:1000) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -461,12 +482,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 1000]`. fn cancel_item_attributes_approval(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `831 + n * (398 ±0)` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 24_447_000 picoseconds. - Weight::from_parts(25_144_000, 4326) - // Standard Error: 4_872 - .saturating_add(Weight::from_parts(6_523_101, 0).saturating_mul(n.into())) + // Measured: `686 + n * (398 ±0)` + // Estimated: `4466 + n * (2954 ±0)` + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(17_000_000, 4466) + // Standard Error: 8_501 + .saturating_add(Weight::from_parts(4_744_468, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -485,10 +506,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `499` // Estimated: `3812` - // Minimum execution time: 39_990_000 picoseconds. - Weight::from_parts(41_098_000, 3812) + // Minimum execution time: 23_000_000 picoseconds. + Weight::from_parts(25_000_000, 3812) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -502,10 +523,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `849` + // Measured: `809` // Estimated: `3812` - // Minimum execution time: 38_030_000 picoseconds. - Weight::from_parts(39_842_000, 3812) + // Minimum execution time: 23_000_000 picoseconds. + Weight::from_parts(25_000_000, 3812) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -519,10 +540,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `398` + // Measured: `325` // Estimated: `3759` - // Minimum execution time: 36_778_000 picoseconds. - Weight::from_parts(38_088_000, 3759) + // Minimum execution time: 21_000_000 picoseconds. + Weight::from_parts(22_000_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -536,10 +557,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `716` + // Measured: `643` // Estimated: `3759` - // Minimum execution time: 36_887_000 picoseconds. - Weight::from_parts(38_406_000, 3759) + // Minimum execution time: 21_000_000 picoseconds. + Weight::from_parts(22_000_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -549,43 +570,47 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn approve_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `410` + // Measured: `337` // Estimated: `4326` - // Minimum execution time: 18_734_000 picoseconds. - Weight::from_parts(19_267_000, 4326) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionApprovals` (r:1 w:0) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) fn cancel_approval() -> Weight { // Proof Size summary in bytes: - // Measured: `418` + // Measured: `345` // Estimated: `4326` - // Minimum execution time: 16_080_000 picoseconds. - Weight::from_parts(16_603_000, 4326) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionApprovals` (r:1 w:0) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) fn clear_all_transfer_approvals() -> Weight { // Proof Size summary in bytes: - // Measured: `418` + // Measured: `345` // Estimated: `4326` - // Minimum execution time: 15_013_000 picoseconds. - Weight::from_parts(15_607_000, 4326) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Minimum execution time: 12_000_000 picoseconds. + Weight::from_parts(14_000_000, 4326) + .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn set_accept_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `76` + // Measured: `3` // Estimated: `3517` - // Minimum execution time: 13_077_000 picoseconds. - Weight::from_parts(13_635_000, 3517) + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(7_000_000, 3517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -595,10 +620,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: - // Measured: `340` + // Measured: `267` // Estimated: `3549` - // Minimum execution time: 17_146_000 picoseconds. - Weight::from_parts(17_453_000, 3549) + // Minimum execution time: 10_000_000 picoseconds. + Weight::from_parts(13_000_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -608,10 +633,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn update_mint_settings() -> Weight { // Proof Size summary in bytes: - // Measured: `323` + // Measured: `250` // Estimated: `3538` - // Minimum execution time: 16_102_000 picoseconds. - Weight::from_parts(16_629_000, 3538) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(11_000_000, 3538) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -625,10 +650,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn set_price() -> Weight { // Proof Size summary in bytes: - // Measured: `518` + // Measured: `478` // Estimated: `4326` - // Minimum execution time: 22_118_000 picoseconds. - Weight::from_parts(22_849_000, 4326) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(15_000_000, 4326) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -644,28 +669,32 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:2) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn buy_item() -> Weight { // Proof Size summary in bytes: - // Measured: `705` - // Estimated: `4326` - // Minimum execution time: 50_369_000 picoseconds. - Weight::from_parts(51_816_000, 4326) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) + // Measured: `877` + // Estimated: `6180` + // Minimum execution time: 49_000_000 picoseconds. + Weight::from_parts(54_000_000, 6180) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) } /// The range of component `n` is `[0, 10]`. fn pay_tips(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_203_000 picoseconds. - Weight::from_parts(3_710_869, 0) - // Standard Error: 8_094 - .saturating_add(Weight::from_parts(2_201_869, 0).saturating_mul(n.into())) + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(1_206_012, 0) + // Standard Error: 11_245 + .saturating_add(Weight::from_parts(1_656_192, 0).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:2 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -673,10 +702,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn create_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `494` + // Measured: `421` // Estimated: `7662` - // Minimum execution time: 18_893_000 picoseconds. - Weight::from_parts(19_506_000, 7662) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 7662) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -686,10 +715,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn cancel_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `513` + // Measured: `440` // Estimated: `4326` - // Minimum execution time: 19_086_000 picoseconds. - Weight::from_parts(19_609_000, 4326) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -705,18 +734,22 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:2 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:4) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:2) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn claim_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `834` + // Measured: `1118` // Estimated: `7662` - // Minimum execution time: 84_103_000 picoseconds. - Weight::from_parts(85_325_000, 7662) - .saturating_add(T::DbWeight::get().reads(9_u64)) - .saturating_add(T::DbWeight::get().writes(10_u64)) + // Minimum execution time: 75_000_000 picoseconds. + Weight::from_parts(84_000_000, 7662) + .saturating_add(T::DbWeight::get().reads(12_u64)) + .saturating_add(T::DbWeight::get().writes(13_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -726,10 +759,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:10 w:10) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) @@ -739,22 +774,22 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `629` + // Measured: `485` // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 128_363_000 picoseconds. - Weight::from_parts(139_474_918, 6078) - // Standard Error: 79_252 - .saturating_add(Weight::from_parts(31_384_027, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) + // Minimum execution time: 90_000_000 picoseconds. + Weight::from_parts(98_359_609, 6078) + // Standard Error: 115_405 + .saturating_add(Weight::from_parts(20_931_944, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) - .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) @@ -766,18 +801,102 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `659` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 66_688_000 picoseconds. - Weight::from_parts(79_208_379, 4326) - // Standard Error: 74_020 - .saturating_add(Weight::from_parts(31_028_221, 0).saturating_mul(n.into())) + // Measured: `514` + // Estimated: `4466 + n * (2954 ±0)` + // Minimum execution time: 47_000_000 picoseconds. + Weight::from_parts(55_680_600, 4466) + // Standard Error: 107_152 + .saturating_add(Weight::from_parts(20_234_822, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionApprovals` (r:1 w:1) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) + fn approve_collection_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `500` + // Estimated: `3602` + // Minimum execution time: 20_000_000 picoseconds. + Weight::from_parts(25_000_000, 3602) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionApprovals` (r:1 w:1) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) + fn force_approve_collection_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `500` + // Estimated: `3602` + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(15_000_000, 3602) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionApprovals` (r:1 w:1) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) + fn cancel_collection_approval() -> Weight { + // Proof Size summary in bytes: + // Measured: `359` + // Estimated: `3602` + // Minimum execution time: 16_000_000 picoseconds. + Weight::from_parts(18_000_000, 3602) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionApprovals` (r:1 w:1) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) + fn force_cancel_collection_approval() -> Weight { + // Proof Size summary in bytes: + // Measured: `359` + // Estimated: `3602` + // Minimum execution time: 16_000_000 picoseconds. + Weight::from_parts(17_000_000, 3602) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionApprovals` (r:1000 w:999) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 1000]`. + fn clear_collection_approvals(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `327 + n * (75 ±0)` + // Estimated: `3602 + n * (2612 ±0)` + // Minimum execution time: 18_000_000 picoseconds. + Weight::from_parts(18_000_000, 3602) + // Standard Error: 6_993 + .saturating_add(Weight::from_parts(3_855_667, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2612).saturating_mul(n.into())) + } + /// Storage: `Nfts::CollectionApprovals` (r:1000 w:999) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 1000]`. + fn force_clear_collection_approvals(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `327 + n * (75 ±0)` + // Estimated: `3602 + n * (2612 ±0)` + // Minimum execution time: 19_000_000 picoseconds. + Weight::from_parts(20_000_000, 3602) + // Standard Error: 6_538 + .saturating_add(Weight::from_parts(3_823_979, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2612).saturating_mul(n.into())) + } } // For backwards compatibility and tests. @@ -794,10 +913,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn create() -> Weight { // Proof Size summary in bytes: - // Measured: `216` + // Measured: `105` // Estimated: `3549` - // Minimum execution time: 34_863_000 picoseconds. - Weight::from_parts(36_679_000, 3549) + // Minimum execution time: 20_000_000 picoseconds. + Weight::from_parts(21_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -813,15 +932,17 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_create() -> Weight { // Proof Size summary in bytes: - // Measured: `76` + // Measured: `3` // Estimated: `3549` - // Minimum execution time: 19_631_000 picoseconds. - Weight::from_parts(20_384_000, 3549) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Collection` (r:1 w:1) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionApprovals` (r:1 w:0) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) @@ -839,15 +960,19 @@ impl WeightInfo for () { /// The range of component `m` is `[0, 1000]`. /// The range of component `c` is `[0, 1000]`. /// The range of component `a` is `[0, 1000]`. - fn destroy(_m: u32, _c: u32, a: u32, ) -> Weight { + fn destroy(m: u32, c: u32, a: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `32204 + a * (366 ±0)` + // Measured: `32137 + a * (366 ±0)` // Estimated: `2523990 + a * (2954 ±0)` - // Minimum execution time: 1_282_083_000 picoseconds. - Weight::from_parts(1_249_191_963, 2523990) - // Standard Error: 4_719 - .saturating_add(Weight::from_parts(6_470_227, 0).saturating_mul(a.into())) - .saturating_add(RocksDbWeight::get().reads(1004_u64)) + // Minimum execution time: 902_000_000 picoseconds. + Weight::from_parts(786_614_356, 2523990) + // Standard Error: 18_860 + .saturating_add(Weight::from_parts(85_114, 0).saturating_mul(m.into())) + // Standard Error: 18_860 + .saturating_add(Weight::from_parts(52_018, 0).saturating_mul(c.into())) + // Standard Error: 18_860 + .saturating_add(Weight::from_parts(4_806_613, 0).saturating_mul(a.into())) + .saturating_add(RocksDbWeight::get().reads(1005_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(RocksDbWeight::get().writes(1005_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(a.into()))) @@ -861,18 +986,20 @@ impl WeightInfo for () { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn mint() -> Weight { // Proof Size summary in bytes: - // Measured: `455` + // Measured: `382` // Estimated: `4326` - // Minimum execution time: 49_055_000 picoseconds. - Weight::from_parts(50_592_000, 4326) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + // Minimum execution time: 36_000_000 picoseconds. + Weight::from_parts(38_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -882,18 +1009,20 @@ impl WeightInfo for () { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) fn force_mint() -> Weight { // Proof Size summary in bytes: - // Measured: `455` + // Measured: `382` // Estimated: `4326` - // Minimum execution time: 47_102_000 picoseconds. - Weight::from_parts(48_772_000, 4326) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) + // Minimum execution time: 35_000_000 picoseconds. + Weight::from_parts(36_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `Nfts::Attribute` (r:1 w:0) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) @@ -905,22 +1034,24 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:1) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:0 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn burn() -> Weight { // Proof Size summary in bytes: - // Measured: `564` + // Measured: `634` // Estimated: `4326` - // Minimum execution time: 52_968_000 picoseconds. - Weight::from_parts(55_136_000, 4326) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) + // Minimum execution time: 39_000_000 picoseconds. + Weight::from_parts(41_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) @@ -932,6 +1063,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionApprovals` (r:1 w:0) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:2) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) @@ -940,12 +1075,12 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `593` - // Estimated: `4326` - // Minimum execution time: 41_140_000 picoseconds. - Weight::from_parts(43_288_000, 4326) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + // Measured: `696` + // Estimated: `6180` + // Minimum execution time: 45_000_000 picoseconds. + Weight::from_parts(52_000_000, 6180) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) @@ -956,12 +1091,12 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 5000]`. fn redeposit(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `763 + i * (108 ±0)` + // Measured: `690 + i * (108 ±0)` // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 14_433_000 picoseconds. - Weight::from_parts(14_664_000, 3549) - // Standard Error: 23_078 - .saturating_add(Weight::from_parts(15_911_377, 0).saturating_mul(i.into())) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 3549) + // Standard Error: 24_440 + .saturating_add(Weight::from_parts(12_497_458, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -973,10 +1108,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 18_307_000 picoseconds. - Weight::from_parts(18_966_000, 3534) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -986,10 +1121,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn unlock_item_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 18_078_000 picoseconds. - Weight::from_parts(18_593_000, 3534) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(11_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -999,10 +1134,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn lock_collection() -> Weight { // Proof Size summary in bytes: - // Measured: `340` + // Measured: `267` // Estimated: `3549` - // Minimum execution time: 15_175_000 picoseconds. - Weight::from_parts(15_762_000, 3549) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1016,10 +1151,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn transfer_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `562` + // Measured: `417` // Estimated: `3593` - // Minimum execution time: 26_164_000 picoseconds. - Weight::from_parts(27_117_000, 3593) + // Minimum execution time: 15_000_000 picoseconds. + Weight::from_parts(16_000_000, 3593) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -1029,10 +1164,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) fn set_team() -> Weight { // Proof Size summary in bytes: - // Measured: `369` + // Measured: `296` // Estimated: `6078` - // Minimum execution time: 38_523_000 picoseconds. - Weight::from_parts(39_486_000, 6078) + // Minimum execution time: 26_000_000 picoseconds. + Weight::from_parts(68_000_000, 6078) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -1042,10 +1177,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) fn force_collection_owner() -> Weight { // Proof Size summary in bytes: - // Measured: `311` + // Measured: `238` // Estimated: `3549` - // Minimum execution time: 15_733_000 picoseconds. - Weight::from_parts(16_227_000, 3549) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -1055,10 +1190,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn force_collection_config() -> Weight { // Proof Size summary in bytes: - // Measured: `276` + // Measured: `203` // Estimated: `3549` - // Minimum execution time: 12_042_000 picoseconds. - Weight::from_parts(12_690_000, 3549) + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(8_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1068,10 +1203,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn lock_item_properties() -> Weight { // Proof Size summary in bytes: - // Measured: `435` + // Measured: `395` // Estimated: `3534` - // Minimum execution time: 17_165_000 picoseconds. - Weight::from_parts(17_769_000, 3534) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(13_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1087,10 +1222,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `499` // Estimated: `3944` - // Minimum execution time: 48_862_000 picoseconds. - Weight::from_parts(50_584_000, 3944) + // Minimum execution time: 29_000_000 picoseconds. + Weight::from_parts(31_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1100,10 +1235,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) fn force_set_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `344` + // Measured: `271` // Estimated: `3944` - // Minimum execution time: 24_665_000 picoseconds. - Weight::from_parts(25_465_000, 3944) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(15_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1117,30 +1252,30 @@ impl WeightInfo for () { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn clear_attribute() -> Weight { // Proof Size summary in bytes: - // Measured: `983` + // Measured: `943` // Estimated: `3944` - // Minimum execution time: 44_617_000 picoseconds. - Weight::from_parts(46_458_000, 3944) + // Minimum execution time: 27_000_000 picoseconds. + Weight::from_parts(28_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) fn approve_item_attributes() -> Weight { // Proof Size summary in bytes: - // Measured: `381` - // Estimated: `4326` - // Minimum execution time: 15_710_000 picoseconds. - Weight::from_parts(16_191_000, 4326) + // Measured: `308` + // Estimated: `4466` + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(12_000_000, 4466) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:1001 w:1000) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -1148,12 +1283,12 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 1000]`. fn cancel_item_attributes_approval(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `831 + n * (398 ±0)` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 24_447_000 picoseconds. - Weight::from_parts(25_144_000, 4326) - // Standard Error: 4_872 - .saturating_add(Weight::from_parts(6_523_101, 0).saturating_mul(n.into())) + // Measured: `686 + n * (398 ±0)` + // Estimated: `4466 + n * (2954 ±0)` + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(17_000_000, 4466) + // Standard Error: 8_501 + .saturating_add(Weight::from_parts(4_744_468, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -1172,10 +1307,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`) fn set_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `539` + // Measured: `499` // Estimated: `3812` - // Minimum execution time: 39_990_000 picoseconds. - Weight::from_parts(41_098_000, 3812) + // Minimum execution time: 23_000_000 picoseconds. + Weight::from_parts(25_000_000, 3812) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1189,10 +1324,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) fn clear_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `849` + // Measured: `809` // Estimated: `3812` - // Minimum execution time: 38_030_000 picoseconds. - Weight::from_parts(39_842_000, 3812) + // Minimum execution time: 23_000_000 picoseconds. + Weight::from_parts(25_000_000, 3812) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1206,10 +1341,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn set_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `398` + // Measured: `325` // Estimated: `3759` - // Minimum execution time: 36_778_000 picoseconds. - Weight::from_parts(38_088_000, 3759) + // Minimum execution time: 21_000_000 picoseconds. + Weight::from_parts(22_000_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1223,10 +1358,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) fn clear_collection_metadata() -> Weight { // Proof Size summary in bytes: - // Measured: `716` + // Measured: `643` // Estimated: `3759` - // Minimum execution time: 36_887_000 picoseconds. - Weight::from_parts(38_406_000, 3759) + // Minimum execution time: 21_000_000 picoseconds. + Weight::from_parts(22_000_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1236,43 +1371,47 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn approve_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `410` + // Measured: `337` // Estimated: `4326` - // Minimum execution time: 18_734_000 picoseconds. - Weight::from_parts(19_267_000, 4326) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionApprovals` (r:1 w:0) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) fn cancel_approval() -> Weight { // Proof Size summary in bytes: - // Measured: `418` + // Measured: `345` // Estimated: `4326` - // Minimum execution time: 16_080_000 picoseconds. - Weight::from_parts(16_603_000, 4326) - .saturating_add(RocksDbWeight::get().reads(1_u64)) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionApprovals` (r:1 w:0) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) fn clear_all_transfer_approvals() -> Weight { // Proof Size summary in bytes: - // Measured: `418` + // Measured: `345` // Estimated: `4326` - // Minimum execution time: 15_013_000 picoseconds. - Weight::from_parts(15_607_000, 4326) - .saturating_add(RocksDbWeight::get().reads(1_u64)) + // Minimum execution time: 12_000_000 picoseconds. + Weight::from_parts(14_000_000, 4326) + .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) fn set_accept_ownership() -> Weight { // Proof Size summary in bytes: - // Measured: `76` + // Measured: `3` // Estimated: `3517` - // Minimum execution time: 13_077_000 picoseconds. - Weight::from_parts(13_635_000, 3517) + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(7_000_000, 3517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1282,10 +1421,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) fn set_collection_max_supply() -> Weight { // Proof Size summary in bytes: - // Measured: `340` + // Measured: `267` // Estimated: `3549` - // Minimum execution time: 17_146_000 picoseconds. - Weight::from_parts(17_453_000, 3549) + // Minimum execution time: 10_000_000 picoseconds. + Weight::from_parts(13_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1295,10 +1434,10 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn update_mint_settings() -> Weight { // Proof Size summary in bytes: - // Measured: `323` + // Measured: `250` // Estimated: `3538` - // Minimum execution time: 16_102_000 picoseconds. - Weight::from_parts(16_629_000, 3538) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(11_000_000, 3538) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1312,10 +1451,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn set_price() -> Weight { // Proof Size summary in bytes: - // Measured: `518` + // Measured: `478` // Estimated: `4326` - // Minimum execution time: 22_118_000 picoseconds. - Weight::from_parts(22_849_000, 4326) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(15_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1331,28 +1470,32 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:2) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn buy_item() -> Weight { // Proof Size summary in bytes: - // Measured: `705` - // Estimated: `4326` - // Minimum execution time: 50_369_000 picoseconds. - Weight::from_parts(51_816_000, 4326) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) + // Measured: `877` + // Estimated: `6180` + // Minimum execution time: 49_000_000 picoseconds. + Weight::from_parts(54_000_000, 6180) + .saturating_add(RocksDbWeight::get().reads(9_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) } /// The range of component `n` is `[0, 10]`. fn pay_tips(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_203_000 picoseconds. - Weight::from_parts(3_710_869, 0) - // Standard Error: 8_094 - .saturating_add(Weight::from_parts(2_201_869, 0).saturating_mul(n.into())) + // Minimum execution time: 1_000_000 picoseconds. + Weight::from_parts(1_206_012, 0) + // Standard Error: 11_245 + .saturating_add(Weight::from_parts(1_656_192, 0).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:2 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -1360,10 +1503,10 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn create_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `494` + // Measured: `421` // Estimated: `7662` - // Minimum execution time: 18_893_000 picoseconds. - Weight::from_parts(19_506_000, 7662) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 7662) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1373,10 +1516,10 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) fn cancel_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `513` + // Measured: `440` // Estimated: `4326` - // Minimum execution time: 19_086_000 picoseconds. - Weight::from_parts(19_609_000, 4326) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1392,18 +1535,22 @@ impl WeightInfo for () { /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemConfigOf` (r:2 w:0) /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:2 w:2) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:4) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:2) /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(89), added: 2564, mode: `MaxEncodedLen`) fn claim_swap() -> Weight { // Proof Size summary in bytes: - // Measured: `834` + // Measured: `1118` // Estimated: `7662` - // Minimum execution time: 84_103_000 picoseconds. - Weight::from_parts(85_325_000, 7662) - .saturating_add(RocksDbWeight::get().reads(9_u64)) - .saturating_add(RocksDbWeight::get().writes(10_u64)) + // Minimum execution time: 75_000_000 picoseconds. + Weight::from_parts(84_000_000, 7662) + .saturating_add(RocksDbWeight::get().reads(12_u64)) + .saturating_add(RocksDbWeight::get().writes(13_u64)) } /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(69), added: 2544, mode: `MaxEncodedLen`) @@ -1413,10 +1560,12 @@ impl WeightInfo for () { /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) - /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) - /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::AccountBalance` (r:1 w:1) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Attribute` (r:10 w:10) /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(479), added: 2954, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) @@ -1426,22 +1575,22 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 10]`. fn mint_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `629` + // Measured: `485` // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 128_363_000 picoseconds. - Weight::from_parts(139_474_918, 6078) - // Standard Error: 79_252 - .saturating_add(Weight::from_parts(31_384_027, 0).saturating_mul(n.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) + // Minimum execution time: 90_000_000 picoseconds. + Weight::from_parts(98_359_609, 6078) + // Standard Error: 115_405 + .saturating_add(Weight::from_parts(20_931_944, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) - .saturating_add(RocksDbWeight::get().writes(6_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:1 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) - /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(1001), added: 3476, mode: `MaxEncodedLen`) /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) /// Storage: `Nfts::Collection` (r:1 w:1) @@ -1453,16 +1602,100 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 10]`. fn set_attributes_pre_signed(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `659` - // Estimated: `4326 + n * (2954 ±0)` - // Minimum execution time: 66_688_000 picoseconds. - Weight::from_parts(79_208_379, 4326) - // Standard Error: 74_020 - .saturating_add(Weight::from_parts(31_028_221, 0).saturating_mul(n.into())) + // Measured: `514` + // Estimated: `4466 + n * (2954 ±0)` + // Minimum execution time: 47_000_000 picoseconds. + Weight::from_parts(55_680_600, 4466) + // Standard Error: 107_152 + .saturating_add(Weight::from_parts(20_234_822, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2954).saturating_mul(n.into())) } + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionApprovals` (r:1 w:1) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) + fn approve_collection_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `500` + // Estimated: `3602` + // Minimum execution time: 20_000_000 picoseconds. + Weight::from_parts(25_000_000, 3602) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::AccountBalance` (r:1 w:0) + /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionApprovals` (r:1 w:1) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) + fn force_approve_collection_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `500` + // Estimated: `3602` + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(15_000_000, 3602) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionApprovals` (r:1 w:1) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) + fn cancel_collection_approval() -> Weight { + // Proof Size summary in bytes: + // Measured: `359` + // Estimated: `3602` + // Minimum execution time: 16_000_000 picoseconds. + Weight::from_parts(18_000_000, 3602) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionApprovals` (r:1 w:1) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) + fn force_cancel_collection_approval() -> Weight { + // Proof Size summary in bytes: + // Measured: `359` + // Estimated: `3602` + // Minimum execution time: 16_000_000 picoseconds. + Weight::from_parts(17_000_000, 3602) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionApprovals` (r:1000 w:999) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 1000]`. + fn clear_collection_approvals(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `327 + n * (75 ±0)` + // Estimated: `3602 + n * (2612 ±0)` + // Minimum execution time: 18_000_000 picoseconds. + Weight::from_parts(18_000_000, 3602) + // Standard Error: 6_993 + .saturating_add(Weight::from_parts(3_855_667, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2612).saturating_mul(n.into())) + } + /// Storage: `Nfts::CollectionApprovals` (r:1000 w:999) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 1000]`. + fn force_clear_collection_approvals(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `327 + n * (75 ±0)` + // Estimated: `3602 + n * (2612 ±0)` + // Minimum execution time: 19_000_000 picoseconds. + Weight::from_parts(20_000_000, 3602) + // Standard Error: 6_538 + .saturating_add(Weight::from_parts(3_823_979, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2612).saturating_mul(n.into())) + } } diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 326b7e594..6a54f368c 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -29,7 +29,11 @@ parameter_types! { parameter_types! { pub NftsPalletFeatures: PalletFeatures = PalletFeatures::all_enabled(); + // Key = 68 bytes (4+16+32+16), Value = 52 bytes (4+32+16) + pub const NftsCollectionBalanceDeposit: Balance = deposit(1, 120); pub const NftsCollectionDeposit: Balance = 10 * UNIT; + // Key = 116 bytes (4+16+32+16+32+16), Value = 21 bytes (1+4+16) + pub const NftsCollectionApprovalDeposit: Balance = deposit(1, 137); pub const NftsItemDeposit: Balance = UNIT / 100; pub const NftsMetadataDepositBase: Balance = deposit(1, 129); pub const NftsAttributeDepositBase: Balance = deposit(1, 0); @@ -41,6 +45,8 @@ impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ApprovalsLimit = ConstU32<20>; type AttributeDepositBase = NftsAttributeDepositBase; + type CollectionApprovalDeposit = NftsCollectionApprovalDeposit; + type CollectionBalanceDeposit = NftsCollectionBalanceDeposit; type CollectionDeposit = NftsCollectionDeposit; // TODO: source from primitives type CollectionId = CollectionId; @@ -120,3 +126,28 @@ impl pallet_assets::Config for Runtime { type StringLimit = AssetsStringLimit; type WeightInfo = pallet_assets::weights::SubstrateWeight; } + +#[cfg(test)] +mod tests { + use frame_support::traits::StorageInfoTrait; + + use super::*; + + #[test] + fn ensure_account_balance_deposit() { + let max_size = pallet_nfts::AccountBalance::::storage_info() + .first() + .and_then(|info| info.max_size) + .unwrap_or_default(); + assert_eq!(deposit(1, max_size), NftsCollectionBalanceDeposit::get()); + } + + #[test] + fn ensure_collection_approval_deposit() { + let max_size = pallet_nfts::CollectionApprovals::::storage_info() + .first() + .and_then(|info| info.max_size) + .unwrap_or_default(); + assert_eq!(deposit(1, max_size), NftsCollectionApprovalDeposit::get()); + } +} diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index f539cbdee..caeb44142 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -648,6 +648,7 @@ mod benches { [pallet_session, SessionBench::] [pallet_timestamp, Timestamp] [pallet_message_queue, MessageQueue] + [pallet_nfts, Nfts] [pallet_sudo, Sudo] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] diff --git a/runtime/testnet/src/config/assets.rs b/runtime/testnet/src/config/assets.rs index 326b7e594..6a54f368c 100644 --- a/runtime/testnet/src/config/assets.rs +++ b/runtime/testnet/src/config/assets.rs @@ -29,7 +29,11 @@ parameter_types! { parameter_types! { pub NftsPalletFeatures: PalletFeatures = PalletFeatures::all_enabled(); + // Key = 68 bytes (4+16+32+16), Value = 52 bytes (4+32+16) + pub const NftsCollectionBalanceDeposit: Balance = deposit(1, 120); pub const NftsCollectionDeposit: Balance = 10 * UNIT; + // Key = 116 bytes (4+16+32+16+32+16), Value = 21 bytes (1+4+16) + pub const NftsCollectionApprovalDeposit: Balance = deposit(1, 137); pub const NftsItemDeposit: Balance = UNIT / 100; pub const NftsMetadataDepositBase: Balance = deposit(1, 129); pub const NftsAttributeDepositBase: Balance = deposit(1, 0); @@ -41,6 +45,8 @@ impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ApprovalsLimit = ConstU32<20>; type AttributeDepositBase = NftsAttributeDepositBase; + type CollectionApprovalDeposit = NftsCollectionApprovalDeposit; + type CollectionBalanceDeposit = NftsCollectionBalanceDeposit; type CollectionDeposit = NftsCollectionDeposit; // TODO: source from primitives type CollectionId = CollectionId; @@ -120,3 +126,28 @@ impl pallet_assets::Config for Runtime { type StringLimit = AssetsStringLimit; type WeightInfo = pallet_assets::weights::SubstrateWeight; } + +#[cfg(test)] +mod tests { + use frame_support::traits::StorageInfoTrait; + + use super::*; + + #[test] + fn ensure_account_balance_deposit() { + let max_size = pallet_nfts::AccountBalance::::storage_info() + .first() + .and_then(|info| info.max_size) + .unwrap_or_default(); + assert_eq!(deposit(1, max_size), NftsCollectionBalanceDeposit::get()); + } + + #[test] + fn ensure_collection_approval_deposit() { + let max_size = pallet_nfts::CollectionApprovals::::storage_info() + .first() + .and_then(|info| info.max_size) + .unwrap_or_default(); + assert_eq!(deposit(1, max_size), NftsCollectionApprovalDeposit::get()); + } +} From 868fcf86a05d0c75903328b447ff3e683c8c39ce Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 16 Jan 2025 12:38:23 +0700 Subject: [PATCH 75/76] chore: rebase pallet-nfts --- pallets/api/src/mock.rs | 2 +- pallets/api/src/nonfungibles/mod.rs | 3 +- pallets/api/src/nonfungibles/tests.rs | 19 +- pallets/nfts/src/benchmarking.rs | 20 +- pallets/nfts/src/common_functions.rs | 91 +- pallets/nfts/src/features/approvals.rs | 43 +- pallets/nfts/src/features/atomic_swap.rs | 6 +- pallets/nfts/src/features/buy_sell.rs | 2 +- .../nfts/src/features/create_delete_item.rs | 18 +- pallets/nfts/src/features/transfer.rs | 25 +- pallets/nfts/src/impl_nonfungibles.rs | 6 +- pallets/nfts/src/lib.rs | 59 +- pallets/nfts/src/mock.rs | 2 +- pallets/nfts/src/tests.rs | 2073 ++++++++++------- pallets/nfts/src/weights.rs | 338 +-- .../integration-tests/src/nonfungibles/mod.rs | 15 +- 16 files changed, 1566 insertions(+), 1156 deletions(-) diff --git a/pallets/api/src/mock.rs b/pallets/api/src/mock.rs index a721ee362..61cbc9fdf 100644 --- a/pallets/api/src/mock.rs +++ b/pallets/api/src/mock.rs @@ -165,8 +165,8 @@ type NftsInstance = pallet_nfts::Instance1; impl pallet_nfts::Config for Test { type ApprovalsLimit = ConstU32<10>; type AttributeDepositBase = ConstU128<1>; - type BalanceDeposit = ConstU128<1>; type CollectionApprovalDeposit = ConstU128<1>; + type CollectionBalanceDeposit = ConstU128<1>; type CollectionDeposit = ConstU128<2>; type CollectionId = u32; type CreateOrigin = AsEnsureOriginWithArg>; diff --git a/pallets/api/src/nonfungibles/mod.rs b/pallets/api/src/nonfungibles/mod.rs index 3057f2b33..47f5d11cb 100644 --- a/pallets/api/src/nonfungibles/mod.rs +++ b/pallets/api/src/nonfungibles/mod.rs @@ -571,7 +571,8 @@ pub mod pallet { .unwrap_or_default(), ), Allowance { collection, owner, operator, item } => ReadResult::Allowance( - NftsOf::::check_approval(&collection, &item, &owner, &operator).is_ok(), + NftsOf::::check_approval_permission(&collection, &item, &owner, &operator) + .is_ok(), ), OwnerOf { collection, item } => ReadResult::OwnerOf(NftsOf::::owner(collection, item)), diff --git a/pallets/api/src/nonfungibles/tests.rs b/pallets/api/src/nonfungibles/tests.rs index aec7c9dcb..cf1f91414 100644 --- a/pallets/api/src/nonfungibles/tests.rs +++ b/pallets/api/src/nonfungibles/tests.rs @@ -232,7 +232,7 @@ fn approve_works() { NonFungibles::approve(signed(owner), collection, Some(item), operator, true), Ok(Some(NftsWeightInfoOf::::approve_transfer()).into()) ); - assert_ok!(Nfts::check_approval(&collection, &Some(item), &owner, &operator)); + assert_ok!(Nfts::check_approval_permission(&collection, &Some(item), &owner, &operator)); System::assert_last_event( Event::Approval { collection, item: Some(item), owner, operator, approved: true } .into(), @@ -242,7 +242,7 @@ fn approve_works() { NonFungibles::approve(signed(owner), collection, Some(item), operator, true), Ok(Some(NftsWeightInfoOf::::approve_transfer()).into()) ); - assert_ok!(Nfts::check_approval(&collection, &Some(item), &owner, &operator)); + assert_ok!(Nfts::check_approval_permission(&collection, &Some(item), &owner, &operator)); System::assert_last_event( Event::Approval { collection, item: Some(item), owner, operator, approved: true } .into(), @@ -282,14 +282,14 @@ fn approve_collection_works() { ); let reserved_balance_after_approve = Balances::reserved_balance(&owner); assert_eq!(reserved_balance_after_approve - reserved_balance_before_approve, 1); - assert_ok!(Nfts::check_approval(&collection, &None, &owner, &operator)); + assert_ok!(Nfts::check_approval_permission(&collection, &None, &owner, &operator)); // Re-approving the transfer of `collection` does not require reserving additional funds. assert_eq!( NonFungibles::approve(signed(owner), collection, None, operator, true), Ok(Some(NftsWeightInfoOf::::approve_collection_transfer()).into()) ); assert_eq!(Balances::reserved_balance(&owner), reserved_balance_after_approve); - assert_ok!(Nfts::check_approval(&collection, &None, &owner, &operator)); + assert_ok!(Nfts::check_approval_permission(&collection, &None, &owner, &operator)); System::assert_last_event( Event::Approval { collection, item: None, owner, operator, approved: true }.into(), ); @@ -325,7 +325,7 @@ fn cancel_approval_works() { Ok(Some(NftsWeightInfoOf::::cancel_approval()).into()) ); assert_eq!( - Nfts::check_approval(&collection, &Some(item), &owner, &operator), + Nfts::check_approval_permission(&collection, &Some(item), &owner, &operator), Err(NftsError::NoPermission.into()) ); }); @@ -349,7 +349,7 @@ fn cancel_collection_approval_works() { // Check error works for `Nfts::cancel_approval()`. assert_noop!( NonFungibles::approve(signed(owner), collection, None, operator, false), - NftsError::Unapproved + NftsError::NotDelegate .with_weight(NftsWeightInfoOf::::cancel_collection_approval()) ); // Successfully cancel the transfer collection approval of `operator` by `owner`. @@ -360,7 +360,7 @@ fn cancel_collection_approval_works() { Ok(Some(NftsWeightInfoOf::::cancel_collection_approval()).into()) ); assert_eq!( - Nfts::check_approval(&collection, &None, &owner, &operator), + Nfts::check_approval_permission(&collection, &None, &owner, &operator), Err(NftsError::NoPermission.into()) ); // Failed to transfer the item by `operator` without permission. @@ -392,7 +392,8 @@ fn clear_all_transfer_approvals_works() { // Successfully clear all transfer approvals. assert_ok!(NonFungibles::clear_all_transfer_approvals(signed(owner), collection, item)); delegates.for_each(|delegate| { - assert!(Nfts::check_approval(&collection, &Some(item), &owner, &delegate).is_err()); + assert!(Nfts::check_approval_permission(&collection, &Some(item), &owner, &delegate) + .is_err()); }); }); } @@ -740,7 +741,7 @@ fn allowance_works() { assert_eq!( NonFungibles::read(Allowance { collection, item: Some(item), owner, operator }) .encode(), - Nfts::check_approval(&collection, &Some(item), &owner, &operator) + Nfts::check_approval_permission(&collection, &Some(item), &owner, &operator) .is_ok() .encode() ); diff --git a/pallets/nfts/src/benchmarking.rs b/pallets/nfts/src/benchmarking.rs index 481fbe17f..4b680f606 100644 --- a/pallets/nfts/src/benchmarking.rs +++ b/pallets/nfts/src/benchmarking.rs @@ -274,7 +274,7 @@ benchmarks_instance_pallet! { mint { let (collection, caller, caller_lookup) = create_collection::(); let item = T::Helper::item(0); - T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance() + T::CollectionDeposit::get() + T::BalanceDeposit::get()); + T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance() + T::CollectionDeposit::get() + T::CollectionBalanceDeposit::get()); }: _(SystemOrigin::Signed(caller.clone()), collection, item, caller_lookup, None) verify { assert_last_event::(Event::Issued { collection, item, owner: caller }.into()); @@ -283,7 +283,7 @@ benchmarks_instance_pallet! { force_mint { let (collection, caller, caller_lookup) = create_collection::(); let item = T::Helper::item(0); - T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance() + T::CollectionDeposit::get() + T::BalanceDeposit::get()); + T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance() + T::CollectionDeposit::get() + T::CollectionBalanceDeposit::get()); }: _(SystemOrigin::Signed(caller.clone()), collection, item, caller_lookup, default_item_config()) verify { assert_last_event::(Event::Issued { collection, item, owner: caller }.into()); @@ -298,13 +298,15 @@ benchmarks_instance_pallet! { } transfer { - let (collection, caller, _) = create_collection::(); - let (item, ..) = mint_item::(0); - + let (collection, ..) = create_collection::(); + let (item, caller, _) = mint_item::(0); + let delegate: T::AccountId = account("delegate", 0, SEED); + let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let target: T::AccountId = account("target", 0, SEED); let target_lookup = T::Lookup::unlookup(target.clone()); - T::Currency::make_free_balance_be(&target, T::Currency::minimum_balance() + T::BalanceDeposit::get()); - }: _(SystemOrigin::Signed(caller.clone()), collection, item, target_lookup) + let origin = SystemOrigin::Signed(caller.clone()).into(); + Nfts::::approve_transfer(origin, collection, item, delegate_lookup, None)?; + }: _(SystemOrigin::Signed(delegate), collection, item, target_lookup) verify { assert_last_event::(Event::Transferred { collection, item, from: caller, to: target }.into()); } @@ -669,7 +671,7 @@ benchmarks_instance_pallet! { let price = ItemPrice::::from(0u32); let origin = SystemOrigin::Signed(seller.clone()).into(); Nfts::::set_price(origin, collection, item, Some(price), Some(buyer_lookup))?; - T::Currency::make_free_balance_be(&buyer, T::Currency::minimum_balance() + price + T::BalanceDeposit::get()); + T::Currency::make_free_balance_be(&buyer, T::Currency::minimum_balance() + price + T::CollectionBalanceDeposit::get()); }: _(SystemOrigin::Signed(buyer.clone()), collection, item, price) verify { assert_last_event::(Event::ItemBought { @@ -759,7 +761,7 @@ benchmarks_instance_pallet! { let duration = T::MaxDeadlineDuration::get(); let target: T::AccountId = account("target", 0, SEED); let target_lookup = T::Lookup::unlookup(target.clone()); - T::Currency::make_free_balance_be(&target, T::Currency::minimum_balance() + T::BalanceDeposit::get()); + T::Currency::make_free_balance_be(&target, T::Currency::minimum_balance() + T::CollectionBalanceDeposit::get()); let origin = SystemOrigin::Signed(caller.clone()); frame_system::Pallet::::set_block_number(One::one()); Nfts::::transfer(origin.clone().into(), collection, item2, target_lookup)?; diff --git a/pallets/nfts/src/common_functions.rs b/pallets/nfts/src/common_functions.rs index 55a70cd06..f27a90290 100644 --- a/pallets/nfts/src/common_functions.rs +++ b/pallets/nfts/src/common_functions.rs @@ -98,10 +98,7 @@ impl, I: 'static> Pallet { pub(crate) fn increment_account_balance( collection: T::CollectionId, owner: &T::AccountId, - (deposit_account, deposit_amount): ( - &::AccountId, - DepositBalanceOf, - ), + (deposit_account, deposit_amount): (&T::AccountId, DepositBalanceOf), ) -> DispatchResult { AccountBalance::::mutate(collection, owner, |maybe_balance| -> DispatchResult { match maybe_balance { @@ -132,7 +129,7 @@ impl, I: 'static> Pallet { maybe_balance.as_mut().ok_or(Error::::NoItemOwned)?; *balance = balance.checked_sub(1).ok_or(ArithmeticError::Underflow)?; - if *balance == 0 { + if balance.is_zero() { T::Currency::unreserve(deposit_account, *deposit_amount); *maybe_balance = None; } @@ -154,3 +151,87 @@ impl, I: 'static> Pallet { .expect("Failed to get next collection ID") } } + +#[cfg(test)] +mod tests { + use crate::{mock::*, tests::*, Currency, Error, ReservableCurrency}; + + #[test] + fn increment_account_balance_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let deposit_account = account(1); + let deposit_amount = balance_deposit(); + let owner = account(2); + assert_noop!( + Nfts::increment_account_balance( + collection_id, + &owner, + (&deposit_account, deposit_amount) + ), + BalancesError::::InsufficientBalance + ); + Balances::make_free_balance_be(&deposit_account, 100); + // Initialize `AccountBalance` and increase the collection item count for the new + // account. + assert_ok!(Nfts::increment_account_balance( + collection_id, + &owner, + (&deposit_account, deposit_amount) + )); + assert_eq!(Balances::reserved_balance(&deposit_account), deposit_amount); + assert_eq!( + AccountBalance::get(collection_id, &owner), + Some((1, (deposit_account.clone(), deposit_amount))) + ); + // Increment the balance of a non-zero balance account. No additional reserves. + assert_ok!(Nfts::increment_account_balance( + collection_id, + &owner, + (&deposit_account, deposit_amount) + )); + assert_eq!(Balances::reserved_balance(&deposit_account), deposit_amount); + assert_eq!( + AccountBalance::get(collection_id, &owner), + Some((2, (deposit_account.clone(), deposit_amount))) + ); + }); + } + + #[test] + fn decrement_account_balance_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let balance = 2u32; + let deposit_account = account(1); + let deposit_amount = balance_deposit(); + let owner = account(2); + + Balances::make_free_balance_be(&deposit_account, 100); + // Decrement non-existing `AccountBalance` record. + assert_noop!( + Nfts::decrement_account_balance(collection_id, &deposit_account), + Error::::NoItemOwned + ); + // Set account balance and reserve `DepositBalance`. + AccountBalance::insert( + collection_id, + &owner, + (&balance, (&deposit_account, deposit_amount)), + ); + Balances::reserve(&deposit_account, deposit_amount).expect("should work"); + // Successfully decrement the value of the `AccountBalance` entry. + assert_ok!(Nfts::decrement_account_balance(collection_id, &owner)); + assert_eq!( + AccountBalance::get(collection_id, &owner), + Some((balance - 1, (deposit_account.clone(), deposit_amount))) + ); + assert_eq!(Balances::reserved_balance(&deposit_account), deposit_amount); + // `AccountBalance` record is deleted, and the depositor's funds are unreserved if + // the `AccountBalance` value reaches zero after decrementing. + assert_ok!(Nfts::decrement_account_balance(collection_id, &owner)); + assert_eq!(Balances::reserved_balance(&deposit_account), 0); + assert!(!AccountBalance::contains_key(collection_id, &owner)); + }); + } +} diff --git a/pallets/nfts/src/features/approvals.rs b/pallets/nfts/src/features/approvals.rs index 9021aac17..f7db22a74 100644 --- a/pallets/nfts/src/features/approvals.rs +++ b/pallets/nfts/src/features/approvals.rs @@ -188,7 +188,7 @@ impl, I: 'static> Pallet { Ok(()) } - /// Approves the transfer of all collection items of `owner` to a delegate. + /// Approves the transfer of all collection items of `owner` to a `delegate`. /// /// This function is used to approve the transfer of all (current and future) collection items /// of `owner` to a `delegate`. The `delegate` account will be allowed to take control of the @@ -203,13 +203,15 @@ impl, I: 'static> Pallet { /// /// - `owner`: The owner of the collection items. /// - `collection`: The identifier of the collection. - /// - `delegate`: The account that will be allowed to take control of the collection items. + /// - `delegate`: The account that will be approved to take control of the collection items. + /// - `deposit`: The reserved amount for granting a collection approval. /// - `maybe_deadline`: The optional deadline (in block numbers) specifying the time limit for /// the approval. pub(crate) fn do_approve_collection_transfer( owner: T::AccountId, collection: T::CollectionId, delegate: T::AccountId, + deposit: DepositBalanceOf, maybe_deadline: Option>, ) -> DispatchResult { ensure!( @@ -218,7 +220,7 @@ impl, I: 'static> Pallet { ); ensure!( AccountBalance::::get(collection, &owner) - .filter(|(balance, _)| *balance > 0) + .filter(|(balance, _)| !balance.is_zero()) .is_some(), Error::::NoItemOwned ); @@ -234,13 +236,10 @@ impl, I: 'static> Pallet { CollectionApprovals::::try_mutate_exists( (&collection, &owner, &delegate), |maybe_approval| -> DispatchResult { - let deposit_required = T::CollectionApprovalDeposit::get(); let current_deposit = - maybe_approval.take().map(|(_, deposit)| deposit).unwrap_or_default(); - if current_deposit < deposit_required { - T::Currency::reserve(&owner, deposit_required - current_deposit)?; - } - *maybe_approval = Some((deadline, deposit_required)); + maybe_approval.map(|(_, deposit)| deposit).unwrap_or_default(); + T::Currency::reserve(&owner, deposit.saturating_sub(current_deposit))?; + *maybe_approval = Some((deadline, deposit)); Ok(()) }, )?; @@ -271,7 +270,7 @@ impl, I: 'static> Pallet { delegate: T::AccountId, ) -> DispatchResult { let (_, deposit) = CollectionApprovals::::take((&collection, &owner, &delegate)) - .ok_or(Error::::Unapproved)?; + .ok_or(Error::::NotDelegate)?; T::Currency::unreserve(&owner, deposit); @@ -317,12 +316,12 @@ impl, I: 'static> Pallet { Ok(removed_approvals) } - /// Checks whether the `delegate` is approved to transfer collection items of `owner`. + /// Checks whether the `delegate` has permission to transfer collection items of `owner`. /// /// - `collection`: The identifier of the collection. /// - `owner`: The owner of the collection items. - /// - `delegate`: The account to check for approval to transfer collection items of `owner`. - fn check_collection_approval( + /// - `delegate`: The account to check for permission to transfer collection items of `owner`. + fn check_collection_approval_permission( collection: &T::CollectionId, owner: &T::AccountId, delegate: &T::AccountId, @@ -337,24 +336,26 @@ impl, I: 'static> Pallet { Ok(()) } - /// Checks whether the `delegate` is approved by `owner` to transfer its collection item(s). If - /// the `delegate` is approved for all `owner`'s collection items it can transfer every item - /// without requiring explicit approval for an item. + /// Checks whether the `delegate` has permission to transfer `owner`'s collection item(s). + /// If the `delegate` has permission to transfer all `owner`'s collection items, they can + /// transfer any item without needing explicit approval for each individual item. /// /// - `collection`: The identifier of the collection. - /// - `maybe_item`: The optional item of the collection that the delegated account has an - /// approval to transfer. If not provided, an approval to transfer all `owner`'s collection + /// - `maybe_item`: The optional item of the collection that the delegated account has + /// permission to transfer. If not provided, permission to transfer all `owner`'s collection /// items will be checked. /// - `owner`: The owner of the specified collection item. - /// - `delegate`: The account to check for approval to transfer collection item(s) of owner. - pub fn check_approval( + /// - `delegate`: The account to check for permission to transfer collection item(s) from the + /// owner. + pub fn check_approval_permission( collection: &T::CollectionId, maybe_item: &Option, owner: &T::AccountId, delegate: &T::AccountId, ) -> DispatchResult { // Check if `delegate` has permission to transfer `owner`'s collection items. - let Err(error) = Self::check_collection_approval(collection, owner, delegate) else { + let Err(error) = Self::check_collection_approval_permission(collection, owner, delegate) + else { return Ok(()); }; diff --git a/pallets/nfts/src/features/atomic_swap.rs b/pallets/nfts/src/features/atomic_swap.rs index 35e857525..1ffd6dce4 100644 --- a/pallets/nfts/src/features/atomic_swap.rs +++ b/pallets/nfts/src/features/atomic_swap.rs @@ -210,17 +210,19 @@ impl, I: 'static> Pallet { // This also removes the swap. Self::do_transfer( - &caller, send_collection_id, send_item_id, receive_item.owner.clone(), + Some(&receive_item.owner), |_, _| Ok(()), )?; + // Owner of `send_item` is responsible for the deposit if the collection balance + // went to zero due to the previous transfer. Self::do_transfer( - &caller, receive_collection_id, receive_item_id, send_item.owner.clone(), + Some(&send_item.owner), |_, _| Ok(()), )?; diff --git a/pallets/nfts/src/features/buy_sell.rs b/pallets/nfts/src/features/buy_sell.rs index d28478cb7..2b4d2967c 100644 --- a/pallets/nfts/src/features/buy_sell.rs +++ b/pallets/nfts/src/features/buy_sell.rs @@ -158,7 +158,7 @@ impl, I: 'static> Pallet { let old_owner = details.owner.clone(); - Self::do_transfer(&buyer, collection, item, buyer.clone(), |_, _| Ok(()))?; + Self::do_transfer(collection, item, buyer.clone(), Some(&buyer), |_, _| Ok(()))?; Self::deposit_event(Event::ItemBought { collection, diff --git a/pallets/nfts/src/features/create_delete_item.rs b/pallets/nfts/src/features/create_delete_item.rs index 9a2e0983c..5c687d427 100644 --- a/pallets/nfts/src/features/create_delete_item.rs +++ b/pallets/nfts/src/features/create_delete_item.rs @@ -69,18 +69,18 @@ impl, I: 'static> Pallet { collection_details.items.saturating_inc(); let collection_config = Self::get_collection_config(&collection)?; - let deposit_amount = - match collection_config.is_setting_enabled(CollectionSetting::DepositRequired) { - true => T::ItemDeposit::get(), - false => Zero::zero(), - }; + let deposit_required = + collection_config.is_setting_enabled(CollectionSetting::DepositRequired); let deposit_account = maybe_depositor.unwrap_or_else(|| collection_details.owner.clone()); + let balance_deposit = deposit_required + .then_some(T::CollectionBalanceDeposit::get()) + .unwrap_or_default(); Self::increment_account_balance( collection, &mint_to, - (&deposit_account, deposit_amount), + (&deposit_account, balance_deposit), )?; let item_owner = mint_to.clone(); @@ -93,9 +93,11 @@ impl, I: 'static> Pallet { collection_details.item_configs.saturating_inc(); } - T::Currency::reserve(&deposit_account, deposit_amount)?; + let item_deposit = + deposit_required.then_some(T::ItemDeposit::get()).unwrap_or_default(); + T::Currency::reserve(&deposit_account, item_deposit)?; - let deposit = ItemDeposit { account: deposit_account, amount: deposit_amount }; + let deposit = ItemDeposit { account: deposit_account, amount: item_deposit }; let details = ItemDetails { owner: item_owner, approvals: ApprovalsOf::::default(), diff --git a/pallets/nfts/src/features/transfer.rs b/pallets/nfts/src/features/transfer.rs index 0549a617e..9f5dc77b4 100644 --- a/pallets/nfts/src/features/transfer.rs +++ b/pallets/nfts/src/features/transfer.rs @@ -25,10 +25,11 @@ use crate::*; impl, I: 'static> Pallet { /// Transfer an NFT to the specified destination account. /// - /// - `caller`: The account transferring the collection item. /// - `collection`: The ID of the collection to which the NFT belongs. /// - `item`: The ID of the NFT to transfer. /// - `dest`: The destination account to which the NFT will be transferred. + /// - `depositor`: The account reserving the `CollectionBalanceDeposit` from if `dest` holds no + /// items in the collection. /// - `with_details`: A closure that provides access to the collection and item details, /// allowing customization of the transfer process. /// @@ -46,10 +47,10 @@ impl, I: 'static> Pallet { /// - If the collection or item is non-transferable /// ([`ItemsNonTransferable`](crate::Error::ItemsNonTransferable)). pub fn do_transfer( - caller: &T::AccountId, collection: T::CollectionId, item: T::ItemId, dest: T::AccountId, + depositor: Option<&T::AccountId>, with_details: impl FnOnce( &CollectionDetailsFor, &mut ItemDetailsFor, @@ -91,19 +92,15 @@ impl, I: 'static> Pallet { // Update account balance of the owner. Self::decrement_account_balance(collection, &details.owner)?; - // Update account balance of the destination account. - let deposit_amount = - match collection_config.is_setting_enabled(CollectionSetting::DepositRequired) { - true => T::BalanceDeposit::get(), - false => Zero::zero(), - }; - // The destination account covers the `BalanceDeposit` if it has sufficient balance. - // Otherwise, the caller is accountable for it. - let deposit_account = match T::Currency::can_reserve(&dest, T::BalanceDeposit::get()) { - true => &dest, - false => caller, - }; + let deposit_amount = collection_config + .is_setting_enabled(CollectionSetting::DepositRequired) + .then_some(T::CollectionBalanceDeposit::get()) + .unwrap_or_default(); + // Reserve `CollectionBalanceDeposit` from the depositor if provided. Otherwise, reserve + // from the item's owner. + let deposit_account = depositor.unwrap_or(&details.owner); + // Update account balance of the destination account. Self::increment_account_balance(collection, &dest, (deposit_account, deposit_amount))?; // Update account ownership information. diff --git a/pallets/nfts/src/impl_nonfungibles.rs b/pallets/nfts/src/impl_nonfungibles.rs index 60e89a747..e8fa4457a 100644 --- a/pallets/nfts/src/impl_nonfungibles.rs +++ b/pallets/nfts/src/impl_nonfungibles.rs @@ -411,7 +411,11 @@ impl, I: 'static> Transfer for Pallet { item: &Self::ItemId, destination: &T::AccountId, ) -> DispatchResult { - Self::do_transfer(destination, *collection, *item, destination.clone(), |_, _| Ok(())) + // The item's owner pays for the deposit of `AccountBalance` if the `dest` holds no items + // in `collection`. If `dest` paid the deposit, a malicious actor could transfer NFTs to + // reserve involuntary deposits for `dest` . The deposit amount can be accounted for in the + // off chain price of the NFT. + Self::do_transfer(*collection, *item, destination.clone(), None, |_, _| Ok(())) } fn disable_transfer(collection: &Self::CollectionId, item: &Self::ItemId) -> DispatchResult { diff --git a/pallets/nfts/src/lib.rs b/pallets/nfts/src/lib.rs index 13510100d..8d9c77fad 100644 --- a/pallets/nfts/src/lib.rs +++ b/pallets/nfts/src/lib.rs @@ -260,11 +260,11 @@ pub mod pallet { #[pallet::constant] type CollectionApprovalDeposit: Get>; - /// The basic amount of funds that must be reversed for an account balance. + /// The basic amount of funds that must be reversed for an account's collection balance. // Key: `sizeof((CollectionId, AccountId))` bytes. // Value: `sizeof((u32, Some(AccountId, Balance)))` bytes. #[pallet::constant] - type BalanceDeposit: Get>; + type CollectionBalanceDeposit: Get>; } /// Details of a collection. @@ -441,6 +441,7 @@ pub mod pallet { T::CollectionId, Blake2_128Concat, T::AccountId, + // (Account's collection items, Deposit details). (u32, AccountDepositOf), >; @@ -453,7 +454,13 @@ pub mod pallet { NMapKey, // owner NMapKey, // delegate ), - (Option>, DepositBalanceOf), + ( + // The optional deadline for the approval. If specified, the approval is valid on or + // before the given block number. + Option>, + // The balance to be deposited. + DepositBalanceOf, + ), >; #[pallet::event] @@ -499,8 +506,9 @@ pub mod pallet { admin: Option, freezer: Option, }, - /// An `item` of a `collection` has been approved by the `owner` for transfer by - /// a `delegate`. + /// A provided `item` of a `collection`, or if no `item` is provided, all items in the + /// `collection` owned by the `owner` have been approved by the `owner` for transfer by a + /// `delegate`. TransferApproved { collection: T::CollectionId, item: Option, @@ -508,8 +516,9 @@ pub mod pallet { delegate: T::AccountId, deadline: Option>, }, - /// An approval for a `delegate` account to transfer a specific `item` in a `collection` or - /// all collection items owned by the `owner` has been cancelled by the owner. + /// An approval for a `delegate` account to transfer a specific `item` in a `collection`, + /// or if no `item` is provided, all collection items owned by the `owner` have been + /// cancelled by the `owner`. ApprovalCancelled { collection: T::CollectionId, item: Option, @@ -663,8 +672,6 @@ pub mod pallet { NotDelegate, /// The delegate turned out to be different to what was expected. WrongDelegate, - /// No approval exists that would allow the transfer. - Unapproved, /// The named owner has not signed ownership acceptance of the collection. Unaccepted, /// The item is locked (non-transferable). @@ -1091,9 +1098,18 @@ pub mod pallet { let origin = ensure_signed(origin)?; let dest = T::Lookup::lookup(dest)?; - Self::do_transfer(&origin, collection, item, dest, |_, details| { + // The item's owner pays for the deposit of `AccountBalance` if the `dest` holds no + // items in `collection`. A malicious actor could have a deposit reserved from `dest` + // without them knowing about the transfer. The deposit amount can be accounted for + // in the off chain price of the NFT. + Self::do_transfer(collection, item, dest, None, |_, details| { if details.owner != origin { - Self::check_approval(&collection, &Some(item), &details.owner, &origin)?; + Self::check_approval_permission( + &collection, + &Some(item), + &details.owner, + &origin, + )?; } Ok(()) }) @@ -2017,15 +2033,22 @@ pub mod pallet { ) -> DispatchResult { let origin = ensure_signed(origin)?; let delegate = T::Lookup::lookup(delegate)?; - Self::do_approve_collection_transfer(origin, collection, delegate, maybe_deadline) + Self::do_approve_collection_transfer( + origin, + collection, + delegate, + T::CollectionApprovalDeposit::get(), + maybe_deadline, + ) } /// Force-approve collection items owned by the `owner` to be transferred by a delegated - /// third-party account. This function reserves the required deposit - /// `CollectionApprovalDeposit` from the `owner` account. + /// third-party account. /// /// Origin must be the `ForceOrigin`. /// + /// Any deposit is left alone. + /// /// - `owner`: The owner of the collection items to be force-approved by the `origin`. /// - `collection`: The collection of the items to be approved for delegated transfer. /// - `delegate`: The account to delegate permission to transfer collection items owned by @@ -2048,7 +2071,13 @@ pub mod pallet { T::ForceOrigin::ensure_origin(origin)?; let delegate = T::Lookup::lookup(delegate)?; let owner = T::Lookup::lookup(owner)?; - Self::do_approve_collection_transfer(owner, collection, delegate, maybe_deadline) + Self::do_approve_collection_transfer( + owner, + collection, + delegate, + Zero::zero(), + maybe_deadline, + ) } /// Cancel a collection approval. diff --git a/pallets/nfts/src/mock.rs b/pallets/nfts/src/mock.rs index 5d3015cff..efd72722f 100644 --- a/pallets/nfts/src/mock.rs +++ b/pallets/nfts/src/mock.rs @@ -65,8 +65,8 @@ parameter_types! { impl Config for Test { type ApprovalsLimit = ConstU32<10>; type AttributeDepositBase = ConstU64<1>; - type BalanceDeposit = ConstU64<1>; type CollectionApprovalDeposit = ConstU64<1>; + type CollectionBalanceDeposit = ConstU64<1>; type CollectionDeposit = ConstU64<2>; type CollectionId = u32; type CreateOrigin = AsEnsureOriginWithArg>; diff --git a/pallets/nfts/src/tests.rs b/pallets/nfts/src/tests.rs index 9dd4b940b..d0c6bff9d 100644 --- a/pallets/nfts/src/tests.rs +++ b/pallets/nfts/src/tests.rs @@ -18,40 +18,35 @@ //! Tests for Nfts pallet. use enumflags2::BitFlags; -use frame_support::{ +pub(crate) use frame_support::{ assert_noop, assert_ok, - dispatch::{DispatchResultWithPostInfo, WithPostDispatchInfo}, + dispatch::WithPostDispatchInfo, traits::{ tokens::nonfungibles_v2::{Create, Destroy, Inspect, Mutate}, Currency, Get, }, }; use frame_system::pallet_prelude::BlockNumberFor; -use pallet_balances::Error as BalancesError; +pub(crate) use pallet_balances::Error as BalancesError; use sp_core::{bounded::BoundedVec, Pair}; use sp_runtime::{ traits::{Dispatchable, IdentifyAccount}, DispatchError::BadOrigin, - DispatchResult, MultiSignature, MultiSigner, + MultiSignature, MultiSigner, }; use crate::{mock::*, Event, SystemConfig, *}; type AccountIdOf = ::AccountId; -type AccountBalance = crate::AccountBalance; +pub(crate) type AccountBalance = crate::AccountBalance; type CollectionApprovals = crate::CollectionApprovals; type CollectionApprovalDeposit = ::CollectionApprovalDeposit; -type CollectionId = ::CollectionId; type WeightOf = ::WeightInfo; -fn account(id: u8) -> AccountIdOf { +pub(crate) fn account(id: u8) -> AccountIdOf { [id; 32].into() } -fn root() -> RuntimeOrigin { - RuntimeOrigin::root() -} - fn none() -> RuntimeOrigin { RuntimeOrigin::none() } @@ -163,54 +158,12 @@ fn item_config_from_disabled_settings(settings: BitFlags) -> ItemCo ItemConfig { settings: ItemSettings::from_disabled(settings) } } -fn clear_collection_approvals( - origin: RuntimeOrigin, - maybe_owner: Option<&AccountId>, - collection: CollectionId, - limit: u32, -) -> DispatchResultWithPostInfo { - match maybe_owner { - Some(owner) => - Nfts::force_clear_collection_approvals(origin, owner.clone(), collection, limit), - None => Nfts::clear_collection_approvals(origin, collection, limit), - } -} - -fn approve_collection_transfer( - origin: RuntimeOrigin, - maybe_owner: Option<&AccountId>, - collection: CollectionId, - delegate: &AccountId, - maybe_deadline: Option>, -) -> DispatchResult { - match maybe_owner { - Some(owner) => Nfts::force_approve_collection_transfer( - origin, - owner.clone(), - collection, - delegate.clone(), - maybe_deadline, - ), - None => - Nfts::approve_collection_transfer(origin, collection, delegate.clone(), maybe_deadline), - } +pub(crate) fn balance_deposit() -> DepositBalanceOf { + <::CollectionBalanceDeposit>::get() } -fn cancel_collection_approval( - origin: RuntimeOrigin, - maybe_owner: Option<&AccountId>, - collection: CollectionId, - delegate: &AccountId, -) -> DispatchResult { - match maybe_owner { - Some(owner) => Nfts::force_cancel_collection_approval( - origin, - owner.clone(), - collection, - delegate.clone(), - ), - None => Nfts::cancel_collection_approval(origin, collection, delegate.clone()), - } +pub(crate) fn item_deposit() -> DepositBalanceOf { + <::ItemDeposit>::get() } #[test] @@ -230,8 +183,6 @@ fn basic_minting_should_work() { )); assert_eq!(collections(), vec![(account(1), 0)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); - // Minting skips deposit as `DepositRequired` is disabled. - assert_eq!(AccountBalance::get(0, &account(1)), Some((1, (account(1), 0)))); assert_eq!(items(), vec![(account(1), 0, 42)]); assert_ok!(Nfts::force_create( @@ -241,8 +192,6 @@ fn basic_minting_should_work() { )); assert_eq!(collections(), vec![(account(1), 0), (account(2), 1)]); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(2)), 1, 69, account(1), None)); - // Minting skips deposit as `DepositRequired` is disabled. - assert_eq!(AccountBalance::get(1, &account(1)), Some((1, (account(2), 0)))); assert_eq!(items(), vec![(account(1), 0, 42), (account(1), 1, 69)]); }); } @@ -250,6 +199,8 @@ fn basic_minting_should_work() { #[test] fn lifecycle_should_work() { new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + Balances::make_free_balance_be(&account(1), 100); Balances::make_free_balance_be(&account(2), 100); assert_ok!(Nfts::create( @@ -274,7 +225,7 @@ fn lifecycle_should_work() { account(10), default_item_config() )); - assert_eq!(Balances::reserved_balance(&account(1)), 6 + 1); // 1 - balance deposit + assert_eq!(Balances::reserved_balance(&account(1)), 6 + balance_deposit); assert_ok!(Nfts::force_mint( RuntimeOrigin::signed(account(1)), 0, @@ -282,27 +233,23 @@ fn lifecycle_should_work() { account(20), default_item_config() )); - assert_eq!(AccountBalance::get(0, account(20)), Some((1, (account(1), 1)))); - assert_eq!(Balances::reserved_balance(&account(1)), 7 + 2); // 2 - balance deposit + assert_eq!(Balances::reserved_balance(&account(1)), 7 + 2 * balance_deposit); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 70, account(1), None)); - assert_eq!(AccountBalance::get(0, &account(1)), Some((1, (account(1), 1)))); assert_eq!(items(), vec![(account(1), 0, 70), (account(10), 0, 42), (account(20), 0, 69)]); assert_eq!(Collection::::get(0).unwrap().items, 3); assert_eq!(Collection::::get(0).unwrap().item_metadatas, 0); assert_eq!(Collection::::get(0).unwrap().item_configs, 3); - assert_eq!(Balances::reserved_balance(&account(1)), 8 + 3); // 3 - balance deposit + assert_eq!(Balances::reserved_balance(&account(1)), 8 + 3 * balance_deposit); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 70, account(2))); - assert!(!AccountBalance::contains_key(0, &account(1))); - assert_eq!(AccountBalance::get(0, account(2)), Some((1, (account(2), 1)))); - assert_eq!(Balances::reserved_balance(&account(1)), 8 + 2); // 2 - balance deposit - assert_eq!(Balances::reserved_balance(&account(2)), 1); // 1 - balance deposit + assert_eq!(Balances::reserved_balance(&account(1)), 8 + 3 * balance_deposit); + assert_eq!(Balances::reserved_balance(&account(2)), 0); assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![42, 42])); - assert_eq!(Balances::reserved_balance(&account(1)), 11 + 2); // 2 - balance deposit + assert_eq!(Balances::reserved_balance(&account(1)), 11 + 3 * balance_deposit); assert!(ItemMetadataOf::::contains_key(0, 42)); assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 69, bvec![69, 69])); - assert_eq!(Balances::reserved_balance(&account(1)), 14 + 2); // 2 - balance deposit + assert_eq!(Balances::reserved_balance(&account(1)), 14 + 3 * balance_deposit); assert!(ItemMetadataOf::::contains_key(0, 69)); assert!(ItemConfigOf::::contains_key(0, 69)); let w = Nfts::get_destroy_witness(&0).unwrap(); @@ -322,9 +269,7 @@ fn lifecycle_should_work() { bvec![0], )); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(10)), 0, 42)); - assert!(!AccountBalance::contains_key(0, account(10))); assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(20)), 0, 69)); - assert!(!AccountBalance::contains_key(0, account(20))); assert_ok!(Nfts::burn(RuntimeOrigin::root(), 0, 70)); let w = Nfts::get_destroy_witness(&0).unwrap(); @@ -332,7 +277,6 @@ fn lifecycle_should_work() { assert_eq!(w.item_metadatas, 0); assert_eq!(w.item_configs, 0); assert_ok!(Nfts::destroy(RuntimeOrigin::signed(account(1)), 0, w)); - assert!(!AccountBalance::contains_key(0, &account(1))); assert_eq!(Balances::reserved_balance(&account(1)), 0); assert!(!Collection::::contains_key(0)); @@ -375,7 +319,6 @@ fn destroy_with_bad_witness_should_not_work() { fn destroy_should_work() { new_test_ext().execute_with(|| { Balances::make_free_balance_be(&account(1), 100); - Balances::make_free_balance_be(&account(2), 100); assert_ok!(Nfts::create( RuntimeOrigin::signed(account(1)), account(1), @@ -383,12 +326,6 @@ fn destroy_should_work() { )); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(2), None)); - assert_ok!(Nfts::approve_collection_transfer( - RuntimeOrigin::signed(account(2)), - 0, - account(3), - None - )); assert_noop!( Nfts::destroy( RuntimeOrigin::signed(account(1)), @@ -402,26 +339,59 @@ fn destroy_should_work() { assert_eq!(Collection::::get(0).unwrap().item_configs, 1); assert_eq!(ItemConfigOf::::iter_prefix(0).count() as u32, 1); assert!(ItemConfigOf::::contains_key(0, 42)); + assert_ok!(Nfts::destroy( + RuntimeOrigin::signed(account(1)), + 0, + Nfts::get_destroy_witness(&0).unwrap() + )); + assert!(!ItemConfigOf::::contains_key(0, 42)); + assert_eq!(ItemConfigOf::::iter_prefix(0).count() as u32, 0); + }); +} + +#[test] +fn destroy_ensures_no_active_collection_approval() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let collection_owner = account(1); + let delegate = account(3); + let item_id = 42; + let item_owner = account(2); + + Balances::make_free_balance_be(&collection_owner, 100); + assert_ok!(Nfts::create( + RuntimeOrigin::signed(collection_owner.clone()), + collection_owner.clone(), + collection_config_with_all_settings_enabled() + )); + + CollectionApprovals::set( + (collection_id, item_owner.clone(), delegate.clone()), + Some((None, 0)), + ); + // Throws error `CollectionApprovalsExist`. assert_noop!( Nfts::destroy( - RuntimeOrigin::signed(account(1)), - 0, - Nfts::get_destroy_witness(&0).unwrap() + RuntimeOrigin::signed(collection_owner.clone()), + collection_id, + Nfts::get_destroy_witness(&collection_id).unwrap() ), Error::::CollectionApprovalsExist ); assert_ok!(Nfts::cancel_collection_approval( - RuntimeOrigin::signed(account(2)), - 0, - account(3) + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate )); + + // Successfully destroy the collection. assert_ok!(Nfts::destroy( - RuntimeOrigin::signed(account(1)), - 0, - Nfts::get_destroy_witness(&0).unwrap() + RuntimeOrigin::signed(collection_owner.clone()), + collection_id, + Nfts::get_destroy_witness(&collection_id).unwrap() )); - assert!(!ItemConfigOf::::contains_key(0, 42)); - assert_eq!(ItemConfigOf::::iter_prefix(0).count() as u32, 0); + assert!(!ItemConfigOf::::contains_key(collection_id, item_id)); + assert_eq!(ItemConfigOf::::iter_prefix(collection_id).count() as u32, collection_id); }); } @@ -433,9 +403,7 @@ fn mint_should_work() { account(1), default_collection_config() )); - // Minting skips deposit as `DepositRequired` is disabled. assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); - assert_eq!(AccountBalance::get(0, account(1)), Some((1, (account(1), 0)))); assert_eq!(Nfts::owner(0, 42).unwrap(), account(1)); assert_eq!(collections(), vec![(account(1), 0)]); assert_eq!(items(), vec![(account(1), 0, 42)]); @@ -501,7 +469,6 @@ fn mint_should_work() { account(2), Some(MintWitness { mint_price: Some(1), ..Default::default() }) )); - assert_eq!(AccountBalance::get(0, account(2)), Some((1, (account(2), 0)))); assert_eq!(Balances::total_balance(&account(2)), 99); // validate types @@ -540,7 +507,6 @@ fn mint_should_work() { account(2), Some(MintWitness { owned_item: Some(43), ..Default::default() }) )); - assert_eq!(AccountBalance::get(1, account(2)), Some((1, (account(2), 0)))); assert!(events().contains(&Event::::PalletAttributeSet { collection: 0, item: Some(43), @@ -562,6 +528,51 @@ fn mint_should_work() { }); } +#[test] +fn mint_should_update_account_balance_works() { + new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + let collection_id = 0; + let dest = account(1); + let owner = account(2); + + Balances::make_free_balance_be(&owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + owner.clone(), + collection_config_with_all_settings_enabled() + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(owner.clone()), + collection_id, + 42, + dest.clone(), + None + )); + // Minting reserves a deposit because `dest` doesn't have an item in the collection yet and + // thus a storage item has to be created. + assert_eq!( + AccountBalance::get(collection_id, dest.clone()), + Some((1, (owner.clone(), balance_deposit))) + ); + assert_eq!(Balances::reserved_balance(&owner), item_deposit() + balance_deposit); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(owner.clone()), + collection_id, + 43, + dest.clone(), + None + )); + // `dest` already has an item in the collection so no extra deposit is reserved. + assert_eq!( + AccountBalance::get(collection_id, &dest), + Some((2, (owner.clone(), balance_deposit))) + ); + assert_eq!(Balances::reserved_balance(&owner), (2 * item_deposit()) + balance_deposit); + assert_eq!(Balances::reserved_balance(&dest), 0); + }); +} + #[test] fn transfer_should_work() { new_test_ext().execute_with(|| { @@ -577,12 +588,8 @@ fn transfer_should_work() { account(2), default_item_config() )); + assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); - // Transferring skips deposit as `DepositRequired` is disabled. - assert!(!AccountBalance::contains_key(0, account(2))); - assert_eq!(AccountBalance::get(0, account(3)), Some((1, (account(2), 0)))); - assert_eq!(Balances::reserved_balance(&account(2)), 0); - assert_eq!(Balances::reserved_balance(&account(3)), 0); assert_eq!(items(), vec![(account(3), 0, 42)]); assert_noop!( Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4)), @@ -597,8 +604,7 @@ fn transfer_should_work() { None )); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(2)), 0, 42, account(4))); - assert!(!AccountBalance::contains_key(0, account(3))); - assert_eq!(AccountBalance::get(0, account(4)), Some((1, (account(2), 0)))); + // validate we can't transfer non-transferable items let collection_id = 1; assert_ok!(Nfts::force_create( @@ -624,6 +630,71 @@ fn transfer_should_work() { }); } +#[test] +fn transfer_should_update_account_balance_works() { + new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + let collection_id = 0; + let delegate = account(1); + let dest = account(2); + let item_id = 42; + let owner = account(3); + + Balances::make_free_balance_be(&owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + owner.clone(), + collection_config_with_all_settings_enabled() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(owner.clone()), + collection_id, + item_id, + owner.clone(), + default_item_config() + )); + assert_ok!(Nfts::transfer( + RuntimeOrigin::signed(owner.clone()), + collection_id, + item_id, + dest.clone() + )); + assert!(!AccountBalance::contains_key(collection_id, &owner)); + assert_eq!( + AccountBalance::get(collection_id, &dest), + Some((1, (owner.clone(), balance_deposit))) + ); + // Reserve funds from `owner` when transferring to `dest`. + assert_eq!(Balances::reserved_balance(&owner), item_deposit() + balance_deposit); + assert_eq!(Balances::reserved_balance(&dest), 0); + + // Approve `delegate` for approved transfer case. + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(dest.clone()), + collection_id, + item_id, + delegate.clone(), + None + )); + Balances::make_free_balance_be(&dest, Balances::minimum_balance() + balance_deposit); + assert_ok!(Nfts::transfer( + RuntimeOrigin::signed(delegate.clone()), + collection_id, + item_id, + owner.clone() + )); + assert_eq!( + AccountBalance::get(collection_id, &owner), + Some((1, (dest.clone(), balance_deposit))) + ); + // Reserve funds from `dest` during a delegated transfer initiated by the + // `delegate` back to `owner`. + assert_eq!(Balances::reserved_balance(&owner), item_deposit()); + assert_eq!(Balances::reserved_balance(&delegate), 0); + assert_eq!(Balances::reserved_balance(&dest), balance_deposit); + }); +} + #[test] fn locking_transfer_should_work() { new_test_ext().execute_with(|| { @@ -714,6 +785,8 @@ fn origin_guards_should_work() { #[test] fn transfer_owner_should_work() { new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + Balances::make_free_balance_be(&account(1), 100); Balances::make_free_balance_be(&account(2), 100); Balances::make_free_balance_be(&account(3), 100); @@ -754,7 +827,7 @@ fn transfer_owner_should_work() { bvec![0u8; 20], )); assert_ok!(Nfts::mint(RuntimeOrigin::signed(account(1)), 0, 42, account(1), None)); - assert_eq!(Balances::reserved_balance(&account(1)), 2); // 1 - metadata deposit, 1 - balance deposit + assert_eq!(Balances::reserved_balance(&account(1)), 1 + balance_deposit); assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0u8; 20])); assert_ok!(Nfts::set_accept_ownership(RuntimeOrigin::signed(account(3)), Some(0))); assert_ok!(Nfts::transfer_ownership(RuntimeOrigin::signed(account(2)), 0, account(3))); @@ -765,10 +838,10 @@ fn transfer_owner_should_work() { assert_eq!(Balances::reserved_balance(&account(3)), 44); assert_ok!(Nfts::transfer(RuntimeOrigin::signed(account(1)), 0, 42, account(2))); - // reserved_balance of accounts 1 & 2 should be unchanged: - assert_eq!(Balances::reserved_balance(&account(1)), 1); - // transfer the collection item reserves account 2's balance. - assert_eq!(Balances::reserved_balance(&account(2)), 1); // 1 - balance deposit + // The reserved balance of account 1 is incremented to create a new storage record for the + // account 2. + assert_eq!(Balances::reserved_balance(&account(1)), 1 + balance_deposit); + assert_eq!(Balances::reserved_balance(&account(2)), 0); // 2's acceptance from before is reset when it became an owner, so it cannot be transferred // without a fresh acceptance. @@ -943,6 +1016,8 @@ fn set_collection_metadata_should_work() { #[test] fn set_item_metadata_should_work() { new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + Balances::make_free_balance_be(&account(1), 30); // Cannot add metadata to unknown item @@ -960,7 +1035,7 @@ fn set_item_metadata_should_work() { // Successfully add metadata and take deposit assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0u8; 20])); - assert_eq!(Balances::free_balance(&account(1)), 7); // free_balance - metadata deposit - item deposit - balance deposit + assert_eq!(Balances::free_balance(&account(1)), 8 - balance_deposit); assert!(ItemMetadataOf::::contains_key(0, 42)); // Force origin works, too. @@ -968,9 +1043,9 @@ fn set_item_metadata_should_work() { // Update deposit assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0u8; 15])); - assert_eq!(Balances::free_balance(&account(1)), 12); // free_balance - metadata deposit - item deposit - balance deposit + assert_eq!(Balances::free_balance(&account(1)), 13 - balance_deposit); assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0u8; 25])); - assert_eq!(Balances::free_balance(&account(1)), 2); // free_balance - metadata deposit - item deposit - balance deposit + assert_eq!(Balances::free_balance(&account(1)), 3 - balance_deposit); // Cannot over-reserve assert_noop!( @@ -1014,6 +1089,8 @@ fn set_item_metadata_should_work() { #[test] fn set_collection_owner_attributes_should_work() { new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + Balances::make_free_balance_be(&account(1), 100); assert_ok!(Nfts::force_create( @@ -1055,7 +1132,7 @@ fn set_collection_owner_attributes_should_work() { (Some(0), AttributeNamespace::CollectionOwner, bvec![1], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(account(1)), 10 + 1); // 10 - attribute deposit, 1 - balance deposit + assert_eq!(Balances::reserved_balance(account(1)), 10 + balance_deposit); assert_eq!(Collection::::get(0).unwrap().owner_deposit, 9); assert_ok!(Nfts::set_attribute( @@ -1074,7 +1151,7 @@ fn set_collection_owner_attributes_should_work() { (Some(0), AttributeNamespace::CollectionOwner, bvec![1], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(account(1)), 19 + 1); // 19 - attribute deposit, 1 - balance deposit + assert_eq!(Balances::reserved_balance(account(1)), 19 + balance_deposit); assert_eq!(Collection::::get(0).unwrap().owner_deposit, 18); assert_ok!(Nfts::clear_attribute( @@ -1091,7 +1168,7 @@ fn set_collection_owner_attributes_should_work() { (Some(0), AttributeNamespace::CollectionOwner, bvec![0], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(account(1)), 16 + 1); // 16 - attribute deposit, 1 - balance deposit + assert_eq!(Balances::reserved_balance(account(1)), 16 + balance_deposit); assert_ok!(Nfts::burn(RuntimeOrigin::root(), 0, 0)); let w = Nfts::get_destroy_witness(&0).unwrap(); @@ -1335,8 +1412,8 @@ fn set_item_owner_attributes_should_work() { Attribute::::get((0, Some(0), AttributeNamespace::ItemOwner, &key)).unwrap(); assert_eq!(deposit.account, Some(account(3))); assert_eq!(deposit.amount, 13); - assert_eq!(Balances::reserved_balance(account(2)), 3); - assert_eq!(Balances::reserved_balance(account(3)), 13 + 1); // 13 - attribute deposit, 1 - balance deposit + assert_eq!(Balances::reserved_balance(account(2)), 3 + balance_deposit()); + assert_eq!(Balances::reserved_balance(account(3)), 13); // validate attributes on item deletion assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(3)), 0, 0)); @@ -1585,7 +1662,7 @@ fn set_attribute_should_respect_lock() { (Some(1), AttributeNamespace::CollectionOwner, bvec![0], bvec![0]), ] ); - assert_eq!(Balances::reserved_balance(account(1)), 11 + 1); // 12 - attribute deposit, 1 - balance deposit + assert_eq!(Balances::reserved_balance(account(1)), 11 + balance_deposit()); assert_ok!(Nfts::set_collection_metadata(RuntimeOrigin::signed(account(1)), 0, bvec![])); assert_ok!(Nfts::lock_collection( @@ -1704,6 +1781,8 @@ fn preserve_config_for_frozen_items() { #[test] fn force_update_collection_should_work() { new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + Balances::make_free_balance_be(&account(1), 100); assert_ok!(Nfts::force_create( @@ -1726,7 +1805,7 @@ fn force_update_collection_should_work() { )); assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 42, bvec![0; 20])); assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(1)), 0, 69, bvec![0; 20])); - assert_eq!(Balances::reserved_balance(account(1)), 65 + 2); // 65 - metadata deposit, 2 - balance deposit + assert_eq!(Balances::reserved_balance(account(1)), 65 + 2 * balance_deposit); // force item status to be free holding assert_ok!(Nfts::force_collection_config( @@ -1755,7 +1834,7 @@ fn force_update_collection_should_work() { Some(account(4)), )); assert_eq!(collections(), vec![(account(5), 0)]); - assert_eq!(Balances::reserved_balance(account(1)), 2 + 2); // 2 - metadata deposit, 2 - balance deposit + assert_eq!(Balances::reserved_balance(account(1)), 2 + 2 * balance_deposit); assert_eq!(Balances::reserved_balance(account(5)), 63); assert_ok!(Nfts::redeposit( @@ -1763,7 +1842,7 @@ fn force_update_collection_should_work() { 0, bvec![0, 42, 50, 69, 100] )); - assert_eq!(Balances::reserved_balance(account(1)), 2); // 2 - balance deposit + assert_eq!(Balances::reserved_balance(account(1)), 2 * balance_deposit); assert_ok!(Nfts::set_metadata(RuntimeOrigin::signed(account(5)), 0, 42, bvec![0; 20])); assert_eq!(Balances::reserved_balance(account(5)), 42); @@ -1821,6 +1900,8 @@ fn force_update_collection_should_work() { #[test] fn burn_works() { new_test_ext().execute_with(|| { + let balance_deposit = balance_deposit(); + Balances::make_free_balance_be(&account(1), 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), @@ -1835,7 +1916,6 @@ fn burn_works() { Some(account(4)), )); - // Throws error `Error::UnknownItem` if burning an unknown collection item. assert_noop!( Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 42), Error::::UnknownItem @@ -1855,36 +1935,59 @@ fn burn_works() { account(5), default_item_config() )); + assert_eq!(Balances::reserved_balance(account(1)), 2 + balance_deposit); - // Throws error `Error::NoItemOwned` if the account does not have an entry in - // `AccountBalance`. - let account_balance = AccountBalance::take(0, account(5)); - assert_noop!( - Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 42), - Error::::NoItemOwned - ); - AccountBalance::set(0, account(5), account_balance); - - // Throws error `Error::NoPermission`. assert_noop!( Nfts::burn(RuntimeOrigin::signed(account(0)), 0, 42), Error::::NoPermission ); - assert_eq!(Balances::reserved_balance(account(1)), 2 + 1); // 2 - item deposit, 1 - balance deposit assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 42)); - // Burn an item unreserving the item deposit while retaining the reservation for `balance - // deposit`. - assert_eq!(Balances::reserved_balance(account(1)), 1 + 1); // 1 - item deposit, 1 - balance deposit assert_ok!(Nfts::burn(RuntimeOrigin::signed(account(5)), 0, 69)); - // Burn an item unreserving the balance deposit when the value of `AccountBalance` reaches - // zero. Remove the `AccountBalance` record. - assert_eq!(Balances::reserved_balance(account(1)), 0); - assert!(!AccountBalance::contains_key(0, &account(5))); assert_eq!(Balances::reserved_balance(account(1)), 0); }); } +#[test] +fn burn_should_update_account_balance_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let owner = account(1); + + Balances::make_free_balance_be(&owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + owner.clone(), + collection_config_with_all_settings_enabled() + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(owner.clone()), + collection_id, + 42, + owner.clone(), + None, + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(owner.clone()), + collection_id, + 43, + owner.clone(), + None, + )); + + assert_ok!(Nfts::burn(RuntimeOrigin::signed(owner.clone()), collection_id, 42)); + assert_eq!( + AccountBalance::get(collection_id, &owner), + Some((1, (owner.clone(), balance_deposit()))) + ); + assert_eq!(Balances::reserved_balance(&owner), item_deposit() + balance_deposit()); + + assert_ok!(Nfts::burn(RuntimeOrigin::signed(owner.clone()), collection_id, 43)); + assert!(!AccountBalance::contains_key(collection_id, &owner)); + assert_eq!(Balances::reserved_balance(&owner), 0); + }); +} + #[test] fn approval_lifecycle_works() { new_test_ext().execute_with(|| { @@ -1957,7 +2060,6 @@ fn approval_lifecycle_works() { #[test] fn cancel_approval_works() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&account(2), 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), account(1), @@ -1995,24 +2097,6 @@ fn cancel_approval_works() { Error::::NotDelegate ); - // Throws `DelegateApprovalConflict`` if the delegate has been granted a collection - // approval. - assert_ok!(Nfts::approve_collection_transfer( - RuntimeOrigin::signed(account(2)), - 0, - account(3), - None - )); - assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3)), - Error::::DelegateApprovalConflict - ); - assert_ok!(Nfts::cancel_collection_approval( - RuntimeOrigin::signed(account(2)), - 0, - account(3) - )); - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); assert!(events().contains(&Event::::ApprovalCancelled { collection: 0, @@ -2054,6 +2138,64 @@ fn cancel_approval_works() { }); } +#[test] +fn cancel_approval_ensures_no_active_collection_approval() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let delegate = account(3); + let item_id = 42; + let owner = account(1); + + Balances::make_free_balance_be(&owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + owner.clone(), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(account(1)), + collection_id, + item_id, + owner.clone(), + default_item_config() + )); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(owner.clone()), + collection_id, + item_id, + delegate.clone(), + None + )); + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(owner.clone()), + collection_id, + delegate.clone(), + None + )); + // Delegate has an active collection approval. + assert_noop!( + Nfts::cancel_approval( + RuntimeOrigin::signed(owner.clone()), + collection_id, + item_id, + delegate.clone() + ), + Error::::DelegateApprovalConflict + ); + assert_ok!(Nfts::cancel_collection_approval( + RuntimeOrigin::signed(owner.clone()), + collection_id, + delegate.clone() + )); + assert_ok!(Nfts::cancel_approval( + RuntimeOrigin::signed(owner), + collection_id, + item_id, + delegate + )); + }); +} + #[test] fn approving_multiple_accounts_works() { new_test_ext().execute_with(|| { @@ -2224,7 +2366,6 @@ fn approval_deadline_works() { #[test] fn cancel_approval_works_with_admin() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&account(2), 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), account(1), @@ -2258,24 +2399,6 @@ fn cancel_approval_works_with_admin() { Error::::NotDelegate ); - // Throws `DelegateApprovalConflict`` if the delegate has been granted a collection - // approval. - assert_ok!(Nfts::approve_collection_transfer( - RuntimeOrigin::signed(account(2)), - 0, - account(3), - None - )); - assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3)), - Error::::DelegateApprovalConflict - ); - assert_ok!(Nfts::cancel_collection_approval( - RuntimeOrigin::signed(account(2)), - 0, - account(3) - )); - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3))); assert!(events().contains(&Event::::ApprovalCancelled { collection: 0, @@ -2294,7 +2417,6 @@ fn cancel_approval_works_with_admin() { #[test] fn cancel_approval_works_with_force() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&account(2), 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), account(1), @@ -2328,24 +2450,6 @@ fn cancel_approval_works_with_force() { Error::::NotDelegate ); - // Throws `DelegateApprovalConflict`` if the delegate has been granted a collection - // approval. - assert_ok!(Nfts::approve_collection_transfer( - RuntimeOrigin::signed(account(2)), - 0, - account(3), - None - )); - assert_noop!( - Nfts::cancel_approval(RuntimeOrigin::signed(account(2)), 0, 42, account(3)), - Error::::DelegateApprovalConflict - ); - assert_ok!(Nfts::cancel_collection_approval( - RuntimeOrigin::signed(account(2)), - 0, - account(3) - )); - assert_ok!(Nfts::cancel_approval(RuntimeOrigin::root(), 0, 42, account(3))); assert!(events().contains(&Event::::ApprovalCancelled { collection: 0, @@ -2363,19 +2467,11 @@ fn cancel_approval_works_with_force() { #[test] fn clear_all_transfer_approvals_works() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&account(1), 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), account(1), default_collection_config() )); - assert_ok!(Nfts::force_mint( - RuntimeOrigin::signed(account(1)), - 0, - 43, - account(1), - default_item_config() - )); assert_ok!(Nfts::force_mint( RuntimeOrigin::signed(account(1)), 0, @@ -2406,25 +2502,6 @@ fn clear_all_transfer_approvals_works() { assert_ok!(Nfts::clear_all_transfer_approvals(RuntimeOrigin::signed(account(2)), 0, 42)); - // Throws `DelegateApprovalConflict` if there are existing collection approvals. - assert_ok!(Nfts::approve_collection_transfer( - RuntimeOrigin::signed(account(1)), - 0, - account(3), - None - )); - assert_noop!( - Nfts::clear_all_transfer_approvals(RuntimeOrigin::signed(account(1)), 0, 42), - Error::::DelegateApprovalConflict - ); - assert_ok!(Nfts::cancel_collection_approval( - RuntimeOrigin::signed(account(1)), - 0, - account(3) - )); - - assert_ok!(Nfts::clear_all_transfer_approvals(RuntimeOrigin::signed(account(2)), 0, 42)); - assert!(events().contains(&Event::::AllApprovalsCancelled { collection: 0, item: 42, @@ -2443,6 +2520,62 @@ fn clear_all_transfer_approvals_works() { }); } +#[test] +fn clear_all_transfer_approvals_ensures_no_active_collection_approval() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let delegate = account(3); + let item_id = 42; + let owner = account(1); + + Balances::make_free_balance_be(&owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + owner.clone(), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(owner.clone()), + collection_id, + item_id, + owner.clone(), + default_item_config() + )); + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(owner.clone()), + collection_id, + item_id, + delegate.clone(), + None + )); + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(owner.clone()), + collection_id, + delegate.clone(), + None + )); + // Delegate has an active collection approval. + assert_noop!( + Nfts::clear_all_transfer_approvals( + RuntimeOrigin::signed(owner.clone()), + collection_id, + item_id + ), + Error::::DelegateApprovalConflict + ); + assert_ok!(Nfts::cancel_collection_approval( + RuntimeOrigin::signed(owner.clone()), + collection_id, + delegate + )); + assert_ok!(Nfts::clear_all_transfer_approvals( + RuntimeOrigin::signed(owner), + collection_id, + item_id + )); + }); +} + #[test] fn max_supply_should_work() { new_test_ext().execute_with(|| { @@ -2779,7 +2912,6 @@ fn buy_item_should_work() { item_1, price_1 + 1, )); - assert_eq!(AccountBalance::get(collection_id, &user_2), Some((1, (user_2.clone(), 0)))); // validate the new owner & balances let item = Item::::get(collection_id, item_1).unwrap(); @@ -2878,6 +3010,54 @@ fn buy_item_should_work() { }); } +#[test] +fn buy_item_should_update_account_balance_works() { + new_test_ext().execute_with(|| { + let user_1 = account(1); + let user_2 = account(2); + let collection_id = 0; + let item = 1; + let price = 20; + + Balances::make_free_balance_be(&user_1, 100); + Balances::make_free_balance_be( + &user_2, + Balances::minimum_balance() + price + balance_deposit(), + ); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + user_1.clone(), + collection_config_with_all_settings_enabled() + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(user_1.clone()), + collection_id, + item, + user_1.clone(), + None + )); + assert_ok!(Nfts::set_price( + RuntimeOrigin::signed(user_1.clone()), + collection_id, + item, + Some(price), + None, + )); + assert_ok!(Nfts::buy_item( + RuntimeOrigin::signed(user_2.clone()), + collection_id, + item, + price, + )); + assert!(!AccountBalance::contains_key(collection_id, &user_1)); + assert_eq!( + AccountBalance::get(collection_id, &user_2), + Some((1, (user_2.clone(), balance_deposit()))) + ); + assert_eq!(Balances::reserved_balance(&user_2), balance_deposit()); + }); +} + #[test] fn pay_tips_should_work() { new_test_ext().execute_with(|| { @@ -3237,9 +3417,6 @@ fn claim_swap_should_work() { item_1, Some(price_with_direction.clone()), )); - // collection `DepositRequired` setting is disabled. - assert_eq!(AccountBalance::get(collection_id, &user_1), Some((2, (user_1.clone(), 0)))); - assert_eq!(AccountBalance::get(collection_id, &user_2), Some((3, (user_1.clone(), 0)))); // validate the new owner let item = Item::::get(collection_id, item_1).unwrap(); @@ -3299,6 +3476,79 @@ fn claim_swap_should_work() { }); } +#[test] +fn claim_swap_should_update_account_balance_works() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + let user_1 = account(1); + let user_2 = account(2); + let collection_id = 0; + let item_1 = 1; + let item_2 = 2; + let price = 100; + let price_with_direction = + PriceWithDirection { amount: price, direction: PriceDirection::Receive.clone() }; + + Balances::make_free_balance_be(&user_1, 1000); + Balances::make_free_balance_be( + &user_2, + Balances::minimum_balance() + balance_deposit() + price, + ); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + user_1.clone(), + collection_config_with_all_settings_enabled() + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(user_1.clone()), + collection_id, + item_1, + user_1.clone(), + None, + )); + assert_ok!(Nfts::mint( + RuntimeOrigin::signed(user_1.clone()), + collection_id, + item_2, + user_2.clone(), + None, + )); + assert_eq!( + Balances::reserved_balance(&user_1), + (2 * item_deposit()) + (2 * balance_deposit()) + ); + assert_ok!(Nfts::create_swap( + RuntimeOrigin::signed(user_1.clone()), + collection_id, + item_1, + collection_id, + Some(item_2), + Some(price_with_direction.clone()), + 2 + )); + assert_ok!(Nfts::claim_swap( + RuntimeOrigin::signed(user_2.clone()), + collection_id, + item_2, + collection_id, + item_1, + Some(price_with_direction), + )); + assert_eq!( + AccountBalance::get(collection_id, &user_1), + Some((1, (user_1.clone(), balance_deposit()))) + ); + assert_eq!( + AccountBalance::get(collection_id, &user_2), + Some((1, (user_2.clone(), balance_deposit()))) + ); + assert_eq!(Balances::reserved_balance(&user_1), (2 * item_deposit()) + balance_deposit()); + // User pays for its own deposit (previously paid by the account who signed the mint + // transaction). + assert_eq!(Balances::reserved_balance(&user_2), balance_deposit()); + }); +} + #[test] fn various_collection_settings() { new_test_ext().execute_with(|| { @@ -3612,7 +3862,6 @@ fn pre_signed_mints_should_work() { signature.clone(), user_1.clone(), )); - assert_eq!(AccountBalance::get(0, user_2.clone()), Some((1, (user_2.clone(), 1)))); assert_eq!(items(), vec![(user_2.clone(), 0, 0)]); let metadata = ItemMetadataOf::::get(0, 0).unwrap(); assert_eq!( @@ -3640,7 +3889,7 @@ fn pre_signed_mints_should_work() { assert_eq!(deposit.amount, 3); assert_eq!(Balances::free_balance(&user_0), 100 - 2 + 10); // 2 - collection deposit, 10 - mint price - assert_eq!(Balances::free_balance(&user_2), 100 - 1 - 1 - 3 - 6 - 10); // 1 - balance deposit, 1 - item deposit, 3 - metadata, 6 - attributes, 10 - mint price + assert_eq!(Balances::free_balance(&user_2), 100 - balance_deposit() - 1 - 3 - 6 - 10); // 1 - item deposit, 3 - metadata, 6 - attributes, 10 - mint price assert_noop!( Nfts::mint_pre_signed( @@ -3815,7 +4064,7 @@ fn pre_signed_attributes_should_work() { assert_eq!(deposit.account, Some(user_2.clone())); assert_eq!(deposit.amount, 3); - assert_eq!(Balances::free_balance(&user_1), 100 - 2 - 1 - 1); // 2 - collection deposit, 1 - item deposit, 1 - balance deposit + assert_eq!(Balances::free_balance(&user_1), 100 - 2 - 1 - balance_deposit()); // 2 - collection deposit, 1 - item deposit assert_eq!(Balances::free_balance(&user_2), 100 - 6); // 6 - attributes // validate the deposit gets returned on attribute update from collection's owner @@ -4138,589 +4387,704 @@ fn clear_collection_metadata_works() { } #[test] -fn mint_requires_deposit_works() { +fn collection_item_works() { new_test_ext().execute_with(|| { let collection_id = 0; - let collection_owner = account(1); - let mut item_id = 42; - let mut item_owner = account(2); + let total_items = 10; + let user_id = account(1); + + // No collection. + assert_eq!(Nfts::collection_items(collection_id), None); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - collection_owner.clone(), - collection_config_with_all_settings_enabled() + user_id.clone(), + default_collection_config() )); - // Throws error `BalancesError::InsufficientBalance`. - assert_noop!( - Nfts::mint( - RuntimeOrigin::signed(collection_owner.clone()), - collection_id, - item_id, - item_owner.clone(), - None - ), - BalancesError::::InsufficientBalance - ); - - Balances::make_free_balance_be(&collection_owner, 100); - // Minting reserves deposit from the collection owner. - { - assert_ok!(Nfts::mint( - RuntimeOrigin::signed(collection_owner.clone()), - collection_id, - item_id, - item_owner.clone(), - None - )); - assert_eq!( - AccountBalance::get(collection_id, item_owner.clone()), - Some((1, (collection_owner.clone(), 1))) - ); - assert_eq!(Balances::reserved_balance(&collection_owner), 1 + 1); // 1 - item deposit, 1 - balance deposit - assert_eq!(Nfts::owner(collection_id, item_id).unwrap(), item_owner); - } - - // Mint for accounts with a non-zero balance requires no additional reserves. - { - item_id = 43; - assert_ok!(Nfts::mint( - RuntimeOrigin::signed(collection_owner.clone()), - collection_id, - item_id, - item_owner.clone(), - None - )); - assert_eq!( - AccountBalance::get(collection_id, &item_owner), - Some((2, (collection_owner.clone(), 1))) - ); - assert_eq!(Balances::reserved_balance(&collection_owner), 2 + 1); // 2 - item deposit, 1 - balance deposit - assert_eq!(Nfts::owner(collection_id, item_id).unwrap(), item_owner); - } - - // Increase the reserved balance on minting for a new `AccountBalance` record. - { - item_id = 44; - item_owner = account(3); - assert_ok!(Nfts::mint( - RuntimeOrigin::signed(collection_owner.clone()), + // Mint items and validate the total supply. + (0..total_items).into_iter().for_each(|i| { + assert_ok!(Nfts::force_mint( + RuntimeOrigin::root(), collection_id, - item_id, - item_owner.clone(), - None + i, + user_id.clone(), + ItemConfig::default() )); - assert_eq!( - AccountBalance::get(collection_id, &item_owner), - Some((1, (collection_owner.clone(), 1))) - ); - assert_eq!(Balances::reserved_balance(&collection_owner), 3 + 2); // 3 - item deposit, 2 - balance deposit - assert_eq!(Nfts::owner(collection_id, item_id).unwrap(), item_owner); - } - - assert_eq!(collections(), vec![(account(1), 0)]); - assert_eq!(items(), vec![(account(2), 0, 42), (account(2), 0, 43), (account(3), 0, 44)]); + }); + assert_eq!(Nfts::collection_items(collection_id), Some(total_items)); }); } #[test] -fn transfer_requires_deposit_works() { +fn clear_collection_approvals_works() { new_test_ext().execute_with(|| { + let balance = 100; let collection_id = 0; - let mut dest = account(3); - let mut item_id = 42; - let owner = account(2); + let item_id = 42; + let item_owner = account(1); + let delegates = 10..20; - Balances::make_free_balance_be(&account(1), 100); - Balances::make_free_balance_be(&account(2), 100); + for origin in [RuntimeOrigin::root(), none()] { + assert_noop!( + Nfts::clear_collection_approvals(origin, collection_id, 0), + BadOrigin.with_weight(WeightOf::clear_collection_approvals(0)) + ); + } assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - account(1), - collection_config_with_all_settings_enabled() + item_owner.clone(), + default_collection_config() )); - - // Transfer an unknown collection item, throws error `Error::UnknownItem`. - assert_noop!( - Nfts::transfer( - RuntimeOrigin::signed(owner.clone()), - collection_id, - item_id, - dest.clone() - ), - Error::::UnknownItem - ); - assert_ok!(Nfts::force_mint( - RuntimeOrigin::signed(account(1)), + RuntimeOrigin::signed(item_owner.clone()), collection_id, item_id, - owner.clone(), + item_owner.clone(), default_item_config() )); + Balances::make_free_balance_be(&item_owner, balance); + // Approve delegates. + let mut approvals = 0u32; + for i in delegates.clone() { + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + account(i), + None + )); + approvals.saturating_inc(); + } - // Throws error `NoItemOwned` since `owner` does not have an `AccountBalance` record - // created. - let account_balance = AccountBalance::take(collection_id, &owner); - assert_noop!( - Nfts::transfer( - RuntimeOrigin::signed(owner.clone()), + // Remove zero collection approvals. + assert_eq!( + Nfts::clear_collection_approvals( + RuntimeOrigin::signed(item_owner.clone()), collection_id, - item_id, - dest.clone() + 0 ), - Error::::NoItemOwned + Ok(Some(WeightOf::clear_collection_approvals(0)).into()) + ); + assert_eq!(Balances::free_balance(&item_owner), balance - approvals as u64); + assert_eq!( + CollectionApprovals::iter_prefix((collection_id, &item_owner)).count(), + approvals as usize ); - AccountBalance::set(collection_id, &owner, account_balance); + assert!(!events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner.clone(), + approvals + })); - // Reserve funds from `owner` as `dest` does not exist. - { - assert_ok!(Nfts::transfer( - RuntimeOrigin::signed(owner.clone()), + // Partially remove collection approvals. + let limit = 1; + assert_eq!( + Nfts::clear_collection_approvals( + RuntimeOrigin::signed(item_owner.clone()), collection_id, - item_id, - dest.clone() - )); - assert_eq!(AccountBalance::get(0, &dest), Some((1, (owner.clone(), 1)))); - assert_eq!(Balances::reserved_balance(&owner), 1); // 1 - balance deposit - assert_eq!(Balances::reserved_balance(&dest), 0); - assert!(items().contains(&(dest, collection_id, item_id))); - } - - // Reserve funds from `owner` since `dest` lacks sufficient balance. - { - item_id = 43; - dest = account(4); + limit + ), + Ok(Some(WeightOf::clear_collection_approvals(limit)).into()) + ); + approvals = approvals - limit; + assert_eq!(Balances::free_balance(&item_owner), balance - approvals as u64); + assert_eq!( + CollectionApprovals::iter_prefix((collection_id, item_owner.clone())).count(), + approvals as usize + ); + assert!(events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner.clone(), + approvals: limit + })); - assert_ok!(Nfts::force_mint( - RuntimeOrigin::signed(account(1)), + // Successfully remove all collection approvals. Only charges post-dispatch weight for + // the removed approvals. + assert_eq!( + Nfts::clear_collection_approvals( + RuntimeOrigin::signed(item_owner.clone()), collection_id, - item_id, - owner.clone(), - default_item_config() - )); + 10 + ), + Ok(Some(WeightOf::clear_collection_approvals(approvals)).into()) + ); + assert_eq!(Balances::free_balance(&item_owner), balance); + assert!(CollectionApprovals::iter_prefix((collection_id, item_owner.clone())) + .count() + .is_zero()); + assert!(events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner.clone(), + approvals, + })); - Balances::make_free_balance_be(&dest, 1); // 1 - ED - assert_ok!(Nfts::transfer( - RuntimeOrigin::signed(owner.clone()), + // Remove collection approvals while there are none. + assert_eq!( + Nfts::force_clear_collection_approvals( + RuntimeOrigin::root(), + item_owner.clone(), collection_id, - item_id, - dest.clone() - )); - assert_eq!(AccountBalance::get(collection_id, &dest), Some((1, (owner.clone(), 1)))); - assert_eq!(Balances::reserved_balance(&owner), 2); // 2 - balance deposit - assert_eq!(Balances::reserved_balance(&dest), 0); - assert!(items().contains(&(dest, collection_id, item_id))); - } - - // Reserves funds from `dest` since `dest` exists and has sufficient balance. - { - item_id = 44; - dest = account(5); + 10 + ), + Ok(Some(WeightOf::clear_collection_approvals(0)).into()) + ); + assert_eq!(Balances::free_balance(&item_owner), balance); + assert!(events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner, + approvals: 0 + })); - assert_ok!(Nfts::force_mint( - RuntimeOrigin::signed(account(1)), - collection_id, - item_id, - owner.clone(), - default_item_config() - )); - Balances::make_free_balance_be(&dest, 2); // 1 - ED, 1 - balance deposit - assert_ok!(Nfts::transfer( - RuntimeOrigin::signed(owner.clone()), - collection_id, - item_id, - dest.clone() - )); - assert_eq!(AccountBalance::get(collection_id, &dest), Some((1, (dest.clone(), 1)))); - assert_eq!(Balances::reserved_balance(&owner), 2); // 2 - balance deposit - assert_eq!(Balances::reserved_balance(&dest), 1); // 1 - balance deposit - assert!(Balances::usable_balance(&dest).is_zero()); - assert!(items().contains(&(dest, collection_id, item_id))); + // Ensure delegates are not able to transfer. + for i in delegates.clone() { + assert_noop!( + Nfts::transfer( + RuntimeOrigin::signed(account(i)), + collection_id, + item_id, + account(5) + ), + Error::::NoPermission + ); } }); } #[test] -fn approve_collection_transfer_works() { +fn force_clear_collection_approvals_works() { new_test_ext().execute_with(|| { - let mut collection_id = 0; - let collection_owner = account(1); - let deadline: BlockNumberFor = 20; - let delegate = account(3); + let balance = 100; + let collection_id = 0; let item_id = 42; - let item_owner = account(2); + let item_owner = account(1); + let delegates = 10..20; - // Origin checks for the `approve_collection_transfer`. - for origin in [root(), none()] { - assert_noop!( - Nfts::approve_collection_transfer(origin, collection_id, delegate.clone(), None), - BadOrigin - ); - } - // Origin checks for the `force_approve_collection_transfer`. for origin in [RuntimeOrigin::signed(item_owner.clone()), none()] { assert_noop!( - Nfts::force_approve_collection_transfer( + Nfts::force_clear_collection_approvals( origin, item_owner.clone(), collection_id, - delegate.clone(), - None + 0 ), - BadOrigin + BadOrigin.with_weight(WeightOf::clear_collection_approvals(0)) ); } - - // Provide balance to accounts. - Balances::make_free_balance_be(&item_owner, 100); - Balances::make_free_balance_be(&delegate, 100); - - for (origin, maybe_item_owner) in [ - // Parameters for `approve_collection_transfer`. - (RuntimeOrigin::signed(item_owner.clone()), None), - // Parameters for `force_approve_collection_transfer`. - (root(), Some(&item_owner)), - ] { - // Approve unknown collection, throws error `Error::NoItemOwned`. - assert_noop!( - approve_collection_transfer( - origin.clone(), - maybe_item_owner, - collection_id, - &delegate, - None - ), - Error::::NoItemOwned - ); - assert_ok!(Nfts::force_create( - RuntimeOrigin::root(), - collection_owner.clone(), - default_collection_config() + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + item_owner.clone(), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + item_id, + item_owner.clone(), + default_item_config() + )); + Balances::make_free_balance_be(&item_owner, balance); + // Approve delegates. + let mut approvals = 0u32; + for i in delegates.clone() { + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + account(i), + None )); + approvals.saturating_inc(); + } - // Approve collection without items, throws error `Error::NoItemOwned`. - assert_noop!( - Nfts::approve_collection_transfer( - RuntimeOrigin::signed(item_owner.clone()), - collection_id, - delegate.clone(), - None - ), - Error::::NoItemOwned - ); - assert_ok!(Nfts::force_mint( - RuntimeOrigin::signed(collection_owner.clone()), + // Remove zero collection approvals. + assert_eq!( + Nfts::force_clear_collection_approvals( + RuntimeOrigin::root(), + item_owner.clone(), collection_id, - item_id, + 0 + ), + Ok(Some(WeightOf::clear_collection_approvals(0)).into()) + ); + assert_eq!(Balances::free_balance(&item_owner), balance - approvals as u64); + assert_eq!( + CollectionApprovals::iter_prefix((collection_id, &item_owner)).count(), + approvals as usize + ); + assert!(!events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner.clone(), + approvals + })); + + // Partially remove collection approvals. + let limit = 1; + assert_eq!( + Nfts::force_clear_collection_approvals( + RuntimeOrigin::root(), item_owner.clone(), - default_item_config() - )); + collection_id, + limit + ), + Ok(Some(WeightOf::clear_collection_approvals(limit)).into()) + ); + approvals = approvals - limit; + assert_eq!(Balances::free_balance(&item_owner), balance - approvals as u64); + assert_eq!( + CollectionApprovals::iter_prefix((collection_id, item_owner.clone())).count(), + approvals as usize + ); + assert!(events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner.clone(), + approvals: limit + })); - // Approving a collection to a delegate with: - // 1. no deadline. - // 2. no deadline, again. - // 3. deadline. - // 3. equal deadline. - // 4. larger deadline. - // 5. smaller deadline. - // 6. no deadline, again. - // - // This tests all cases of approving the same delegate. - for deadline in [ - None, - None, - Some(deadline), - Some(deadline), - Some(deadline * 2), - Some(deadline), - None, - ] { - assert_ok!(approve_collection_transfer( - origin.clone(), - maybe_item_owner, - collection_id, - &delegate, - deadline, - )); - let deadline = deadline.map(|d| d + 1); - System::assert_last_event( - Event::::TransferApproved { - collection: collection_id, - item: None, - owner: item_owner.clone(), - delegate: delegate.clone(), - deadline, - } - .into(), - ); - assert_eq!(Balances::reserved_balance(&item_owner), 1); - assert_eq!( - CollectionApprovals::get((collection_id, &item_owner, &delegate)), - Some((deadline, CollectionApprovalDeposit::get())) - ); - } + // Successfully remove all collection approvals. Only charges post-dispatch weight for + // the removed approvals. + assert_eq!( + Nfts::force_clear_collection_approvals( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + 10 + ), + Ok(Some(WeightOf::clear_collection_approvals(approvals)).into()) + ); + assert_eq!(Balances::free_balance(&item_owner), balance); + assert!(CollectionApprovals::iter_prefix((collection_id, item_owner.clone())) + .count() + .is_zero()); + assert!(events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner.clone(), + approvals, + })); - // Set collection settings to non transferable, throws error - // `Error::ItemsNonTransferable`. - assert_ok!(Nfts::lock_collection( - RuntimeOrigin::signed(collection_owner.clone()), + // Remove collection approvals while there are none. + assert_eq!( + Nfts::force_clear_collection_approvals( + RuntimeOrigin::root(), + item_owner.clone(), collection_id, - CollectionSettings::from_disabled(CollectionSetting::TransferableItems.into()) - )); + 10 + ), + Ok(Some(WeightOf::clear_collection_approvals(0)).into()) + ); + assert_eq!(Balances::free_balance(&item_owner), balance); + assert!(events().contains(&Event::::ApprovalsCancelled { + collection: collection_id, + owner: item_owner, + approvals: 0 + })); + + // Ensure delegates are not able to transfer. + for i in delegates.clone() { assert_noop!( - approve_collection_transfer( - origin.clone(), - maybe_item_owner, + Nfts::transfer( + RuntimeOrigin::signed(account(i)), collection_id, - &delegate, - None + item_id, + account(5) ), - Error::::ItemsNonTransferable + Error::::NoPermission ); - - // To reset reserved balance. - assert_ok!(Nfts::cancel_collection_approval( - RuntimeOrigin::signed(item_owner.clone()), - collection_id, - delegate.clone() - )); - collection_id.saturating_inc(); } }); } #[test] -fn cancel_collection_approval_works() { +fn approve_collection_transfer_works() { new_test_ext().execute_with(|| { let collection_id = 0; let collection_owner = account(1); + let deadline: BlockNumberFor = 20; let delegate = account(3); + let deposit = CollectionApprovalDeposit::get(); let item_id = 42; let item_owner = account(2); - // Origin checks for the `cancel_collection_approval`. - for origin in [root(), none()] { - assert_noop!( - Nfts::cancel_collection_approval(origin, collection_id, delegate.clone()), - BadOrigin - ); - } - // Origin checks for the `force_cancel_collection_approval`. - for origin in [RuntimeOrigin::signed(item_owner.clone()), none()] { + for origin in [RuntimeOrigin::root(), none()] { assert_noop!( - Nfts::force_cancel_collection_approval( - origin, - item_owner.clone(), - collection_id, - delegate.clone() - ), + Nfts::approve_collection_transfer(origin, collection_id, delegate.clone(), None), BadOrigin ); } - - Balances::make_free_balance_be(&item_owner, 100); + // Approve unknown collection. + assert_noop!( + Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + None + ), + Error::::NoItemOwned + ); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), collection_owner.clone(), default_collection_config() )); + // Approve collection without items. + assert_noop!( + Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + None + ), + Error::::NoItemOwned + ); assert_ok!(Nfts::force_mint( - RuntimeOrigin::signed(collection_owner), + RuntimeOrigin::signed(collection_owner.clone()), collection_id, item_id, item_owner.clone(), default_item_config() )); + // Approve collection without balance. + assert_noop!( + Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + None + ), + BalancesError::::InsufficientBalance, + ); - for (origin, maybe_owner) in [ - // Parameters for `cancel_collection_approval`. - (RuntimeOrigin::signed(item_owner.clone()), None), - // Parameters for `force_cancel_collection_approval`. - (root(), Some(&item_owner)), - ] { + Balances::make_free_balance_be(&item_owner, 100); + // Approving a collection to a delegate with: + // 1. no deadline. + // 2. no deadline, again. + // 3. deadline. + // 3. equal deadline. + // 4. larger deadline. + // 5. smaller deadline. + // 6. no deadline, again. + // + // This tests all cases of approving the same delegate. + for deadline in + [None, None, Some(deadline), Some(deadline), Some(deadline * 2), Some(deadline), None] + { assert_ok!(Nfts::approve_collection_transfer( RuntimeOrigin::signed(item_owner.clone()), collection_id, delegate.clone(), - None + deadline, )); - // Cancel an approval for a non existing collection. - assert_noop!( - cancel_collection_approval(origin.clone(), maybe_owner, 1, &delegate), - Error::::Unapproved + let deadline = deadline.map(|d| d + 1); + System::assert_last_event( + Event::::TransferApproved { + collection: collection_id, + item: None, + owner: item_owner.clone(), + delegate: delegate.clone(), + deadline, + } + .into(), + ); + assert_eq!(Balances::reserved_balance(&item_owner), deposit); + assert_eq!( + CollectionApprovals::get((collection_id, &item_owner, &delegate)), + Some((deadline, deposit)) ); - // Cancel an unapproved delegate. + } + + // Set collection settings to non transferable. + assert_ok!(Nfts::lock_collection( + RuntimeOrigin::signed(collection_owner), + collection_id, + CollectionSettings::from_disabled(CollectionSetting::TransferableItems.into()) + )); + assert_noop!( + Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner), + collection_id, + delegate, + None + ), + Error::::ItemsNonTransferable + ); + }); +} + +#[test] +fn force_approve_collection_transfer_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let collection_owner = account(1); + let deadline: BlockNumberFor = 20; + let delegate = account(3); + let item_id = 42; + let item_owner = account(2); + + for origin in [RuntimeOrigin::signed(item_owner.clone()), none()] { assert_noop!( - cancel_collection_approval( - origin.clone(), - maybe_owner, + Nfts::force_approve_collection_transfer( + origin, + item_owner.clone(), collection_id, - &account(69), + delegate.clone(), + None ), - Error::::Unapproved + BadOrigin ); + } + // Approve unknown collection. + assert_noop!( + Nfts::force_approve_collection_transfer( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + delegate.clone(), + None + ), + Error::::NoItemOwned + ); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + collection_owner.clone(), + default_collection_config() + )); + // Approve collection without items. + assert_noop!( + Nfts::force_approve_collection_transfer( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + delegate.clone(), + None + ), + Error::::NoItemOwned + ); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(collection_owner.clone()), + collection_id, + item_id, + item_owner.clone(), + default_item_config() + )); + // Approve collection without balance. + assert_ok!(Nfts::force_approve_collection_transfer( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + delegate.clone(), + None + )); - // Successfully cancel a collection approval. - assert_ok!(cancel_collection_approval( - origin.clone(), - maybe_owner, + Balances::make_free_balance_be(&item_owner, 100); + // Approving a collection to a delegate with: + // 1. no deadline. + // 2. no deadline, again. + // 3. deadline. + // 3. equal deadline. + // 4. larger deadline. + // 5. smaller deadline. + // 6. no deadline, again. + // + // This tests all cases of approving the same delegate. + for deadline in + [None, None, Some(deadline), Some(deadline), Some(deadline * 2), Some(deadline), None] + { + assert_ok!(Nfts::force_approve_collection_transfer( + RuntimeOrigin::root(), + item_owner.clone(), collection_id, - &delegate + delegate.clone(), + deadline, )); - assert_eq!(Balances::reserved_balance(&item_owner), 0); - assert!(!CollectionApprovals::contains_key((collection_id, &item_owner, &delegate))); + let deadline = deadline.map(|d| d + 1); System::assert_last_event( - Event::::ApprovalCancelled { + Event::::TransferApproved { collection: collection_id, item: None, owner: item_owner.clone(), delegate: delegate.clone(), + deadline, } .into(), ); + assert_eq!(Balances::reserved_balance(&item_owner), 0); + assert_eq!( + CollectionApprovals::get((collection_id, &item_owner, &delegate)), + Some((deadline, 0)) + ); } + + // Set collection settings to non transferable. + assert_ok!(Nfts::lock_collection( + RuntimeOrigin::signed(collection_owner), + collection_id, + CollectionSettings::from_disabled(CollectionSetting::TransferableItems.into()) + )); + assert_noop!( + Nfts::force_approve_collection_transfer( + RuntimeOrigin::root(), + item_owner, + collection_id, + delegate, + None + ), + Error::::ItemsNonTransferable + ); }); } #[test] -fn clear_collection_approvals_works() { +fn cancel_collection_approval_works() { new_test_ext().execute_with(|| { - let balance = 100; let collection_id = 0; + let collection_owner = account(1); + let delegate = account(3); let item_id = 42; - let item_owner = account(1); - let delegates = 10..20; + let item_owner = account(2); - // Origin checks for the `clear_collection_approvals`. - for origin in [root(), none()] { + for origin in [RuntimeOrigin::root(), none()] { assert_noop!( - Nfts::clear_collection_approvals(origin, collection_id, 0), - BadOrigin.with_weight(WeightOf::clear_collection_approvals(0)) + Nfts::cancel_collection_approval(origin, collection_id, delegate.clone()), + BadOrigin ); } - // Origin checks for the `force_clear_collection_approvals`. + Balances::make_free_balance_be(&item_owner, 100); + assert_ok!(Nfts::force_create( + RuntimeOrigin::root(), + collection_owner.clone(), + default_collection_config() + )); + assert_ok!(Nfts::force_mint( + RuntimeOrigin::signed(collection_owner), + collection_id, + item_id, + item_owner.clone(), + default_item_config() + )); + // Cancel an approval for a non existing collection. + assert_noop!( + Nfts::cancel_collection_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone() + ), + Error::::NotDelegate + ); + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + None + )); + // Cancel an unapproved delegate. + assert_noop!( + Nfts::cancel_collection_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + account(69) + ), + Error::::NotDelegate + ); + // Successfully cancel a collection approval. + assert_ok!(Nfts::cancel_collection_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone() + )); + assert_eq!(Balances::reserved_balance(&item_owner), 0); + assert!(!CollectionApprovals::contains_key((collection_id, &item_owner, &delegate))); + System::assert_last_event( + Event::::ApprovalCancelled { + collection: collection_id, + item: None, + owner: item_owner, + delegate, + } + .into(), + ); + }); +} + +#[test] +fn force_cancel_collection_approval_works() { + new_test_ext().execute_with(|| { + let collection_id = 0; + let collection_owner = account(1); + let delegate = account(3); + let item_id = 42; + let item_owner = account(2); + for origin in [RuntimeOrigin::signed(item_owner.clone()), none()] { assert_noop!( - Nfts::force_clear_collection_approvals( + Nfts::force_cancel_collection_approval( origin, item_owner.clone(), collection_id, - 0 + delegate.clone() ), - BadOrigin.with_weight(WeightOf::clear_collection_approvals(0)) + BadOrigin ); } - + Balances::make_free_balance_be(&item_owner, 100); assert_ok!(Nfts::force_create( RuntimeOrigin::root(), - item_owner.clone(), + collection_owner.clone(), default_collection_config() )); assert_ok!(Nfts::force_mint( - RuntimeOrigin::signed(item_owner.clone()), + RuntimeOrigin::signed(collection_owner), collection_id, item_id, item_owner.clone(), - default_item_config() + default_item_config() + )); + // Cancel an approval for a non existing collection. + assert_noop!( + Nfts::force_cancel_collection_approval( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + delegate.clone() + ), + Error::::NotDelegate + ); + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + None + )); + // Cancel an unapproved delegate. + assert_noop!( + Nfts::force_cancel_collection_approval( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + account(69) + ), + Error::::NotDelegate + ); + // Successfully cancel a collection approval. + assert_ok!(Nfts::force_cancel_collection_approval( + RuntimeOrigin::root(), + item_owner.clone(), + collection_id, + delegate.clone() )); - Balances::make_free_balance_be(&item_owner, balance); - - for (origin, maybe_owner) in [ - // Parameters for `clear_collection_approvals`. - (root(), Some(&item_owner)), - // Parameters for `force_clear_collection_approvals`. - (RuntimeOrigin::signed(item_owner.clone()), None), - ] { - // Approve delegates. - let mut approvals = 0u32; - for i in delegates.clone() { - assert_ok!(Nfts::approve_collection_transfer( - RuntimeOrigin::signed(item_owner.clone()), - collection_id, - account(i), - None - )); - approvals.saturating_inc(); - } - - // Remove zero collection approvals. - assert_eq!( - clear_collection_approvals(origin.clone(), maybe_owner, collection_id, 0), - Ok(Some(WeightOf::clear_collection_approvals(0)).into()) - ); - assert_eq!(Balances::free_balance(&item_owner), balance - approvals as u64); - assert_eq!( - CollectionApprovals::iter_prefix((collection_id, &item_owner)).count(), - approvals as usize - ); - assert!(!events().contains(&Event::::ApprovalsCancelled { + assert_eq!(Balances::reserved_balance(&item_owner), 0); + assert!(!CollectionApprovals::contains_key((collection_id, &item_owner, &delegate))); + System::assert_last_event( + Event::::ApprovalCancelled { collection: collection_id, - owner: item_owner.clone(), - approvals - })); - - // Partially remove collection approvals. - assert_eq!( - clear_collection_approvals(origin.clone(), maybe_owner.clone(), collection_id, 1), - Ok(Some(WeightOf::clear_collection_approvals(1)).into()) - ); - assert_eq!(Balances::free_balance(&item_owner), balance - (approvals as u64) + 1); - assert_eq!( - CollectionApprovals::iter_prefix((collection_id, item_owner.clone())).count(), - approvals as usize - 1 - ); - assert!(events().contains(&Event::::ApprovalsCancelled { - collection: collection_id, - owner: item_owner.clone(), - approvals: 1 - })); - - // Successfully remove all collection approvals. Only charges post-dispatch weight for - // the removed approvals. - assert_eq!( - clear_collection_approvals(origin.clone(), maybe_owner.clone(), collection_id, 10), - Ok(Some(WeightOf::clear_collection_approvals(9)).into()) - ); - assert_eq!(Balances::free_balance(&item_owner), balance); - assert!(CollectionApprovals::iter_prefix((collection_id, item_owner.clone())) - .count() - .is_zero()); - assert!(events().contains(&Event::::ApprovalsCancelled { - collection: collection_id, - owner: item_owner.clone(), - approvals: approvals - 1 - })); - - // Remove zero collection approvals. - assert_eq!( - clear_collection_approvals(origin.clone(), maybe_owner.clone(), collection_id, 10), - Ok(Some(WeightOf::clear_collection_approvals(0)).into()) - ); - assert_eq!(Balances::free_balance(&item_owner), balance); - assert!(events().contains(&Event::::ApprovalsCancelled { - collection: collection_id, - owner: item_owner.clone(), - approvals: 0 - })); - - // Ensure delegates are not able to transfer. - for i in delegates.clone() { - assert_noop!( - Nfts::transfer( - RuntimeOrigin::signed(account(i)), - collection_id, - item_id, - account(5) - ), - Error::::NoPermission - ); + item: None, + owner: item_owner, + delegate, } - } + .into(), + ); }); } #[test] -fn check_approval_without_deadline_works() { +fn check_approval_permission_without_deadline_works() { new_test_ext().execute_with(|| { let collection_id = 0; let collection_owner = account(1); @@ -4736,11 +5100,11 @@ fn check_approval_without_deadline_works() { )); // Item doesn't exist. assert_noop!( - Nfts::check_approval(&collection_id, &None, &item_owner, &delegate), + Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate), Error::::NoPermission ); assert_noop!( - Nfts::check_approval(&collection_id, &Some(item_id), &item_owner, &delegate), + Nfts::check_approval_permission(&collection_id, &Some(item_id), &item_owner, &delegate), Error::::UnknownItem ); assert_ok!(Nfts::force_mint( @@ -4752,60 +5116,59 @@ fn check_approval_without_deadline_works() { )); // No approval. assert_noop!( - Nfts::check_approval(&collection_id, &None, &item_owner, &delegate), + Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate), Error::::NoPermission ); assert_noop!( - Nfts::check_approval(&collection_id, &Some(item_id), &item_owner, &delegate), + Nfts::check_approval_permission(&collection_id, &Some(item_id), &item_owner, &delegate), Error::::NoPermission ); + // Approve collection without deadline. - { - assert_ok!(Nfts::approve_collection_transfer( - RuntimeOrigin::signed(item_owner.clone()), - collection_id, - delegate.clone(), - None - )); - assert_ok!(Nfts::check_approval(&collection_id, &None, &item_owner, &delegate)); - assert_ok!(Nfts::check_approval( - &collection_id, - &Some(item_id), - &item_owner, - &delegate - )); - assert_ok!(Nfts::cancel_collection_approval( - RuntimeOrigin::signed(item_owner.clone()), - collection_id, - delegate.clone() - )); - } + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + None + )); + assert_ok!(Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate)); + assert_ok!(Nfts::check_approval_permission( + &collection_id, + &Some(item_id), + &item_owner, + &delegate + )); + assert_ok!(Nfts::cancel_collection_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone() + )); + // Approve item without deadline. - { - assert_ok!(Nfts::approve_transfer( - RuntimeOrigin::signed(item_owner.clone()), - collection_id, - item_id, - delegate.clone(), - None - )); - assert_noop!( - Nfts::check_approval(&collection_id, &None, &item_owner, &delegate), - Error::::NoPermission - ); - assert_ok!(Nfts::check_approval( - &collection_id, - &Some(item_id), - &item_owner, - &delegate - )); - assert_ok!(Nfts::cancel_approval( - RuntimeOrigin::signed(item_owner.clone()), - collection_id, - item_id, - delegate.clone() - )); - } + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + item_id, + delegate.clone(), + None + )); + assert_noop!( + Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate), + Error::::NoPermission + ); + assert_ok!(Nfts::check_approval_permission( + &collection_id, + &Some(item_id), + &item_owner, + &delegate + )); + assert_ok!(Nfts::cancel_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + item_id, + delegate.clone() + )); + // Approve collection and item without deadline. assert_ok!(Nfts::approve_transfer( RuntimeOrigin::signed(item_owner.clone()), @@ -4820,13 +5183,18 @@ fn check_approval_without_deadline_works() { delegate.clone(), None )); - assert_ok!(Nfts::check_approval(&collection_id, &None, &item_owner, &delegate)); - assert_ok!(Nfts::check_approval(&collection_id, &Some(item_id), &item_owner, &delegate)); + assert_ok!(Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate)); + assert_ok!(Nfts::check_approval_permission( + &collection_id, + &Some(item_id), + &item_owner, + &delegate + )); }); } #[test] -fn check_approval_with_deadline_works() { +fn check_approval_permission_with_deadline_works() { new_test_ext().execute_with(|| { let collection_id = 0; let collection_owner = account(1); @@ -4847,202 +5215,105 @@ fn check_approval_with_deadline_works() { item_owner.clone(), default_item_config() )); + // Approve collection with deadline. - { - let deadline: BlockNumberFor = 10; - assert_ok!(Nfts::approve_collection_transfer( - RuntimeOrigin::signed(item_owner.clone()), - collection_id, - delegate.clone(), - Some(deadline), - )); - assert_ok!(Nfts::check_approval(&collection_id, &None, &item_owner, &delegate)); - assert_ok!(Nfts::check_approval( - &collection_id, - &Some(item_id), - &item_owner, - &delegate - )); - // Expire approval. - System::set_block_number(deadline + System::block_number() + 1); - assert_noop!( - Nfts::check_approval(&collection_id, &None, &item_owner, &delegate), - Error::::ApprovalExpired - ); - assert_noop!( - Nfts::check_approval(&collection_id, &Some(item_id), &item_owner, &delegate), - Error::::NoPermission - ); - assert_ok!(Nfts::cancel_collection_approval( - RuntimeOrigin::signed(item_owner.clone()), - collection_id, - delegate.clone(), - )); - } - // Approve item with deadline. - { - let deadline: BlockNumberFor = 20; - assert_ok!(Nfts::approve_transfer( - RuntimeOrigin::signed(item_owner.clone()), - collection_id, - item_id, - delegate.clone(), - Some(deadline), - )); - assert_noop!( - Nfts::check_approval(&collection_id, &None, &item_owner, &delegate), - Error::::NoPermission - ); - assert_ok!(Nfts::check_approval( - &collection_id, - &Some(item_id), - &item_owner, - &delegate - )); - // Expire approval. - System::set_block_number(deadline + System::block_number() + 1); - assert_noop!( - Nfts::check_approval(&collection_id, &None, &item_owner, &delegate), - Error::::NoPermission - ); - assert_noop!( - Nfts::check_approval(&collection_id, &Some(item_id), &item_owner, &delegate), - Error::::ApprovalExpired - ); - assert_ok!(Nfts::cancel_approval( - RuntimeOrigin::signed(item_owner.clone()), - collection_id, - item_id, - delegate.clone(), - )); - } + let deadline: BlockNumberFor = 10; + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + Some(deadline), + )); + assert_ok!(Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate)); + assert_ok!(Nfts::check_approval_permission( + &collection_id, + &Some(item_id), + &item_owner, + &delegate + )); + // Expire approval. + System::set_block_number(deadline + System::block_number() + 1); assert_noop!( - Nfts::check_approval(&collection_id, &None, &item_owner, &delegate), - Error::::NoPermission + Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate), + Error::::ApprovalExpired ); assert_noop!( - Nfts::check_approval(&collection_id, &Some(item_id), &item_owner, &delegate), + Nfts::check_approval_permission(&collection_id, &Some(item_id), &item_owner, &delegate), Error::::NoPermission ); - }); -} - -#[test] -fn collection_item_works() { - new_test_ext().execute_with(|| { - let collection_id = 0; - let total_items = 10; - let user_id = account(1); - - // No collection. - assert_eq!(Nfts::collection_items(collection_id), None); - - assert_ok!(Nfts::force_create( - RuntimeOrigin::root(), - user_id.clone(), - default_collection_config() + assert_ok!(Nfts::cancel_collection_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), )); - // Mint items and validate the total supply. - (0..total_items).into_iter().for_each(|i| { - assert_ok!(Nfts::force_mint( - RuntimeOrigin::root(), - collection_id, - i, - user_id.clone(), - ItemConfig::default() - )); - }); - assert_eq!(Nfts::collection_items(collection_id), Some(total_items)); - }); -} - -#[test] -fn increment_account_balance_works() { - new_test_ext().execute_with(|| { - let collection_id = 0; - let deposit_account = account(1); - let owner = account(2); - - // Throws error `BalancesError::InsufficientBalance`. + // Approve item with deadline. + let deadline: BlockNumberFor = 20; + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + item_id, + delegate.clone(), + Some(deadline), + )); assert_noop!( - Nfts::increment_account_balance(collection_id, &owner, (&deposit_account, 1)), - BalancesError::::InsufficientBalance + Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate), + Error::::NoPermission ); - - Balances::make_free_balance_be(&deposit_account, 100); - // Initialize `AccountBalance` and increase the collection item count for the new account. - assert_ok!(Nfts::increment_account_balance(collection_id, &owner, (&deposit_account, 1))); - assert_eq!(Balances::reserved_balance(&account(1)), 1); - assert_eq!( - AccountBalance::get(collection_id, &owner), - Some((1, (deposit_account.clone(), 1))) + assert_ok!(Nfts::check_approval_permission( + &collection_id, + &Some(item_id), + &item_owner, + &delegate + )); + // Expire approval. + System::set_block_number(deadline + System::block_number() + 1); + assert_noop!( + Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate), + Error::::NoPermission ); - - // Increment the balance of a non-zero balance account. No additional reserves. - (1..10).into_iter().for_each(|i| { - assert_ok!(Nfts::increment_account_balance( - collection_id, - &owner, - (&deposit_account, 1) - )); - assert_eq!(Balances::reserved_balance(&deposit_account), 1); - assert_eq!( - AccountBalance::get(collection_id, &owner), - Some((i + 1, (deposit_account.clone(), 1))) - ); - }); - }); -} - -#[test] -fn decrement_account_balance_works() { - new_test_ext().execute_with(|| { - let collection_id = 0; - let balance = 3u32; - let deposit_account = account(1); - let owner = account(2); - - Balances::make_free_balance_be(&deposit_account, 100); - // Decrement non-existing `AccountBalance` record. assert_noop!( - Nfts::decrement_account_balance(collection_id, &deposit_account), - Error::::NoItemOwned + Nfts::check_approval_permission(&collection_id, &Some(item_id), &item_owner, &delegate), + Error::::ApprovalExpired ); + assert_ok!(Nfts::cancel_approval( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + item_id, + delegate.clone(), + )); - (0..balance).into_iter().for_each(|_| { - assert_ok!(Nfts::increment_account_balance( - collection_id, - &owner, - (&deposit_account, 1) - )); - }); - - // Successfully decrement the value of the `AccountBalance` entry. - let balance_before_decrement = - AccountBalance::get(collection_id, &owner).map(|a| a.0).unwrap(); - assert_ok!(Nfts::decrement_account_balance(collection_id, &owner)); - let balance_after_decrement = - AccountBalance::get(collection_id, &owner).map(|a| a.0).unwrap(); - assert_eq!(balance_before_decrement - 1, balance_after_decrement); - assert_eq!(Balances::reserved_balance(&deposit_account), 1); - assert_eq!( - AccountBalance::get(collection_id, &owner), - Some((balance - 1, (deposit_account.clone(), 1))) + // Approve collection and item with deadline. + let deadline: BlockNumberFor = 30; + assert_ok!(Nfts::approve_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + item_id, + delegate.clone(), + Some(deadline) + )); + assert_ok!(Nfts::approve_collection_transfer( + RuntimeOrigin::signed(item_owner.clone()), + collection_id, + delegate.clone(), + Some(deadline) + )); + assert_ok!(Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate)); + assert_ok!(Nfts::check_approval_permission( + &collection_id, + &Some(item_id), + &item_owner, + &delegate + )); + // Expire approvals. + System::set_block_number(deadline + System::block_number() + 1); + assert_noop!( + Nfts::check_approval_permission(&collection_id, &None, &item_owner, &delegate), + Error::::ApprovalExpired ); - - // Decrement value of `AccountBalance` if it is non-zero. - assert_ok!(Nfts::decrement_account_balance(collection_id, &owner)); - assert_eq!(Balances::reserved_balance(&deposit_account), 1); - assert_eq!( - AccountBalance::get(collection_id, &owner), - Some((balance - 2, (deposit_account.clone(), 1))) + assert_noop!( + Nfts::check_approval_permission(&collection_id, &Some(item_id), &item_owner, &delegate), + Error::::ApprovalExpired ); - - // `AccountBalance` record is deleted, and the depositor's funds are unreserved if - // the `AccountBalance` value reaches zero after decrementing. - assert_ok!(Nfts::decrement_account_balance(collection_id, &owner)); - assert_eq!(Balances::reserved_balance(&deposit_account), 0); - assert!(!AccountBalance::contains_key(collection_id, &owner)); }); } diff --git a/pallets/nfts/src/weights.rs b/pallets/nfts/src/weights.rs index 974b1f8f2..34e2d5408 100644 --- a/pallets/nfts/src/weights.rs +++ b/pallets/nfts/src/weights.rs @@ -1,8 +1,24 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. //! Autogenerated weights for `pallet_nfts` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 40.0.0 -//! DATE: 2024-12-22, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-01-14, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `R0GUE`, CPU: `` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` @@ -118,7 +134,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `3` // Estimated: `3549` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 3549) + Weight::from_parts(12_000_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -147,14 +163,14 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `32137 + a * (366 ±0)` // Estimated: `2523990 + a * (2954 ±0)` - // Minimum execution time: 893_000_000 picoseconds. - Weight::from_parts(814_084_483, 2523990) - // Standard Error: 18_466 - .saturating_add(Weight::from_parts(26_897, 0).saturating_mul(m.into())) - // Standard Error: 18_466 - .saturating_add(Weight::from_parts(87_809, 0).saturating_mul(c.into())) - // Standard Error: 18_466 - .saturating_add(Weight::from_parts(4_861_675, 0).saturating_mul(a.into())) + // Minimum execution time: 902_000_000 picoseconds. + Weight::from_parts(786_614_356, 2523990) + // Standard Error: 18_860 + .saturating_add(Weight::from_parts(85_114, 0).saturating_mul(m.into())) + // Standard Error: 18_860 + .saturating_add(Weight::from_parts(52_018, 0).saturating_mul(c.into())) + // Standard Error: 18_860 + .saturating_add(Weight::from_parts(4_806_613, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(1005_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(1005_u64)) @@ -179,7 +195,7 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `382` // Estimated: `4326` - // Minimum execution time: 37_000_000 picoseconds. + // Minimum execution time: 36_000_000 picoseconds. Weight::from_parts(38_000_000, 4326) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) @@ -202,8 +218,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `382` // Estimated: `4326` - // Minimum execution time: 36_000_000 picoseconds. - Weight::from_parts(39_000_000, 4326) + // Minimum execution time: 35_000_000 picoseconds. + Weight::from_parts(36_000_000, 4326) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -231,8 +247,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `634` // Estimated: `4326` - // Minimum execution time: 42_000_000 picoseconds. - Weight::from_parts(43_000_000, 4326) + // Minimum execution time: 39_000_000 picoseconds. + Weight::from_parts(41_000_000, 4326) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } @@ -246,10 +262,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionApprovals` (r:1 w:0) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:2 w:2) /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:2) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) @@ -258,12 +274,12 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `765` + // Measured: `696` // Estimated: `6180` - // Minimum execution time: 47_000_000 picoseconds. - Weight::from_parts(50_000_000, 6180) + // Minimum execution time: 45_000_000 picoseconds. + Weight::from_parts(52_000_000, 6180) .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(8_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) @@ -276,10 +292,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `690 + i * (108 ±0)` // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 8_000_000 picoseconds. - Weight::from_parts(9_000_000, 3549) - // Standard Error: 41_268 - .saturating_add(Weight::from_parts(12_689_751, 0).saturating_mul(i.into())) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 3549) + // Standard Error: 24_440 + .saturating_add(Weight::from_parts(12_497_458, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -337,7 +353,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `417` // Estimated: `3593` // Minimum execution time: 15_000_000 picoseconds. - Weight::from_parts(15_000_000, 3593) + Weight::from_parts(16_000_000, 3593) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -349,8 +365,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `296` // Estimated: `6078` - // Minimum execution time: 24_000_000 picoseconds. - Weight::from_parts(25_000_000, 6078) + // Minimum execution time: 26_000_000 picoseconds. + Weight::from_parts(68_000_000, 6078) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -363,7 +379,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `238` // Estimated: `3549` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(9_000_000, 3549) + Weight::from_parts(10_000_000, 3549) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -376,7 +392,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `203` // Estimated: `3549` // Minimum execution time: 7_000_000 picoseconds. - Weight::from_parts(7_000_000, 3549) + Weight::from_parts(8_000_000, 3549) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -388,8 +404,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3534` - // Minimum execution time: 10_000_000 picoseconds. - Weight::from_parts(11_000_000, 3534) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(13_000_000, 3534) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -407,8 +423,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `499` // Estimated: `3944` - // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(28_000_000, 3944) + // Minimum execution time: 29_000_000 picoseconds. + Weight::from_parts(31_000_000, 3944) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -420,8 +436,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `271` // Estimated: `3944` - // Minimum execution time: 13_000_000 picoseconds. - Weight::from_parts(14_000_000, 3944) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(15_000_000, 3944) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -437,8 +453,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `943` // Estimated: `3944` - // Minimum execution time: 26_000_000 picoseconds. - Weight::from_parts(27_000_000, 3944) + // Minimum execution time: 27_000_000 picoseconds. + Weight::from_parts(28_000_000, 3944) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -451,7 +467,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `308` // Estimated: `4466` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(9_000_000, 4466) + Weight::from_parts(12_000_000, 4466) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -469,9 +485,9 @@ impl WeightInfo for SubstrateWeight { // Measured: `686 + n * (398 ±0)` // Estimated: `4466 + n * (2954 ±0)` // Minimum execution time: 14_000_000 picoseconds. - Weight::from_parts(14_000_000, 4466) - // Standard Error: 11_599 - .saturating_add(Weight::from_parts(4_782_076, 0).saturating_mul(n.into())) + Weight::from_parts(17_000_000, 4466) + // Standard Error: 8_501 + .saturating_add(Weight::from_parts(4_744_468, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -493,7 +509,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `499` // Estimated: `3812` // Minimum execution time: 23_000_000 picoseconds. - Weight::from_parts(24_000_000, 3812) + Weight::from_parts(25_000_000, 3812) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -509,8 +525,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `809` // Estimated: `3812` - // Minimum execution time: 22_000_000 picoseconds. - Weight::from_parts(23_000_000, 3812) + // Minimum execution time: 23_000_000 picoseconds. + Weight::from_parts(25_000_000, 3812) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -543,8 +559,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `643` // Estimated: `3759` - // Minimum execution time: 22_000_000 picoseconds. - Weight::from_parts(23_000_000, 3759) + // Minimum execution time: 21_000_000 picoseconds. + Weight::from_parts(22_000_000, 3759) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -569,8 +585,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `345` // Estimated: `4326` - // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 4326) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4326) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -594,7 +610,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `3` // Estimated: `3517` // Minimum execution time: 7_000_000 picoseconds. - Weight::from_parts(8_000_000, 3517) + Weight::from_parts(7_000_000, 3517) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -607,7 +623,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `267` // Estimated: `3549` // Minimum execution time: 10_000_000 picoseconds. - Weight::from_parts(10_000_000, 3549) + Weight::from_parts(13_000_000, 3549) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -619,7 +635,7 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `250` // Estimated: `3538` - // Minimum execution time: 10_000_000 picoseconds. + // Minimum execution time: 9_000_000 picoseconds. Weight::from_parts(11_000_000, 3538) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) @@ -636,8 +652,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `478` // Estimated: `4326` - // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 4326) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(15_000_000, 4326) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -665,8 +681,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `877` // Estimated: `6180` - // Minimum execution time: 53_000_000 picoseconds. - Weight::from_parts(55_000_000, 6180) + // Minimum execution time: 49_000_000 picoseconds. + Weight::from_parts(54_000_000, 6180) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } @@ -676,9 +692,9 @@ impl WeightInfo for SubstrateWeight { // Measured: `0` // Estimated: `0` // Minimum execution time: 1_000_000 picoseconds. - Weight::from_parts(1_497_803, 0) - // Standard Error: 5_639 - .saturating_add(Weight::from_parts(1_502_698, 0).saturating_mul(n.into())) + Weight::from_parts(1_206_012, 0) + // Standard Error: 11_245 + .saturating_add(Weight::from_parts(1_656_192, 0).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:2 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -689,7 +705,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `421` // Estimated: `7662` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 7662) + Weight::from_parts(12_000_000, 7662) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -730,8 +746,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1118` // Estimated: `7662` - // Minimum execution time: 79_000_000 picoseconds. - Weight::from_parts(82_000_000, 7662) + // Minimum execution time: 75_000_000 picoseconds. + Weight::from_parts(84_000_000, 7662) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(13_u64)) } @@ -760,10 +776,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `485` // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 91_000_000 picoseconds. - Weight::from_parts(95_221_709, 6078) - // Standard Error: 128_983 - .saturating_add(Weight::from_parts(22_458_028, 0).saturating_mul(n.into())) + // Minimum execution time: 90_000_000 picoseconds. + Weight::from_parts(98_359_609, 6078) + // Standard Error: 115_405 + .saturating_add(Weight::from_parts(20_931_944, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(7_u64)) @@ -788,9 +804,9 @@ impl WeightInfo for SubstrateWeight { // Measured: `514` // Estimated: `4466 + n * (2954 ±0)` // Minimum execution time: 47_000_000 picoseconds. - Weight::from_parts(54_326_784, 4466) - // Standard Error: 99_430 - .saturating_add(Weight::from_parts(20_625_932, 0).saturating_mul(n.into())) + Weight::from_parts(55_680_600, 4466) + // Standard Error: 107_152 + .saturating_add(Weight::from_parts(20_234_822, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -808,7 +824,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `500` // Estimated: `3602` // Minimum execution time: 20_000_000 picoseconds. - Weight::from_parts(24_000_000, 3602) + Weight::from_parts(25_000_000, 3602) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -822,8 +838,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `500` // Estimated: `3602` - // Minimum execution time: 21_000_000 picoseconds. - Weight::from_parts(24_000_000, 3602) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(15_000_000, 3602) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -834,7 +850,7 @@ impl WeightInfo for SubstrateWeight { // Measured: `359` // Estimated: `3602` // Minimum execution time: 16_000_000 picoseconds. - Weight::from_parts(17_000_000, 3602) + Weight::from_parts(18_000_000, 3602) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -856,10 +872,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `327 + n * (75 ±0)` // Estimated: `3602 + n * (2612 ±0)` - // Minimum execution time: 20_000_000 picoseconds. - Weight::from_parts(22_000_000, 3602) - // Standard Error: 8_973 - .saturating_add(Weight::from_parts(3_888_488, 0).saturating_mul(n.into())) + // Minimum execution time: 18_000_000 picoseconds. + Weight::from_parts(18_000_000, 3602) + // Standard Error: 6_993 + .saturating_add(Weight::from_parts(3_855_667, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) @@ -872,10 +888,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `327 + n * (75 ±0)` // Estimated: `3602 + n * (2612 ±0)` - // Minimum execution time: 18_000_000 picoseconds. - Weight::from_parts(33_601_852, 3602) - // Standard Error: 7_525 - .saturating_add(Weight::from_parts(3_464_828, 0).saturating_mul(n.into())) + // Minimum execution time: 19_000_000 picoseconds. + Weight::from_parts(20_000_000, 3602) + // Standard Error: 6_538 + .saturating_add(Weight::from_parts(3_823_979, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) @@ -919,7 +935,7 @@ impl WeightInfo for () { // Measured: `3` // Estimated: `3549` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 3549) + Weight::from_parts(12_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -948,14 +964,14 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `32137 + a * (366 ±0)` // Estimated: `2523990 + a * (2954 ±0)` - // Minimum execution time: 893_000_000 picoseconds. - Weight::from_parts(814_084_483, 2523990) - // Standard Error: 18_466 - .saturating_add(Weight::from_parts(26_897, 0).saturating_mul(m.into())) - // Standard Error: 18_466 - .saturating_add(Weight::from_parts(87_809, 0).saturating_mul(c.into())) - // Standard Error: 18_466 - .saturating_add(Weight::from_parts(4_861_675, 0).saturating_mul(a.into())) + // Minimum execution time: 902_000_000 picoseconds. + Weight::from_parts(786_614_356, 2523990) + // Standard Error: 18_860 + .saturating_add(Weight::from_parts(85_114, 0).saturating_mul(m.into())) + // Standard Error: 18_860 + .saturating_add(Weight::from_parts(52_018, 0).saturating_mul(c.into())) + // Standard Error: 18_860 + .saturating_add(Weight::from_parts(4_806_613, 0).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(1005_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(a.into()))) .saturating_add(RocksDbWeight::get().writes(1005_u64)) @@ -980,7 +996,7 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `382` // Estimated: `4326` - // Minimum execution time: 37_000_000 picoseconds. + // Minimum execution time: 36_000_000 picoseconds. Weight::from_parts(38_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) @@ -1003,8 +1019,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `382` // Estimated: `4326` - // Minimum execution time: 36_000_000 picoseconds. - Weight::from_parts(39_000_000, 4326) + // Minimum execution time: 35_000_000 picoseconds. + Weight::from_parts(36_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -1032,8 +1048,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `634` // Estimated: `4326` - // Minimum execution time: 42_000_000 picoseconds. - Weight::from_parts(43_000_000, 4326) + // Minimum execution time: 39_000_000 picoseconds. + Weight::from_parts(41_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } @@ -1047,10 +1063,10 @@ impl WeightInfo for () { /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) /// Storage: `Nfts::Item` (r:1 w:1) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionApprovals` (r:1 w:0) + /// Proof: `Nfts::CollectionApprovals` (`max_values`: None, `max_size`: Some(137), added: 2612, mode: `MaxEncodedLen`) /// Storage: `Nfts::AccountBalance` (r:2 w:2) /// Proof: `Nfts::AccountBalance` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Nfts::Account` (r:0 w:2) /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(88), added: 2563, mode: `MaxEncodedLen`) /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) @@ -1059,12 +1075,12 @@ impl WeightInfo for () { /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) fn transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `765` + // Measured: `696` // Estimated: `6180` - // Minimum execution time: 47_000_000 picoseconds. - Weight::from_parts(50_000_000, 6180) + // Minimum execution time: 45_000_000 picoseconds. + Weight::from_parts(52_000_000, 6180) .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(8_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) } /// Storage: `Nfts::Collection` (r:1 w:0) /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`) @@ -1077,10 +1093,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `690 + i * (108 ±0)` // Estimated: `3549 + i * (3336 ±0)` - // Minimum execution time: 8_000_000 picoseconds. - Weight::from_parts(9_000_000, 3549) - // Standard Error: 41_268 - .saturating_add(Weight::from_parts(12_689_751, 0).saturating_mul(i.into())) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 3549) + // Standard Error: 24_440 + .saturating_add(Weight::from_parts(12_497_458, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(i.into()))) @@ -1138,7 +1154,7 @@ impl WeightInfo for () { // Measured: `417` // Estimated: `3593` // Minimum execution time: 15_000_000 picoseconds. - Weight::from_parts(15_000_000, 3593) + Weight::from_parts(16_000_000, 3593) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -1150,8 +1166,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `296` // Estimated: `6078` - // Minimum execution time: 24_000_000 picoseconds. - Weight::from_parts(25_000_000, 6078) + // Minimum execution time: 26_000_000 picoseconds. + Weight::from_parts(68_000_000, 6078) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -1164,7 +1180,7 @@ impl WeightInfo for () { // Measured: `238` // Estimated: `3549` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(9_000_000, 3549) + Weight::from_parts(10_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -1177,7 +1193,7 @@ impl WeightInfo for () { // Measured: `203` // Estimated: `3549` // Minimum execution time: 7_000_000 picoseconds. - Weight::from_parts(7_000_000, 3549) + Weight::from_parts(8_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1189,8 +1205,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `395` // Estimated: `3534` - // Minimum execution time: 10_000_000 picoseconds. - Weight::from_parts(11_000_000, 3534) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(13_000_000, 3534) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1208,8 +1224,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `499` // Estimated: `3944` - // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(28_000_000, 3944) + // Minimum execution time: 29_000_000 picoseconds. + Weight::from_parts(31_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1221,8 +1237,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `271` // Estimated: `3944` - // Minimum execution time: 13_000_000 picoseconds. - Weight::from_parts(14_000_000, 3944) + // Minimum execution time: 14_000_000 picoseconds. + Weight::from_parts(15_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1238,8 +1254,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `943` // Estimated: `3944` - // Minimum execution time: 26_000_000 picoseconds. - Weight::from_parts(27_000_000, 3944) + // Minimum execution time: 27_000_000 picoseconds. + Weight::from_parts(28_000_000, 3944) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1252,7 +1268,7 @@ impl WeightInfo for () { // Measured: `308` // Estimated: `4466` // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(9_000_000, 4466) + Weight::from_parts(12_000_000, 4466) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1270,9 +1286,9 @@ impl WeightInfo for () { // Measured: `686 + n * (398 ±0)` // Estimated: `4466 + n * (2954 ±0)` // Minimum execution time: 14_000_000 picoseconds. - Weight::from_parts(14_000_000, 4466) - // Standard Error: 11_599 - .saturating_add(Weight::from_parts(4_782_076, 0).saturating_mul(n.into())) + Weight::from_parts(17_000_000, 4466) + // Standard Error: 8_501 + .saturating_add(Weight::from_parts(4_744_468, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -1294,7 +1310,7 @@ impl WeightInfo for () { // Measured: `499` // Estimated: `3812` // Minimum execution time: 23_000_000 picoseconds. - Weight::from_parts(24_000_000, 3812) + Weight::from_parts(25_000_000, 3812) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1310,8 +1326,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `809` // Estimated: `3812` - // Minimum execution time: 22_000_000 picoseconds. - Weight::from_parts(23_000_000, 3812) + // Minimum execution time: 23_000_000 picoseconds. + Weight::from_parts(25_000_000, 3812) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1344,8 +1360,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `643` // Estimated: `3759` - // Minimum execution time: 22_000_000 picoseconds. - Weight::from_parts(23_000_000, 3759) + // Minimum execution time: 21_000_000 picoseconds. + Weight::from_parts(22_000_000, 3759) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1370,8 +1386,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `345` // Estimated: `4326` - // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 4326) + // Minimum execution time: 11_000_000 picoseconds. + Weight::from_parts(12_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1395,7 +1411,7 @@ impl WeightInfo for () { // Measured: `3` // Estimated: `3517` // Minimum execution time: 7_000_000 picoseconds. - Weight::from_parts(8_000_000, 3517) + Weight::from_parts(7_000_000, 3517) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1408,7 +1424,7 @@ impl WeightInfo for () { // Measured: `267` // Estimated: `3549` // Minimum execution time: 10_000_000 picoseconds. - Weight::from_parts(10_000_000, 3549) + Weight::from_parts(13_000_000, 3549) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1420,7 +1436,7 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `250` // Estimated: `3538` - // Minimum execution time: 10_000_000 picoseconds. + // Minimum execution time: 9_000_000 picoseconds. Weight::from_parts(11_000_000, 3538) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) @@ -1437,8 +1453,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `478` // Estimated: `4326` - // Minimum execution time: 12_000_000 picoseconds. - Weight::from_parts(13_000_000, 4326) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(15_000_000, 4326) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1466,8 +1482,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `877` // Estimated: `6180` - // Minimum execution time: 53_000_000 picoseconds. - Weight::from_parts(55_000_000, 6180) + // Minimum execution time: 49_000_000 picoseconds. + Weight::from_parts(54_000_000, 6180) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } @@ -1477,9 +1493,9 @@ impl WeightInfo for () { // Measured: `0` // Estimated: `0` // Minimum execution time: 1_000_000 picoseconds. - Weight::from_parts(1_497_803, 0) - // Standard Error: 5_639 - .saturating_add(Weight::from_parts(1_502_698, 0).saturating_mul(n.into())) + Weight::from_parts(1_206_012, 0) + // Standard Error: 11_245 + .saturating_add(Weight::from_parts(1_656_192, 0).saturating_mul(n.into())) } /// Storage: `Nfts::Item` (r:2 w:0) /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(861), added: 3336, mode: `MaxEncodedLen`) @@ -1490,7 +1506,7 @@ impl WeightInfo for () { // Measured: `421` // Estimated: `7662` // Minimum execution time: 11_000_000 picoseconds. - Weight::from_parts(11_000_000, 7662) + Weight::from_parts(12_000_000, 7662) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1531,8 +1547,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1118` // Estimated: `7662` - // Minimum execution time: 79_000_000 picoseconds. - Weight::from_parts(82_000_000, 7662) + // Minimum execution time: 75_000_000 picoseconds. + Weight::from_parts(84_000_000, 7662) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(13_u64)) } @@ -1561,10 +1577,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `485` // Estimated: `6078 + n * (2954 ±0)` - // Minimum execution time: 91_000_000 picoseconds. - Weight::from_parts(95_221_709, 6078) - // Standard Error: 128_983 - .saturating_add(Weight::from_parts(22_458_028, 0).saturating_mul(n.into())) + // Minimum execution time: 90_000_000 picoseconds. + Weight::from_parts(98_359_609, 6078) + // Standard Error: 115_405 + .saturating_add(Weight::from_parts(20_931_944, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(7_u64)) @@ -1589,9 +1605,9 @@ impl WeightInfo for () { // Measured: `514` // Estimated: `4466 + n * (2954 ±0)` // Minimum execution time: 47_000_000 picoseconds. - Weight::from_parts(54_326_784, 4466) - // Standard Error: 99_430 - .saturating_add(Weight::from_parts(20_625_932, 0).saturating_mul(n.into())) + Weight::from_parts(55_680_600, 4466) + // Standard Error: 107_152 + .saturating_add(Weight::from_parts(20_234_822, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -1609,7 +1625,7 @@ impl WeightInfo for () { // Measured: `500` // Estimated: `3602` // Minimum execution time: 20_000_000 picoseconds. - Weight::from_parts(24_000_000, 3602) + Weight::from_parts(25_000_000, 3602) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1623,8 +1639,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `500` // Estimated: `3602` - // Minimum execution time: 21_000_000 picoseconds. - Weight::from_parts(24_000_000, 3602) + // Minimum execution time: 13_000_000 picoseconds. + Weight::from_parts(15_000_000, 3602) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1635,7 +1651,7 @@ impl WeightInfo for () { // Measured: `359` // Estimated: `3602` // Minimum execution time: 16_000_000 picoseconds. - Weight::from_parts(17_000_000, 3602) + Weight::from_parts(18_000_000, 3602) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1657,10 +1673,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `327 + n * (75 ±0)` // Estimated: `3602 + n * (2612 ±0)` - // Minimum execution time: 20_000_000 picoseconds. - Weight::from_parts(22_000_000, 3602) - // Standard Error: 8_973 - .saturating_add(Weight::from_parts(3_888_488, 0).saturating_mul(n.into())) + // Minimum execution time: 18_000_000 picoseconds. + Weight::from_parts(18_000_000, 3602) + // Standard Error: 6_993 + .saturating_add(Weight::from_parts(3_855_667, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) @@ -1673,10 +1689,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `327 + n * (75 ±0)` // Estimated: `3602 + n * (2612 ±0)` - // Minimum execution time: 18_000_000 picoseconds. - Weight::from_parts(33_601_852, 3602) - // Standard Error: 7_525 - .saturating_add(Weight::from_parts(3_464_828, 0).saturating_mul(n.into())) + // Minimum execution time: 19_000_000 picoseconds. + Weight::from_parts(20_000_000, 3602) + // Standard Error: 6_538 + .saturating_add(Weight::from_parts(3_823_979, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) diff --git a/pop-api/integration-tests/src/nonfungibles/mod.rs b/pop-api/integration-tests/src/nonfungibles/mod.rs index 6281285e8..9bf542b12 100644 --- a/pop-api/integration-tests/src/nonfungibles/mod.rs +++ b/pop-api/integration-tests/src/nonfungibles/mod.rs @@ -65,7 +65,7 @@ fn allowance_works() { // No collection item is created. assert_eq!( allowance(&addr.clone(), COLLECTION, None, addr.clone(), ALICE), - Ok(!Nfts::check_approval(&COLLECTION, &None, &addr, &ALICE).is_err()), + Ok(!Nfts::check_approval_permission(&COLLECTION, &None, &addr, &ALICE).is_err()), ); assert_eq!(allowance(&addr.clone(), COLLECTION, None, addr.clone(), ALICE), Ok(false)); @@ -73,7 +73,8 @@ fn allowance_works() { let (_, item) = nfts::create_collection_mint_and_approve(&addr, &addr, ITEM, &addr, &ALICE); assert_eq!( allowance(&addr.clone(), COLLECTION, Some(item), addr.clone(), ALICE), - Ok(Nfts::check_approval(&COLLECTION, &Some(item), &addr.clone(), &ALICE).is_ok()), + Ok(Nfts::check_approval_permission(&COLLECTION, &Some(item), &addr.clone(), &ALICE) + .is_ok()), ); assert_eq!(allowance(&addr.clone(), COLLECTION, Some(item), addr.clone(), ALICE), Ok(true)); }); @@ -130,7 +131,8 @@ fn approve_item_transfer_works() { // Successful approvals. let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); assert_ok!(approve(&addr, collection, Some(item), ALICE, true)); - assert!(Nfts::check_approval(&collection, &Some(item), &addr.clone(), &ALICE).is_ok()); + assert!(Nfts::check_approval_permission(&collection, &Some(item), &addr.clone(), &ALICE) + .is_ok()); // Successfully emit event. let owner = account_id_from_slice(addr.as_ref()); let operator = account_id_from_slice(ALICE.as_ref()); @@ -138,7 +140,8 @@ fn approve_item_transfer_works() { assert_eq!(last_contract_event(), expected.as_slice()); // New value overrides old value. assert_ok!(approve(&addr, collection, Some(item), ALICE, false)); - assert!(Nfts::check_approval(&collection, &Some(item), &addr.clone(), &ALICE).is_err()); + assert!(Nfts::check_approval_permission(&collection, &Some(item), &addr.clone(), &ALICE) + .is_err()); }); } @@ -155,7 +158,7 @@ fn approve_collection_transfer_works() { // Successful approvals. let (collection, item) = nfts::create_collection_and_mint_to(&addr, &addr, &addr, ITEM); assert_ok!(approve(&addr, collection, None, ALICE, true)); - assert!(Nfts::check_approval(&collection, &None, &addr.clone(), &ALICE).is_ok()); + assert!(Nfts::check_approval_permission(&collection, &None, &addr.clone(), &ALICE).is_ok()); // Successfully emit event. let owner = account_id_from_slice(addr.as_ref()); let operator = account_id_from_slice(ALICE.as_ref()); @@ -163,7 +166,7 @@ fn approve_collection_transfer_works() { assert_eq!(last_contract_event(), expected.as_slice()); // New value overrides old value. assert_ok!(approve(&addr, collection, None, ALICE, false)); - assert!(Nfts::check_approval(&collection, &None, &addr.clone(), &ALICE).is_err()); + assert!(Nfts::check_approval_permission(&collection, &None, &addr.clone(), &ALICE).is_err()); }); } From 2134e08e3eb6c54b2f50448376b6191cefd22549 Mon Sep 17 00:00:00 2001 From: chungquantin <56880684+chungquantin@users.noreply.github.com> Date: Thu, 16 Jan 2025 12:42:56 +0700 Subject: [PATCH 76/76] chore: reformat --- pop-api/Cargo.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index a2b56f31b..d21a30f7a 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -17,12 +17,12 @@ sp-io = { version = "37.0.0", default-features = false, features = [ ] } [lib] -crate-type = ["rlib"] +crate-type = [ "rlib" ] name = "pop_api" path = "src/lib.rs" [features] -default = ["std"] -fungibles = [] -nonfungibles = [] -std = ["ink/std", "pop-primitives/std", "sp-io/std"] +default = [ "std" ] +fungibles = [ ] +nonfungibles = [ ] +std = [ "ink/std", "pop-primitives/std", "sp-io/std" ]