Skip to content

Commit

Permalink
Uniques: An economically-secure basic-featured NFT pallet (paritytech…
Browse files Browse the repository at this point in the history
…#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 <[email protected]>

* Update frame/uniques/src/lib.rs

Co-authored-by: Shawn Tabrizi <[email protected]>

* Update frame/uniques/src/lib.rs

Co-authored-by: Shawn Tabrizi <[email protected]>

* Update frame/uniques/src/lib.rs

Co-authored-by: Shawn Tabrizi <[email protected]>

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

* Update frame/uniques/src/lib.rs

Co-authored-by: Lohann Paterno Coutinho Ferreira <[email protected]>

* Update frame/uniques/src/lib.rs

Co-authored-by: Lohann Paterno Coutinho Ferreira <[email protected]>

* Update frame/uniques/src/lib.rs

Co-authored-by: Lohann Paterno Coutinho Ferreira <[email protected]>

* Update frame/uniques/src/lib.rs

Co-authored-by: Lohann Paterno Coutinho Ferreira <[email protected]>

* Fixes

* Update frame/uniques/README.md

Co-authored-by: Alexander Popiak <[email protected]>

* Update frame/uniques/README.md

Co-authored-by: Alexander Popiak <[email protected]>

* Update frame/uniques/README.md

Co-authored-by: Alexander Popiak <[email protected]>

* Docs

* Bump

Co-authored-by: Shawn Tabrizi <[email protected]>
Co-authored-by: Parity Bot <[email protected]>
Co-authored-by: Lohann Paterno Coutinho Ferreira <[email protected]>
Co-authored-by: Alexander Popiak <[email protected]>
  • Loading branch information
5 people authored Jun 1, 2021
1 parent fa23b18 commit d8b3fce
Show file tree
Hide file tree
Showing 17 changed files with 2,973 additions and 15 deletions.
16 changes: 16 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 @@ -125,6 +125,7 @@ members = [
"frame/transaction-payment/rpc/runtime-api",
"frame/treasury",
"frame/tips",
"frame/uniques",
"frame/utility",
"frame/vesting",
"primitives/allocator",
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-treasury = { version = "3.0.0", default-features = false, path = "../../.
pallet-utility = { version = "3.0.0", default-features = false, path = "../../../frame/utility" }
pallet-transaction-payment = { version = "3.0.0", default-features = false, path = "../../../frame/transaction-payment" }
pallet-transaction-payment-rpc-runtime-api = { version = "3.0.0", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" }
pallet-uniques = { version = "3.0.0", default-features = false, path = "../../../frame/uniques" }
pallet-vesting = { version = "3.0.0", default-features = false, path = "../../../frame/vesting" }

max-encoded-len = { version = "3.0.0", default-features = false, path = "../../../max-encoded-len", features = [ "derive" ] }
Expand Down Expand Up @@ -157,6 +158,7 @@ std = [
"sp-version/std",
"pallet-society/std",
"pallet-recovery/std",
"pallet-uniques/std",
"pallet-vesting/std",
"log/std",
"frame-try-runtime/std",
Expand Down Expand Up @@ -194,6 +196,7 @@ runtime-benchmarks = [
"pallet-tips/runtime-benchmarks",
"pallet-treasury/runtime-benchmarks",
"pallet-utility/runtime-benchmarks",
"pallet-uniques/runtime-benchmarks",
"pallet-vesting/runtime-benchmarks",
"pallet-offences-benchmarking",
"pallet-session-benchmarking",
Expand Down Expand Up @@ -237,6 +240,7 @@ try-runtime = [
"pallet-utility/try-runtime",
"pallet-society/try-runtime",
"pallet-recovery/try-runtime",
"pallet-uniques/try-runtime",
"pallet-vesting/try-runtime",
"pallet-gilt/try-runtime",
]
Expand Down
28 changes: 27 additions & 1 deletion bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// and set impl_version to 0. If only runtime
// implementation changes and behavior does not, then leave spec_version as
// is and increment impl_version.
spec_version: 266,
spec_version: 267,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 2,
Expand Down Expand Up @@ -1090,6 +1090,30 @@ impl pallet_gilt::Config for Runtime {
type WeightInfo = pallet_gilt::weights::SubstrateWeight<Runtime>;
}

parameter_types! {
pub const ClassDeposit: Balance = 100 * DOLLARS;
pub const InstanceDeposit: Balance = 1 * DOLLARS;
pub const KeyLimit: u32 = 32;
pub const ValueLimit: u32 = 256;
}

impl pallet_uniques::Config for Runtime {
type Event = Event;
type ClassId = u32;
type InstanceId = u32;
type Currency = Balances;
type ForceOrigin = frame_system::EnsureRoot<AccountId>;
type ClassDeposit = ClassDeposit;
type InstanceDeposit = InstanceDeposit;
type MetadataDepositBase = MetadataDepositBase;
type AttributeDepositBase = MetadataDepositBase;
type DepositPerByte = MetadataDepositPerByte;
type StringLimit = StringLimit;
type KeyLimit = KeyLimit;
type ValueLimit = ValueLimit;
type WeightInfo = pallet_uniques::weights::SubstrateWeight<Runtime>;
}

construct_runtime!(
pub enum Runtime where
Block = Block,
Expand Down Expand Up @@ -1134,6 +1158,7 @@ construct_runtime!(
Mmr: pallet_mmr::{Pallet, Storage},
Lottery: pallet_lottery::{Pallet, Call, Storage, Event<T>},
Gilt: pallet_gilt::{Pallet, Call, Storage, Event<T>, Config},
Uniques: pallet_uniques::{Pallet, Call, Storage, Event<T>},
}
);

Expand Down Expand Up @@ -1508,6 +1533,7 @@ impl_runtime_apis! {
add_benchmark!(params, batches, pallet_timestamp, Timestamp);
add_benchmark!(params, batches, pallet_tips, Tips);
add_benchmark!(params, batches, pallet_treasury, Treasury);
add_benchmark!(params, batches, pallet_uniques, Uniques);
add_benchmark!(params, batches, pallet_utility, Utility);
add_benchmark!(params, batches, pallet_vesting, Vesting);

Expand Down
8 changes: 4 additions & 4 deletions frame/assets/src/impl_fungibles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,26 +127,26 @@ impl<T: Config<I>, I: 'static> fungibles::Unbalanced<T::AccountId> for Pallet<T,
});
}
fn decrease_balance(asset: T::AssetId, who: &T::AccountId, amount: Self::Balance)
-> Result<Self::Balance, DispatchError>
-> Result<Self::Balance, DispatchError>
{
let f = DebitFlags { keep_alive: false, best_effort: false };
Self::decrease_balance(asset, who, amount, f, |_, _| Ok(()))
}
fn decrease_balance_at_most(asset: T::AssetId, who: &T::AccountId, amount: Self::Balance)
-> Self::Balance
-> Self::Balance
{
let f = DebitFlags { keep_alive: false, best_effort: true };
Self::decrease_balance(asset, who, amount, f, |_, _| Ok(()))
.unwrap_or(Zero::zero())
}
fn increase_balance(asset: T::AssetId, who: &T::AccountId, amount: Self::Balance)
-> Result<Self::Balance, DispatchError>
-> Result<Self::Balance, DispatchError>
{
Self::increase_balance(asset, who, amount, |_| Ok(()))?;
Ok(amount)
}
fn increase_balance_at_most(asset: T::AssetId, who: &T::AccountId, amount: Self::Balance)
-> Self::Balance
-> Self::Balance
{
match Self::increase_balance(asset, who, amount, |_| Ok(())) {
Ok(()) => amount,
Expand Down
16 changes: 7 additions & 9 deletions frame/assets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,6 @@ pub mod pallet {
/// - `owner`: The owner of this class of assets. The owner has full superuser permissions
/// over this asset, but may later change and configure the permissions using `transfer_ownership`
/// and `set_team`.
/// - `max_zombies`: The total number of accounts which may hold assets in this class yet
/// have no existential deposit.
/// - `min_balance`: The minimum balance of this new asset that any single account must
/// have. If an account's balance is reduced below this, then it collapses to zero.
///
Expand Down Expand Up @@ -588,8 +586,8 @@ pub mod pallet {
/// to zero.
///
/// Weight: `O(1)`
/// Modes: Pre-existence of `target`; Post-existence of sender; Prior & post zombie-status
/// of sender; Account pre-existence of `target`.
/// Modes: Pre-existence of `target`; Post-existence of sender; Account pre-existence of
/// `target`.
#[pallet::weight(T::WeightInfo::transfer())]
pub(super) fn transfer(
origin: OriginFor<T>,
Expand Down Expand Up @@ -624,8 +622,8 @@ pub mod pallet {
/// to zero.
///
/// Weight: `O(1)`
/// Modes: Pre-existence of `target`; Post-existence of sender; Prior & post zombie-status
/// of sender; Account pre-existence of `target`.
/// Modes: Pre-existence of `target`; Post-existence of sender; Account pre-existence of
/// `target`.
#[pallet::weight(T::WeightInfo::transfer_keep_alive())]
pub(super) fn transfer_keep_alive(
origin: OriginFor<T>,
Expand Down Expand Up @@ -661,8 +659,8 @@ pub mod pallet {
/// to zero.
///
/// Weight: `O(1)`
/// Modes: Pre-existence of `dest`; Post-existence of `source`; Prior & post zombie-status
/// of `source`; Account pre-existence of `dest`.
/// Modes: Pre-existence of `dest`; Post-existence of `source`; Account pre-existence of
/// `dest`.
#[pallet::weight(T::WeightInfo::force_transfer())]
pub(super) fn force_transfer(
origin: OriginFor<T>,
Expand Down Expand Up @@ -779,7 +777,7 @@ pub mod pallet {
///
/// Origin must be Signed and the sender should be the Admin of the asset `id`.
///
/// - `id`: The identifier of the asset to be frozen.
/// - `id`: The identifier of the asset to be thawed.
///
/// Emits `Thawed`.
///
Expand Down
6 changes: 6 additions & 0 deletions frame/support/src/storage/bounded_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ impl<T, S> BoundedVec<T, S> {
}
}

impl<T, S: Get<u32>> From<BoundedVec<T, S>> for Vec<T> {
fn from(x: BoundedVec<T, S>) -> Vec<T> {
x.0
}
}

impl<T, S: Get<u32>> BoundedVec<T, S> {
/// Get the bound of the type in `usize`.
pub fn bound() -> usize {
Expand Down
2 changes: 1 addition & 1 deletion frame/support/src/storage/types/nmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ where

/// Iter over all value of the storage.
///
/// NOTE: If a value failed to decode becaues storage is corrupted then it is skipped.
/// NOTE: If a value failed to decode because storage is corrupted then it is skipped.
pub fn iter_values() -> crate::storage::PrefixIterator<Value> {
<Self as crate::storage::StoragePrefixedMap<Value>>::iter_values()
}
Expand Down
46 changes: 46 additions & 0 deletions frame/uniques/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
[package]
name = "pallet-uniques"
version = "3.0.0"
authors = ["Parity Technologies <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
homepage = "https://substrate.dev"
repository = "https://github.com/paritytech/substrate/"
description = "FRAME NFT asset management pallet"
readme = "README.md"

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

[dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" }
sp-core = { version = "3.0.0", default-features = false, path = "../../primitives/core" }
sp-runtime = { version = "3.0.0", default-features = false, path = "../../primitives/runtime" }
frame-support = { version = "3.0.0", default-features = false, path = "../support" }
frame-system = { version = "3.0.0", default-features = false, path = "../system" }
frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true }

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

[features]
default = ["std"]
std = [
"codec/std",
"sp-std/std",
"sp-core/std",
"sp-runtime/std",
"frame-support/std",
"frame-system/std",
"frame-benchmarking/std",
]
runtime-benchmarks = [
"frame-benchmarking",
"sp-runtime/runtime-benchmarks",
"frame-system/runtime-benchmarks",
]
try-runtime = ["frame-support/try-runtime"]
78 changes: 78 additions & 0 deletions frame/uniques/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Uniques Module

A simple, secure module for dealing with non-fungible assets.

## Overview

The Uniques module provides functionality for asset management of non-fungible asset classes, including:

* Asset Issuance
* Asset Transfer
* Asset Destruction

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).

The supported dispatchable functions are documented in the [`uniques::Call`](https://docs.rs/pallet-uniques/latest/pallet_uniques/pallet/enum.Call.html) enum.

### Terminology

* **Asset issuance:** The creation of a new asset instance.
* **Asset transfer:** The action of transferring an asset instance from one account to another.
* **Asset burning:** The destruction of an asset instance.
* **Non-fungible asset:** An asset for which each unit has unique characteristics. There is exactly
one instance of such an asset in existance and there is exactly one owning account.

### Goals

The Uniques pallet in Substrate is designed to make the following possible:

* Allow accounts to permissionlessly create asset classes (collections of asset instances).
* Allow a named (permissioned) account to mint and burn unique assets within a class.
* Move asset instances between accounts permissionlessly.
* Allow a named (permissioned) account to freeze and unfreeze unique assets within a
class or the entire class.
* Allow the owner of an asset instance to delegate the ability to transfer the asset to some
named third-party.

## Interface

### Permissionless dispatchables
* `create`: Create a new asset class by placing a deposit.
* `transfer`: Transfer an asset instance to a new owner.
* `redeposit`: Update the deposit amount of an asset instance, potentially freeing funds.
* `approve_transfer`: Name a delegate who may authorise a transfer.
* `cancel_approval`: Revert the effects of a previous `approve_transfer`.

### Permissioned dispatchables
* `destroy`: Destroy an asset class.
* `mint`: Mint a new asset instance within an asset class.
* `burn`: Burn an asset instance within an asset class.
* `freeze`: Prevent an individual asset from being transferred.
* `thaw`: Revert the effects of a previous `freeze`.
* `freeze_class`: Prevent all asset within a class from being transferred.
* `thaw_class`: Revert the effects of a previous `freeze_class`.
* `transfer_ownership`: Alter the owner of an asset class, moving all associated deposits.
* `set_team`: Alter the permissioned accounts of an asset class.

### Metadata (permissioned) dispatchables
* `set_attribute`: Set a metadata attribute of an asset instance or class.
* `clear_attribute`: Remove a metadata attribute of an asset instance or class.
* `set_metadata`: Set general metadata of an asset instance.
* `clear_metadata`: Remove general metadata of an asset instance.
* `set_class_metadata`: Set general metadata of an asset class.
* `clear_class_metadata`: Remove general metadata of an asset class.

### Force (i.e. governance) dispatchables
* `force_create`: Create a new asset class.
* `force_asset_status`: Alter the underlying characteristics of an asset class.

Please refer to the [`Call`](https://docs.rs/pallet-assets/latest/pallet_assets/enum.Call.html) enum
and its associated variants for documentation on each function.

## Related Modules

* [`System`](https://docs.rs/frame-system/latest/frame_system/)
* [`Support`](https://docs.rs/frame-support/latest/frame_support/)
* [`Assets`](https://docs.rs/pallet-assets/latest/pallet_assetss/)

License: Apache-2.0
Loading

0 comments on commit d8b3fce

Please sign in to comment.