difftreelog
fix revert set_allowance
in: master
8 files changed
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -1298,7 +1298,6 @@
spender: T::CrossAccountId,
token: TokenId,
amount: u128,
- nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo;
fn transfer_from(
&self,
pallets/fungible/src/common.rsdiffbeforeafterboth--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -226,7 +226,6 @@
spender: T::CrossAccountId,
token: TokenId,
amount: u128,
- _nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
ensure!(
token == TokenId::default(),
pallets/nonfungible/src/common.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -308,15 +308,14 @@
spender: T::CrossAccountId,
token: TokenId,
amount: u128,
- nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);
with_weight(
if amount == 1 {
- <Pallet<T>>::set_allowance(self, &sender, token, Some(&spender), nesting_budget)
+ <Pallet<T>>::set_allowance(self, &sender, token, Some(&spender))
} else {
- <Pallet<T>>::set_allowance(self, &sender, token, None, nesting_budget)
+ <Pallet<T>>::set_allowance(self, &sender, token, None)
},
<CommonWeights<T>>::approve(),
)
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -269,11 +269,8 @@
let caller = T::CrossAccountId::from_eth(caller);
let approved = T::CrossAccountId::from_eth(approved);
let token = token_id.try_into()?;
- let budget = self
- .recorder
- .weight_calls_budget(<StructureWeight<T>>::find_parent());
- <Pallet<T>>::set_allowance(self, &caller, token, Some(&approved), &budget)
+ <Pallet<T>>::set_allowance(self, &caller, token, Some(&approved))
.map_err(dispatch_to_evm::<T>)?;
Ok(())
}
pallets/nonfungible/src/lib.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -878,7 +878,6 @@
sender: &T::CrossAccountId,
token: TokenId,
spender: Option<&T::CrossAccountId>,
- nesting_budget: &dyn Budget,
) -> DispatchResult {
if collection.permissions.access() == AccessMode::AllowList {
collection.check_allowlist(sender)?;
@@ -890,16 +889,10 @@
if let Some(spender) = spender {
<PalletCommon<T>>::ensure_correct_receiver(spender)?;
}
-
- let is_owned = <PalletStructure<T>>::check_indirectly_owned(
- sender.clone(),
- collection.id,
- token,
- None,
- nesting_budget
- )?;
- if !is_owned {
+ let token_data =
+ <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;
+ if &token_data.owner != sender {
ensure!(
collection.ignores_owned_amount(sender),
<CommonError<T>>::CantApproveMoreThanOwned
@@ -926,9 +919,6 @@
// `from`, `to` checked in [`transfer`]
collection.check_allowlist(spender)?;
}
- if <Allowance<T>>::get((collection.id, token)).as_ref() == Some(spender) {
- return Ok(());
- }
if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {
// TODO: should collection owner be allowed to perform this transfer?
ensure!(
@@ -943,6 +933,9 @@
);
return Ok(());
}
+ if <Allowance<T>>::get((collection.id, token)).as_ref() == Some(spender) {
+ return Ok(());
+ }
ensure!(
collection.ignores_allowance(spender),
<CommonError<T>>::ApprovedValueTooLow
pallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617#![cfg_attr(not(feature = "std"), no_std)]1819use frame_support::{pallet_prelude::*, transactional, BoundedVec, dispatch::DispatchResult};20use frame_system::{pallet_prelude::*, ensure_signed};21use sp_runtime::{DispatchError, Permill, traits::StaticLookup};22use sp_std::vec::Vec;23use up_data_structs::{*, mapping::TokenAddressMapping};24use pallet_common::{25 Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,26};27use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};28use pallet_structure::Pallet as PalletStructure;29use pallet_evm::account::CrossAccountId;30use core::convert::AsRef;3132pub use pallet::*;3334pub mod misc;35pub mod property;3637use misc::*;38pub use property::*;3940use RmrkProperty::*;4142const NESTING_BUDGET: u32 = 5;4344#[frame_support::pallet]45pub mod pallet {46 use super::*;47 use pallet_evm::account;4849 #[pallet::config]50 pub trait Config:51 frame_system::Config + pallet_common::Config + pallet_nonfungible::Config + account::Config52 {53 type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;54 }5556 #[pallet::storage]57 #[pallet::getter(fn collection_index)]58 pub type CollectionIndex<T: Config> = StorageValue<_, RmrkCollectionId, ValueQuery>;5960 #[pallet::storage]61 pub type UniqueCollectionId<T: Config> =62 StorageMap<_, Twox64Concat, RmrkCollectionId, CollectionId, ValueQuery>;6364 #[pallet::storage]65 pub type RmrkInernalCollectionId<T: Config> =66 StorageMap<_, Twox64Concat, CollectionId, RmrkCollectionId, ValueQuery>;6768 #[pallet::pallet]69 #[pallet::generate_store(pub(super) trait Store)]70 pub struct Pallet<T>(_);7172 #[pallet::event]73 #[pallet::generate_deposit(pub(super) fn deposit_event)]74 pub enum Event<T: Config> {75 CollectionCreated {76 issuer: T::AccountId,77 collection_id: RmrkCollectionId,78 },79 CollectionDestroyed {80 issuer: T::AccountId,81 collection_id: RmrkCollectionId,82 },83 IssuerChanged {84 old_issuer: T::AccountId,85 new_issuer: T::AccountId,86 collection_id: RmrkCollectionId,87 },88 CollectionLocked {89 issuer: T::AccountId,90 collection_id: RmrkCollectionId,91 },92 NftMinted {93 owner: T::AccountId,94 collection_id: RmrkCollectionId,95 nft_id: RmrkNftId,96 },97 NFTBurned {98 owner: T::AccountId,99 nft_id: RmrkNftId,100 },101 PropertySet {102 collection_id: RmrkCollectionId,103 maybe_nft_id: Option<RmrkNftId>,104 key: RmrkKeyString,105 value: RmrkValueString,106 },107 ResourceAdded {108 nft_id: RmrkNftId,109 resource_id: RmrkResourceId,110 },111 ResourceRemoval {112 nft_id: RmrkNftId,113 resource_id: RmrkResourceId,114 },115 }116117 #[pallet::error]118 pub enum Error<T> {119 /* Unique-specific events */120 CorruptedCollectionType,121 NftTypeEncodeError,122 RmrkPropertyKeyIsTooLong,123 RmrkPropertyValueIsTooLong,124125 /* RMRK compatible events */126 CollectionNotEmpty,127 NoAvailableCollectionId,128 NoAvailableNftId,129 CollectionUnknown,130 NoPermission,131 CollectionFullOrLocked,132 ResourceDoesntExist,133 }134135 #[pallet::call]136 impl<T: Config> Pallet<T> {137 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]138 #[transactional]139 pub fn create_collection(140 origin: OriginFor<T>,141 metadata: RmrkString,142 max: Option<u32>,143 symbol: RmrkCollectionSymbol,144 ) -> DispatchResult {145 let sender = ensure_signed(origin)?;146147 let limits = CollectionLimits {148 owner_can_transfer: Some(false),149 token_limit: max,150 ..Default::default()151 };152153 let data = CreateCollectionData {154 limits: Some(limits),155 token_prefix: symbol156 .into_inner()157 .try_into()158 .map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,159 permissions: Some(CollectionPermissions {160 nesting: Some(NestingRule::Owner),161 ..Default::default()162 }),163 ..Default::default()164 };165166 let unique_collection_id = Self::init_collection(167 T::CrossAccountId::from_sub(sender.clone()),168 data,169 [170 Self::rmrk_property(Metadata, &metadata)?,171 Self::rmrk_property(CollectionType, &misc::CollectionType::Regular)?,172 ]173 .into_iter(),174 )?;175 let rmrk_collection_id = <CollectionIndex<T>>::get();176177 <UniqueCollectionId<T>>::insert(rmrk_collection_id, unique_collection_id);178 <RmrkInernalCollectionId<T>>::insert(unique_collection_id, rmrk_collection_id);179180 <CollectionIndex<T>>::mutate(|n| *n += 1);181182 Self::deposit_event(Event::CollectionCreated {183 issuer: sender,184 collection_id: rmrk_collection_id,185 });186187 Ok(())188 }189190 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]191 #[transactional]192 pub fn destroy_collection(193 origin: OriginFor<T>,194 collection_id: RmrkCollectionId,195 ) -> DispatchResult {196 let sender = ensure_signed(origin)?;197 let cross_sender = T::CrossAccountId::from_sub(sender.clone());198199 let collection = Self::get_typed_nft_collection(200 Self::unique_collection_id(collection_id)?,201 misc::CollectionType::Regular,202 )?;203204 ensure!(205 collection.total_supply() == 0,206 <Error<T>>::CollectionNotEmpty207 );208209 <PalletNft<T>>::destroy_collection(collection, &cross_sender)210 .map_err(Self::map_common_err_to_proxy)?;211212 Self::deposit_event(Event::CollectionDestroyed {213 issuer: sender,214 collection_id,215 });216217 Ok(())218 }219220 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]221 #[transactional]222 pub fn change_collection_issuer(223 origin: OriginFor<T>,224 collection_id: RmrkCollectionId,225 new_issuer: <T::Lookup as StaticLookup>::Source,226 ) -> DispatchResult {227 let sender = ensure_signed(origin)?;228229 let new_issuer = T::Lookup::lookup(new_issuer)?;230231 Self::change_collection_owner(232 Self::unique_collection_id(collection_id)?,233 misc::CollectionType::Regular,234 sender.clone(),235 new_issuer.clone(),236 )?;237238 Self::deposit_event(Event::IssuerChanged {239 old_issuer: sender,240 new_issuer,241 collection_id,242 });243244 Ok(())245 }246247 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]248 #[transactional]249 pub fn lock_collection(250 origin: OriginFor<T>,251 collection_id: RmrkCollectionId,252 ) -> DispatchResult {253 let sender = ensure_signed(origin)?;254 let cross_sender = T::CrossAccountId::from_sub(sender.clone());255256 let collection = Self::get_typed_nft_collection(257 Self::unique_collection_id(collection_id)?,258 misc::CollectionType::Regular,259 )?;260261 Self::check_collection_owner(&collection, &cross_sender)?;262263 let token_count = collection.total_supply();264265 let mut collection = collection.into_inner();266 collection.limits.token_limit = Some(token_count);267 collection.save()?;268269 Self::deposit_event(Event::CollectionLocked {270 issuer: sender,271 collection_id,272 });273274 Ok(())275 }276277 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]278 #[transactional]279 pub fn mint_nft(280 origin: OriginFor<T>,281 owner: T::AccountId,282 collection_id: RmrkCollectionId,283 recipient: Option<T::AccountId>,284 royalty_amount: Option<Permill>,285 metadata: RmrkString,286 ) -> DispatchResult {287 let sender = ensure_signed(origin)?;288 let sender = T::CrossAccountId::from_sub(sender);289 let cross_owner = T::CrossAccountId::from_sub(owner.clone());290291 let royalty_info = royalty_amount.map(|amount| rmrk::RoyaltyInfo {292 recipient: recipient.unwrap_or_else(|| owner.clone()),293 amount,294 });295296 let collection = Self::get_typed_nft_collection(297 Self::unique_collection_id(collection_id)?,298 misc::CollectionType::Regular,299 )?;300301 let nft_id = Self::create_nft(302 &sender,303 &cross_owner,304 &collection,305 [306 Self::rmrk_property(TokenType, &NftType::Regular)?,307 Self::rmrk_property(RoyaltyInfo, &royalty_info)?,308 Self::rmrk_property(Metadata, &metadata)?,309 Self::rmrk_property(Equipped, &false)?,310 Self::rmrk_property(311 ResourceCollection,312 &Self::init_collection(313 sender.clone(),314 CreateCollectionData {315 ..Default::default()316 },317 [Self::rmrk_property(318 CollectionType,319 &misc::CollectionType::Resource,320 )?]321 .into_iter(),322 )?,323 )?, // todo possibly add limits to the collection if rmrk warrants them324 Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,325 ]326 .into_iter(),327 )328 .map_err(|err| match err {329 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),330 err => Self::map_common_err_to_proxy(err),331 })?;332333 Self::deposit_event(Event::NftMinted {334 owner,335 collection_id,336 nft_id: nft_id.0,337 });338339 Ok(())340 }341342 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]343 #[transactional]344 pub fn burn_nft(345 origin: OriginFor<T>,346 collection_id: RmrkCollectionId,347 nft_id: RmrkNftId,348 ) -> DispatchResult {349 let sender = ensure_signed(origin)?;350 let cross_sender = T::CrossAccountId::from_sub(sender.clone());351352 Self::destroy_nft(353 cross_sender,354 Self::unique_collection_id(collection_id)?,355 misc::CollectionType::Regular,356 nft_id.into(),357 )?;358359 Self::deposit_event(Event::NFTBurned {360 owner: sender,361 nft_id,362 });363364 Ok(())365 }366367 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]368 #[transactional]369 pub fn send(370 origin: OriginFor<T>,371 rmrk_collection_id: RmrkCollectionId,372 rmrk_nft_id: RmrkNftId,373 new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,374 ) -> DispatchResult {375 let sender = ensure_signed(origin.clone())?;376 let cross_sender = T::CrossAccountId::from_sub(sender.clone());377378 let collection_id = Self::unique_collection_id(rmrk_collection_id)?;379 let nft_id = rmrk_nft_id.into();380381 let token_data = <TokenData<T>>::get((collection_id, nft_id))382 .ok_or(<Error<T>>::NoAvailableNftId)?;383384 let from = token_data.owner;385386 let collection = Self::get_typed_nft_collection(387 collection_id,388 misc::CollectionType::Regular,389 )?;390391 let budget = budget::Value::new(NESTING_BUDGET);392393 let target_owner;394395 match new_owner {396 RmrkAccountIdOrCollectionNftTuple::AccountId(account_id) => {397 target_owner = T::CrossAccountId::from_sub(account_id);398 },399 RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(target_collection_id, target_nft_id) => {400 let target_collection_id = Self::unique_collection_id(target_collection_id)?;401402 target_owner = T::CrossTokenAddressMapping::token_to_address(403 target_collection_id,404 target_nft_id.into(),405 );406407 let spender = <PalletStructure<T>>::get_indirect_owner(408 target_collection_id,409 target_nft_id.into(),410 Some((collection_id, nft_id)),411 &budget,412 )?;413414 let is_approval_required = cross_sender != spender;415416 if is_approval_required {417 // FIXME418 // <PalletNft<T>>::set_allowance(419 // &collection,420 // &cross_sender,421 // nft_id,422 // Some(&spender),423 // &budget424 // ).map_err(Self::map_common_err_to_proxy)?;425426 return Ok(());427 }428 }429 }430431 <PalletNft<T>>::transfer_from(432 &collection,433 &cross_sender,434 &from,435 &target_owner,436 nft_id,437 &budget438 ).map_err(Self::map_common_err_to_proxy)?;439440 Ok(())441 }442443 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]444 #[transactional]445 pub fn set_property(446 origin: OriginFor<T>,447 #[pallet::compact] rmrk_collection_id: RmrkCollectionId,448 maybe_nft_id: Option<RmrkNftId>,449 key: RmrkKeyString,450 value: RmrkValueString,451 ) -> DispatchResult {452 let sender = ensure_signed(origin)?;453 let sender = T::CrossAccountId::from_sub(sender);454455 let collection_id = Self::unique_collection_id(rmrk_collection_id)?;456 let budget = budget::Value::new(NESTING_BUDGET);457458 match maybe_nft_id {459 Some(nft_id) => {460 let token_id: TokenId = nft_id.into();461462 Self::ensure_nft_owner(collection_id, token_id, &sender, &budget)?;463 Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;464465 <PalletNft<T>>::set_scoped_token_property(466 collection_id,467 token_id,468 PropertyScope::Rmrk,469 Self::rmrk_property(UserProperty(key.as_slice()), &value)?,470 )?;471 }472 None => {473 let collection = Self::get_typed_nft_collection(474 collection_id,475 misc::CollectionType::Regular,476 )?;477478 Self::check_collection_owner(&collection, &sender)?;479480 <PalletCommon<T>>::set_scoped_collection_property(481 collection_id,482 PropertyScope::Rmrk,483 Self::rmrk_property(UserProperty(key.as_slice()), &value)?,484 )?;485 }486 }487488 Self::deposit_event(Event::PropertySet {489 collection_id: rmrk_collection_id,490 maybe_nft_id,491 key,492 value,493 });494495 Ok(())496 }497498 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]499 #[transactional]500 pub fn add_basic_resource(501 origin: OriginFor<T>,502 collection_id: RmrkCollectionId,503 nft_id: RmrkNftId,504 resource: RmrkBasicResource,505 ) -> DispatchResult {506 let sender = ensure_signed(origin.clone())?;507508 let resource_id = Self::resource_add(509 sender,510 Self::unique_collection_id(collection_id)?,511 nft_id.into(),512 [513 Self::rmrk_property(TokenType, &NftType::Resource)?,514 Self::rmrk_property(ResourceType, &misc::ResourceType::Basic)?,515 Self::rmrk_property(Src, &resource.src)?,516 Self::rmrk_property(Metadata, &resource.metadata)?,517 Self::rmrk_property(License, &resource.license)?,518 Self::rmrk_property(Thumb, &resource.thumb)?,519 ]520 .into_iter(),521 )?;522523 Self::deposit_event(Event::ResourceAdded {524 nft_id,525 resource_id,526 });527 Ok(())528 }529530 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]531 #[transactional]532 pub fn add_composable_resource(533 origin: OriginFor<T>,534 collection_id: RmrkCollectionId,535 nft_id: RmrkNftId,536 _resource_id: RmrkBoundedResource,537 resource: RmrkComposableResource,538 ) -> DispatchResult {539 let sender = ensure_signed(origin.clone())?;540541 let resource_id = Self::resource_add(542 sender,543 Self::unique_collection_id(collection_id)?,544 nft_id.into(),545 [546 Self::rmrk_property(TokenType, &NftType::Resource)?,547 Self::rmrk_property(ResourceType, &misc::ResourceType::Composable)?,548 Self::rmrk_property(Parts, &resource.parts)?,549 Self::rmrk_property(Base, &resource.base)?,550 Self::rmrk_property(Src, &resource.src)?,551 Self::rmrk_property(Metadata, &resource.metadata)?,552 Self::rmrk_property(License, &resource.license)?,553 Self::rmrk_property(Thumb, &resource.thumb)?,554 ]555 .into_iter(),556 )?;557558 Self::deposit_event(Event::ResourceAdded {559 nft_id,560 resource_id,561 });562 Ok(())563 }564565 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]566 #[transactional]567 pub fn add_slot_resource(568 origin: OriginFor<T>,569 collection_id: RmrkCollectionId,570 nft_id: RmrkNftId,571 resource: RmrkSlotResource,572 ) -> DispatchResult {573 let sender = ensure_signed(origin.clone())?;574575 let resource_id = Self::resource_add(576 sender,577 Self::unique_collection_id(collection_id)?,578 nft_id.into(),579 [580 Self::rmrk_property(TokenType, &NftType::Resource)?,581 Self::rmrk_property(ResourceType, &misc::ResourceType::Slot)?,582 Self::rmrk_property(Base, &resource.base)?,583 Self::rmrk_property(Src, &resource.src)?,584 Self::rmrk_property(Metadata, &resource.metadata)?,585 Self::rmrk_property(Slot, &resource.slot)?,586 Self::rmrk_property(License, &resource.license)?,587 Self::rmrk_property(Thumb, &resource.thumb)?,588 ]589 .into_iter(),590 )?;591592 Self::deposit_event(Event::ResourceAdded {593 nft_id,594 resource_id,595 });596 Ok(())597 }598599 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]600 #[transactional]601 pub fn remove_resource(602 origin: OriginFor<T>,603 collection_id: RmrkCollectionId,604 nft_id: RmrkNftId,605 resource_id: RmrkResourceId,606 ) -> DispatchResult {607 let sender = ensure_signed(origin.clone())?;608609 Self::resource_remove(610 sender,611 Self::unique_collection_id(collection_id)?,612 nft_id.into(),613 resource_id.into(),614 )?;615616 Self::deposit_event(Event::ResourceRemoval {617 nft_id,618 resource_id,619 });620 Ok(())621 }622 }623}624625impl<T: Config> Pallet<T> {626 pub fn rmrk_property_key(rmrk_key: RmrkProperty) -> Result<PropertyKey, DispatchError> {627 let key = rmrk_key.to_key::<T>()?;628629 let scoped_key = PropertyScope::Rmrk630 .apply(key)631 .map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)?;632633 Ok(scoped_key)634 }635636 // todo think about renaming these637 pub fn rmrk_property<E: Encode>(638 rmrk_key: RmrkProperty,639 value: &E,640 ) -> Result<Property, DispatchError> {641 let key = rmrk_key.to_key::<T>()?;642643 let value = value644 .encode()645 .try_into()646 .map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong)?;647648 let property = Property { key, value };649650 Ok(property)651 }652653 pub fn decode_property<D: Decode>(vec: PropertyValue) -> Result<D, DispatchError> {654 vec.decode()655 .map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong.into())656 }657658 pub fn rebind<L, S>(vec: &BoundedVec<u8, L>) -> Result<BoundedVec<u8, S>, DispatchError>659 where660 BoundedVec<u8, S>: TryFrom<Vec<u8>>,661 {662 vec.rebind()663 .map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong.into())664 }665666 fn init_collection(667 sender: T::CrossAccountId,668 data: CreateCollectionData<T::AccountId>,669 properties: impl Iterator<Item = Property>,670 ) -> Result<CollectionId, DispatchError> {671 let collection_id = <PalletNft<T>>::init_collection(sender, data);672673 if let Err(DispatchError::Arithmetic(_)) = &collection_id {674 return Err(<Error<T>>::NoAvailableCollectionId.into());675 }676677 <PalletCommon<T>>::set_scoped_collection_properties(678 collection_id?,679 PropertyScope::Rmrk,680 properties,681 )?;682683 collection_id684 }685686 pub fn create_nft(687 sender: &T::CrossAccountId,688 owner: &T::CrossAccountId,689 collection: &NonfungibleHandle<T>,690 properties: impl Iterator<Item = Property>,691 ) -> Result<TokenId, DispatchError> {692 let data = CreateNftExData {693 properties: BoundedVec::default(),694 owner: owner.clone(),695 };696697 let budget = budget::Value::new(NESTING_BUDGET);698699 <PalletNft<T>>::create_item(collection, sender, data, &budget)?;700701 let nft_id = <PalletNft<T>>::current_token_id(collection.id);702703 <PalletNft<T>>::set_scoped_token_properties(704 collection.id,705 nft_id,706 PropertyScope::Rmrk,707 properties,708 )?;709710 Ok(nft_id)711 }712713 fn destroy_nft(714 sender: T::CrossAccountId,715 collection_id: CollectionId,716 collection_type: misc::CollectionType,717 token_id: TokenId,718 ) -> DispatchResult {719 let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;720721 <PalletNft<T>>::burn(&collection, &sender, token_id)722 .map_err(Self::map_common_err_to_proxy)?;723724 Ok(())725 }726727 fn resource_add(728 sender: T::AccountId,729 collection_id: CollectionId,730 token_id: TokenId,731 resource_properties: impl Iterator<Item = Property>,732 ) -> Result<RmrkResourceId, DispatchError> {733 let collection =734 Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;735 ensure!(collection.owner == sender, Error::<T>::NoPermission);736737 // Check NFT lock status // todo depends on market, maybe later738 //ensure!(!Pallet::<T>::is_locked(collection_id, nft_id), pallet_uniques::Error::<T>::Locked);739740 let sender = T::CrossAccountId::from_sub(sender);741 let budget = budget::Value::new(NESTING_BUDGET);742 let pending = Self::ensure_nft_owner(collection_id, token_id, &sender, &budget).is_err();743744 let resource_collection_id: CollectionId =745 Self::get_nft_property_decoded(collection_id, token_id, ResourceCollection)?;746 let resource_collection =747 Self::get_typed_nft_collection(resource_collection_id, misc::CollectionType::Resource)?;748749 // todo probably add extra connections to bases, slots, etc., when RMRK starts to use them750751 let resource_id = Self::create_nft(752 &sender, // todo owner of the nft?753 &sender,754 &resource_collection,755 resource_properties.chain(756 [757 Self::rmrk_property(PendingResourceAccept, &pending)?,758 Self::rmrk_property(PendingResourceRemoval, &false)?,759 ]760 .into_iter(),761 ),762 )763 .map_err(|err| match err {764 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),765 err => Self::map_common_err_to_proxy(err),766 })?;767768 Ok(resource_id.0)769 }770771 fn resource_remove(772 sender: T::AccountId,773 collection_id: CollectionId,774 nft_id: TokenId,775 resource_id: TokenId,776 ) -> DispatchResult {777 let collection =778 Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;779 ensure!(collection.owner == sender, Error::<T>::NoPermission);780781 let resource_collection_id: CollectionId =782 Self::get_nft_property_decoded(collection_id, nft_id, ResourceCollection)?;783 let resource_collection =784 Self::get_typed_nft_collection(resource_collection_id, misc::CollectionType::Resource)?;785 ensure!(786 <PalletNft<T>>::token_exists(&resource_collection, resource_id),787 Error::<T>::ResourceDoesntExist788 );789790 let budget = up_data_structs::budget::Value::new(10);791 let topmost_owner =792 <PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)?;793794 let sender = T::CrossAccountId::from_sub(sender);795 if topmost_owner == sender {796 <PalletNft<T>>::burn(&resource_collection, &sender, resource_id)797 .map_err(Self::map_common_err_to_proxy)?;798 } else {799 <PalletNft<T>>::set_scoped_token_property(800 resource_collection_id,801 resource_id,802 PropertyScope::Rmrk,803 Self::rmrk_property(PendingResourceRemoval, &true)?,804 )?;805 }806807 Ok(())808 }809810 fn change_collection_owner(811 collection_id: CollectionId,812 collection_type: misc::CollectionType,813 sender: T::AccountId,814 new_owner: T::AccountId,815 ) -> DispatchResult {816 let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;817 Self::check_collection_owner(&collection, &T::CrossAccountId::from_sub(sender))?;818819 let mut collection = collection.into_inner();820821 collection.owner = new_owner;822 collection.save()823 }824825 fn check_collection_owner(826 collection: &NonfungibleHandle<T>,827 account: &T::CrossAccountId,828 ) -> DispatchResult {829 collection830 .check_is_owner(account)831 .map_err(Self::map_common_err_to_proxy)832 }833834 pub fn last_collection_idx() -> RmrkCollectionId {835 <CollectionIndex<T>>::get()836 }837838 pub fn unique_collection_id(839 rmrk_collection_id: RmrkCollectionId,840 ) -> Result<CollectionId, DispatchError> {841 <UniqueCollectionId<T>>::try_get(rmrk_collection_id)842 .map_err(|_| <Error<T>>::CollectionUnknown.into())843 }844845 pub fn rmrk_collection_id(846 unique_collection_id: CollectionId847 ) -> Result<RmrkCollectionId, DispatchError> {848 <RmrkInernalCollectionId<T>>::try_get(unique_collection_id)849 .map_err(|_| <Error<T>>::CollectionUnknown.into())850 }851852 pub fn get_nft_collection(853 collection_id: CollectionId,854 ) -> Result<NonfungibleHandle<T>, DispatchError> {855 let collection = <CollectionHandle<T>>::try_get(collection_id)856 .map_err(|_| <Error<T>>::CollectionUnknown)?;857858 match collection.mode {859 CollectionMode::NFT => Ok(NonfungibleHandle::cast(collection)),860 _ => Err(<Error<T>>::CollectionUnknown.into()),861 }862 }863864 pub fn collection_exists(collection_id: CollectionId) -> bool {865 <CollectionHandle<T>>::try_get(collection_id).is_ok()866 }867868 pub fn get_collection_property(869 collection_id: CollectionId,870 key: RmrkProperty,871 ) -> Result<PropertyValue, DispatchError> {872 let collection_property = <PalletCommon<T>>::collection_properties(collection_id)873 .get(&Self::rmrk_property_key(key)?)874 .ok_or(<Error<T>>::CollectionUnknown)?875 .clone();876877 Ok(collection_property)878 }879880 pub fn get_collection_property_decoded<V: Decode>(881 collection_id: CollectionId,882 key: RmrkProperty,883 ) -> Result<V, DispatchError> {884 Self::decode_property(Self::get_collection_property(collection_id, key)?)885 }886887 pub fn get_collection_type(888 collection_id: CollectionId,889 ) -> Result<misc::CollectionType, DispatchError> {890 Self::get_collection_property_decoded(collection_id, CollectionType)891 .map_err(|_| <Error<T>>::CorruptedCollectionType.into())892 }893894 pub fn ensure_collection_type(895 collection_id: CollectionId,896 collection_type: misc::CollectionType,897 ) -> DispatchResult {898 let actual_type = Self::get_collection_type(collection_id)?;899 ensure!(900 actual_type == collection_type,901 <CommonError<T>>::NoPermission902 );903904 Ok(())905 }906907 pub fn get_typed_nft_collection(908 collection_id: CollectionId,909 collection_type: misc::CollectionType,910 ) -> Result<NonfungibleHandle<T>, DispatchError> {911 Self::ensure_collection_type(collection_id, collection_type)?;912913 Self::get_nft_collection(collection_id)914 }915916 pub fn get_typed_nft_collection_mapped(917 rmrk_collection_id: RmrkCollectionId,918 collection_type: misc::CollectionType,919 ) -> Result<(NonfungibleHandle<T>, CollectionId), DispatchError> {920 let unique_collection_id = Self::unique_collection_id(rmrk_collection_id)?;921922 let collection = Self::get_typed_nft_collection(unique_collection_id, collection_type)?;923924 Ok((collection, unique_collection_id))925 }926927 pub fn get_nft_property(928 collection_id: CollectionId,929 nft_id: TokenId,930 key: RmrkProperty,931 ) -> Result<PropertyValue, DispatchError> {932 let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))933 .get(&Self::rmrk_property_key(key)?)934 .ok_or(<Error<T>>::NoAvailableNftId)? // todo replace with better error?935 .clone();936937 Ok(nft_property)938 }939940 pub fn get_nft_property_decoded<V: Decode>(941 collection_id: CollectionId,942 nft_id: TokenId,943 key: RmrkProperty,944 ) -> Result<V, DispatchError> {945 Self::decode_property(Self::get_nft_property(collection_id, nft_id, key)?)946 }947948 pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {949 <TokenData<T>>::contains_key((collection_id, nft_id))950 }951952 pub fn get_nft_type(953 collection_id: CollectionId,954 token_id: TokenId,955 ) -> Result<NftType, DispatchError> {956 Self::get_nft_property_decoded(collection_id, token_id, TokenType)957 .map_err(|_| <Error<T>>::NftTypeEncodeError.into())958 }959960 pub fn ensure_nft_type(961 collection_id: CollectionId,962 token_id: TokenId,963 nft_type: NftType,964 ) -> DispatchResult {965 let actual_type = Self::get_nft_type(collection_id, token_id)?;966 ensure!(actual_type == nft_type, <Error<T>>::NoPermission);967968 Ok(())969 }970971 pub fn ensure_nft_owner(972 collection_id: CollectionId,973 token_id: TokenId,974 possible_owner: &T::CrossAccountId,975 nesting_budget: &dyn budget::Budget976 ) -> DispatchResult {977 let is_owned = <PalletStructure<T>>::check_indirectly_owned(978 possible_owner.clone(),979 collection_id,980 token_id,981 None,982 nesting_budget,983 )?;984985 ensure!(986 is_owned,987 <Error<T>>::NoPermission988 );989990 Ok(())991 }992993 pub fn filter_user_properties<Key, Value, R, Mapper>(994 collection_id: CollectionId,995 token_id: Option<TokenId>,996 filter_keys: Option<Vec<RmrkPropertyKey>>,997 mapper: Mapper,998 ) -> Result<Vec<R>, DispatchError>999 where1000 Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,1001 Value: Decode + Default,1002 Mapper: Fn(Key, Value) -> R,1003 {1004 filter_keys1005 .map(|keys| {1006 let properties = keys1007 .into_iter()1008 .filter_map(|key| {1009 let key: Key = key.try_into().ok()?;10101011 let value = match token_id {1012 Some(token_id) => Self::get_nft_property_decoded(1013 collection_id,1014 token_id,1015 UserProperty(key.as_ref()),1016 ),1017 None => Self::get_collection_property_decoded(1018 collection_id,1019 UserProperty(key.as_ref()),1020 ),1021 }1022 .ok()?;10231024 Some(mapper(key, value))1025 })1026 .collect();10271028 Ok(properties)1029 })1030 .unwrap_or_else(|| {1031 let properties =1032 Self::iterate_user_properties(collection_id, token_id, mapper)?.collect();10331034 Ok(properties)1035 })1036 }10371038 pub fn iterate_user_properties<Key, Value, R, Mapper>(1039 collection_id: CollectionId,1040 token_id: Option<TokenId>,1041 mapper: Mapper,1042 ) -> Result<impl Iterator<Item = R>, DispatchError>1043 where1044 Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,1045 Value: Decode + Default,1046 Mapper: Fn(Key, Value) -> R,1047 {1048 let key_prefix = Self::rmrk_property_key(UserProperty(b""))?;10491050 let properties = match token_id {1051 Some(token_id) => <PalletNft<T>>::token_properties((collection_id, token_id)),1052 None => <PalletCommon<T>>::collection_properties(collection_id),1053 };10541055 let properties = properties.into_iter().filter_map(move |(key, value)| {1056 let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;10571058 let key: Key = key.to_vec().try_into().ok()?;1059 let value: Value = value.decode().ok()?;10601061 Some(mapper(key, value))1062 });10631064 Ok(properties)1065 }10661067 fn map_common_err_to_proxy(err: DispatchError) -> DispatchError {1068 map_common_err_to_proxy! {1069 match err {1070 NoPermission => NoPermission,1071 CollectionTokenLimitExceeded => CollectionFullOrLocked,1072 PublicMintingNotAllowed => NoPermission,1073 TokenNotFound => NoAvailableNftId,1074 ApprovedValueTooLow => NoPermission1075 }1076 }1077 }1078}pallets/refungible/src/common.rsdiffbeforeafterboth--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -254,7 +254,6 @@
spender: T::CrossAccountId,
token: TokenId,
amount: u128,
- _nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
with_weight(
<Pallet<T>>::set_allowance(self, &sender, &spender, token, amount),
pallets/unique/src/lib.rsdiffbeforeafterboth--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -815,9 +815,8 @@
#[transactional]
pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
- let budget = budget::Value::new(NESTING_BUDGET);
- dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount, &budget))
+ dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))
}
/// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.