difftreelog
misk: generalize 2 methods
in: master
3 files changed
pallets/common/src/lib.rsdiffbeforeafterboth66 ensure,66 ensure,67 traits::{Imbalance, Get, Currency, WithdrawReasons, ExistenceRequirement},67 traits::{Imbalance, Get, Currency, WithdrawReasons, ExistenceRequirement},68 dispatch::Pays,68 dispatch::Pays,69 transactional,69 transactional, fail,70};70};71use pallet_evm::GasWeightMapping;71use pallet_evm::GasWeightMapping;72use up_data_structs::{72use up_data_structs::{73 AccessMode,73 COLLECTION_NUMBER_LIMIT,74 COLLECTION_NUMBER_LIMIT,74 Collection,75 Collection,75 RpcCollection,76 RpcCollection,125use sp_core::H160;126use sp_core::H160;126use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};127use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};128129use crate::erc::CollectionHelpersEvents;127#[cfg(feature = "runtime-benchmarks")]130#[cfg(feature = "runtime-benchmarks")]128pub mod benchmarking;131pub mod benchmarking;129pub mod dispatch;132pub mod dispatch;1264 Ok(())1267 Ok(())1265 }1268 }12691270 /// A batch operation to add, edit or remove properties for a token.1271 /// It sets or removes a token's properties according to1272 /// `properties_updates` contents:1273 /// * sets a property under the <key> with the value provided `(<key>, Some(<value>))`1274 /// * removes a property under the <key> if the value is `None` `(<key>, None)`.1275 ///1276 /// - `nesting_budget`: Limit for searching parents in-depth to check ownership.1277 /// - `is_token_create`: Indicates that method is called during token initialization.1278 /// Allows to bypass ownership check.1279 ///1280 /// All affected properties should have `mutable` permission1281 /// to be **deleted** or to be **set more than once**,1282 /// and the sender should have permission to edit those properties.1283 ///1284 /// This function fires an event for each property change.1285 /// In case of an error, all the changes (including the events) will be reverted1286 /// since the function is transactional.1287 pub fn modify_token_properties(1288 collection: &CollectionHandle<T>,1289 sender: &T::CrossAccountId,1290 token_id: TokenId,1291 properties_updates: impl Iterator<Item = (PropertyKey, Option<PropertyValue>)>,1292 is_token_create: bool,1293 mut stored_properties: Properties,1294 is_token_owner: impl Fn() -> Result<bool, DispatchError>,1295 set_token_properties: impl FnOnce(Properties),1296 ) -> DispatchResult {1297 let is_collection_admin = collection.is_owner_or_admin(sender);1298 let permissions = Self::property_permissions(collection.id);12991300 for (key, value) in properties_updates {1301 let permission = permissions1302 .get(&key)1303 .cloned()1304 .unwrap_or_else(PropertyPermission::none);13051306 let is_property_exists = stored_properties.get(&key).is_some();13071308 match permission {1309 PropertyPermission { mutable: false, .. } if is_property_exists => {1310 return Err(<Error<T>>::NoPermission.into());1311 }13121313 PropertyPermission {1314 collection_admin,1315 token_owner,1316 ..1317 } => {1318 //TODO: investigate threats during public minting.1319 let is_token_create =1320 is_token_create && (collection_admin || token_owner) && value.is_some();1321 if !(is_token_create1322 || (collection_admin && is_collection_admin)1323 || (token_owner && is_token_owner()?))1324 {1325 fail!(<Error<T>>::NoPermission);1326 }1327 }1328 }13291330 match value {1331 Some(value) => {1332 stored_properties1333 .try_set(key.clone(), value)1334 .map_err(<Error<T>>::from)?;13351336 Self::deposit_event(Event::TokenPropertySet(collection.id, token_id, key));1337 }1338 None => {1339 stored_properties.remove(&key).map_err(<Error<T>>::from)?;13401341 Self::deposit_event(Event::TokenPropertyDeleted(collection.id, token_id, key));1342 }1343 }13441345 <PalletEvm<T>>::deposit_log(1346 CollectionHelpersEvents::TokenChanged {1347 collection_id: eth::collection_id_to_address(collection.id),1348 token_id: token_id.into(),1349 }1350 .to_log(T::ContractAddress::get()),1351 );1352 }13531354 set_token_properties(stored_properties);13551356 Ok(())1357 }13581359 /// Sets or unsets the approval of a given operator.1360 ///1361 /// The `operator` is allowed to transfer all token pieces of the `owner` on their behalf.1362 /// - `owner`: Token owner1363 /// - `operator`: Operator1364 /// - `approve`: Should operator status be granted or revoked?1365 pub fn set_allowance_for_all(1366 collection: &CollectionHandle<T>,1367 owner: &T::CrossAccountId,1368 operator: &T::CrossAccountId,1369 approve: bool,1370 set_allowance: impl FnOnce(),1371 log: evm_coder::ethereum::Log,1372 ) -> DispatchResult {1373 if collection.permissions.access() == AccessMode::AllowList {1374 collection.check_allowlist(owner)?;1375 collection.check_allowlist(operator)?;1376 }13771378 Self::ensure_correct_receiver(operator)?;13791380 set_allowance();13811382 <PalletEvm<T>>::deposit_log(log);1383 Self::deposit_event(Event::ApprovedForAll(1384 collection.id,1385 owner.clone(),1386 operator.clone(),1387 approve,1388 ));1389 Ok(())1390 }126613911267 /// Set collection property.1392 /// Set collection property.1268 ///1393 ///pallets/nonfungible/src/lib.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -101,18 +101,18 @@
};
use up_data_structs::{
AccessMode, CollectionId, CollectionFlags, CustomDataLimit, TokenId, CreateCollectionData,
- CreateNftExData, mapping::TokenAddressMapping, budget::Budget, Property, PropertyPermission,
- PropertyKey, PropertyValue, PropertyKeyPermission, Properties, PropertyScope, TrySetProperty,
- TokenChild, AuxPropertyValue, PropertiesPermissionMap,
+ CreateNftExData, mapping::TokenAddressMapping, budget::Budget, Property, PropertyKey,
+ PropertyValue, PropertyKeyPermission, Properties, PropertyScope, TrySetProperty, TokenChild,
+ AuxPropertyValue, PropertiesPermissionMap,
};
use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
use pallet_common::{
Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, CollectionHandle,
- eth::collection_id_to_address, erc::CollectionHelpersEvents,
+ eth::collection_id_to_address,
};
use pallet_structure::{Pallet as PalletStructure, Error as StructureError};
use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
-use sp_core::{H160, Get};
+use sp_core::H160;
use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};
use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
use core::ops::Deref;
@@ -578,10 +578,6 @@
}
/// A batch operation to add, edit or remove properties for a token.
- /// It sets or removes a token's properties according to
- /// `properties_updates` contents:
- /// * sets a property under the <key> with the value provided `(<key>, Some(<value>))`
- /// * removes a property under the <key> if the value is `None` `(<key>, None)`.
///
/// - `nesting_budget`: Limit for searching parents in-depth to check ownership.
/// - `is_token_create`: Indicates that method is called during token initialization.
@@ -603,97 +599,30 @@
is_token_create: bool,
nesting_budget: &dyn Budget,
) -> DispatchResult {
- let mut collection_admin_status = None;
- let mut token_owner_result = None;
-
- let mut is_collection_admin =
- || *collection_admin_status.get_or_insert_with(|| collection.is_owner_or_admin(sender));
+ let is_token_owner = || {
+ let is_owned = <PalletStructure<T>>::check_indirectly_owned(
+ sender.clone(),
+ collection.id,
+ token_id,
+ None,
+ nesting_budget,
+ )?;
- let mut is_token_owner = || {
- *token_owner_result.get_or_insert_with(|| -> Result<bool, DispatchError> {
- let is_owned = <PalletStructure<T>>::check_indirectly_owned(
- sender.clone(),
- collection.id,
- token_id,
- None,
- nesting_budget,
- )?;
-
- Ok(is_owned)
- })
+ Ok(is_owned)
};
-
- let mut stored_properties = <TokenProperties<T>>::get((collection.id, token_id));
- let permissions = <PalletCommon<T>>::property_permissions(collection.id);
-
- for (key, value) in properties_updates {
- let permission = permissions
- .get(&key)
- .cloned()
- .unwrap_or_else(PropertyPermission::none);
-
- let is_property_exists = stored_properties.get(&key).is_some();
-
- match permission {
- PropertyPermission { mutable: false, .. } if is_property_exists => {
- return Err(<CommonError<T>>::NoPermission.into());
- }
-
- PropertyPermission {
- collection_admin,
- token_owner,
- ..
- } => {
- //TODO: investigate threats during public minting.
- if is_token_create && (collection_admin || token_owner) && value.is_some() {
- // Pass
- } else if collection_admin && is_collection_admin() {
- // Pass
- } else if token_owner && is_token_owner()? {
- // Pass
- } else {
- fail!(<CommonError<T>>::NoPermission);
- }
- }
- }
- match value {
- Some(value) => {
- stored_properties
- .try_set(key.clone(), value)
- .map_err(<CommonError<T>>::from)?;
-
- <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertySet(
- collection.id,
- token_id,
- key,
- ));
- }
- None => {
- stored_properties
- .remove(&key)
- .map_err(<CommonError<T>>::from)?;
-
- <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertyDeleted(
- collection.id,
- token_id,
- key,
- ));
- }
- }
-
- <PalletEvm<T>>::deposit_log(
- CollectionHelpersEvents::TokenChanged {
- collection_id: collection_id_to_address(collection.id),
- token_id: token_id.into(),
- }
- .to_log(T::ContractAddress::get()),
- );
- }
-
- <TokenProperties<T>>::set((collection.id, token_id), stored_properties);
+ let stored_properties = <TokenProperties<T>>::get((collection.id, token_id));
- Ok(())
+ <PalletCommon<T>>::modify_token_properties(
+ collection,
+ sender,
+ token_id,
+ properties_updates,
+ is_token_create,
+ stored_properties,
+ is_token_owner,
+ |properties| <TokenProperties<T>>::set((collection.id, token_id), properties),
+ )
}
/// Batch operation to add or edit properties for the token
@@ -1418,31 +1347,19 @@
operator: &T::CrossAccountId,
approve: bool,
) -> DispatchResult {
- if collection.permissions.access() == AccessMode::AllowList {
- collection.check_allowlist(owner)?;
- collection.check_allowlist(operator)?;
- }
-
- <PalletCommon<T>>::ensure_correct_receiver(operator)?;
-
- // =========
-
- <CollectionAllowance<T>>::insert((collection.id, owner, operator), approve);
- <PalletEvm<T>>::deposit_log(
+ <PalletCommon<T>>::set_allowance_for_all(
+ collection,
+ owner,
+ operator,
+ approve,
+ || <CollectionAllowance<T>>::insert((collection.id, owner, operator), approve),
ERC721Events::ApprovalForAll {
owner: *owner.as_eth(),
operator: *operator.as_eth(),
approved: approve,
}
.to_log(collection_id_to_address(collection.id)),
- );
- <PalletCommon<T>>::deposit_event(CommonEvent::ApprovedForAll(
- collection.id,
- owner.clone(),
- operator.clone(),
- approve,
- ));
- Ok(())
+ )
}
/// Tells whether the given `owner` approves the `operator`.
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -92,22 +92,22 @@
use core::ops::Deref;
use evm_coder::ToLog;
-use frame_support::{ensure, fail, storage::with_transaction, transactional};
+use frame_support::{ensure, storage::with_transaction, transactional};
use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
use pallet_evm_coder_substrate::WithRecorder;
use pallet_common::{
CommonCollectionOperations, Error as CommonError, eth::collection_id_to_address,
- Event as CommonEvent, Pallet as PalletCommon, erc::CollectionHelpersEvents,
+ Event as CommonEvent, Pallet as PalletCommon,
};
use pallet_structure::Pallet as PalletStructure;
-use sp_core::{Get, H160};
+use sp_core::H160;
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, CollectionFlags, CreateCollectionData,
mapping::TokenAddressMapping, MAX_REFUNGIBLE_PIECES, Property, PropertyKey,
- PropertyKeyPermission, PropertyPermission, PropertyScope, PropertyValue, TokenId,
- TrySetProperty, PropertiesPermissionMap, CreateRefungibleExMultipleOwners, TokenOwnerError,
+ PropertyKeyPermission, PropertyScope, PropertyValue, TokenId, TrySetProperty,
+ PropertiesPermissionMap, CreateRefungibleExMultipleOwners, TokenOwnerError,
};
pub use pallet::*;
@@ -245,8 +245,8 @@
pub type CollectionAllowance<T: Config> = StorageNMap<
Key = (
Key<Twox64Concat, CollectionId>,
- Key<Blake2_128Concat, T::CrossAccountId>,
- Key<Blake2_128Concat, T::CrossAccountId>,
+ Key<Blake2_128Concat, T::CrossAccountId>, // Owner
+ Key<Blake2_128Concat, T::CrossAccountId>, // Operator
),
Value = bool,
QueryKind = ValueQuery,
@@ -541,7 +541,6 @@
is_token_create: bool,
nesting_budget: &dyn Budget,
) -> DispatchResult {
- let is_collection_admin = || collection.is_owner_or_admin(sender);
let is_token_owner = || -> Result<bool, DispatchError> {
let balance = collection.balance(sender.clone(), token_id);
let total_pieces: u128 =
@@ -560,77 +559,19 @@
Ok(is_bundle_owner)
};
-
- let mut stored_properties = <TokenProperties<T>>::get((collection.id, token_id));
- let permissions = <PalletCommon<T>>::property_permissions(collection.id);
-
- for (key, value) in properties_updates {
- let permission = permissions
- .get(&key)
- .cloned()
- .unwrap_or_else(PropertyPermission::none);
-
- let is_property_exists = stored_properties.get(&key).is_some();
-
- match permission {
- PropertyPermission { mutable: false, .. } if is_property_exists => {
- return Err(<CommonError<T>>::NoPermission.into());
- }
- PropertyPermission {
- collection_admin,
- token_owner,
- ..
- } => {
- //TODO: investigate threats during public minting.
- let is_token_create =
- is_token_create && (collection_admin || token_owner) && value.is_some();
- if !(is_token_create
- || (collection_admin && is_collection_admin())
- || (token_owner && is_token_owner()?))
- {
- fail!(<CommonError<T>>::NoPermission);
- }
- }
- }
-
- match value {
- Some(value) => {
- stored_properties
- .try_set(key.clone(), value)
- .map_err(<CommonError<T>>::from)?;
-
- <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertySet(
- collection.id,
- token_id,
- key,
- ));
- }
- None => {
- stored_properties
- .remove(&key)
- .map_err(<CommonError<T>>::from)?;
+ let stored_properties = <TokenProperties<T>>::get((collection.id, token_id));
- <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertyDeleted(
- collection.id,
- token_id,
- key,
- ));
- }
- }
-
- <PalletEvm<T>>::deposit_log(
- CollectionHelpersEvents::TokenChanged {
- collection_id: collection_id_to_address(collection.id),
- token_id: token_id.into(),
- }
- .to_log(T::ContractAddress::get()),
- );
- }
-
- <TokenProperties<T>>::set((collection.id, token_id), stored_properties);
-
- Ok(())
+ <PalletCommon<T>>::modify_token_properties(
+ collection,
+ sender,
+ token_id,
+ properties_updates,
+ is_token_create,
+ stored_properties,
+ is_token_owner,
+ |properties| <TokenProperties<T>>::set((collection.id, token_id), properties),
+ )
}
pub fn set_token_properties(
@@ -1465,31 +1406,19 @@
operator: &T::CrossAccountId,
approve: bool,
) -> DispatchResult {
- if collection.permissions.access() == AccessMode::AllowList {
- collection.check_allowlist(owner)?;
- collection.check_allowlist(operator)?;
- }
-
- <PalletCommon<T>>::ensure_correct_receiver(operator)?;
-
- // =========
-
- <CollectionAllowance<T>>::insert((collection.id, owner, operator), approve);
- <PalletEvm<T>>::deposit_log(
+ <PalletCommon<T>>::set_allowance_for_all(
+ collection,
+ owner,
+ operator,
+ approve,
+ || <CollectionAllowance<T>>::insert((collection.id, owner, operator), approve),
ERC721Events::ApprovalForAll {
owner: *owner.as_eth(),
operator: *operator.as_eth(),
approved: approve,
}
.to_log(collection_id_to_address(collection.id)),
- );
- <PalletCommon<T>>::deposit_event(CommonEvent::ApprovedForAll(
- collection.id,
- owner.clone(),
- operator.clone(),
- approve,
- ));
- Ok(())
+ )
}
/// Tells whether the given `owner` approves the `operator`.