Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit d8b3fce

Browse files
gavofyorkshawntabriziParity BotLohannapopiak
authored
Uniques: An economically-secure basic-featured NFT pallet (#8813)
* Uniques: An economically-secure basic-featured NFT pallet * force_transfer * freeze/thaw * team management * approvals * Fixes * force_asset_status * class_metadata * instance metadata * Fixes * use nmap * Fixes * class metadata has information field * Intiial mock/tests and a fix * Remove impl_non_fungibles * Docs * Update frame/uniques/src/lib.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Update frame/uniques/src/lib.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Update frame/uniques/src/lib.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Update frame/uniques/src/lib.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Reserve, don't transfer. * Fixes * Tests * Tests * refresh_deposit * Tests and proper handling of metdata destruction * test burn * Tests * Update impl_fungibles.rs * Initial benchmarking * benchmark * Fixes * cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_uniques --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/uniques/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Attributes * Attribute metadata * Fixes * Update frame/uniques/README.md * Docs * Docs * Docs * Simple metadata * Use BoundedVec * cargo run --release --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_uniques --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/uniques/src/weights.rs --template=./.maintain/frame-weight-template.hbs * Update frame/uniques/src/lib.rs Co-authored-by: Lohann Paterno Coutinho Ferreira <developer@lohann.dev> * Update frame/uniques/src/lib.rs Co-authored-by: Lohann Paterno Coutinho Ferreira <developer@lohann.dev> * Update frame/uniques/src/lib.rs Co-authored-by: Lohann Paterno Coutinho Ferreira <developer@lohann.dev> * Update frame/uniques/src/lib.rs Co-authored-by: Lohann Paterno Coutinho Ferreira <developer@lohann.dev> * Update frame/uniques/src/lib.rs Co-authored-by: Lohann Paterno Coutinho Ferreira <developer@lohann.dev> * Fixes * Update frame/uniques/README.md Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update frame/uniques/README.md Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update frame/uniques/README.md Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Docs * Bump Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> Co-authored-by: Parity Bot <admin@parity.io> Co-authored-by: Lohann Paterno Coutinho Ferreira <developer@lohann.dev> Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>
1 parent fa23b18 commit d8b3fce

File tree

17 files changed

+2973
-15
lines changed

17 files changed

+2973
-15
lines changed

Cargo.lock

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ members = [
125125
"frame/transaction-payment/rpc/runtime-api",
126126
"frame/treasury",
127127
"frame/tips",
128+
"frame/uniques",
128129
"frame/utility",
129130
"frame/vesting",
130131
"primitives/allocator",

bin/node/runtime/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ pallet-treasury = { version = "3.0.0", default-features = false, path = "../../.
8585
pallet-utility = { version = "3.0.0", default-features = false, path = "../../../frame/utility" }
8686
pallet-transaction-payment = { version = "3.0.0", default-features = false, path = "../../../frame/transaction-payment" }
8787
pallet-transaction-payment-rpc-runtime-api = { version = "3.0.0", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" }
88+
pallet-uniques = { version = "3.0.0", default-features = false, path = "../../../frame/uniques" }
8889
pallet-vesting = { version = "3.0.0", default-features = false, path = "../../../frame/vesting" }
8990

9091
max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../max-encoded-len", features = [ "derive" ] }
@@ -157,6 +158,7 @@ std = [
157158
"sp-version/std",
158159
"pallet-society/std",
159160
"pallet-recovery/std",
161+
"pallet-uniques/std",
160162
"pallet-vesting/std",
161163
"log/std",
162164
"frame-try-runtime/std",
@@ -194,6 +196,7 @@ runtime-benchmarks = [
194196
"pallet-tips/runtime-benchmarks",
195197
"pallet-treasury/runtime-benchmarks",
196198
"pallet-utility/runtime-benchmarks",
199+
"pallet-uniques/runtime-benchmarks",
197200
"pallet-vesting/runtime-benchmarks",
198201
"pallet-offences-benchmarking",
199202
"pallet-session-benchmarking",
@@ -237,6 +240,7 @@ try-runtime = [
237240
"pallet-utility/try-runtime",
238241
"pallet-society/try-runtime",
239242
"pallet-recovery/try-runtime",
243+
"pallet-uniques/try-runtime",
240244
"pallet-vesting/try-runtime",
241245
"pallet-gilt/try-runtime",
242246
]

bin/node/runtime/src/lib.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
114114
// and set impl_version to 0. If only runtime
115115
// implementation changes and behavior does not, then leave spec_version as
116116
// is and increment impl_version.
117-
spec_version: 266,
117+
spec_version: 267,
118118
impl_version: 0,
119119
apis: RUNTIME_API_VERSIONS,
120120
transaction_version: 2,
@@ -1090,6 +1090,30 @@ impl pallet_gilt::Config for Runtime {
10901090
type WeightInfo = pallet_gilt::weights::SubstrateWeight<Runtime>;
10911091
}
10921092

1093+
parameter_types! {
1094+
pub const ClassDeposit: Balance = 100 * DOLLARS;
1095+
pub const InstanceDeposit: Balance = 1 * DOLLARS;
1096+
pub const KeyLimit: u32 = 32;
1097+
pub const ValueLimit: u32 = 256;
1098+
}
1099+
1100+
impl pallet_uniques::Config for Runtime {
1101+
type Event = Event;
1102+
type ClassId = u32;
1103+
type InstanceId = u32;
1104+
type Currency = Balances;
1105+
type ForceOrigin = frame_system::EnsureRoot<AccountId>;
1106+
type ClassDeposit = ClassDeposit;
1107+
type InstanceDeposit = InstanceDeposit;
1108+
type MetadataDepositBase = MetadataDepositBase;
1109+
type AttributeDepositBase = MetadataDepositBase;
1110+
type DepositPerByte = MetadataDepositPerByte;
1111+
type StringLimit = StringLimit;
1112+
type KeyLimit = KeyLimit;
1113+
type ValueLimit = ValueLimit;
1114+
type WeightInfo = pallet_uniques::weights::SubstrateWeight<Runtime>;
1115+
}
1116+
10931117
construct_runtime!(
10941118
pub enum Runtime where
10951119
Block = Block,
@@ -1134,6 +1158,7 @@ construct_runtime!(
11341158
Mmr: pallet_mmr::{Pallet, Storage},
11351159
Lottery: pallet_lottery::{Pallet, Call, Storage, Event<T>},
11361160
Gilt: pallet_gilt::{Pallet, Call, Storage, Event<T>, Config},
1161+
Uniques: pallet_uniques::{Pallet, Call, Storage, Event<T>},
11371162
}
11381163
);
11391164

@@ -1508,6 +1533,7 @@ impl_runtime_apis! {
15081533
add_benchmark!(params, batches, pallet_timestamp, Timestamp);
15091534
add_benchmark!(params, batches, pallet_tips, Tips);
15101535
add_benchmark!(params, batches, pallet_treasury, Treasury);
1536+
add_benchmark!(params, batches, pallet_uniques, Uniques);
15111537
add_benchmark!(params, batches, pallet_utility, Utility);
15121538
add_benchmark!(params, batches, pallet_vesting, Vesting);
15131539

frame/assets/src/impl_fungibles.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,26 +127,26 @@ impl<T: Config<I>, I: 'static> fungibles::Unbalanced<T::AccountId> for Pallet<T,
127127
});
128128
}
129129
fn decrease_balance(asset: T::AssetId, who: &T::AccountId, amount: Self::Balance)
130-
-> Result<Self::Balance, DispatchError>
130+
-> Result<Self::Balance, DispatchError>
131131
{
132132
let f = DebitFlags { keep_alive: false, best_effort: false };
133133
Self::decrease_balance(asset, who, amount, f, |_, _| Ok(()))
134134
}
135135
fn decrease_balance_at_most(asset: T::AssetId, who: &T::AccountId, amount: Self::Balance)
136-
-> Self::Balance
136+
-> Self::Balance
137137
{
138138
let f = DebitFlags { keep_alive: false, best_effort: true };
139139
Self::decrease_balance(asset, who, amount, f, |_, _| Ok(()))
140140
.unwrap_or(Zero::zero())
141141
}
142142
fn increase_balance(asset: T::AssetId, who: &T::AccountId, amount: Self::Balance)
143-
-> Result<Self::Balance, DispatchError>
143+
-> Result<Self::Balance, DispatchError>
144144
{
145145
Self::increase_balance(asset, who, amount, |_| Ok(()))?;
146146
Ok(amount)
147147
}
148148
fn increase_balance_at_most(asset: T::AssetId, who: &T::AccountId, amount: Self::Balance)
149-
-> Self::Balance
149+
-> Self::Balance
150150
{
151151
match Self::increase_balance(asset, who, amount, |_| Ok(())) {
152152
Ok(()) => amount,

frame/assets/src/lib.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,6 @@ pub mod pallet {
417417
/// - `owner`: The owner of this class of assets. The owner has full superuser permissions
418418
/// over this asset, but may later change and configure the permissions using `transfer_ownership`
419419
/// and `set_team`.
420-
/// - `max_zombies`: The total number of accounts which may hold assets in this class yet
421-
/// have no existential deposit.
422420
/// - `min_balance`: The minimum balance of this new asset that any single account must
423421
/// have. If an account's balance is reduced below this, then it collapses to zero.
424422
///
@@ -588,8 +586,8 @@ pub mod pallet {
588586
/// to zero.
589587
///
590588
/// Weight: `O(1)`
591-
/// Modes: Pre-existence of `target`; Post-existence of sender; Prior & post zombie-status
592-
/// of sender; Account pre-existence of `target`.
589+
/// Modes: Pre-existence of `target`; Post-existence of sender; Account pre-existence of
590+
/// `target`.
593591
#[pallet::weight(T::WeightInfo::transfer())]
594592
pub(super) fn transfer(
595593
origin: OriginFor<T>,
@@ -624,8 +622,8 @@ pub mod pallet {
624622
/// to zero.
625623
///
626624
/// Weight: `O(1)`
627-
/// Modes: Pre-existence of `target`; Post-existence of sender; Prior & post zombie-status
628-
/// of sender; Account pre-existence of `target`.
625+
/// Modes: Pre-existence of `target`; Post-existence of sender; Account pre-existence of
626+
/// `target`.
629627
#[pallet::weight(T::WeightInfo::transfer_keep_alive())]
630628
pub(super) fn transfer_keep_alive(
631629
origin: OriginFor<T>,
@@ -661,8 +659,8 @@ pub mod pallet {
661659
/// to zero.
662660
///
663661
/// Weight: `O(1)`
664-
/// Modes: Pre-existence of `dest`; Post-existence of `source`; Prior & post zombie-status
665-
/// of `source`; Account pre-existence of `dest`.
662+
/// Modes: Pre-existence of `dest`; Post-existence of `source`; Account pre-existence of
663+
/// `dest`.
666664
#[pallet::weight(T::WeightInfo::force_transfer())]
667665
pub(super) fn force_transfer(
668666
origin: OriginFor<T>,
@@ -779,7 +777,7 @@ pub mod pallet {
779777
///
780778
/// Origin must be Signed and the sender should be the Admin of the asset `id`.
781779
///
782-
/// - `id`: The identifier of the asset to be frozen.
780+
/// - `id`: The identifier of the asset to be thawed.
783781
///
784782
/// Emits `Thawed`.
785783
///

frame/support/src/storage/bounded_vec.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ impl<T, S> BoundedVec<T, S> {
9494
}
9595
}
9696

97+
impl<T, S: Get<u32>> From<BoundedVec<T, S>> for Vec<T> {
98+
fn from(x: BoundedVec<T, S>) -> Vec<T> {
99+
x.0
100+
}
101+
}
102+
97103
impl<T, S: Get<u32>> BoundedVec<T, S> {
98104
/// Get the bound of the type in `usize`.
99105
pub fn bound() -> usize {

frame/support/src/storage/types/nmap.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ where
272272

273273
/// Iter over all value of the storage.
274274
///
275-
/// NOTE: If a value failed to decode becaues storage is corrupted then it is skipped.
275+
/// NOTE: If a value failed to decode because storage is corrupted then it is skipped.
276276
pub fn iter_values() -> crate::storage::PrefixIterator<Value> {
277277
<Self as crate::storage::StoragePrefixedMap<Value>>::iter_values()
278278
}

frame/uniques/Cargo.toml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
[package]
2+
name = "pallet-uniques"
3+
version = "3.0.0"
4+
authors = ["Parity Technologies <admin@parity.io>"]
5+
edition = "2018"
6+
license = "Apache-2.0"
7+
homepage = "https://substrate.dev"
8+
repository = "https://github.com/paritytech/substrate/"
9+
description = "FRAME NFT asset management pallet"
10+
readme = "README.md"
11+
12+
[package.metadata.docs.rs]
13+
targets = ["x86_64-unknown-linux-gnu"]
14+
15+
[dependencies]
16+
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
17+
sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" }
18+
sp-core = { version = "3.0.0", default-features = false, path = "../../primitives/core" }
19+
sp-runtime = { version = "3.0.0", default-features = false, path = "../../primitives/runtime" }
20+
frame-support = { version = "3.0.0", default-features = false, path = "../support" }
21+
frame-system = { version = "3.0.0", default-features = false, path = "../system" }
22+
frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true }
23+
24+
[dev-dependencies]
25+
sp-std = { version = "3.0.0", path = "../../primitives/std" }
26+
sp-core = { version = "3.0.0", path = "../../primitives/core" }
27+
sp-io = { version = "3.0.0", path = "../../primitives/io" }
28+
pallet-balances = { version = "3.0.0", path = "../balances" }
29+
30+
[features]
31+
default = ["std"]
32+
std = [
33+
"codec/std",
34+
"sp-std/std",
35+
"sp-core/std",
36+
"sp-runtime/std",
37+
"frame-support/std",
38+
"frame-system/std",
39+
"frame-benchmarking/std",
40+
]
41+
runtime-benchmarks = [
42+
"frame-benchmarking",
43+
"sp-runtime/runtime-benchmarks",
44+
"frame-system/runtime-benchmarks",
45+
]
46+
try-runtime = ["frame-support/try-runtime"]

frame/uniques/README.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Uniques Module
2+
3+
A simple, secure module for dealing with non-fungible assets.
4+
5+
## Overview
6+
7+
The Uniques module provides functionality for asset management of non-fungible asset classes, including:
8+
9+
* Asset Issuance
10+
* Asset Transfer
11+
* Asset Destruction
12+
13+
To use it in your runtime, you need to implement the assets [`uniques::Config`](https://docs.rs/pallet-uniques/latest/pallet_uniques/pallet/trait.Config.html).
14+
15+
The supported dispatchable functions are documented in the [`uniques::Call`](https://docs.rs/pallet-uniques/latest/pallet_uniques/pallet/enum.Call.html) enum.
16+
17+
### Terminology
18+
19+
* **Asset issuance:** The creation of a new asset instance.
20+
* **Asset transfer:** The action of transferring an asset instance from one account to another.
21+
* **Asset burning:** The destruction of an asset instance.
22+
* **Non-fungible asset:** An asset for which each unit has unique characteristics. There is exactly
23+
one instance of such an asset in existance and there is exactly one owning account.
24+
25+
### Goals
26+
27+
The Uniques pallet in Substrate is designed to make the following possible:
28+
29+
* Allow accounts to permissionlessly create asset classes (collections of asset instances).
30+
* Allow a named (permissioned) account to mint and burn unique assets within a class.
31+
* Move asset instances between accounts permissionlessly.
32+
* Allow a named (permissioned) account to freeze and unfreeze unique assets within a
33+
class or the entire class.
34+
* Allow the owner of an asset instance to delegate the ability to transfer the asset to some
35+
named third-party.
36+
37+
## Interface
38+
39+
### Permissionless dispatchables
40+
* `create`: Create a new asset class by placing a deposit.
41+
* `transfer`: Transfer an asset instance to a new owner.
42+
* `redeposit`: Update the deposit amount of an asset instance, potentially freeing funds.
43+
* `approve_transfer`: Name a delegate who may authorise a transfer.
44+
* `cancel_approval`: Revert the effects of a previous `approve_transfer`.
45+
46+
### Permissioned dispatchables
47+
* `destroy`: Destroy an asset class.
48+
* `mint`: Mint a new asset instance within an asset class.
49+
* `burn`: Burn an asset instance within an asset class.
50+
* `freeze`: Prevent an individual asset from being transferred.
51+
* `thaw`: Revert the effects of a previous `freeze`.
52+
* `freeze_class`: Prevent all asset within a class from being transferred.
53+
* `thaw_class`: Revert the effects of a previous `freeze_class`.
54+
* `transfer_ownership`: Alter the owner of an asset class, moving all associated deposits.
55+
* `set_team`: Alter the permissioned accounts of an asset class.
56+
57+
### Metadata (permissioned) dispatchables
58+
* `set_attribute`: Set a metadata attribute of an asset instance or class.
59+
* `clear_attribute`: Remove a metadata attribute of an asset instance or class.
60+
* `set_metadata`: Set general metadata of an asset instance.
61+
* `clear_metadata`: Remove general metadata of an asset instance.
62+
* `set_class_metadata`: Set general metadata of an asset class.
63+
* `clear_class_metadata`: Remove general metadata of an asset class.
64+
65+
### Force (i.e. governance) dispatchables
66+
* `force_create`: Create a new asset class.
67+
* `force_asset_status`: Alter the underlying characteristics of an asset class.
68+
69+
Please refer to the [`Call`](https://docs.rs/pallet-assets/latest/pallet_assets/enum.Call.html) enum
70+
and its associated variants for documentation on each function.
71+
72+
## Related Modules
73+
74+
* [`System`](https://docs.rs/frame-system/latest/frame_system/)
75+
* [`Support`](https://docs.rs/frame-support/latest/frame_support/)
76+
* [`Assets`](https://docs.rs/pallet-assets/latest/pallet_assetss/)
77+
78+
License: Apache-2.0

0 commit comments

Comments
 (0)