git.delta.rocks / unique-network / refs/commits / ec332a0b04f6

difftreelog

refactor(pallet-refungible) disallow invalid bulk mints

Yaroslav Bolyukin2022-08-04parent: #b7c1009.patch.diff
in: master
`create_multiple_items_ex` was allowing invalid (that will be always
rejected at runtime level) refungible mint extrinsics, by passing
multiple users into `RefungibleMultipleItems` call.

5 files changed

modifiedpallets/refungible/Cargo.tomldiffbeforeafterboth
--- a/pallets/refungible/Cargo.toml
+++ b/pallets/refungible/Cargo.toml
@@ -28,6 +28,7 @@
 sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }
 sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }
 sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }
+derivative = { version = "2.2.0", features = ["use_core"] }
 
 [features]
 default = ["std"]
modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
19use sp_std::collections::btree_map::BTreeMap;19use sp_std::collections::btree_map::BTreeMap;
20use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, traits::Get};20use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, traits::Get};
21use up_data_structs::{21use up_data_structs::{
22 CollectionId, TokenId, CreateItemExData, CreateRefungibleExData, budget::Budget, Property,22 CollectionId, TokenId, CreateItemExData, budget::Budget, Property, PropertyKey, PropertyValue,
23 PropertyKey, PropertyValue, PropertyKeyPermission, CreateItemData, CollectionPropertiesVec,23 PropertyKeyPermission, CollectionPropertiesVec, CreateRefungibleExMultipleOwners,
24 CreateRefungibleExSingleOwner,
24};25};
25use pallet_common::{26use pallet_common::{
26 CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight,27 CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight,
3233
33use crate::{34use crate::{
34 AccountBalance, Allowance, Balance, Config, Error, Owned, Pallet, RefungibleHandle,35 AccountBalance, Allowance, Balance, Config, Error, Owned, Pallet, RefungibleHandle,
35 SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted, TotalSupply,36 SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted, TotalSupply, CreateItemData,
36};37};
3738
38macro_rules! max_weight_of {39macro_rules! max_weight_of {
58 <SelfWeightOf<T>>::create_item()59 <SelfWeightOf<T>>::create_item()
59 }60 }
6061
61 fn create_multiple_items(data: &[CreateItemData]) -> Weight {62 fn create_multiple_items(data: &[up_data_structs::CreateItemData]) -> Weight {
62 <SelfWeightOf<T>>::create_multiple_items(data.len() as u32).saturating_add(63 <SelfWeightOf<T>>::create_multiple_items(data.len() as u32).saturating_add(
63 data.iter()64 data.iter()
64 .map(|data| match data {65 .map(|data| match data {
65 CreateItemData::ReFungible(rft_data) => {66 up_data_structs::CreateItemData::ReFungible(rft_data) => {
66 properties_weight::<T>(&rft_data.properties)67 properties_weight::<T>(&rft_data.properties)
67 }68 }
68 _ => 0,69 _ => 0,
152fn map_create_data<T: Config>(153fn map_create_data<T: Config>(
153 data: up_data_structs::CreateItemData,154 data: up_data_structs::CreateItemData,
154 to: &T::CrossAccountId,155 to: &T::CrossAccountId,
155) -> Result<CreateRefungibleExData<T::CrossAccountId>, DispatchError> {156) -> Result<CreateItemData<T::CrossAccountId>, DispatchError> {
156 match data {157 match data {
157 up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateRefungibleExData {158 up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateItemData {
158 users: {159 users: {
159 let mut out = BTreeMap::new();160 let mut out = BTreeMap::new();
160 out.insert(to.clone(), data.pieces);161 out.insert(to.clone(), data.pieces);
214 ) -> DispatchResultWithPostInfo {215 ) -> DispatchResultWithPostInfo {
215 let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);216 let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);
216 let data = match data {217 let data = match data {
217 CreateItemExData::RefungibleMultipleOwners(r) => vec![r],218 CreateItemExData::RefungibleMultipleOwners(CreateRefungibleExMultipleOwners {
219 users,
220 properties,
221 }) => vec![CreateItemData { users, properties }],
218 CreateItemExData::RefungibleMultipleItems(r)222 CreateItemExData::RefungibleMultipleItems(r) => r
223 .into_inner()
224 .into_iter()
219 if r.iter().all(|i| i.users.len() == 1) =>225 .map(
220 {226 |CreateRefungibleExSingleOwner {
227 user,
228 pieces,
229 properties,
230 }| CreateItemData {
231 users: BTreeMap::from([(user, pieces)])
232 .try_into()
233 .expect("limit >= 1"),
234 properties,
235 },
236 )
221 r.into_inner()237 .collect(),
222 }
223 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),238 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),
224 };239 };
225240
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -494,7 +494,7 @@
 		<Pallet<T>>::create_item(
 			self,
 			&caller,
-			CreateItemData::<T> {
+			CreateItemData::<T::CrossAccountId> {
 				users,
 				properties: CollectionPropertiesVec::default(),
 			},
@@ -560,7 +560,7 @@
 		<Pallet<T>>::create_item(
 			self,
 			&caller,
-			CreateItemData::<T> { users, properties },
+			CreateItemData::<T::CrossAccountId> { users, properties },
 			&budget,
 		)
 		.map_err(dispatch_to_evm::<T>)?;
@@ -717,7 +717,7 @@
 			.collect::<BTreeMap<_, _>>()
 			.try_into()
 			.unwrap();
-		let create_item_data = CreateItemData::<T> {
+		let create_item_data = CreateItemData::<T::CrossAccountId> {
 			users,
 			properties: CollectionPropertiesVec::default(),
 		};
@@ -777,7 +777,7 @@
 				})
 				.map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;
 
-			let create_item_data = CreateItemData::<T> {
+			let create_item_data = CreateItemData::<T::CrossAccountId> {
 				users: users.clone(),
 				properties,
 			};
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -93,7 +93,9 @@
 use codec::{Encode, Decode, MaxEncodedLen};
 use core::ops::Deref;
 use evm_coder::ToLog;
-use frame_support::{BoundedVec, ensure, fail, storage::with_transaction, transactional};
+use frame_support::{
+	BoundedVec, ensure, fail, storage::with_transaction, transactional, pallet_prelude::ConstU32,
+};
 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
 use pallet_evm_coder_substrate::WithRecorder;
 use pallet_common::{
@@ -106,11 +108,13 @@
 use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};
 use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
 use up_data_structs::{
-	AccessMode, budget::Budget, CollectionId, CreateCollectionData, CreateRefungibleExData,
-	CustomDataLimit, mapping::TokenAddressMapping, MAX_REFUNGIBLE_PIECES, TokenId, Property,
+	AccessMode, budget::Budget, CollectionId, CreateCollectionData, CustomDataLimit,
+	mapping::TokenAddressMapping, MAX_REFUNGIBLE_PIECES, MAX_ITEMS_PER_BATCH, TokenId, Property,
 	PropertyKey, PropertyKeyPermission, PropertyPermission, PropertyScope, PropertyValue,
-	TrySetProperty,
+	TrySetProperty, CollectionPropertiesVec,
 };
+use frame_support::BoundedBTreeMap;
+use derivative::Derivative;
 
 pub use pallet::*;
 #[cfg(feature = "runtime-benchmarks")]
@@ -120,8 +124,13 @@
 pub mod erc_token;
 pub mod weights;
 
-pub type CreateItemData<T> =
-	CreateRefungibleExData<<T as pallet_evm::account::Config>::CrossAccountId>;
+#[derive(Derivative, Clone)]
+pub struct CreateItemData<CrossAccountId> {
+	#[derivative(Debug(format_with = "bounded::map_debug"))]
+	pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,
+	#[derivative(Debug(format_with = "bounded::vec_debug"))]
+	pub properties: CollectionPropertiesVec,
+}
 pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
 
 /// Token data, stored independently from other data used to describe it
@@ -873,7 +882,7 @@
 	pub fn create_multiple_items(
 		collection: &RefungibleHandle<T>,
 		sender: &T::CrossAccountId,
-		data: Vec<CreateItemData<T>>,
+		data: Vec<CreateItemData<T::CrossAccountId>>,
 		nesting_budget: &dyn Budget,
 	) -> DispatchResult {
 		if !collection.is_owner_or_admin(sender) {
@@ -1213,7 +1222,7 @@
 	pub fn create_item(
 		collection: &RefungibleHandle<T>,
 		sender: &T::CrossAccountId,
-		data: CreateItemData<T>,
+		data: CreateItemData<T::CrossAccountId>,
 		nesting_budget: &dyn Budget,
 	) -> DispatchResult {
 		Self::create_multiple_items(collection, sender, vec![data], nesting_budget)
modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -826,13 +826,23 @@
 /// Extended data for create ReFungible item.
 #[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]
 #[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]
-pub struct CreateRefungibleExData<CrossAccountId> {
+pub struct CreateRefungibleExMultipleOwners<CrossAccountId> {
 	#[derivative(Debug(format_with = "bounded::map_debug"))]
 	pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,
 	#[derivative(Debug(format_with = "bounded::vec_debug"))]
 	pub properties: CollectionPropertiesVec,
 }
 
+/// Extended data for create ReFungible item.
+#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]
+#[derivative(Debug(bound = "CrossAccountId: fmt::Debug"))]
+pub struct CreateRefungibleExSingleOwner<CrossAccountId> {
+	pub user: CrossAccountId,
+	pub pieces: u128,
+	#[derivative(Debug(format_with = "bounded::vec_debug"))]
+	pub properties: CollectionPropertiesVec,
+}
+
 /// Unified extended data for creating item.
 #[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]
 #[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]
@@ -853,12 +863,12 @@
 	/// many tokens, each may have only one owner
 	RefungibleMultipleItems(
 		#[derivative(Debug(format_with = "bounded::vec_debug"))]
-		BoundedVec<CreateRefungibleExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,
+		BoundedVec<CreateRefungibleExSingleOwner<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,
 	),
 
 	/// Extended data for create ReFungible item in case of
 	/// single token, which may have many owners
-	RefungibleMultipleOwners(CreateRefungibleExData<CrossAccountId>),
+	RefungibleMultipleOwners(CreateRefungibleExMultipleOwners<CrossAccountId>),
 }
 
 impl From<CreateNftData> for CreateItemData {