mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-21 02:45:43 +00:00
NFTs fractionalization (#12565)
* Copy Uniques into Nfts * Connect new pallet * Update weights * Nfts: Multiple approvals (#12178) * multiple approvals * clear * tests & clean up * fix in logic & fmt * fix benchmarks * deadline * test deadline * current_block + deadline * update ApprovedTransfer event * benchmark * docs * Update frame/nfts/src/lib.rs Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com> * fmt fix * Update frame/nfts/src/lib.rs Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com> * update tests * anyone can cancel * Update frame/nfts/src/tests.rs Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com> * fmt * fix logic * unnecessary line * ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts * Update frame/nfts/src/lib.rs * Update lib.rs * fmt * Update frame/nfts/src/lib.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Update frame/nfts/src/lib.rs Co-authored-by: Squirrel <gilescope@gmail.com> * fmt * Update frame/nfts/src/lib.rs Co-authored-by: Squirrel <gilescope@gmail.com> * suggestion * new line * ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com> Co-authored-by: command-bot <> Co-authored-by: Squirrel <gilescope@gmail.com> * Fixes * cargo fmt * Fixes * Fixes * Fix CI * Nfts: Fix Auto-Increment (#12223) * commit * passing benchmarks * clean up * sync * runtime implementation * fix * fmt * fix benchmark * cfg * remove try-increment-id * remove unused error * impl Incrementable for unsigned types * clean up * fix in tests * not needed anymore * Use OptionQuery Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Rename Origin to RuntimeOrigin * [Uniques V2] Tips (#12168) * Allow to add tips when buying an NFT * Chore * Rework tips feature * Add weights + benchmarks * Convert tuple to struct * Fix benchmark * ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts * Update frame/nfts/src/benchmarking.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix benchmarks * Revert the bounded_vec![] approach * ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts Co-authored-by: command-bot <> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * [Uniques V2] Atomic NFTs swap (#12285) * Atomic NFTs swap * Fmt * Fix benchmark * Rename swap -> atomic_swap * Update target balance * Rollback * Fix * ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts * Make desired item optional * Apply suggestions * Update frame/nfts/src/features/atomic_swap.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Rename fields * Optimisation * Add a comment * deadline -> maybe_deadline * Add docs * Change comments * Add price direction field * ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts * Wrap price and direction * Fix benchmarks * Use ensure! instead of if {} * Make duration param mandatory and limit it to MaxDeadlineDuration * Make the code safer * Fix clippy * Chore * Remove unused vars * try * try 2 * try 3 Co-authored-by: command-bot <> Co-authored-by: Squirrel <gilescope@gmail.com> * [Uniques V2] Feature flags (#12367) * Basics * WIP: change the data format * Refactor * Remove redundant new() method * Rename settings * Enable tests * Chore * Change params order * Delete the config on collection removal * Chore * Remove redundant system features * Rename force_item_status to force_collection_status * Update node runtime * Chore * Remove thaw_collection * Chore * Connect collection.is_frozen to config * Allow to lock the collection in a new way * Move free_holding into settings * Connect collection's metadata locker to feature flags * DRY * Chore * Connect pallet level feature flags * Prepare tests for the new changes * Implement Item settings * Allow to lock the metadata or attributes of an item * Common -> Settings * Extract settings related code to a separate file * Move feature flag checks inside the do_* methods * Split settings.rs into parts * Extract repeated code into macro * Extract macros into their own file * Chore * Fix traits * Fix traits * Test SystemFeatures * Fix benchmarks * Add missing benchmark * Fix node/runtime/lib.rs * ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts * Keep item's config on burn if it's not empty * Fix the merge artifacts * Fmt * Add SystemFeature::NoSwaps check * Rename SystemFeatures to PalletFeatures * Rename errors * Add docs * Change error message * Rework pallet features * Move macros * Change comments * Fmt * Refactor Incrementable * Use pub(crate) for do_* functions * Update comments * Refactor freeze and lock functions * Rework Collection config and Item confg api * Chore * Make clippy happy * Chore * Update comment * RequiredDeposit => DepositRequired * Address comments Co-authored-by: command-bot <> * [Uniques V2] Refactor roles (#12437) * Basics * WIP: change the data format * Refactor * Remove redundant new() method * Rename settings * Enable tests * Chore * Change params order * Delete the config on collection removal * Chore * Remove redundant system features * Rename force_item_status to force_collection_status * Update node runtime * Chore * Remove thaw_collection * Chore * Connect collection.is_frozen to config * Allow to lock the collection in a new way * Move free_holding into settings * Connect collection's metadata locker to feature flags * DRY * Chore * Connect pallet level feature flags * Prepare tests for the new changes * Implement Item settings * Allow to lock the metadata or attributes of an item * Common -> Settings * Extract settings related code to a separate file * Move feature flag checks inside the do_* methods * Split settings.rs into parts * Extract repeated code into macro * Extract macros into their own file * Chore * Fix traits * Fix traits * Test SystemFeatures * Fix benchmarks * Add missing benchmark * Fix node/runtime/lib.rs * ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts * Keep item's config on burn if it's not empty * Fix the merge artifacts * Fmt * Add SystemFeature::NoSwaps check * Refactor roles structure * Rename SystemFeatures to PalletFeatures * Rename errors * Add docs * Change error message * Rework pallet features * Move macros * Change comments * Fmt * Refactor Incrementable * Use pub(crate) for do_* functions * Update comments * Refactor freeze and lock functions * Rework Collection config and Item confg api * Chore * Make clippy happy * Chore * Fix artifacts * Address comments * Further refactoring * Add comments * Add tests for group_roles_by_account() * Update frame/nfts/src/impl_nonfungibles.rs * Add test * Replace Itertools group_by with a custom implementation * ItemsNotTransferable => ItemsNonTransferable * Update frame/nfts/src/features/roles.rs Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com> * Address PR comments * Add missed comment Co-authored-by: command-bot <> Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com> * Fix copy * Remove storage_prefix * Remove transactional * Initial commit SFT pallet. * Update comment * [Uniques V2] Minting options (#12483) * Basics * WIP: change the data format * Refactor * Remove redundant new() method * Rename settings * Enable tests * Chore * Change params order * Delete the config on collection removal * Chore * Remove redundant system features * Rename force_item_status to force_collection_status * Update node runtime * Chore * Remove thaw_collection * Chore * Connect collection.is_frozen to config * Allow to lock the collection in a new way * Move free_holding into settings * Connect collection's metadata locker to feature flags * DRY * Chore * Connect pallet level feature flags * Prepare tests for the new changes * Implement Item settings * Allow to lock the metadata or attributes of an item * Common -> Settings * Extract settings related code to a separate file * Move feature flag checks inside the do_* methods * Split settings.rs into parts * Extract repeated code into macro * Extract macros into their own file * Chore * Fix traits * Fix traits * Test SystemFeatures * Fix benchmarks * Add missing benchmark * Fix node/runtime/lib.rs * ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts * Keep item's config on burn if it's not empty * Fix the merge artifacts * Fmt * Add SystemFeature::NoSwaps check * Rename SystemFeatures to PalletFeatures * Rename errors * Add docs * Change error message * Change the format of CollectionConfig to store more data * Move max supply to the CollectionConfig and allow to change it * Remove ItemConfig from the mint() function and use the one set in mint settings * Add different mint options * Allow to change the mint settings * Add a force_mint() method * Check mint params * Some optimisations * Cover with tests * Remove merge artifacts * Chore * Use the new has_role() method * Rework item deposits * More tests * Refactoring * Address comments * Refactor lock_collection() * Update frame/nfts/src/types.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Update frame/nfts/src/types.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Update frame/nfts/src/lib.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Update frame/nfts/src/lib.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Private => Issuer * Add more tests * Fix benchmarks * Add benchmarks for new methods * [Uniques v2] Refactoring (#12570) * Move do_set_price() and do_buy_item() to buy_sell.rs * Move approvals to feature file * Move metadata to feature files * Move the rest of methods to feature files * Remove artifacts * Split force_collection_status into 2 methods * Fix benchmarks * Fix benchmarks * Update deps Co-authored-by: command-bot <> Co-authored-by: Squirrel <gilescope@gmail.com> * Rename module to NFT fractionalisation * Loose coupling for pallet-assets * cargo fmt * [Uniques V2] Smart attributes (#12702) * Basics * WIP: change the data format * Refactor * Remove redundant new() method * Rename settings * Enable tests * Chore * Change params order * Delete the config on collection removal * Chore * Remove redundant system features * Rename force_item_status to force_collection_status * Update node runtime * Chore * Remove thaw_collection * Chore * Connect collection.is_frozen to config * Allow to lock the collection in a new way * Move free_holding into settings * Connect collection's metadata locker to feature flags * DRY * Chore * Connect pallet level feature flags * Prepare tests for the new changes * Implement Item settings * Allow to lock the metadata or attributes of an item * Common -> Settings * Extract settings related code to a separate file * Move feature flag checks inside the do_* methods * Split settings.rs into parts * Extract repeated code into macro * Extract macros into their own file * Chore * Fix traits * Fix traits * Test SystemFeatures * Fix benchmarks * Add missing benchmark * Fix node/runtime/lib.rs * ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts * Keep item's config on burn if it's not empty * Fix the merge artifacts * Fmt * Add SystemFeature::NoSwaps check * Rename SystemFeatures to PalletFeatures * Rename errors * Add docs * Change error message * Change the format of CollectionConfig to store more data * Move max supply to the CollectionConfig and allow to change it * Remove ItemConfig from the mint() function and use the one set in mint settings * Add different mint options * Allow to change the mint settings * Add a force_mint() method * Check mint params * Some optimisations * Cover with tests * Remove merge artifacts * Chore * Use the new has_role() method * Rework item deposits * More tests * Refactoring * Address comments * Refactor lock_collection() * Update frame/nfts/src/types.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Update frame/nfts/src/types.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Update frame/nfts/src/lib.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Update frame/nfts/src/lib.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Private => Issuer * Add more tests * Fix benchmarks * Add benchmarks for new methods * [Uniques v2] Refactoring (#12570) * Move do_set_price() and do_buy_item() to buy_sell.rs * Move approvals to feature file * Move metadata to feature files * Move the rest of methods to feature files * Remove artifacts * Smart attributes * Split force_collection_status into 2 methods * Fix benchmarks * Fix benchmarks * Update deps * Fix merge artifact * Weights + benchmarks + docs * Change params order * Chore * Update frame/nfts/src/lib.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Update frame/nfts/src/lib.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Update docs * Update frame/nfts/src/lib.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Add PalletId * Chore * Add tests * More tests * Add doc * Update errors snapshots * Ensure we track the owner_deposit field correctly Co-authored-by: command-bot <> Co-authored-by: Squirrel <gilescope@gmail.com> * [Uniques V2] Final improvements (#12736) * Use KeyPrefixIterator instead of Box * Change create_collection() * Restrict from claiming NFTs twice * Update Readme * Remove dead code * Refactoring * Update readme * Fix clippy * Update frame/nfts/src/lib.rs Co-authored-by: Squirrel <gilescope@gmail.com> * ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts * Update docs * Typo * Fix benchmarks * Add more docs * Replace uniques with nfts, add minted volume storage * DepositRequired setting should affect only the attributes within the CollectionOwner namespace * Add unlock functionality * [NFTs] Implement missed methods to set the attributes from other pallets (#12919) * Implement missed methods to set the attributes from other pallets * Revert snapshots * Update snapshot * Update snapshot * Revert snapshot changes * Update snapshots * Yet another snapshot update.. * Asset to NFT id storage mutations * Minor fixes * Minor comments * cargo fmt * Remove benchmarking, unused clone() * Update frame/support/src/traits/tokens/nonfungible_v2.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/support/src/traits/tokens/nonfungible_v2.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/support/src/traits/tokens/nonfungible_v2.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/support/src/traits/tokens/nonfungibles_v2.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nfts/src/lib.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nfts/src/lib.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nfts/src/lib.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nfts/src/lib.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nfts/src/lib.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/support/src/traits/tokens/nonfungible_v2.rs * Update frame/nfts/src/lib.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/support/src/traits/tokens/nonfungibles_v2.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nfts/src/lib.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nfts/src/lib.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nfts/src/lib.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nfts/src/lib.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Address comments * [NFTs] Add the new `owner` param to mint() method (#12997) * Add the new `owner` param to mint() method * Fmt * Address comments * ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts * Fmt * Update frame/nfts/src/common_functions.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nfts/src/types.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nfts/src/types.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nfts/src/types.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nfts/src/types.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nfts/src/types.rs Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Add call indexes * Update snapshots * Refactor nft fractionalisation pallet (#13008) * Refactoring * Make it compile * Add tests * Rename * Rework nfts locking * Update cargo.lock * Connect the latest changes to the runtime-kitchensink * Add benchmarks, fix other issues * Chore * Chore 2 * Chore 3 * Add runtime-benchmarks * Rename * Set metadata * Make fields public * Chore * Created asset shouldn't be sufficient * Add documentation * minor edit to docs * Minor corrections Co-authored-by: lana-shanghai <svetlana.konstantinovna@gmail.com> * fmt * Add fee reserved before creating an asset * Use ReservableCurrency for fee deposit * Improvements * Revert fmt changes * A bit more cleanup * Consistent naming * Make it more generic * Leftover * Use Vec<u8> instead of String * Update to the latest + improve the Locker trait * Refactor NFTs locker * Replace Vec with BoundedVec, add clearer errors * cargo fmt * Add README about unlocking NFTs * add constant definition * add fortitude & precision to asset related functions * fix mock and tests * transfer ExistentialDeposit to pallet if it's balance is below * Refactoring * Simplify the locking mechanism * Use PalletAttributes enum instead of the LOCKED_NFT_KEY * Fix benchmark * Add missing licence details * Update Cargo.toml * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_nft_fractionalization * Apply suggestions from code review Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> * Update frame/nft-fractionalization/README.md Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> --------- Co-authored-by: Jegor Sidorenko <jegor@parity.io> Co-authored-by: Sergej Sakac <73715684+Szegoo@users.noreply.github.com> Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com> Co-authored-by: Squirrel <gilescope@gmail.com> Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com> Co-authored-by: command-bot <> Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,389 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2022 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.
|
||||
|
||||
//! # NFT Fractionalization Pallet
|
||||
//!
|
||||
//! This pallet provides the basic functionality that should allow users
|
||||
//! to leverage partial ownership, transfers, and sales, of illiquid assets,
|
||||
//! whether real-world assets represented by their digital twins, or NFTs,
|
||||
//! or original NFTs.
|
||||
//!
|
||||
//! The functionality allows a user to lock an NFT they own, create a new
|
||||
//! fungible asset, and mint a set amount of tokens (`fractions`).
|
||||
//!
|
||||
//! It also allows the user to burn 100% of the asset and to unlock the NFT
|
||||
//! into their account.
|
||||
//!
|
||||
//! ### Functions
|
||||
//!
|
||||
//! * `fractionalize`: Lock the NFT and create and mint a new fungible asset.
|
||||
//! * `unify`: Return 100% of the asset and unlock the NFT.
|
||||
|
||||
// Ensure we're `no_std` when compiling for Wasm.
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
mod types;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benchmarking;
|
||||
#[cfg(test)]
|
||||
pub mod mock;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub mod weights;
|
||||
|
||||
use frame_system::Config as SystemConfig;
|
||||
pub use pallet::*;
|
||||
pub use scale_info::Type;
|
||||
pub use types::*;
|
||||
pub use weights::WeightInfo;
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
use frame_support::{
|
||||
dispatch::DispatchResult,
|
||||
ensure,
|
||||
pallet_prelude::*,
|
||||
sp_runtime::traits::{AccountIdConversion, StaticLookup},
|
||||
traits::{
|
||||
fungible::{
|
||||
hold::{Inspect as HoldInspectFungible, Mutate as HoldMutateFungible},
|
||||
Inspect as InspectFungible, Mutate as MutateFungible,
|
||||
},
|
||||
fungibles::{
|
||||
metadata::{MetadataDeposit, Mutate as MutateMetadata},
|
||||
Create, Destroy, Inspect, Mutate,
|
||||
},
|
||||
tokens::{
|
||||
nonfungibles_v2::{Inspect as NonFungiblesInspect, Transfer},
|
||||
AssetId, Balance as AssetBalance,
|
||||
Fortitude::Polite,
|
||||
Precision::{BestEffort, Exact},
|
||||
Preservation::Preserve,
|
||||
},
|
||||
},
|
||||
BoundedVec, PalletId,
|
||||
};
|
||||
use frame_system::pallet_prelude::*;
|
||||
use scale_info::prelude::{format, string::String};
|
||||
use sp_runtime::traits::{One, Zero};
|
||||
use sp_std::{fmt::Display, prelude::*};
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T>(PhantomData<T>);
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config {
|
||||
/// The overarching event type.
|
||||
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
||||
|
||||
/// The currency mechanism, used for paying for deposits.
|
||||
type Currency: InspectFungible<Self::AccountId>
|
||||
+ MutateFungible<Self::AccountId>
|
||||
+ HoldInspectFungible<Self::AccountId>
|
||||
+ HoldMutateFungible<Self::AccountId>;
|
||||
|
||||
#[pallet::constant]
|
||||
type HoldReason: Get<<Self::Currency as HoldInspectFungible<Self::AccountId>>::Reason>;
|
||||
|
||||
/// The deposit paid by the user locking an NFT. The deposit is returned to the original NFT
|
||||
/// owner when the asset is unified and the NFT is unlocked.
|
||||
#[pallet::constant]
|
||||
type Deposit: Get<DepositOf<Self>>;
|
||||
|
||||
/// Identifier for the collection of NFT.
|
||||
type NftCollectionId: Member + Parameter + MaxEncodedLen + Copy + Display;
|
||||
|
||||
/// The type used to identify an NFT within a collection.
|
||||
type NftId: Member + Parameter + MaxEncodedLen + Copy + Display;
|
||||
|
||||
/// The type used to describe the amount of fractions converted into assets.
|
||||
type AssetBalance: AssetBalance;
|
||||
|
||||
/// The type used to identify the assets created during fractionalization.
|
||||
type AssetId: AssetId;
|
||||
|
||||
/// Registry for the minted assets.
|
||||
type Assets: Inspect<Self::AccountId, AssetId = Self::AssetId, Balance = Self::AssetBalance>
|
||||
+ Create<Self::AccountId>
|
||||
+ Destroy<Self::AccountId>
|
||||
+ Mutate<Self::AccountId>
|
||||
+ MutateMetadata<Self::AccountId>
|
||||
+ MetadataDeposit<DepositOf<Self>>;
|
||||
|
||||
/// Registry for minted NFTs.
|
||||
type Nfts: NonFungiblesInspect<
|
||||
Self::AccountId,
|
||||
ItemId = Self::NftId,
|
||||
CollectionId = Self::NftCollectionId,
|
||||
> + Transfer<Self::AccountId>;
|
||||
|
||||
/// The pallet's id, used for deriving its sovereign account ID.
|
||||
#[pallet::constant]
|
||||
type PalletId: Get<PalletId>;
|
||||
|
||||
/// The newly created asset's symbol.
|
||||
#[pallet::constant]
|
||||
type NewAssetSymbol: Get<BoundedVec<u8, Self::StringLimit>>;
|
||||
|
||||
/// The newly created asset's name.
|
||||
#[pallet::constant]
|
||||
type NewAssetName: Get<BoundedVec<u8, Self::StringLimit>>;
|
||||
|
||||
/// The maximum length of a name or symbol stored on-chain.
|
||||
#[pallet::constant]
|
||||
type StringLimit: Get<u32>;
|
||||
|
||||
/// A set of helper functions for benchmarking.
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type BenchmarkHelper: BenchmarkHelper<Self::AssetId, Self::NftCollectionId, Self::NftId>;
|
||||
|
||||
/// Weight information for extrinsics in this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
|
||||
/// Keeps track of the corresponding NFT ID, asset ID and amount minted.
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn nft_to_asset)]
|
||||
pub type NftToAsset<T: Config> = StorageMap<
|
||||
_,
|
||||
Blake2_128Concat,
|
||||
(T::NftCollectionId, T::NftId),
|
||||
Details<AssetIdOf<T>, AssetBalanceOf<T>, DepositOf<T>, T::AccountId>,
|
||||
OptionQuery,
|
||||
>;
|
||||
|
||||
#[pallet::event]
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event<T: Config> {
|
||||
/// An NFT was successfully fractionalized.
|
||||
NftFractionalized {
|
||||
nft_collection: T::NftCollectionId,
|
||||
nft: T::NftId,
|
||||
fractions: AssetBalanceOf<T>,
|
||||
asset: AssetIdOf<T>,
|
||||
beneficiary: T::AccountId,
|
||||
},
|
||||
/// An NFT was successfully returned back.
|
||||
NftUnified {
|
||||
nft_collection: T::NftCollectionId,
|
||||
nft: T::NftId,
|
||||
asset: AssetIdOf<T>,
|
||||
beneficiary: T::AccountId,
|
||||
},
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
/// Asset ID does not correspond to locked NFT.
|
||||
IncorrectAssetId,
|
||||
/// The signing account has no permission to do the operation.
|
||||
NoPermission,
|
||||
/// NFT doesn't exist.
|
||||
NftNotFound,
|
||||
/// NFT has not yet been fractionalised.
|
||||
NftNotFractionalized,
|
||||
}
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Lock the NFT and mint a new fungible asset.
|
||||
///
|
||||
/// The dispatch origin for this call must be Signed.
|
||||
/// The origin must be the owner of the NFT they are trying to lock.
|
||||
///
|
||||
/// `Deposit` funds of sender are reserved.
|
||||
///
|
||||
/// - `nft_collection_id`: The ID used to identify the collection of the NFT.
|
||||
/// Is used within the context of `pallet_nfts`.
|
||||
/// - `nft_id`: The ID used to identify the NFT within the given collection.
|
||||
/// Is used within the context of `pallet_nfts`.
|
||||
/// - `asset_id`: The ID of the new asset. It must not exist.
|
||||
/// Is used within the context of `pallet_assets`.
|
||||
/// - `beneficiary`: The account that will receive the newly created asset.
|
||||
/// - `fractions`: The total issuance of the newly created asset class.
|
||||
///
|
||||
/// Emits `NftFractionalized` event when successful.
|
||||
#[pallet::call_index(0)]
|
||||
#[pallet::weight(T::WeightInfo::fractionalize())]
|
||||
pub fn fractionalize(
|
||||
origin: OriginFor<T>,
|
||||
nft_collection_id: T::NftCollectionId,
|
||||
nft_id: T::NftId,
|
||||
asset_id: AssetIdOf<T>,
|
||||
beneficiary: AccountIdLookupOf<T>,
|
||||
fractions: AssetBalanceOf<T>,
|
||||
) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
let beneficiary = T::Lookup::lookup(beneficiary)?;
|
||||
|
||||
let nft_owner =
|
||||
T::Nfts::owner(&nft_collection_id, &nft_id).ok_or(Error::<T>::NftNotFound)?;
|
||||
ensure!(nft_owner == who, Error::<T>::NoPermission);
|
||||
|
||||
let pallet_account = Self::get_pallet_account();
|
||||
let deposit = T::Deposit::get();
|
||||
T::Currency::hold(&T::HoldReason::get(), &nft_owner, deposit)?;
|
||||
Self::do_lock_nft(nft_collection_id, nft_id)?;
|
||||
Self::do_create_asset(asset_id, pallet_account.clone())?;
|
||||
Self::do_mint_asset(asset_id, &beneficiary, fractions)?;
|
||||
Self::do_set_metadata(asset_id, &who, &pallet_account, &nft_collection_id, &nft_id)?;
|
||||
|
||||
NftToAsset::<T>::insert(
|
||||
(nft_collection_id, nft_id),
|
||||
Details { asset: asset_id, fractions, asset_creator: nft_owner, deposit },
|
||||
);
|
||||
|
||||
Self::deposit_event(Event::NftFractionalized {
|
||||
nft_collection: nft_collection_id,
|
||||
nft: nft_id,
|
||||
fractions,
|
||||
asset: asset_id,
|
||||
beneficiary,
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Burn the total issuance of the fungible asset and return (unlock) the locked NFT.
|
||||
///
|
||||
/// The dispatch origin for this call must be Signed.
|
||||
///
|
||||
/// `Deposit` funds will be returned to `asset_creator`.
|
||||
///
|
||||
/// - `nft_collection_id`: The ID used to identify the collection of the NFT.
|
||||
/// Is used within the context of `pallet_nfts`.
|
||||
/// - `nft_id`: The ID used to identify the NFT within the given collection.
|
||||
/// Is used within the context of `pallet_nfts`.
|
||||
/// - `asset_id`: The ID of the asset being returned and destroyed. Must match
|
||||
/// the original ID of the created asset, corresponding to the NFT.
|
||||
/// Is used within the context of `pallet_assets`.
|
||||
/// - `beneficiary`: The account that will receive the unified NFT.
|
||||
///
|
||||
/// Emits `NftUnified` event when successful.
|
||||
#[pallet::call_index(1)]
|
||||
#[pallet::weight(T::WeightInfo::unify())]
|
||||
pub fn unify(
|
||||
origin: OriginFor<T>,
|
||||
nft_collection_id: T::NftCollectionId,
|
||||
nft_id: T::NftId,
|
||||
asset_id: AssetIdOf<T>,
|
||||
beneficiary: AccountIdLookupOf<T>,
|
||||
) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
let beneficiary = T::Lookup::lookup(beneficiary)?;
|
||||
|
||||
NftToAsset::<T>::try_mutate_exists((nft_collection_id, nft_id), |maybe_details| {
|
||||
let details = maybe_details.take().ok_or(Error::<T>::NftNotFractionalized)?;
|
||||
ensure!(details.asset == asset_id, Error::<T>::IncorrectAssetId);
|
||||
|
||||
let deposit = details.deposit;
|
||||
let asset_creator = details.asset_creator;
|
||||
Self::do_burn_asset(asset_id, &who, details.fractions)?;
|
||||
Self::do_unlock_nft(nft_collection_id, nft_id, &beneficiary)?;
|
||||
T::Currency::release(&T::HoldReason::get(), &asset_creator, deposit, BestEffort)?;
|
||||
|
||||
Self::deposit_event(Event::NftUnified {
|
||||
nft_collection: nft_collection_id,
|
||||
nft: nft_id,
|
||||
asset: asset_id,
|
||||
beneficiary,
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// The account ID of the pallet.
|
||||
///
|
||||
/// This actually does computation. If you need to keep using it, then make sure you cache
|
||||
/// the value and only call this once.
|
||||
fn get_pallet_account() -> T::AccountId {
|
||||
T::PalletId::get().into_account_truncating()
|
||||
}
|
||||
|
||||
/// Transfer the NFT from the account holding that NFT to the pallet's account.
|
||||
fn do_lock_nft(nft_collection_id: T::NftCollectionId, nft_id: T::NftId) -> DispatchResult {
|
||||
T::Nfts::disable_transfer(&nft_collection_id, &nft_id)
|
||||
}
|
||||
|
||||
/// Transfer the NFT to the account returning the tokens.
|
||||
fn do_unlock_nft(
|
||||
nft_collection_id: T::NftCollectionId,
|
||||
nft_id: T::NftId,
|
||||
account: &T::AccountId,
|
||||
) -> DispatchResult {
|
||||
T::Nfts::enable_transfer(&nft_collection_id, &nft_id)?;
|
||||
T::Nfts::transfer(&nft_collection_id, &nft_id, account)
|
||||
}
|
||||
|
||||
/// Create the new asset.
|
||||
fn do_create_asset(asset_id: AssetIdOf<T>, admin: T::AccountId) -> DispatchResult {
|
||||
T::Assets::create(asset_id, admin, false, One::one())
|
||||
}
|
||||
|
||||
/// Mint the `amount` of tokens with `asset_id` into the beneficiary's account.
|
||||
fn do_mint_asset(
|
||||
asset_id: AssetIdOf<T>,
|
||||
beneficiary: &T::AccountId,
|
||||
amount: AssetBalanceOf<T>,
|
||||
) -> DispatchResult {
|
||||
T::Assets::mint_into(asset_id, beneficiary, amount)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Burn tokens from the account.
|
||||
fn do_burn_asset(
|
||||
asset_id: AssetIdOf<T>,
|
||||
account: &T::AccountId,
|
||||
amount: AssetBalanceOf<T>,
|
||||
) -> DispatchResult {
|
||||
T::Assets::burn_from(asset_id, account, amount, Exact, Polite)?;
|
||||
T::Assets::start_destroy(asset_id, None)
|
||||
}
|
||||
|
||||
/// Set the metadata for the newly created asset.
|
||||
fn do_set_metadata(
|
||||
asset_id: AssetIdOf<T>,
|
||||
depositor: &T::AccountId,
|
||||
pallet_account: &T::AccountId,
|
||||
nft_collection_id: &T::NftCollectionId,
|
||||
nft_id: &T::NftId,
|
||||
) -> DispatchResult {
|
||||
let name = format!(
|
||||
"{} {nft_collection_id}-{nft_id}",
|
||||
String::from_utf8_lossy(&T::NewAssetName::get())
|
||||
);
|
||||
let symbol: &[u8] = &T::NewAssetSymbol::get();
|
||||
let existential_deposit = T::Currency::minimum_balance();
|
||||
let pallet_account_balance = T::Currency::balance(&pallet_account);
|
||||
|
||||
if pallet_account_balance < existential_deposit {
|
||||
T::Currency::transfer(&depositor, &pallet_account, existential_deposit, Preserve)?;
|
||||
}
|
||||
let metadata_deposit = T::Assets::calc_metadata_deposit(name.as_bytes(), symbol);
|
||||
if !metadata_deposit.is_zero() {
|
||||
T::Currency::transfer(&depositor, &pallet_account, metadata_deposit, Preserve)?;
|
||||
}
|
||||
T::Assets::set(asset_id, &pallet_account, name.into(), symbol.into(), 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user