Skip to content

Commit

Permalink
NFTs fractionalization (paritytech#12565)
Browse files Browse the repository at this point in the history
* Copy Uniques into Nfts

* Connect new pallet

* Update weights

* Nfts: Multiple approvals (paritytech#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 <[email protected]>

* fmt fix

* Update frame/nfts/src/lib.rs

Co-authored-by: Jegor Sidorenko <[email protected]>

* update tests

* anyone can cancel

* Update frame/nfts/src/tests.rs

Co-authored-by: Jegor Sidorenko <[email protected]>

* 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 <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <[email protected]>

* fmt

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <[email protected]>

* suggestion

* new line

* ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts

Co-authored-by: Jegor Sidorenko <[email protected]>
Co-authored-by: command-bot <>
Co-authored-by: Squirrel <[email protected]>

* Fixes

* cargo fmt

* Fixes

* Fixes

* Fix CI

* Nfts: Fix Auto-Increment (paritytech#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 <[email protected]>

* Rename Origin to RuntimeOrigin

* [Uniques V2] Tips (paritytech#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 <[email protected]>

* 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 <[email protected]>

* [Uniques V2] Atomic NFTs swap (paritytech#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 <[email protected]>

* 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 <[email protected]>

* [Uniques V2] Feature flags (paritytech#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 (paritytech#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 <[email protected]>

* Address PR comments

* Add missed comment

Co-authored-by: command-bot <>
Co-authored-by: Muharem Ismailov <[email protected]>

* Fix copy

* Remove storage_prefix

* Remove transactional

* Initial commit SFT pallet.

* Update comment

* [Uniques V2] Minting options (paritytech#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 <[email protected]>

* Update frame/nfts/src/types.rs

Co-authored-by: Squirrel <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <[email protected]>

* Private => Issuer

* Add more tests

* Fix benchmarks

* Add benchmarks for new methods

* [Uniques v2] Refactoring (paritytech#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 <[email protected]>

* Rename module to NFT fractionalisation

* Loose coupling for pallet-assets

* cargo fmt

* [Uniques V2] Smart attributes (paritytech#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 <[email protected]>

* Update frame/nfts/src/types.rs

Co-authored-by: Squirrel <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <[email protected]>

* Private => Issuer

* Add more tests

* Fix benchmarks

* Add benchmarks for new methods

* [Uniques v2] Refactoring (paritytech#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 <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <[email protected]>

* Update docs

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <[email protected]>

* 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 <[email protected]>

* [Uniques V2] Final improvements (paritytech#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 <[email protected]>

* ".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 (paritytech#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 <[email protected]>

* Update frame/support/src/traits/tokens/nonfungible_v2.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/support/src/traits/tokens/nonfungible_v2.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/support/src/traits/tokens/nonfungibles_v2.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/support/src/traits/tokens/nonfungible_v2.rs

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/support/src/traits/tokens/nonfungibles_v2.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <[email protected]>

* Address comments

* [NFTs] Add the new `owner` param to mint() method (paritytech#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 <[email protected]>

* Update frame/nfts/src/types.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/nfts/src/types.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/nfts/src/types.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/nfts/src/types.rs

Co-authored-by: joe petrowski <[email protected]>

* Update frame/nfts/src/types.rs

Co-authored-by: joe petrowski <[email protected]>

* Add call indexes

* Update snapshots

* Refactor nft fractionalisation pallet (paritytech#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 <[email protected]>

* 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 <[email protected]>

* Update frame/nft-fractionalization/README.md

Co-authored-by: joe petrowski <[email protected]>

---------

Co-authored-by: Jegor Sidorenko <[email protected]>
Co-authored-by: Sergej Sakac <[email protected]>
Co-authored-by: Jegor Sidorenko <[email protected]>
Co-authored-by: Squirrel <[email protected]>
Co-authored-by: Keith Yeung <[email protected]>
Co-authored-by: Oliver Tale-Yazdi <[email protected]>
Co-authored-by: Muharem Ismailov <[email protected]>
Co-authored-by: command-bot <>
Co-authored-by: joe petrowski <[email protected]>
  • Loading branch information
9 people authored and nathanwhit committed Jul 19, 2023
1 parent c3f0ac7 commit 6eddc0f
Show file tree
Hide file tree
Showing 23 changed files with 1,483 additions and 9 deletions.
20 changes: 20 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ members = [
"frame/message-queue",
"frame/nfts",
"frame/nfts/runtime-api",
"frame/nft-fractionalization",
"frame/nomination-pools",
"frame/nomination-pools/fuzzer",
"frame/nomination-pools/benchmarking",
Expand Down
4 changes: 4 additions & 0 deletions bin/node/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ pallet-mmr = { version = "4.0.0-dev", default-features = false, path = "../../..
pallet-multisig = { version = "4.0.0-dev", default-features = false, path = "../../../frame/multisig" }
pallet-nfts = { version = "4.0.0-dev", default-features = false, path = "../../../frame/nfts" }
pallet-nfts-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/nfts/runtime-api" }
pallet-nft-fractionalization = { version = "4.0.0-dev", default-features = false, path = "../../../frame/nft-fractionalization" }
pallet-nomination-pools = { version = "1.0.0", default-features = false, path = "../../../frame/nomination-pools"}
pallet-nomination-pools-benchmarking = { version = "1.0.0", default-features = false, optional = true, path = "../../../frame/nomination-pools/benchmarking" }
pallet-nomination-pools-runtime-api = { version = "1.0.0-dev", default-features = false, path = "../../../frame/nomination-pools/runtime-api" }
Expand Down Expand Up @@ -219,6 +220,7 @@ std = [
"pallet-uniques/std",
"pallet-nfts/std",
"pallet-nfts-runtime-api/std",
"pallet-nft-fractionalization/std",
"pallet-vesting/std",
"log/std",
"frame-try-runtime?/std",
Expand Down Expand Up @@ -283,6 +285,7 @@ runtime-benchmarks = [
"pallet-utility/runtime-benchmarks",
"pallet-uniques/runtime-benchmarks",
"pallet-nfts/runtime-benchmarks",
"pallet-nft-fractionalization/runtime-benchmarks",
"pallet-vesting/runtime-benchmarks",
"pallet-whitelist/runtime-benchmarks",
"frame-system-benchmarking/runtime-benchmarks",
Expand Down Expand Up @@ -349,6 +352,7 @@ try-runtime = [
"pallet-transaction-storage/try-runtime",
"pallet-uniques/try-runtime",
"pallet-nfts/try-runtime",
"pallet-nft-fractionalization/try-runtime",
"pallet-vesting/try-runtime",
"pallet-whitelist/try-runtime",
]
35 changes: 33 additions & 2 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use frame_support::{
},
ConstantMultiplier, IdentityFee, Weight,
},
PalletId, RuntimeDebug,
BoundedVec, PalletId, RuntimeDebug,
};
use frame_system::{
limits::{BlockLength, BlockWeights},
Expand Down Expand Up @@ -445,6 +445,8 @@ parameter_types! {
pub enum HoldReason {
/// The NIS Pallet has reserved it for a non-fungible receipt.
Nis,
/// Used by the NFT Fractionalization Pallet.
NftFractionalization,
}

impl pallet_balances::Config for Runtime {
Expand All @@ -460,7 +462,7 @@ impl pallet_balances::Config for Runtime {
type FreezeIdentifier = ();
type MaxFreezes = ();
type HoldIdentifier = HoldReason;
type MaxHolds = ConstU32<1>;
type MaxHolds = ConstU32<2>;
}

parameter_types! {
Expand Down Expand Up @@ -1612,6 +1614,33 @@ impl pallet_core_fellowship::Config for Runtime {
type EvidenceSize = ConstU32<16_384>;
}

parameter_types! {
pub const NftFractionalizationPalletId: PalletId = PalletId(*b"fraction");
pub NewAssetSymbol: BoundedVec<u8, StringLimit> = (*b"FRAC").to_vec().try_into().unwrap();
pub NewAssetName: BoundedVec<u8, StringLimit> = (*b"Frac").to_vec().try_into().unwrap();
pub const NftFractionalizationHoldReason: HoldReason = HoldReason::NftFractionalization;
}

impl pallet_nft_fractionalization::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Deposit = AssetDeposit;
type Currency = Balances;
type NewAssetSymbol = NewAssetSymbol;
type NewAssetName = NewAssetName;
type StringLimit = StringLimit;
type NftCollectionId = <Self as pallet_nfts::Config>::CollectionId;
type NftId = <Self as pallet_nfts::Config>::ItemId;
type AssetBalance = <Self as pallet_balances::Config>::Balance;
type AssetId = <Self as pallet_assets::Config>::AssetId;
type Assets = Assets;
type Nfts = Nfts;
type PalletId = NftFractionalizationPalletId;
type WeightInfo = pallet_nft_fractionalization::weights::SubstrateWeight<Runtime>;
type HoldReason = NftFractionalizationHoldReason;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = ();
}

parameter_types! {
pub Features: PalletFeatures = PalletFeatures::all_enabled();
pub const MaxAttributesPerCall: u32 = 10;
Expand Down Expand Up @@ -1829,6 +1858,7 @@ construct_runtime!(
Nis: pallet_nis,
Uniques: pallet_uniques,
Nfts: pallet_nfts,
NftFractionalization: pallet_nft_fractionalization,
Salary: pallet_salary,
CoreFellowship: pallet_core_fellowship,
TransactionStorage: pallet_transaction_storage,
Expand Down Expand Up @@ -1972,6 +2002,7 @@ mod benches {
[pallet_asset_rate, AssetRate]
[pallet_uniques, Uniques]
[pallet_nfts, Nfts]
[pallet_nft_fractionalization, NftFractionalization]
[pallet_utility, Utility]
[pallet_vesting, Vesting]
[pallet_whitelist, Whitelist]
Expand Down
11 changes: 8 additions & 3 deletions frame/assets/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -962,9 +962,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
ensure!(metadata.as_ref().map_or(true, |m| !m.is_frozen), Error::<T, I>::NoPermission);

let old_deposit = metadata.take().map_or(Zero::zero(), |m| m.deposit);
let new_deposit = T::MetadataDepositPerByte::get()
.saturating_mul(((name.len() + symbol.len()) as u32).into())
.saturating_add(T::MetadataDepositBase::get());
let new_deposit = Self::calc_metadata_deposit(&name, &symbol);

if new_deposit > old_deposit {
T::Currency::reserve(from, new_deposit - old_deposit)?;
Expand All @@ -991,6 +989,13 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
})
}

/// Calculate the metadata deposit for the provided data.
pub(super) fn calc_metadata_deposit(name: &[u8], symbol: &[u8]) -> DepositBalanceOf<T, I> {
T::MetadataDepositPerByte::get()
.saturating_mul(((name.len() + symbol.len()) as u32).into())
.saturating_add(T::MetadataDepositBase::get())
}

/// Returns all the non-zero balances for all assets of the given `account`.
pub fn account_balances(account: T::AccountId) -> Vec<(T::AssetId, T::Balance)> {
Asset::<T, I>::iter_keys()
Expand Down
13 changes: 13 additions & 0 deletions frame/assets/src/impl_fungibles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,19 @@ impl<T: Config<I>, I: 'static> fungibles::metadata::Mutate<<T as SystemConfig>::
}
}

impl<T: Config<I>, I: 'static>
fungibles::metadata::MetadataDeposit<
<T::Currency as Currency<<T as SystemConfig>::AccountId>>::Balance,
> for Pallet<T, I>
{
fn calc_metadata_deposit(
name: &[u8],
symbol: &[u8],
) -> <T::Currency as Currency<<T as SystemConfig>::AccountId>>::Balance {
Self::calc_metadata_deposit(&name, &symbol)
}
}

impl<T: Config<I>, I: 'static> fungibles::approvals::Inspect<<T as SystemConfig>::AccountId>
for Pallet<T, I>
{
Expand Down
52 changes: 52 additions & 0 deletions frame/nft-fractionalization/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[package]
name = "pallet-nft-fractionalization"
version = "4.0.0-dev"
authors = ["Parity Technologies <[email protected]>"]
edition = "2021"
license = "Apache-2.0"
homepage = "https://substrate.io"
repository = "https://github.com/paritytech/substrate/"
description = "FRAME pallet to convert non-fungible to fungible tokens."
readme = "README.md"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false }
log = { version = "0.4.17", default-features = false }
scale-info = { version = "2.5.0", default-features = false, features = ["derive"] }
frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../benchmarking" }
frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../assets" }
pallet-nfts = { version = "4.0.0-dev", default-features = false, path = "../nfts" }
sp-runtime = { version = "7.0.0", default-features = false, path = "../../primitives/runtime" }
sp-std = { version = "5.0.0", default-features = false, path = "../../primitives/std" }

[dev-dependencies]
pallet-balances = { version = "4.0.0-dev", path = "../balances" }
sp-core = { version = "7.0.0", path = "../../primitives/core" }
sp-io = { version = "7.0.0", path = "../../primitives/io" }
sp-std = { version = "5.0.0", path = "../../primitives/std" }

[features]
default = ["std"]
std = [
"codec/std",
"frame-benchmarking/std",
"frame-support/std",
"frame-system/std",
"log/std",
"pallet-assets/std",
"pallet-nfts/std",
"scale-info/std",
"sp-runtime/std",
"sp-std/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
try-runtime = ["frame-support/try-runtime"]
6 changes: 6 additions & 0 deletions frame/nft-fractionalization/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
### Lock NFT

Lock an NFT from `pallet-nfts` and mint fungible assets from `pallet-assets`.

The NFT gets locked by putting a system-level attribute named `Locked`. This prevents the NFT from being transferred further.
The NFT becomes unlocked when the `Locked` attribute is removed. In order to unify the fungible asset and unlock the NFT, an account must hold the full issuance of the asset the NFT was fractionalised into. Holding less of the fungible asset will not allow the unlocking of the NFT.
135 changes: 135 additions & 0 deletions frame/nft-fractionalization/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// This file is part of Substrate.

// Copyright (C) 2020-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 benchmarking.

#![cfg(feature = "runtime-benchmarks")]

use super::*;
use frame_benchmarking::{benchmarks, whitelisted_caller};
use frame_support::{
assert_ok,
traits::{
fungible::{Inspect as InspectFungible, Mutate as MutateFungible},
tokens::nonfungibles_v2::{Create, Mutate},
Get,
},
};
use frame_system::RawOrigin as SystemOrigin;
use pallet_nfts::{CollectionConfig, CollectionSettings, ItemConfig, MintSettings};
use sp_runtime::traits::StaticLookup;
use sp_std::prelude::*;

use crate::Pallet as NftFractionalization;

type BalanceOf<T> =
<<T as Config>::Currency as InspectFungible<<T as SystemConfig>::AccountId>>::Balance;

type CollectionConfigOf<T> = CollectionConfig<
BalanceOf<T>,
<T as SystemConfig>::BlockNumber,
<T as Config>::NftCollectionId,
>;

fn default_collection_config<T: Config>() -> CollectionConfigOf<T>
where
T::Currency: InspectFungible<T::AccountId>,
{
CollectionConfig {
settings: CollectionSettings::all_enabled(),
max_supply: None,
mint_settings: MintSettings::default(),
}
}

fn mint_nft<T: Config>(nft_id: T::NftId) -> (T::AccountId, AccountIdLookupOf<T>)
where
T::Nfts: Create<T::AccountId, CollectionConfig<BalanceOf<T>, T::BlockNumber, T::NftCollectionId>>
+ Mutate<T::AccountId, ItemConfig>,
{
let caller: T::AccountId = whitelisted_caller();
let caller_lookup = T::Lookup::unlookup(caller.clone());
let ed = T::Currency::minimum_balance();
let multiplier = BalanceOf::<T>::from(100u8);
T::Currency::set_balance(&caller, ed * multiplier + T::Deposit::get() * multiplier);

assert_ok!(T::Nfts::create_collection(&caller, &caller, &default_collection_config::<T>()));
let collection = T::BenchmarkHelper::collection(0);
assert_ok!(T::Nfts::mint_into(&collection, &nft_id, &caller, &ItemConfig::default(), true));
(caller, caller_lookup)
}

fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
let events = frame_system::Pallet::<T>::events();
let system_event: <T as frame_system::Config>::RuntimeEvent = generic_event.into();
// compare to the last event record
let frame_system::EventRecord { event, .. } = &events[events.len() - 1];
assert_eq!(event, &system_event);
}

benchmarks! {
where_clause {
where
T::Nfts: Create<T::AccountId, CollectionConfig<BalanceOf<T>, T::BlockNumber, T::NftCollectionId>>
+ Mutate<T::AccountId, ItemConfig>,
}

fractionalize {
let asset = T::BenchmarkHelper::asset(0);
let collection = T::BenchmarkHelper::collection(0);
let nft = T::BenchmarkHelper::nft(0);
let (caller, caller_lookup) = mint_nft::<T>(nft);
}: _(SystemOrigin::Signed(caller.clone()), collection, nft, asset, caller_lookup, 1000u32.into())
verify {
assert_last_event::<T>(
Event::NftFractionalized {
nft_collection: collection,
nft,
fractions: 1000u32.into(),
asset,
beneficiary: caller,
}.into()
);
}

unify {
let asset = T::BenchmarkHelper::asset(0);
let collection = T::BenchmarkHelper::collection(0);
let nft = T::BenchmarkHelper::nft(0);
let (caller, caller_lookup) = mint_nft::<T>(nft);
NftFractionalization::<T>::fractionalize(
SystemOrigin::Signed(caller.clone()).into(),
collection,
nft,
asset,
caller_lookup.clone(),
1000u32.into(),
)?;
}: _(SystemOrigin::Signed(caller.clone()), collection, nft, asset, caller_lookup)
verify {
assert_last_event::<T>(
Event::NftUnified {
nft_collection: collection,
nft,
asset,
beneficiary: caller,
}.into()
);
}

impl_benchmark_test_suite!(NftFractionalization, crate::mock::new_test_ext(), crate::mock::Test);
}
Loading

0 comments on commit 6eddc0f

Please sign in to comment.