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
28sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }28sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }
29sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }29sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }
30sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }30sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }
31derivative = { version = "2.2.0", features = ["use_core"] }
3132
32[features]33[features]
33default = ["std"]34default = ["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
494 <Pallet<T>>::create_item(494 <Pallet<T>>::create_item(
495 self,495 self,
496 &caller,496 &caller,
497 CreateItemData::<T> {497 CreateItemData::<T::CrossAccountId> {
498 users,498 users,
499 properties: CollectionPropertiesVec::default(),499 properties: CollectionPropertiesVec::default(),
500 },500 },
560 <Pallet<T>>::create_item(560 <Pallet<T>>::create_item(
561 self,561 self,
562 &caller,562 &caller,
563 CreateItemData::<T> { users, properties },563 CreateItemData::<T::CrossAccountId> { users, properties },
564 &budget,564 &budget,
565 )565 )
566 .map_err(dispatch_to_evm::<T>)?;566 .map_err(dispatch_to_evm::<T>)?;
717 .collect::<BTreeMap<_, _>>()717 .collect::<BTreeMap<_, _>>()
718 .try_into()718 .try_into()
719 .unwrap();719 .unwrap();
720 let create_item_data = CreateItemData::<T> {720 let create_item_data = CreateItemData::<T::CrossAccountId> {
721 users,721 users,
722 properties: CollectionPropertiesVec::default(),722 properties: CollectionPropertiesVec::default(),
723 };723 };
777 })777 })
778 .map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;778 .map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;
779779
780 let create_item_data = CreateItemData::<T> {780 let create_item_data = CreateItemData::<T::CrossAccountId> {
781 users: users.clone(),781 users: users.clone(),
782 properties,782 properties,
783 };783 };
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
94use core::ops::Deref;94use core::ops::Deref;
95use evm_coder::ToLog;95use evm_coder::ToLog;
96use frame_support::{BoundedVec, ensure, fail, storage::with_transaction, transactional};96use frame_support::{
97 BoundedVec, ensure, fail, storage::with_transaction, transactional, pallet_prelude::ConstU32,
98};
97use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};99use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
98use pallet_evm_coder_substrate::WithRecorder;100use pallet_evm_coder_substrate::WithRecorder;
106use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};108use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};
107use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};109use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
108use up_data_structs::{110use up_data_structs::{
109 AccessMode, budget::Budget, CollectionId, CreateCollectionData, CreateRefungibleExData,111 AccessMode, budget::Budget, CollectionId, CreateCollectionData, CustomDataLimit,
110 CustomDataLimit, mapping::TokenAddressMapping, MAX_REFUNGIBLE_PIECES, TokenId, Property,112 mapping::TokenAddressMapping, MAX_REFUNGIBLE_PIECES, MAX_ITEMS_PER_BATCH, TokenId, Property,
111 PropertyKey, PropertyKeyPermission, PropertyPermission, PropertyScope, PropertyValue,113 PropertyKey, PropertyKeyPermission, PropertyPermission, PropertyScope, PropertyValue,
112 TrySetProperty,114 TrySetProperty, CollectionPropertiesVec,
113};115};
116use frame_support::BoundedBTreeMap;
117use derivative::Derivative;
114118
115pub use pallet::*;119pub use pallet::*;
116#[cfg(feature = "runtime-benchmarks")]120#[cfg(feature = "runtime-benchmarks")]
120pub mod erc_token;124pub mod erc_token;
121pub mod weights;125pub mod weights;
122126
127#[derive(Derivative, Clone)]
123pub type CreateItemData<T> =128pub struct CreateItemData<CrossAccountId> {
129 #[derivative(Debug(format_with = "bounded::map_debug"))]
124 CreateRefungibleExData<<T as pallet_evm::account::Config>::CrossAccountId>;130 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,
131 #[derivative(Debug(format_with = "bounded::vec_debug"))]
132 pub properties: CollectionPropertiesVec,
133}
125pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;134pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
126135
127/// Token data, stored independently from other data used to describe it136/// Token data, stored independently from other data used to describe it
873 pub fn create_multiple_items(882 pub fn create_multiple_items(
874 collection: &RefungibleHandle<T>,883 collection: &RefungibleHandle<T>,
875 sender: &T::CrossAccountId,884 sender: &T::CrossAccountId,
876 data: Vec<CreateItemData<T>>,885 data: Vec<CreateItemData<T::CrossAccountId>>,
877 nesting_budget: &dyn Budget,886 nesting_budget: &dyn Budget,
878 ) -> DispatchResult {887 ) -> DispatchResult {
879 if !collection.is_owner_or_admin(sender) {888 if !collection.is_owner_or_admin(sender) {
1213 pub fn create_item(1222 pub fn create_item(
1214 collection: &RefungibleHandle<T>,1223 collection: &RefungibleHandle<T>,
1215 sender: &T::CrossAccountId,1224 sender: &T::CrossAccountId,
1216 data: CreateItemData<T>,1225 data: CreateItemData<T::CrossAccountId>,
1217 nesting_budget: &dyn Budget,1226 nesting_budget: &dyn Budget,
1218 ) -> DispatchResult {1227 ) -> DispatchResult {
1219 Self::create_multiple_items(collection, sender, vec![data], nesting_budget)1228 Self::create_multiple_items(collection, sender, vec![data], nesting_budget)
modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
826/// Extended data for create ReFungible item.826/// Extended data for create ReFungible item.
827#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]827#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]
828#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]828#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]
829pub struct CreateRefungibleExData<CrossAccountId> {829pub struct CreateRefungibleExMultipleOwners<CrossAccountId> {
830 #[derivative(Debug(format_with = "bounded::map_debug"))]830 #[derivative(Debug(format_with = "bounded::map_debug"))]
831 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,831 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,
832 #[derivative(Debug(format_with = "bounded::vec_debug"))]832 #[derivative(Debug(format_with = "bounded::vec_debug"))]
833 pub properties: CollectionPropertiesVec,833 pub properties: CollectionPropertiesVec,
834}834}
835
836/// Extended data for create ReFungible item.
837#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]
838#[derivative(Debug(bound = "CrossAccountId: fmt::Debug"))]
839pub struct CreateRefungibleExSingleOwner<CrossAccountId> {
840 pub user: CrossAccountId,
841 pub pieces: u128,
842 #[derivative(Debug(format_with = "bounded::vec_debug"))]
843 pub properties: CollectionPropertiesVec,
844}
835845
836/// Unified extended data for creating item.846/// Unified extended data for creating item.
837#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]847#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]
853 /// many tokens, each may have only one owner863 /// many tokens, each may have only one owner
854 RefungibleMultipleItems(864 RefungibleMultipleItems(
855 #[derivative(Debug(format_with = "bounded::vec_debug"))]865 #[derivative(Debug(format_with = "bounded::vec_debug"))]
856 BoundedVec<CreateRefungibleExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,866 BoundedVec<CreateRefungibleExSingleOwner<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,
857 ),867 ),
858868
859 /// Extended data for create ReFungible item in case of869 /// Extended data for create ReFungible item in case of
860 /// single token, which may have many owners870 /// single token, which may have many owners
861 RefungibleMultipleOwners(CreateRefungibleExData<CrossAccountId>),871 RefungibleMultipleOwners(CreateRefungibleExMultipleOwners<CrossAccountId>),
862}872}
863873
864impl From<CreateNftData> for CreateItemData {874impl From<CreateNftData> for CreateItemData {