Skip to content

Added BoundedVec and MaxEncodedLen #496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
50 changes: 37 additions & 13 deletions nft/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,26 @@
#![allow(clippy::unused_unit)]

use codec::{Decode, Encode};
use frame_support::{ensure, pallet_prelude::*, Parameter};
use frame_support::{
ensure,
pallet_prelude::*,
traits::{Get, MaxEncodedLen},
BoundedVec, Parameter,
};
use sp_runtime::{
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedSub, MaybeSerializeDeserialize, Member, One, Zero},
DispatchError, DispatchResult, RuntimeDebug,
};
use sp_std::vec::Vec;
use sp_std::{convert::TryInto, vec::Vec};

mod mock;
mod tests;

/// Class info
#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug)]
pub struct ClassInfo<TokenId, AccountId, Data> {
#[derive(Encode, Decode, Clone, Eq, PartialEq, MaxEncodedLen, RuntimeDebug)]
pub struct ClassInfo<TokenId, AccountId, Data, ClassMetadataOf> {
/// Class metadata
pub metadata: Vec<u8>,
pub metadata: ClassMetadataOf,
/// Total issuance for the class
pub total_issuance: TokenId,
/// Class owner
Expand All @@ -46,10 +51,10 @@ pub struct ClassInfo<TokenId, AccountId, Data> {
}

/// Token info
#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug)]
pub struct TokenInfo<AccountId, Data> {
#[derive(Encode, Decode, Clone, Eq, PartialEq, MaxEncodedLen, RuntimeDebug)]
pub struct TokenInfo<AccountId, Data, TokenMetadataOf> {
/// Token metadata
pub metadata: Vec<u8>,
pub metadata: TokenMetadataOf,
/// Token owner
pub owner: AccountId,
/// Token Properties
Expand All @@ -72,11 +77,22 @@ pub mod module {
type ClassData: Parameter + Member + MaybeSerializeDeserialize;
/// The token properties type
type TokenData: Parameter + Member + MaybeSerializeDeserialize;
/// The maximum size of a class's metadata
type MaxClassMetadata: Get<u32>;
/// The maximum size of a token's metadata
type MaxTokenMetadata: Get<u32>;
}

pub type ClassInfoOf<T> =
ClassInfo<<T as Config>::TokenId, <T as frame_system::Config>::AccountId, <T as Config>::ClassData>;
pub type TokenInfoOf<T> = TokenInfo<<T as frame_system::Config>::AccountId, <T as Config>::TokenData>;
pub type ClassMetadataOf<T> = BoundedVec<u8, <T as Config>::MaxClassMetadata>;
pub type TokenMetadataOf<T> = BoundedVec<u8, <T as Config>::MaxTokenMetadata>;
pub type ClassInfoOf<T> = ClassInfo<
<T as Config>::TokenId,
<T as frame_system::Config>::AccountId,
<T as Config>::ClassData,
ClassMetadataOf<T>,
>;
pub type TokenInfoOf<T> =
TokenInfo<<T as frame_system::Config>::AccountId, <T as Config>::TokenData, TokenMetadataOf<T>>;

pub type GenesisTokenData<T> = (
<T as frame_system::Config>::AccountId, // Token owner
Expand Down Expand Up @@ -108,6 +124,8 @@ pub mod module {
/// Can not destroy class
/// Total issuance is not 0
CannotDestroyClass,
/// Failed because the Maximum amount of metadata was exceeded
MaxMetadataExceeded,
}

/// Next available class ID.
Expand Down Expand Up @@ -184,14 +202,17 @@ impl<T: Config> Pallet<T> {
metadata: Vec<u8>,
data: T::ClassData,
) -> Result<T::ClassId, DispatchError> {
let bounded_metadata: BoundedVec<u8, T::MaxClassMetadata> =
metadata.try_into().map_err(|_| Error::<T>::MaxMetadataExceeded)?;

let class_id = NextClassId::<T>::try_mutate(|id| -> Result<T::ClassId, DispatchError> {
let current_id = *id;
*id = id.checked_add(&One::one()).ok_or(Error::<T>::NoAvailableClassId)?;
Ok(current_id)
})?;

let info = ClassInfo {
metadata,
metadata: bounded_metadata,
total_issuance: Default::default(),
owner: owner.clone(),
data,
Expand Down Expand Up @@ -228,6 +249,9 @@ impl<T: Config> Pallet<T> {
data: T::TokenData,
) -> Result<T::TokenId, DispatchError> {
NextTokenId::<T>::try_mutate(class_id, |id| -> Result<T::TokenId, DispatchError> {
let bounded_metadata: BoundedVec<u8, T::MaxTokenMetadata> =
metadata.try_into().map_err(|_| Error::<T>::MaxMetadataExceeded)?;

let token_id = *id;
*id = id.checked_add(&One::one()).ok_or(Error::<T>::NoAvailableTokenId)?;

Expand All @@ -241,7 +265,7 @@ impl<T: Config> Pallet<T> {
})?;

let token_info = TokenInfo {
metadata,
metadata: bounded_metadata,
owner: owner.clone(),
data,
};
Expand Down
7 changes: 7 additions & 0 deletions nft/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,18 @@ impl frame_system::Config for Runtime {
type OnSetCode = ();
}

parameter_types! {
pub const MaxClassMetadata: u32 = 1;
pub const MaxTokenMetadata: u32 = 1;
}

impl Config for Runtime {
type ClassId = u64;
type TokenId = u64;
type ClassData = ();
type TokenData = ();
type MaxClassMetadata = MaxClassMetadata;
type MaxTokenMetadata = MaxTokenMetadata;
}

type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Runtime>;
Expand Down
15 changes: 15 additions & 0 deletions nft/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,18 @@ fn destroy_class_should_fail() {
assert_eq!(Classes::<Runtime>::contains_key(CLASS_ID), false);
});
}

#[test]
fn exceeding_max_metadata_should_fail() {
ExtBuilder::default().build().execute_with(|| {
assert_noop!(
NonFungibleTokenModule::create_class(&ALICE, vec![1, 2], ()),
Error::<Runtime>::MaxMetadataExceeded
);
assert_ok!(NonFungibleTokenModule::create_class(&ALICE, vec![1], ()));
assert_noop!(
NonFungibleTokenModule::mint(&BOB, CLASS_ID, vec![1, 2], ()),
Error::<Runtime>::MaxMetadataExceeded
);
});
}
4 changes: 2 additions & 2 deletions rewards/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mod mock;
mod tests;

use codec::{FullCodec, HasCompact};
use frame_support::pallet_prelude::*;
use frame_support::{pallet_prelude::*, traits::MaxEncodedLen};
use orml_traits::RewardHandler;
use sp_runtime::{
traits::{AtLeast32BitUnsigned, MaybeSerializeDeserialize, Member, Saturating, Zero},
Expand All @@ -17,7 +17,7 @@ use sp_std::{
};

/// The Reward Pool Info.
#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, Default)]
#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, Default, MaxEncodedLen)]
pub struct PoolInfo<Share: HasCompact, Balance: HasCompact> {
/// Total shares amount
#[codec(compact)]
Expand Down