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

Uniques: An economically-secure basic-featured NFT pallet #8813

Merged
merged 61 commits into from
Jun 1, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
2d98b0d
Uniques: An economically-secure basic-featured NFT pallet
gavofyork May 14, 2021
628b1bd
Merge remote-tracking branch 'origin/master' into gav-uniques
gavofyork May 16, 2021
aa84878
force_transfer
gavofyork May 16, 2021
0c0c4cb
freeze/thaw
gavofyork May 16, 2021
a203c1f
team management
gavofyork May 16, 2021
b2c20f8
approvals
gavofyork May 16, 2021
f98dcaf
Fixes
gavofyork May 16, 2021
da78f22
force_asset_status
gavofyork May 16, 2021
ee5f32a
class_metadata
gavofyork May 17, 2021
c148760
instance metadata
gavofyork May 17, 2021
ec47648
Fixes
gavofyork May 17, 2021
2949d12
use nmap
gavofyork May 17, 2021
30f2f9e
Fixes
gavofyork May 17, 2021
00c8e04
class metadata has information field
gavofyork May 17, 2021
326beba
Intiial mock/tests and a fix
gavofyork May 19, 2021
f5c9d1d
Remove impl_non_fungibles
gavofyork May 19, 2021
7874135
Docs
gavofyork May 19, 2021
6a231a8
Update frame/uniques/src/lib.rs
gavofyork May 19, 2021
4699b23
Update frame/uniques/src/lib.rs
gavofyork May 19, 2021
fb6ea03
Update frame/uniques/src/lib.rs
gavofyork May 19, 2021
87cc1d8
Update frame/uniques/src/lib.rs
gavofyork May 19, 2021
3ad9a52
Merge remote-tracking branch 'origin/master' into gav-uniques
gavofyork May 19, 2021
8e8b4df
Reserve, don't transfer.
gavofyork May 19, 2021
01f9713
Fixes
gavofyork May 19, 2021
4bf6f54
Tests
gavofyork May 19, 2021
821de3d
Tests
gavofyork May 19, 2021
d410298
refresh_deposit
gavofyork May 19, 2021
d703510
Tests and proper handling of metdata destruction
gavofyork May 19, 2021
59ff5e9
test burn
gavofyork May 19, 2021
4be8928
Tests
gavofyork May 19, 2021
de1eb5a
Update impl_fungibles.rs
gavofyork May 20, 2021
53c666c
Initial benchmarking
gavofyork May 20, 2021
1545abe
benchmark
gavofyork May 20, 2021
24e08cc
Fixes
gavofyork May 20, 2021
3027c7b
Merge branch 'master' of https://github.com/paritytech/substrate into…
May 20, 2021
da6f748
cargo run --release --features=runtime-benchmarks --manifest-path=bin…
May 20, 2021
95e49b9
Attributes
gavofyork May 20, 2021
ccaf6ec
Attribute metadata
gavofyork May 20, 2021
c51153f
Fixes
gavofyork May 20, 2021
5361afb
Update frame/uniques/README.md
gavofyork May 21, 2021
87ab1b4
Merge branch 'gav-uniques-attributes' into gav-uniques
gavofyork May 21, 2021
8a45594
Docs
gavofyork May 21, 2021
dad10a7
Docs
gavofyork May 21, 2021
33fd4a8
Docs
gavofyork May 21, 2021
31c6e03
Simple metadata
gavofyork May 21, 2021
092127c
Use BoundedVec
gavofyork May 24, 2021
67b190b
Merge branch 'master' of https://github.com/paritytech/substrate into…
May 24, 2021
f9f6f51
cargo run --release --features=runtime-benchmarks --manifest-path=bin…
May 24, 2021
f38e9b9
Update frame/uniques/src/lib.rs
gavofyork May 31, 2021
04c900a
Update frame/uniques/src/lib.rs
gavofyork May 31, 2021
d41c1b4
Update frame/uniques/src/lib.rs
gavofyork May 31, 2021
7353b34
Update frame/uniques/src/lib.rs
gavofyork May 31, 2021
f84688d
Update frame/uniques/src/lib.rs
gavofyork May 31, 2021
bd82d6e
Fixes
gavofyork May 31, 2021
dce127c
Merge branch 'gav-uniques' of github.com:paritytech/substrate into ga…
gavofyork May 31, 2021
ca0b97c
Update frame/uniques/README.md
gavofyork May 31, 2021
59dbd0f
Update frame/uniques/README.md
gavofyork May 31, 2021
2e36b5c
Update frame/uniques/README.md
gavofyork May 31, 2021
f50d089
Docs
gavofyork Jun 1, 2021
f240bc4
Bump
gavofyork Jun 1, 2021
765a780
Merge branch 'master' into gav-uniques
gavofyork Jun 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
class_metadata
  • Loading branch information
gavofyork committed May 17, 2021
commit ee5f32a7a328e845f8e110eef30b7b303b8d7350
173 changes: 51 additions & 122 deletions frame/uniques/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,12 +207,10 @@ pub mod pallet {
/// An asset `class` has had its attributes changed by the `Force` origin.
/// \[ class \]
AssetStatusChanged(T::ClassId),
/*
/// New metadata has been set for an asset. \[asset_id, name, symbol, decimals, is_frozen\]
MetadataSet(T::ClassId, Vec<u8>, Vec<u8>, u8, bool),
/// Metadata has been cleared for an asset. \[asset_id\]
/// New metadata has been set for an asset. \[ asset_id, name, is_frozen \]
MetadataSet(T::ClassId, Vec<u8>, bool),
/// Metadata has been cleared for an asset. \[ asset_id \]
MetadataCleared(T::ClassId),
*/
}

#[pallet::error]
Expand All @@ -237,9 +235,8 @@ pub mod pallet {
NoDelegate,
/// No approval exists that would allow the transfer.
Unapproved,
/* /// Invalid metadata given.
/// Invalid metadata given.
BadMetadata,
*/
}

#[pallet::hooks]
Expand Down Expand Up @@ -958,168 +955,100 @@ pub mod pallet {
})
}

/*
/// Set the metadata for an asset.
/// Set the metadata for an asset class.
///
/// Origin must be Signed and the sender should be the Owner of the asset `id`.
/// Origin must be Signed and the sender should be the Owner of the asset `class`.
///
/// Funds of sender are reserved according to the formula:
/// `MetadataDepositBase + MetadataDepositPerByte * (name.len + symbol.len)` taking into
/// account any already reserved funds.
///
/// - `class`: The identifier of the asset to update.
/// - `name`: The user friendly name of this asset. Limited in length by `StringLimit`.
/// - `symbol`: The exchange symbol for this asset. Limited in length by `StringLimit`.
/// - `decimals`: The number of decimals this asset uses to represent one unit.
/// - `is_frozen`: Whether the metadata should be frozen against further changes.
///
/// Emits `MetadataSet`.
///
/// Weight: `O(1)`
#[pallet::weight(T::WeightInfo::set_metadata(name.len() as u32, symbol.len() as u32))]
pub(super) fn set_metadata(
#[pallet::weight(T::WeightInfo::set_class_metadata(name.len() as u32))]
pub(super) fn set_class_metadata(
origin: OriginFor<T>,
#[pallet::compact] class: T::ClassId,
name: Vec<u8>,
symbol: Vec<u8>,
decimals: u8,
is_frozen: bool,
) -> DispatchResult {
let origin = ensure_signed(origin)?;
let maybe_check_owner = T::ForceOrigin::try_origin(origin)
.map(|_| None)
.or_else(|origin| ensure_signed(origin).map(Some))?;

ensure!(name.len() <= T::StringLimit::get() as usize, Error::<T, I>::BadMetadata);
ensure!(symbol.len() <= T::StringLimit::get() as usize, Error::<T, I>::BadMetadata);

let d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?;
ensure!(&origin == &d.owner, Error::<T, I>::NoPermission);
if let Some(check_owner) = &maybe_check_owner {
let details = Class::<T, I>::get(&class).ok_or(Error::<T, I>::Unknown)?;
ensure!(check_owner == &details.owner, Error::<T, I>::NoPermission);
}

Metadata::<T, I>::try_mutate_exists(id, |metadata| {
ensure!(
metadata.as_ref().map_or(true, |m| !m.is_frozen),
Error::<T, I>::NoPermission
);
ClassMetadataOf::<T, I>::try_mutate_exists(class, |metadata| {
ensure!(metadata.as_ref().map_or(true, |m| !m.is_frozen), Error::<T, I>::Frozen);

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());

if new_deposit > old_deposit {
T::Currency::reserve(&origin, new_deposit - old_deposit)?;
let deposit = if let Some(owner) = maybe_check_owner {
let deposit = T::MetadataDepositPerByte::get()
.saturating_mul((name.len() as u32).into())
.saturating_add(T::MetadataDepositBase::get());

if deposit > old_deposit {
T::Currency::reserve(&owner, deposit - old_deposit)?;
} else {
T::Currency::unreserve(&owner, old_deposit - deposit);
}
deposit
} else {
T::Currency::unreserve(&origin, old_deposit - new_deposit);
}

*metadata = Some(AssetMetadata {
deposit: new_deposit,
name: name.clone(),
symbol: symbol.clone(),
decimals,
is_frozen: false,
});

Self::deposit_event(Event::MetadataSet(id, name, symbol, decimals, false));
Ok(())
})
}

/// Clear the metadata for an asset.
///
/// Origin must be Signed and the sender should be the Owner of the asset `id`.
///
/// Any deposit is freed for the asset owner.
///
/// - `class`: The identifier of the asset to clear.
///
/// Emits `MetadataCleared`.
///
/// Weight: `O(1)`
#[pallet::weight(T::WeightInfo::clear_metadata())]
pub(super) fn clear_metadata(
origin: OriginFor<T>,
#[pallet::compact] class: T::ClassId,
) -> DispatchResult {
let origin = ensure_signed(origin)?;
old_deposit
};

let d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?;
ensure!(&origin == &d.owner, Error::<T, I>::NoPermission);

Metadata::<T, I>::try_mutate_exists(id, |metadata| {
let deposit = metadata.take().ok_or(Error::<T, I>::Unknown)?.deposit;
T::Currency::unreserve(&d.owner, deposit);
Self::deposit_event(Event::MetadataCleared(id));
Ok(())
})
}

/// Force the metadata for an asset to some value.
///
/// Origin must be ForceOrigin.
///
/// Any deposit is left alone.
///
/// - `class`: The identifier of the asset to update.
/// - `name`: The user friendly name of this asset. Limited in length by `StringLimit`.
/// - `symbol`: The exchange symbol for this asset. Limited in length by `StringLimit`.
/// - `decimals`: The number of decimals this asset uses to represent one unit.
///
/// Emits `MetadataSet`.
///
/// Weight: `O(N + S)` where N and S are the length of the name and symbol respectively.
#[pallet::weight(T::WeightInfo::force_set_metadata(name.len() as u32, symbol.len() as u32))]
pub(super) fn force_set_metadata(
origin: OriginFor<T>,
#[pallet::compact] class: T::ClassId,
name: Vec<u8>,
symbol: Vec<u8>,
decimals: u8,
is_frozen: bool,
) -> DispatchResult {
T::ForceOrigin::ensure_origin(origin)?;

ensure!(name.len() <= T::StringLimit::get() as usize, Error::<T, I>::BadMetadata);
ensure!(symbol.len() <= T::StringLimit::get() as usize, Error::<T, I>::BadMetadata);

ensure!(Asset::<T, I>::contains_key(id), Error::<T, I>::Unknown);
Metadata::<T, I>::try_mutate_exists(id, |metadata| {
let deposit = metadata.take().map_or(Zero::zero(), |m| m.deposit);
*metadata = Some(AssetMetadata {
*metadata = Some(ClassMetadata {
deposit,
name: name.clone(),
symbol: symbol.clone(),
decimals,
is_frozen,
});

Self::deposit_event(Event::MetadataSet(id, name, symbol, decimals, is_frozen));
Self::deposit_event(Event::MetadataSet(class, name, false));
Ok(())
})
}

/// Clear the metadata for an asset.
/// Clear the metadata for an asset class.
///
/// Origin must be ForceOrigin.
/// Origin must be Signed and the sender should be the Owner of the asset `class`.
///
/// Any deposit is returned.
/// Any deposit is freed for the asset class owner.
///
/// - `class`: The identifier of the asset to clear.
/// - `class`: The identifier of the asset class whose metadata to clear.
///
/// Emits `MetadataCleared`.
///
/// Weight: `O(1)`
#[pallet::weight(T::WeightInfo::force_clear_metadata())]
pub(super) fn force_clear_metadata(
#[pallet::weight(T::WeightInfo::clear_class_metadata())]
pub(super) fn clear_class_metadata(
origin: OriginFor<T>,
#[pallet::compact] class: T::ClassId,
) -> DispatchResult {
T::ForceOrigin::ensure_origin(origin)?;
let maybe_check_owner = T::ForceOrigin::try_origin(origin)
.map(|_| None)
.or_else(|origin| ensure_signed(origin).map(Some))?;

let d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?;
Metadata::<T, I>::try_mutate_exists(id, |metadata| {
let details = Class::<T, I>::get(&class).ok_or(Error::<T, I>::Unknown)?;
if let Some(check_owner) = &maybe_check_owner {
ensure!(check_owner == &details.owner, Error::<T, I>::NoPermission);
}

ClassMetadataOf::<T, I>::try_mutate_exists(class, |metadata| {
let deposit = metadata.take().ok_or(Error::<T, I>::Unknown)?.deposit;
T::Currency::unreserve(&d.owner, deposit);
Self::deposit_event(Event::MetadataCleared(id));
T::Currency::unreserve(&details.owner, deposit);
Self::deposit_event(Event::MetadataCleared(class));
Ok(())
})
}
*/
}
}
38 changes: 19 additions & 19 deletions frame/uniques/src/weights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,10 @@ pub trait WeightInfo {
fn cancel_approval() -> Weight;
fn force_cancel_approval() -> Weight;
fn force_asset_status() -> Weight;
/* fn set_metadata(n: u32, s: u32, ) -> Weight;
fn clear_metadata() -> Weight;
fn force_set_metadata(n: u32, s: u32, ) -> Weight;
fn force_clear_metadata() -> Weight;
*/
fn set_class_metadata(n: u32, ) -> Weight;
fn clear_class_metadata() -> Weight;
fn set_instance_metadata(n: u32, i: u32, ) -> Weight;
fn clear_instance_metadata() -> Weight;
}

/// Weights for pallet_assets using the Substrate node and recommended hardware.
Expand Down Expand Up @@ -170,30 +169,31 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
/* fn set_metadata(_n: u32, s: u32, ) -> Weight {
fn set_class_metadata(n: u32, ) -> Weight {
(53_367_000 as Weight)
// Standard Error: 0
.saturating_add((8_000 as Weight).saturating_mul(s as Weight))
.saturating_add((8_000 as Weight).saturating_mul(n as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn clear_metadata() -> Weight {
fn clear_class_metadata() -> Weight {
(51_721_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn force_set_metadata(_n: u32, s: u32, ) -> Weight {
fn set_instance_metadata(n: u32, i: u32, ) -> Weight {
(27_117_000 as Weight)
// Standard Error: 0
.saturating_add((5_000 as Weight).saturating_mul(s as Weight))
.saturating_add((5_000 as Weight).saturating_mul(n as Weight))
.saturating_add((5_000 as Weight).saturating_mul(i as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn force_clear_metadata() -> Weight {
fn clear_instance_metadata() -> Weight {
(51_598_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}*/
}
}

// For backwards compatibility and tests
Expand Down Expand Up @@ -296,29 +296,29 @@ impl WeightInfo for () {
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
/* fn set_metadata(_n: u32, s: u32, ) -> Weight {
fn set_class_metadata(n: u32, ) -> Weight {
(53_367_000 as Weight)
// Standard Error: 0
.saturating_add((8_000 as Weight).saturating_mul(s as Weight))
.saturating_add((8_000 as Weight).saturating_mul(n as Weight))
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn clear_metadata() -> Weight {
fn clear_class_metadata() -> Weight {
(51_721_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn force_set_metadata(_n: u32, s: u32, ) -> Weight {
fn set_instance_metadata(n: u32, i: u32, ) -> Weight {
(27_117_000 as Weight)
// Standard Error: 0
.saturating_add((5_000 as Weight).saturating_mul(s as Weight))
.saturating_add((5_000 as Weight).saturating_mul(n as Weight))
.saturating_add((5_000 as Weight).saturating_mul(i as Weight))
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn force_clear_metadata() -> Weight {
fn clear_instance_metadata() -> Weight {
(51_598_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
*/
}