difftreelog
feat nest on create/transfer
in: master
12 files changed
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -723,17 +723,20 @@
sender: T::CrossAccountId,
to: T::CrossAccountId,
data: CreateItemData,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo;
fn create_multiple_items(
&self,
sender: T::CrossAccountId,
to: T::CrossAccountId,
data: Vec<CreateItemData>,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo;
fn create_multiple_items_ex(
&self,
sender: T::CrossAccountId,
data: CreateItemExData<T::CrossAccountId>,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo;
fn burn_item(
&self,
@@ -748,6 +751,7 @@
to: T::CrossAccountId,
token: TokenId,
amount: u128,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo;
fn approve(
&self,
@@ -781,11 +785,12 @@
data: BoundedVec<u8, CustomDataLimit>,
) -> DispatchResultWithPostInfo;
- fn nest_token(
+ fn check_nesting(
&self,
sender: T::CrossAccountId,
- from: (CollectionId, TokenId),
+ from: CollectionId,
under: TokenId,
+ budget: &dyn Budget,
) -> DispatchResult;
fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId>;
pallets/evm-coder-substrate/src/lib.rsdiffbeforeafterboth--- a/pallets/evm-coder-substrate/src/lib.rs
+++ b/pallets/evm-coder-substrate/src/lib.rs
@@ -55,7 +55,6 @@
use frame_system::ensure_signed;
pub use frame_support::dispatch::DispatchResult;
- use frame_support::{pallet_prelude::*, traits::PalletInfo};
use frame_system::pallet_prelude::*;
/// DispatchError is opaque, but we need to somehow extract correct error in case of OutOfGas failure
pallets/fungible/src/common.rsdiffbeforeafterboth--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -17,7 +17,7 @@
use core::marker::PhantomData;
use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};
-use up_data_structs::{TokenId, CreateItemExData, budget::Budget};
+use up_data_structs::{TokenId, CollectionId, CreateItemExData, budget::Budget};
use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
use sp_runtime::ArithmeticError;
use sp_std::{vec::Vec, vec};
@@ -78,10 +78,11 @@
sender: T::CrossAccountId,
to: T::CrossAccountId,
data: up_data_structs::CreateItemData,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
match data {
up_data_structs::CreateItemData::Fungible(data) => with_weight(
- <Pallet<T>>::create_item(self, &sender, (to, data.value)),
+ <Pallet<T>>::create_item(self, &sender, (to, data.value), nesting_budget),
<CommonWeights<T>>::create_item(),
),
_ => fail!(<Error<T>>::NotFungibleDataUsedToMintFungibleCollectionToken),
@@ -93,6 +94,7 @@
sender: T::CrossAccountId,
to: T::CrossAccountId,
data: Vec<up_data_structs::CreateItemData>,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
let mut sum: u128 = 0;
for data in data {
@@ -107,7 +109,7 @@
}
with_weight(
- <Pallet<T>>::create_item(self, &sender, (to, sum)),
+ <Pallet<T>>::create_item(self, &sender, (to, sum), nesting_budget),
<CommonWeights<T>>::create_item(),
)
}
@@ -116,6 +118,7 @@
&self,
sender: <T>::CrossAccountId,
data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);
let data = match data {
@@ -124,7 +127,7 @@
};
with_weight(
- <Pallet<T>>::create_multiple_items(self, &sender, data.into_inner()),
+ <Pallet<T>>::create_multiple_items(self, &sender, data.into_inner(), nesting_budget),
weight,
)
}
@@ -152,6 +155,7 @@
to: T::CrossAccountId,
token: TokenId,
amount: u128,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
ensure!(
token == TokenId::default(),
@@ -159,7 +163,7 @@
);
with_weight(
- <Pallet<T>>::transfer(self, &from, &to, amount),
+ <Pallet<T>>::transfer(self, &from, &to, amount, nesting_budget),
<CommonWeights<T>>::transfer(),
)
}
@@ -230,11 +234,12 @@
fail!(<Error<T>>::FungibleItemsDontHaveData)
}
- fn nest_token(
+ fn check_nesting(
&self,
_sender: <T>::CrossAccountId,
- _from: (up_data_structs::CollectionId, TokenId),
+ _from: CollectionId,
_under: TokenId,
+ _budget: &dyn Budget,
) -> sp_runtime::DispatchResult {
fail!(<Error<T>>::FungibleDisallowsNesting)
}
pallets/fungible/src/erc.rsdiffbeforeafterboth--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -81,8 +81,11 @@
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let amount = amount.try_into().map_err(|_| "amount overflow")?;
+ let budget = self
+ .recorder
+ .weight_calls_budget(<StructureWeight<T>>::find_parent());
- <Pallet<T>>::transfer(self, &caller, &to, amount).map_err(|_| "transfer error")?;
+ <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;
Ok(true)
}
#[weight(<SelfWeightOf<T>>::transfer_from())]
pallets/fungible/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 core::ops::Deref;20use frame_support::{ensure};21use pallet_evm::account::CrossAccountId;22use up_data_structs::{23 AccessMode, CollectionId, TokenId, CreateCollectionData, mapping::TokenAddressMapping,24 budget::Budget,25};26use pallet_common::{27 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,28 CollectionHandle, dispatch::CollectionDispatch,29};30use pallet_structure::Pallet as PalletStructure;31use pallet_evm_coder_substrate::WithRecorder;32use sp_core::H160;33use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};34use sp_std::collections::btree_map::BTreeMap;3536pub use pallet::*;3738use crate::erc::ERC20Events;39#[cfg(feature = "runtime-benchmarks")]40pub mod benchmarking;41pub mod common;42pub mod erc;43pub mod weights;4445pub type CreateItemData<T> = (<T as pallet_evm::account::Config>::CrossAccountId, u128);46pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;4748#[frame_support::pallet]49pub mod pallet {50 use frame_support::{Blake2_128, Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};51 use up_data_structs::CollectionId;52 use super::weights::WeightInfo;5354 #[pallet::error]55 pub enum Error<T> {56 /// Not Fungible item data used to mint in Fungible collection.57 NotFungibleDataUsedToMintFungibleCollectionToken,58 /// Not default id passed as TokenId argument59 FungibleItemsHaveNoId,60 /// Tried to set data for fungible item61 FungibleItemsDontHaveData,62 /// Fungible token does not support nested63 FungibleDisallowsNesting,64 }6566 #[pallet::config]67 pub trait Config:68 frame_system::Config + pallet_common::Config + pallet_structure::Config69 {70 type WeightInfo: WeightInfo;71 }7273 #[pallet::pallet]74 #[pallet::generate_store(pub(super) trait Store)]75 pub struct Pallet<T>(_);7677 #[pallet::storage]78 pub type TotalSupply<T: Config> =79 StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u128, QueryKind = ValueQuery>;8081 #[pallet::storage]82 pub type Balance<T: Config> = StorageNMap<83 Key = (84 Key<Twox64Concat, CollectionId>,85 Key<Blake2_128Concat, T::CrossAccountId>,86 ),87 Value = u128,88 QueryKind = ValueQuery,89 >;9091 #[pallet::storage]92 pub type Allowance<T: Config> = StorageNMap<93 Key = (94 Key<Twox64Concat, CollectionId>,95 Key<Blake2_128, T::CrossAccountId>,96 Key<Blake2_128Concat, T::CrossAccountId>,97 ),98 Value = u128,99 QueryKind = ValueQuery,100 >;101}102103pub struct FungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);104impl<T: Config> FungibleHandle<T> {105 pub fn cast(inner: pallet_common::CollectionHandle<T>) -> Self {106 Self(inner)107 }108 pub fn into_inner(self) -> pallet_common::CollectionHandle<T> {109 self.0110 }111}112impl<T: Config> WithRecorder<T> for FungibleHandle<T> {113 fn recorder(&self) -> &pallet_evm_coder_substrate::SubstrateRecorder<T> {114 self.0.recorder()115 }116 fn into_recorder(self) -> pallet_evm_coder_substrate::SubstrateRecorder<T> {117 self.0.into_recorder()118 }119}120impl<T: Config> Deref for FungibleHandle<T> {121 type Target = pallet_common::CollectionHandle<T>;122123 fn deref(&self) -> &Self::Target {124 &self.0125 }126}127128impl<T: Config> Pallet<T> {129 pub fn init_collection(130 owner: T::AccountId,131 data: CreateCollectionData<T::AccountId>,132 ) -> Result<CollectionId, DispatchError> {133 <PalletCommon<T>>::init_collection(owner, data)134 }135 pub fn destroy_collection(136 collection: FungibleHandle<T>,137 sender: &T::CrossAccountId,138 ) -> DispatchResult {139 let id = collection.id;140141 // =========142143 PalletCommon::destroy_collection(collection.0, sender)?;144145 <TotalSupply<T>>::remove(id);146 <Balance<T>>::remove_prefix((id,), None);147 <Allowance<T>>::remove_prefix((id,), None);148 Ok(())149 }150151 pub fn burn(152 collection: &FungibleHandle<T>,153 owner: &T::CrossAccountId,154 amount: u128,155 ) -> DispatchResult {156 let total_supply = <TotalSupply<T>>::get(collection.id)157 .checked_sub(amount)158 .ok_or(<CommonError<T>>::TokenValueTooLow)?;159160 let balance = <Balance<T>>::get((collection.id, owner))161 .checked_sub(amount)162 .ok_or(<CommonError<T>>::TokenValueTooLow)?;163164 if collection.access == AccessMode::AllowList {165 collection.check_allowlist(owner)?;166 }167168 // =========169170 if balance == 0 {171 <Balance<T>>::remove((collection.id, owner));172 } else {173 <Balance<T>>::insert((collection.id, owner), balance);174 }175 <TotalSupply<T>>::insert(collection.id, total_supply);176177 collection.log_mirrored(ERC20Events::Transfer {178 from: *owner.as_eth(),179 to: H160::default(),180 value: amount.into(),181 });182 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(183 collection.id,184 TokenId::default(),185 owner.clone(),186 amount,187 ));188 Ok(())189 }190191 pub fn transfer(192 collection: &FungibleHandle<T>,193 from: &T::CrossAccountId,194 to: &T::CrossAccountId,195 amount: u128,196 ) -> DispatchResult {197 ensure!(198 collection.limits.transfers_enabled(),199 <CommonError<T>>::TransferNotAllowed,200 );201202 if collection.access == AccessMode::AllowList {203 collection.check_allowlist(from)?;204 collection.check_allowlist(to)?;205 }206 <PalletCommon<T>>::ensure_correct_receiver(to)?;207208 let balance_from = <Balance<T>>::get((collection.id, from))209 .checked_sub(amount)210 .ok_or(<CommonError<T>>::TokenValueTooLow)?;211 let balance_to = if from != to {212 Some(213 <Balance<T>>::get((collection.id, to))214 .checked_add(amount)215 .ok_or(ArithmeticError::Overflow)?,216 )217 } else {218 None219 };220221 if let Some(target) = T::CrossTokenAddressMapping::address_to_token(to) {222 let handle = <CollectionHandle<T>>::try_get(target.0)?;223 let dispatch = T::CollectionDispatch::dispatch(handle);224 let dispatch = dispatch.as_dyn();225226 // =========227228 dispatch.nest_token(from.clone(), (collection.id, TokenId::default()), target.1)?;229 }230231 if let Some(balance_to) = balance_to {232 // from != to233 if balance_from == 0 {234 <Balance<T>>::remove((collection.id, from));235 } else {236 <Balance<T>>::insert((collection.id, from), balance_from);237 }238 <Balance<T>>::insert((collection.id, to), balance_to);239 }240241 collection.log_mirrored(ERC20Events::Transfer {242 from: *from.as_eth(),243 to: *to.as_eth(),244 value: amount.into(),245 });246 <PalletCommon<T>>::deposit_event(CommonEvent::Transfer(247 collection.id,248 TokenId::default(),249 from.clone(),250 to.clone(),251 amount,252 ));253 Ok(())254 }255256 pub fn create_multiple_items(257 collection: &FungibleHandle<T>,258 sender: &T::CrossAccountId,259 data: BTreeMap<T::CrossAccountId, u128>,260 ) -> DispatchResult {261 if !collection.is_owner_or_admin(sender) {262 ensure!(263 collection.mint_mode,264 <CommonError<T>>::PublicMintingNotAllowed265 );266 collection.check_allowlist(sender)?;267268 for (owner, _) in data.iter() {269 collection.check_allowlist(owner)?;270 }271 }272273 let total_supply = data274 .iter()275 .map(|(_, v)| *v)276 .try_fold(<TotalSupply<T>>::get(collection.id), |acc, v| {277 acc.checked_add(v)278 })279 .ok_or(ArithmeticError::Overflow)?;280281 let mut balances = data;282 for (k, v) in balances.iter_mut() {283 *v = <Balance<T>>::get((collection.id, &k))284 .checked_add(*v)285 .ok_or(ArithmeticError::Overflow)?;286 }287288 // =========289290 <TotalSupply<T>>::insert(collection.id, total_supply);291 for (user, amount) in balances {292 <Balance<T>>::insert((collection.id, &user), amount);293294 collection.log_mirrored(ERC20Events::Transfer {295 from: H160::default(),296 to: *user.as_eth(),297 value: amount.into(),298 });299 <PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(300 collection.id,301 TokenId::default(),302 user.clone(),303 amount,304 ));305 }306307 Ok(())308 }309310 fn set_allowance_unchecked(311 collection: &FungibleHandle<T>,312 owner: &T::CrossAccountId,313 spender: &T::CrossAccountId,314 amount: u128,315 ) {316 if amount == 0 {317 <Allowance<T>>::remove((collection.id, owner, spender));318 } else {319 <Allowance<T>>::insert((collection.id, owner, spender), amount);320 }321322 collection.log_mirrored(ERC20Events::Approval {323 owner: *owner.as_eth(),324 spender: *spender.as_eth(),325 value: amount.into(),326 });327 <PalletCommon<T>>::deposit_event(CommonEvent::Approved(328 collection.id,329 TokenId(0),330 owner.clone(),331 spender.clone(),332 amount,333 ));334 }335336 pub fn set_allowance(337 collection: &FungibleHandle<T>,338 owner: &T::CrossAccountId,339 spender: &T::CrossAccountId,340 amount: u128,341 ) -> DispatchResult {342 if collection.access == AccessMode::AllowList {343 collection.check_allowlist(owner)?;344 collection.check_allowlist(spender)?;345 }346347 if <Balance<T>>::get((collection.id, owner)) < amount {348 ensure!(349 collection.ignores_owned_amount(owner),350 <CommonError<T>>::CantApproveMoreThanOwned351 );352 }353354 // =========355356 Self::set_allowance_unchecked(collection, owner, spender, amount);357 Ok(())358 }359360 fn check_allowed(361 collection: &FungibleHandle<T>,362 spender: &T::CrossAccountId,363 from: &T::CrossAccountId,364 amount: u128,365 nesting_budget: &dyn Budget,366 ) -> Result<Option<u128>, DispatchError> {367 if spender.conv_eq(from) {368 return Ok(None);369 }370 if collection.access == AccessMode::AllowList {371 // `from`, `to` checked in [`transfer`]372 collection.check_allowlist(spender)?;373 }374 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {375 // TODO: should collection owner be allowed to perform this transfer?376 ensure!(377 <PalletStructure<T>>::indirectly_owned(378 spender.clone(),379 source.0,380 source.1,381 nesting_budget382 )?,383 <CommonError<T>>::ApprovedValueTooLow,384 );385 return Ok(None);386 }387 let allowance = <Allowance<T>>::get((collection.id, from, spender)).checked_sub(amount);388 if allowance.is_none() {389 ensure!(390 collection.ignores_allowance(spender),391 <CommonError<T>>::ApprovedValueTooLow392 );393 }394395 Ok(allowance)396 }397398 pub fn transfer_from(399 collection: &FungibleHandle<T>,400 spender: &T::CrossAccountId,401 from: &T::CrossAccountId,402 to: &T::CrossAccountId,403 amount: u128,404 nesting_budget: &dyn Budget,405 ) -> DispatchResult {406 let allowance = Self::check_allowed(collection, spender, from, amount, nesting_budget)?;407408 // =========409410 Self::transfer(collection, from, to, amount)?;411 if let Some(allowance) = allowance {412 Self::set_allowance_unchecked(collection, from, spender, allowance);413 }414 Ok(())415 }416417 pub fn burn_from(418 collection: &FungibleHandle<T>,419 spender: &T::CrossAccountId,420 from: &T::CrossAccountId,421 amount: u128,422 nesting_budget: &dyn Budget,423 ) -> DispatchResult {424 let allowance = Self::check_allowed(collection, spender, from, amount, nesting_budget)?;425426 // =========427428 Self::burn(collection, from, amount)?;429 if let Some(allowance) = allowance {430 Self::set_allowance_unchecked(collection, from, spender, allowance);431 }432 Ok(())433 }434435 /// Delegated to `create_multiple_items`436 pub fn create_item(437 collection: &FungibleHandle<T>,438 sender: &T::CrossAccountId,439 data: CreateItemData<T>,440 ) -> DispatchResult {441 Self::create_multiple_items(collection, sender, [(data.0, data.1)].into_iter().collect())442 }443}1// 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 core::ops::Deref;20use frame_support::{ensure};21use pallet_evm::account::CrossAccountId;22use up_data_structs::{23 AccessMode, CollectionId, TokenId, CreateCollectionData, mapping::TokenAddressMapping,24 budget::Budget,25};26use pallet_common::{27 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,28 CollectionHandle, dispatch::CollectionDispatch,29};30use pallet_structure::Pallet as PalletStructure;31use pallet_evm_coder_substrate::WithRecorder;32use sp_core::H160;33use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};34use sp_std::collections::btree_map::BTreeMap;3536pub use pallet::*;3738use crate::erc::ERC20Events;39#[cfg(feature = "runtime-benchmarks")]40pub mod benchmarking;41pub mod common;42pub mod erc;43pub mod weights;4445pub type CreateItemData<T> = (<T as pallet_evm::account::Config>::CrossAccountId, u128);46pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;4748#[frame_support::pallet]49pub mod pallet {50 use frame_support::{Blake2_128, Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};51 use up_data_structs::CollectionId;52 use super::weights::WeightInfo;5354 #[pallet::error]55 pub enum Error<T> {56 /// Not Fungible item data used to mint in Fungible collection.57 NotFungibleDataUsedToMintFungibleCollectionToken,58 /// Not default id passed as TokenId argument59 FungibleItemsHaveNoId,60 /// Tried to set data for fungible item61 FungibleItemsDontHaveData,62 /// Fungible token does not support nested63 FungibleDisallowsNesting,64 }6566 #[pallet::config]67 pub trait Config:68 frame_system::Config + pallet_common::Config + pallet_structure::Config69 {70 type WeightInfo: WeightInfo;71 }7273 #[pallet::pallet]74 #[pallet::generate_store(pub(super) trait Store)]75 pub struct Pallet<T>(_);7677 #[pallet::storage]78 pub type TotalSupply<T: Config> =79 StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u128, QueryKind = ValueQuery>;8081 #[pallet::storage]82 pub type Balance<T: Config> = StorageNMap<83 Key = (84 Key<Twox64Concat, CollectionId>,85 Key<Blake2_128Concat, T::CrossAccountId>,86 ),87 Value = u128,88 QueryKind = ValueQuery,89 >;9091 #[pallet::storage]92 pub type Allowance<T: Config> = StorageNMap<93 Key = (94 Key<Twox64Concat, CollectionId>,95 Key<Blake2_128, T::CrossAccountId>,96 Key<Blake2_128Concat, T::CrossAccountId>,97 ),98 Value = u128,99 QueryKind = ValueQuery,100 >;101}102103pub struct FungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);104impl<T: Config> FungibleHandle<T> {105 pub fn cast(inner: pallet_common::CollectionHandle<T>) -> Self {106 Self(inner)107 }108 pub fn into_inner(self) -> pallet_common::CollectionHandle<T> {109 self.0110 }111}112impl<T: Config> WithRecorder<T> for FungibleHandle<T> {113 fn recorder(&self) -> &pallet_evm_coder_substrate::SubstrateRecorder<T> {114 self.0.recorder()115 }116 fn into_recorder(self) -> pallet_evm_coder_substrate::SubstrateRecorder<T> {117 self.0.into_recorder()118 }119}120impl<T: Config> Deref for FungibleHandle<T> {121 type Target = pallet_common::CollectionHandle<T>;122123 fn deref(&self) -> &Self::Target {124 &self.0125 }126}127128impl<T: Config> Pallet<T> {129 pub fn init_collection(130 owner: T::AccountId,131 data: CreateCollectionData<T::AccountId>,132 ) -> Result<CollectionId, DispatchError> {133 <PalletCommon<T>>::init_collection(owner, data)134 }135 pub fn destroy_collection(136 collection: FungibleHandle<T>,137 sender: &T::CrossAccountId,138 ) -> DispatchResult {139 let id = collection.id;140141 // =========142143 PalletCommon::destroy_collection(collection.0, sender)?;144145 <TotalSupply<T>>::remove(id);146 <Balance<T>>::remove_prefix((id,), None);147 <Allowance<T>>::remove_prefix((id,), None);148 Ok(())149 }150151 pub fn burn(152 collection: &FungibleHandle<T>,153 owner: &T::CrossAccountId,154 amount: u128,155 ) -> DispatchResult {156 let total_supply = <TotalSupply<T>>::get(collection.id)157 .checked_sub(amount)158 .ok_or(<CommonError<T>>::TokenValueTooLow)?;159160 let balance = <Balance<T>>::get((collection.id, owner))161 .checked_sub(amount)162 .ok_or(<CommonError<T>>::TokenValueTooLow)?;163164 if collection.access == AccessMode::AllowList {165 collection.check_allowlist(owner)?;166 }167168 // =========169170 if balance == 0 {171 <Balance<T>>::remove((collection.id, owner));172 } else {173 <Balance<T>>::insert((collection.id, owner), balance);174 }175 <TotalSupply<T>>::insert(collection.id, total_supply);176177 collection.log_mirrored(ERC20Events::Transfer {178 from: *owner.as_eth(),179 to: H160::default(),180 value: amount.into(),181 });182 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(183 collection.id,184 TokenId::default(),185 owner.clone(),186 amount,187 ));188 Ok(())189 }190191 pub fn transfer(192 collection: &FungibleHandle<T>,193 from: &T::CrossAccountId,194 to: &T::CrossAccountId,195 amount: u128,196 nesting_budget: &dyn Budget,197 ) -> DispatchResult {198 ensure!(199 collection.limits.transfers_enabled(),200 <CommonError<T>>::TransferNotAllowed,201 );202203 if collection.access == AccessMode::AllowList {204 collection.check_allowlist(from)?;205 collection.check_allowlist(to)?;206 }207 <PalletCommon<T>>::ensure_correct_receiver(to)?;208209 let balance_from = <Balance<T>>::get((collection.id, from))210 .checked_sub(amount)211 .ok_or(<CommonError<T>>::TokenValueTooLow)?;212 let balance_to = if from != to {213 Some(214 <Balance<T>>::get((collection.id, to))215 .checked_add(amount)216 .ok_or(ArithmeticError::Overflow)?,217 )218 } else {219 None220 };221222 if let Some(target) = T::CrossTokenAddressMapping::address_to_token(to) {223 let handle = <CollectionHandle<T>>::try_get(target.0)?;224 let dispatch = T::CollectionDispatch::dispatch(handle);225 let dispatch = dispatch.as_dyn();226227 dispatch.check_nesting(from.clone(), collection.id, target.1, nesting_budget)?;228 }229230 // =========231232 if let Some(balance_to) = balance_to {233 // from != to234 if balance_from == 0 {235 <Balance<T>>::remove((collection.id, from));236 } else {237 <Balance<T>>::insert((collection.id, from), balance_from);238 }239 <Balance<T>>::insert((collection.id, to), balance_to);240 }241242 collection.log_mirrored(ERC20Events::Transfer {243 from: *from.as_eth(),244 to: *to.as_eth(),245 value: amount.into(),246 });247 <PalletCommon<T>>::deposit_event(CommonEvent::Transfer(248 collection.id,249 TokenId::default(),250 from.clone(),251 to.clone(),252 amount,253 ));254 Ok(())255 }256257 pub fn create_multiple_items(258 collection: &FungibleHandle<T>,259 sender: &T::CrossAccountId,260 data: BTreeMap<T::CrossAccountId, u128>,261 nesting_budget: &dyn Budget,262 ) -> DispatchResult {263 if !collection.is_owner_or_admin(sender) {264 ensure!(265 collection.mint_mode,266 <CommonError<T>>::PublicMintingNotAllowed267 );268 collection.check_allowlist(sender)?;269270 for (owner, _) in data.iter() {271 collection.check_allowlist(owner)?;272 }273 }274275 let total_supply = data276 .iter()277 .map(|(_, v)| *v)278 .try_fold(<TotalSupply<T>>::get(collection.id), |acc, v| {279 acc.checked_add(v)280 })281 .ok_or(ArithmeticError::Overflow)?;282283 let mut balances = data;284 for (k, v) in balances.iter_mut() {285 *v = <Balance<T>>::get((collection.id, &k))286 .checked_add(*v)287 .ok_or(ArithmeticError::Overflow)?;288 }289290 for (to, _) in balances.iter() {291 if let Some(target) = T::CrossTokenAddressMapping::address_to_token(to) {292 let handle = <CollectionHandle<T>>::try_get(target.0)?;293 let dispatch = T::CollectionDispatch::dispatch(handle);294 let dispatch = dispatch.as_dyn();295296 dispatch.check_nesting(sender.clone(), collection.id, target.1, nesting_budget)?;297 }298 }299300 // =========301302 <TotalSupply<T>>::insert(collection.id, total_supply);303 for (user, amount) in balances {304 <Balance<T>>::insert((collection.id, &user), amount);305306 collection.log_mirrored(ERC20Events::Transfer {307 from: H160::default(),308 to: *user.as_eth(),309 value: amount.into(),310 });311 <PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(312 collection.id,313 TokenId::default(),314 user.clone(),315 amount,316 ));317 }318319 Ok(())320 }321322 fn set_allowance_unchecked(323 collection: &FungibleHandle<T>,324 owner: &T::CrossAccountId,325 spender: &T::CrossAccountId,326 amount: u128,327 ) {328 if amount == 0 {329 <Allowance<T>>::remove((collection.id, owner, spender));330 } else {331 <Allowance<T>>::insert((collection.id, owner, spender), amount);332 }333334 collection.log_mirrored(ERC20Events::Approval {335 owner: *owner.as_eth(),336 spender: *spender.as_eth(),337 value: amount.into(),338 });339 <PalletCommon<T>>::deposit_event(CommonEvent::Approved(340 collection.id,341 TokenId(0),342 owner.clone(),343 spender.clone(),344 amount,345 ));346 }347348 pub fn set_allowance(349 collection: &FungibleHandle<T>,350 owner: &T::CrossAccountId,351 spender: &T::CrossAccountId,352 amount: u128,353 ) -> DispatchResult {354 if collection.access == AccessMode::AllowList {355 collection.check_allowlist(owner)?;356 collection.check_allowlist(spender)?;357 }358359 if <Balance<T>>::get((collection.id, owner)) < amount {360 ensure!(361 collection.ignores_owned_amount(owner),362 <CommonError<T>>::CantApproveMoreThanOwned363 );364 }365366 // =========367368 Self::set_allowance_unchecked(collection, owner, spender, amount);369 Ok(())370 }371372 fn check_allowed(373 collection: &FungibleHandle<T>,374 spender: &T::CrossAccountId,375 from: &T::CrossAccountId,376 amount: u128,377 nesting_budget: &dyn Budget,378 ) -> Result<Option<u128>, DispatchError> {379 if spender.conv_eq(from) {380 return Ok(None);381 }382 if collection.access == AccessMode::AllowList {383 // `from`, `to` checked in [`transfer`]384 collection.check_allowlist(spender)?;385 }386 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {387 // TODO: should collection owner be allowed to perform this transfer?388 ensure!(389 <PalletStructure<T>>::indirectly_owned(390 spender.clone(),391 source.0,392 source.1,393 nesting_budget394 )?,395 <CommonError<T>>::ApprovedValueTooLow,396 );397 return Ok(None);398 }399 let allowance = <Allowance<T>>::get((collection.id, from, spender)).checked_sub(amount);400 if allowance.is_none() {401 ensure!(402 collection.ignores_allowance(spender),403 <CommonError<T>>::ApprovedValueTooLow404 );405 }406407 Ok(allowance)408 }409410 pub fn transfer_from(411 collection: &FungibleHandle<T>,412 spender: &T::CrossAccountId,413 from: &T::CrossAccountId,414 to: &T::CrossAccountId,415 amount: u128,416 nesting_budget: &dyn Budget,417 ) -> DispatchResult {418 let allowance = Self::check_allowed(collection, spender, from, amount, nesting_budget)?;419420 // =========421422 Self::transfer(collection, from, to, amount, nesting_budget)?;423 if let Some(allowance) = allowance {424 Self::set_allowance_unchecked(collection, from, spender, allowance);425 }426 Ok(())427 }428429 pub fn burn_from(430 collection: &FungibleHandle<T>,431 spender: &T::CrossAccountId,432 from: &T::CrossAccountId,433 amount: u128,434 nesting_budget: &dyn Budget,435 ) -> DispatchResult {436 let allowance = Self::check_allowed(collection, spender, from, amount, nesting_budget)?;437438 // =========439440 Self::burn(collection, from, amount)?;441 if let Some(allowance) = allowance {442 Self::set_allowance_unchecked(collection, from, spender, allowance);443 }444 Ok(())445 }446447 /// Delegated to `create_multiple_items`448 pub fn create_item(449 collection: &FungibleHandle<T>,450 sender: &T::CrossAccountId,451 data: CreateItemData<T>,452 nesting_budget: &dyn Budget,453 ) -> DispatchResult {454 Self::create_multiple_items(455 collection,456 sender,457 [(data.0, data.1)].into_iter().collect(),458 nesting_budget,459 )460 }461}pallets/nonfungible/src/common.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -89,9 +89,15 @@
sender: T::CrossAccountId,
to: T::CrossAccountId,
data: up_data_structs::CreateItemData,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
with_weight(
- <Pallet<T>>::create_item(self, &sender, map_create_data::<T>(data, &to)?),
+ <Pallet<T>>::create_item(
+ self,
+ &sender,
+ map_create_data::<T>(data, &to)?,
+ nesting_budget,
+ ),
<CommonWeights<T>>::create_item(),
)
}
@@ -101,6 +107,7 @@
sender: T::CrossAccountId,
to: T::CrossAccountId,
data: Vec<up_data_structs::CreateItemData>,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
let data = data
.into_iter()
@@ -109,7 +116,7 @@
let amount = data.len();
with_weight(
- <Pallet<T>>::create_multiple_items(self, &sender, data),
+ <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),
<CommonWeights<T>>::create_multiple_items(amount as u32),
)
}
@@ -118,6 +125,7 @@
&self,
sender: <T>::CrossAccountId,
data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);
let data = match data {
@@ -126,7 +134,7 @@
};
with_weight(
- <Pallet<T>>::create_multiple_items(self, &sender, data.into_inner()),
+ <Pallet<T>>::create_multiple_items(self, &sender, data.into_inner(), nesting_budget),
weight,
)
}
@@ -154,11 +162,12 @@
to: T::CrossAccountId,
token: TokenId,
amount: u128,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);
if amount == 1 {
with_weight(
- <Pallet<T>>::transfer(self, &from, &to, token),
+ <Pallet<T>>::transfer(self, &from, &to, token, nesting_budget),
<CommonWeights<T>>::transfer(),
)
} else {
@@ -239,13 +248,14 @@
)
}
- fn nest_token(
+ fn check_nesting(
&self,
sender: T::CrossAccountId,
- (from, _): (CollectionId, TokenId),
+ from: CollectionId,
under: TokenId,
+ budget: &dyn Budget,
) -> sp_runtime::DispatchResult {
- <Pallet<T>>::nest_token(self, sender, from, under)
+ <Pallet<T>>::check_nesting(self, sender, from, under, budget)
}
fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -256,6 +256,10 @@
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let token_id: u32 = token_id.try_into()?;
+ let budget = self
+ .recorder
+ .weight_calls_budget(<StructureWeight<T>>::find_parent());
+
if <TokensMinted<T>>::get(self.id)
.checked_add(1)
.ok_or("item id overflow")?
@@ -272,6 +276,7 @@
variable_data: BoundedVec::default(),
owner: to,
},
+ &budget,
)
.map_err(dispatch_to_evm::<T>)?;
@@ -296,6 +301,10 @@
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;
+ let budget = self
+ .recorder
+ .weight_calls_budget(<StructureWeight<T>>::find_parent());
+
if <TokensMinted<T>>::get(self.id)
.checked_add(1)
.ok_or("item id overflow")?
@@ -314,6 +323,7 @@
variable_data: BoundedVec::default(),
owner: to,
},
+ &budget,
)
.map_err(dispatch_to_evm::<T>)?;
Ok(true)
@@ -338,8 +348,11 @@
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let token = token_id.try_into()?;
+ let budget = self
+ .recorder
+ .weight_calls_budget(<StructureWeight<T>>::find_parent());
- <Pallet<T>>::transfer(self, &caller, &to, token).map_err(dispatch_to_evm::<T>)?;
+ <Pallet<T>>::transfer(self, &caller, &to, token, &budget).map_err(dispatch_to_evm::<T>)?;
Ok(())
}
@@ -409,6 +422,9 @@
let mut expected_index = <TokensMinted<T>>::get(self.id)
.checked_add(1)
.ok_or("item id overflow")?;
+ let budget = self
+ .recorder
+ .weight_calls_budget(<StructureWeight<T>>::find_parent());
let total_tokens = token_ids.len();
for id in token_ids.into_iter() {
@@ -426,7 +442,8 @@
})
.collect();
- <Pallet<T>>::create_multiple_items(self, &caller, data).map_err(dispatch_to_evm::<T>)?;
+ <Pallet<T>>::create_multiple_items(self, &caller, data, &budget)
+ .map_err(dispatch_to_evm::<T>)?;
Ok(true)
}
@@ -447,6 +464,9 @@
let mut expected_index = <TokensMinted<T>>::get(self.id)
.checked_add(1)
.ok_or("item id overflow")?;
+ let budget = self
+ .recorder
+ .weight_calls_budget(<StructureWeight<T>>::find_parent());
let mut data = Vec::with_capacity(tokens.len());
for (id, token_uri) in tokens {
@@ -465,7 +485,8 @@
});
}
- <Pallet<T>>::create_multiple_items(self, &caller, data).map_err(dispatch_to_evm::<T>)?;
+ <Pallet<T>>::create_multiple_items(self, &caller, data, &budget)
+ .map_err(dispatch_to_evm::<T>)?;
Ok(true)
}
}
pallets/nonfungible/src/lib.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -251,6 +251,7 @@
from: &T::CrossAccountId,
to: &T::CrossAccountId,
token: TokenId,
+ nesting_budget: &dyn Budget,
) -> DispatchResult {
ensure!(
collection.limits.transfers_enabled(),
@@ -294,12 +295,12 @@
let handle = <CollectionHandle<T>>::try_get(target.0)?;
let dispatch = T::CollectionDispatch::dispatch(handle);
let dispatch = dispatch.as_dyn();
-
- // =========
- dispatch.nest_token(from.clone(), (collection.id, token), target.1)?;
+ dispatch.check_nesting(from.clone(), collection.id, target.1, nesting_budget)?;
}
+ // =========
+
<TokenData<T>>::insert(
(collection.id, token),
ItemData {
@@ -340,6 +341,7 @@
collection: &NonfungibleHandle<T>,
sender: &T::CrossAccountId,
data: Vec<CreateItemData<T>>,
+ nesting_budget: &dyn Budget,
) -> DispatchResult {
if !collection.is_owner_or_admin(sender) {
ensure!(
@@ -379,6 +381,16 @@
);
}
+ for (to, _) in balances.iter() {
+ if let Some(target) = T::CrossTokenAddressMapping::address_to_token(to) {
+ let handle = <CollectionHandle<T>>::try_get(target.0)?;
+ let dispatch = T::CollectionDispatch::dispatch(handle);
+ let dispatch = dispatch.as_dyn();
+
+ dispatch.check_nesting(sender.clone(), collection.id, target.1, nesting_budget)?;
+ }
+ }
+
// =========
<TokensMinted<T>>::insert(collection.id, tokens_minted);
@@ -556,7 +568,7 @@
// =========
// Allowance is reset in [`transfer`]
- Self::transfer(collection, from, to, token)
+ Self::transfer(collection, from, to, token, nesting_budget)
}
pub fn burn_from(
@@ -595,35 +607,34 @@
Ok(())
}
- pub fn nest_token(
+ pub fn check_nesting(
handle: &NonfungibleHandle<T>,
sender: T::CrossAccountId,
from: CollectionId,
under: TokenId,
+ nesting_budget: &dyn Budget,
) -> DispatchResult {
fn ensure_sender_allowed<T: Config>(
collection: CollectionId,
token: TokenId,
sender: T::CrossAccountId,
+ budget: &dyn Budget,
) -> DispatchResult {
ensure!(
- <TokenData<T>>::get((collection, token))
- .ok_or(<CommonError<T>>::TokenNotFound)?
- .owner
- .conv_eq(&sender),
+ <PalletStructure<T>>::indirectly_owned(sender, collection, token, budget)?,
<CommonError<T>>::OnlyOwnerAllowedToNest,
);
Ok(())
}
match handle.limits.nesting_rule() {
NestingRule::Disabled => fail!(<CommonError<T>>::NestingIsDisabled),
- NestingRule::Owner => ensure_sender_allowed::<T>(from, under, sender)?,
+ NestingRule::Owner => ensure_sender_allowed::<T>(from, under, sender, nesting_budget)?,
NestingRule::OwnerRestricted(whitelist) => {
ensure!(
whitelist.contains(&from),
<CommonError<T>>::SourceCollectionIsNotAllowedToNest
);
- ensure_sender_allowed::<T>(from, under, sender)?
+ ensure_sender_allowed::<T>(from, under, sender, nesting_budget)?
}
}
Ok(())
@@ -634,7 +645,8 @@
collection: &NonfungibleHandle<T>,
sender: &T::CrossAccountId,
data: CreateItemData<T>,
+ nesting_budget: &dyn Budget,
) -> DispatchResult {
- Self::create_multiple_items(collection, sender, vec![data])
+ Self::create_multiple_items(collection, sender, vec![data], nesting_budget)
}
}
pallets/refungible/src/common.rsdiffbeforeafterboth--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -19,7 +19,8 @@
use sp_std::collections::btree_map::BTreeMap;
use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight, BoundedVec};
use up_data_structs::{
- TokenId, CustomDataLimit, CreateItemExData, CreateRefungibleExData, budget::Budget,
+ CollectionId, TokenId, CustomDataLimit, CreateItemExData, CreateRefungibleExData,
+ budget::Budget,
};
use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
use sp_runtime::DispatchError;
@@ -120,9 +121,15 @@
sender: T::CrossAccountId,
to: T::CrossAccountId,
data: up_data_structs::CreateItemData,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
with_weight(
- <Pallet<T>>::create_item(self, &sender, map_create_data::<T>(data, &to)?),
+ <Pallet<T>>::create_item(
+ self,
+ &sender,
+ map_create_data::<T>(data, &to)?,
+ nesting_budget,
+ ),
<CommonWeights<T>>::create_item(),
)
}
@@ -132,6 +139,7 @@
sender: T::CrossAccountId,
to: T::CrossAccountId,
data: Vec<up_data_structs::CreateItemData>,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
let data = data
.into_iter()
@@ -140,7 +148,7 @@
let amount = data.len();
with_weight(
- <Pallet<T>>::create_multiple_items(self, &sender, data),
+ <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),
<CommonWeights<T>>::create_multiple_items(amount as u32),
)
}
@@ -149,6 +157,7 @@
&self,
sender: <T>::CrossAccountId,
data: CreateItemExData<T::CrossAccountId>,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);
let data = match data {
@@ -162,7 +171,7 @@
};
with_weight(
- <Pallet<T>>::create_multiple_items(self, &sender, data),
+ <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),
weight,
)
}
@@ -185,9 +194,10 @@
to: T::CrossAccountId,
token: TokenId,
amount: u128,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
with_weight(
- <Pallet<T>>::transfer(self, &from, &to, token, amount),
+ <Pallet<T>>::transfer(self, &from, &to, token, amount, nesting_budget),
<CommonWeights<T>>::transfer(),
)
}
@@ -247,11 +257,12 @@
)
}
- fn nest_token(
+ fn check_nesting(
&self,
_sender: <T>::CrossAccountId,
- _from: (up_data_structs::CollectionId, TokenId),
+ _from: CollectionId,
_under: TokenId,
+ _budget: &dyn Budget,
) -> sp_runtime::DispatchResult {
fail!(<Error<T>>::RefungibleDisallowsNesting)
}
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -289,6 +289,7 @@
to: &T::CrossAccountId,
token: TokenId,
amount: u128,
+ nesting_budget: &dyn Budget,
) -> DispatchResult {
ensure!(
collection.limits.transfers_enabled(),
@@ -351,10 +352,10 @@
let dispatch = T::CollectionDispatch::dispatch(handle);
let dispatch = dispatch.as_dyn();
- // =========
+ dispatch.check_nesting(from.clone(), collection.id, target.1, nesting_budget)?;
+ }
- dispatch.nest_token(from.clone(), (collection.id, token), target.1)?;
- }
+ // =========
if let Some(balance_to) = balance_to {
// from != to
@@ -389,6 +390,7 @@
collection: &RefungibleHandle<T>,
sender: &T::CrossAccountId,
data: Vec<CreateRefungibleExData<T::CrossAccountId>>,
+ nesting_budget: &dyn Budget,
) -> DispatchResult {
if !collection.is_owner_or_admin(sender) {
ensure!(
@@ -453,6 +455,23 @@
}
}
+ for token in data.iter() {
+ for (to, _) in token.users.iter() {
+ if let Some(target) = T::CrossTokenAddressMapping::address_to_token(to) {
+ let handle = <CollectionHandle<T>>::try_get(target.0)?;
+ let dispatch = T::CollectionDispatch::dispatch(handle);
+ let dispatch = dispatch.as_dyn();
+
+ dispatch.check_nesting(
+ sender.clone(),
+ collection.id,
+ target.1,
+ nesting_budget,
+ )?;
+ }
+ }
+ }
+
// =========
<TokensMinted<T>>::insert(collection.id, tokens_minted);
@@ -591,7 +610,7 @@
// =========
- Self::transfer(collection, from, to, token, amount)?;
+ Self::transfer(collection, from, to, token, amount, nesting_budget)?;
if let Some(allowance) = allowance {
Self::set_allowance_unchecked(collection, from, spender, token, allowance);
}
@@ -648,7 +667,8 @@
collection: &RefungibleHandle<T>,
sender: &T::CrossAccountId,
data: CreateRefungibleExData<T::CrossAccountId>,
+ nesting_budget: &dyn Budget,
) -> DispatchResult {
- Self::create_multiple_items(collection, sender, vec![data])
+ Self::create_multiple_items(collection, sender, vec![data], nesting_budget)
}
}
pallets/structure/src/lib.rsdiffbeforeafterboth--- a/pallets/structure/src/lib.rs
+++ b/pallets/structure/src/lib.rs
@@ -19,7 +19,6 @@
use frame_support::Parameter;
use frame_support::dispatch::{GetDispatchInfo, UnfilteredDispatchable};
use frame_support::pallet_prelude::*;
- use frame_system::pallet_prelude::*;
use super::*;
pallets/unique/src/lib.rsdiffbeforeafterboth--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -693,8 +693,9 @@
#[transactional]
pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+ let budget = budget::Value::new(2);
- dispatch_call::<T, _>(collection_id, |d| d.create_item(sender, owner, data))
+ dispatch_call::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))
}
/// This method creates multiple items in a collection created with CreateCollection method.
@@ -720,16 +721,18 @@
pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {
ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+ let budget = budget::Value::new(2);
- dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data))
+ dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))
}
#[weight = <CommonWeights<T>>::create_multiple_items_ex(&data)]
#[transactional]
pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+ let budget = budget::Value::new(2);
- dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data))
+ dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))
}
// TODO! transaction weight
@@ -839,8 +842,9 @@
#[transactional]
pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+ let budget = budget::Value::new(2);
- dispatch_call::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value))
+ dispatch_call::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))
}
/// Set, change, or remove approved address to transfer the ownership of the NFT.