git.delta.rocks / unique-network / refs/commits / 7e808da4a3d9

difftreelog

fix revert set_allowance

Daniel Shiposha2022-06-05parent: #e099d8f.patch.diff
in: master

8 files changed

modifiedpallets/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,
modifiedpallets/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(),
modifiedpallets/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(),
 		)
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
before · pallets/nonfungible/src/erc.rs
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/>.1617extern crate alloc;18use core::{19	char::{REPLACEMENT_CHARACTER, decode_utf16},20	convert::TryInto,21};22use evm_coder::{ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*, weight};23use frame_support::BoundedVec;24use up_data_structs::{25	TokenId, PropertyPermission, PropertyKeyPermission, Property, CollectionId, PropertyKey,26	CollectionPropertiesVec,27};28use pallet_evm_coder_substrate::dispatch_to_evm;29use sp_std::vec::Vec;30use pallet_common::{31	erc::{CommonEvmHandler, PrecompileResult, CollectionCall, token_uri_key},32	CollectionHandle, CollectionPropertyPermissions,33};34use pallet_evm::{account::CrossAccountId, PrecompileHandle};35use pallet_evm_coder_substrate::call;36use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};3738use crate::{39	AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,40	SelfWeightOf, weights::WeightInfo, TokenProperties,41};4243#[solidity_interface(name = "TokenProperties")]44impl<T: Config> NonfungibleHandle<T> {45	fn set_token_property_permission(46		&mut self,47		caller: caller,48		key: string,49		is_mutable: bool,50		collection_admin: bool,51		token_owner: bool,52	) -> Result<()> {53		let caller = T::CrossAccountId::from_eth(caller);54		<Pallet<T>>::set_property_permission(55			self,56			&caller,57			PropertyKeyPermission {58				key: <Vec<u8>>::from(key)59					.try_into()60					.map_err(|_| "too long key")?,61				permission: PropertyPermission {62					mutable: is_mutable,63					collection_admin,64					token_owner,65				},66			},67		)68		.map_err(dispatch_to_evm::<T>)69	}7071	fn set_property(72		&mut self,73		caller: caller,74		token_id: uint256,75		key: string,76		value: bytes,77	) -> Result<()> {78		let caller = T::CrossAccountId::from_eth(caller);79		let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;80		let key = <Vec<u8>>::from(key)81			.try_into()82			.map_err(|_| "key too long")?;83		let value = value.try_into().map_err(|_| "value too long")?;8485		<Pallet<T>>::set_token_property(self, &caller, TokenId(token_id), Property { key, value })86			.map_err(dispatch_to_evm::<T>)87	}8889	fn delete_property(&mut self, token_id: uint256, caller: caller, key: string) -> Result<()> {90		let caller = T::CrossAccountId::from_eth(caller);91		let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;92		let key = <Vec<u8>>::from(key)93			.try_into()94			.map_err(|_| "key too long")?;9596		<Pallet<T>>::delete_token_property(self, &caller, TokenId(token_id), key)97			.map_err(dispatch_to_evm::<T>)98	}99100	/// Throws error if key not found101	fn property(&self, token_id: uint256, key: string) -> Result<bytes> {102		let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;103		let key = <Vec<u8>>::from(key)104			.try_into()105			.map_err(|_| "key too long")?;106107		let props = <TokenProperties<T>>::get((self.id, token_id));108		let prop = props.get(&key).ok_or("key not found")?;109110		Ok(prop.to_vec())111	}112}113114#[derive(ToLog)]115pub enum ERC721Events {116	Transfer {117		#[indexed]118		from: address,119		#[indexed]120		to: address,121		#[indexed]122		token_id: uint256,123	},124	Approval {125		#[indexed]126		owner: address,127		#[indexed]128		approved: address,129		#[indexed]130		token_id: uint256,131	},132	#[allow(dead_code)]133	ApprovalForAll {134		#[indexed]135		owner: address,136		#[indexed]137		operator: address,138		approved: bool,139	},140}141142#[derive(ToLog)]143pub enum ERC721MintableEvents {144	#[allow(dead_code)]145	MintingFinished {},146}147148#[solidity_interface(name = "ERC721Metadata")]149impl<T: Config> NonfungibleHandle<T> {150	fn name(&self) -> Result<string> {151		Ok(decode_utf16(self.name.iter().copied())152			.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))153			.collect::<string>())154	}155156	fn symbol(&self) -> Result<string> {157		Ok(string::from_utf8_lossy(&self.token_prefix).into())158	}159160	/// Returns token's const_metadata161	#[solidity(rename_selector = "tokenURI")]162	fn token_uri(&self, token_id: uint256) -> Result<string> {163		let key = token_uri_key();164		if !has_token_permission::<T>(self.id, &key) {165			return Err("No tokenURI permission".into());166		}167168		self.consume_store_reads(1)?;169		let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;170171		let properties = <TokenProperties<T>>::try_get((self.id, token_id))172			.map_err(|_| Error::Revert("Token properties not found".into()))?;173		if let Some(property) = properties.get(&key) {174			return Ok(string::from_utf8_lossy(property).into());175		}176177		Err("Property tokenURI not found".into())178	}179}180181#[solidity_interface(name = "ERC721Enumerable")]182impl<T: Config> NonfungibleHandle<T> {183	fn token_by_index(&self, index: uint256) -> Result<uint256> {184		Ok(index)185	}186187	/// Not implemented188	fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {189		// TODO: Not implemetable190		Err("not implemented".into())191	}192193	fn total_supply(&self) -> Result<uint256> {194		self.consume_store_reads(1)?;195		Ok(<Pallet<T>>::total_supply(self).into())196	}197}198199#[solidity_interface(name = "ERC721", events(ERC721Events))]200impl<T: Config> NonfungibleHandle<T> {201	fn balance_of(&self, owner: address) -> Result<uint256> {202		self.consume_store_reads(1)?;203		let owner = T::CrossAccountId::from_eth(owner);204		let balance = <AccountBalance<T>>::get((self.id, owner));205		Ok(balance.into())206	}207	fn owner_of(&self, token_id: uint256) -> Result<address> {208		self.consume_store_reads(1)?;209		let token: TokenId = token_id.try_into()?;210		Ok(*<TokenData<T>>::get((self.id, token))211			.ok_or("token not found")?212			.owner213			.as_eth())214	}215	/// Not implemented216	fn safe_transfer_from_with_data(217		&mut self,218		_from: address,219		_to: address,220		_token_id: uint256,221		_data: bytes,222		_value: value,223	) -> Result<void> {224		// TODO: Not implemetable225		Err("not implemented".into())226	}227	/// Not implemented228	fn safe_transfer_from(229		&mut self,230		_from: address,231		_to: address,232		_token_id: uint256,233		_value: value,234	) -> Result<void> {235		// TODO: Not implemetable236		Err("not implemented".into())237	}238239	#[weight(<SelfWeightOf<T>>::transfer_from())]240	fn transfer_from(241		&mut self,242		caller: caller,243		from: address,244		to: address,245		token_id: uint256,246		_value: value,247	) -> Result<void> {248		let caller = T::CrossAccountId::from_eth(caller);249		let from = T::CrossAccountId::from_eth(from);250		let to = T::CrossAccountId::from_eth(to);251		let token = token_id.try_into()?;252		let budget = self253			.recorder254			.weight_calls_budget(<StructureWeight<T>>::find_parent());255256		<Pallet<T>>::transfer_from(self, &caller, &from, &to, token, &budget)257			.map_err(dispatch_to_evm::<T>)?;258		Ok(())259	}260261	#[weight(<SelfWeightOf<T>>::approve())]262	fn approve(263		&mut self,264		caller: caller,265		approved: address,266		token_id: uint256,267		_value: value,268	) -> Result<void> {269		let caller = T::CrossAccountId::from_eth(caller);270		let approved = T::CrossAccountId::from_eth(approved);271		let token = token_id.try_into()?;272		let budget = self273			.recorder274			.weight_calls_budget(<StructureWeight<T>>::find_parent());275276		<Pallet<T>>::set_allowance(self, &caller, token, Some(&approved), &budget)277			.map_err(dispatch_to_evm::<T>)?;278		Ok(())279	}280281	/// Not implemented282	fn set_approval_for_all(283		&mut self,284		_caller: caller,285		_operator: address,286		_approved: bool,287	) -> Result<void> {288		// TODO: Not implemetable289		Err("not implemented".into())290	}291292	/// Not implemented293	fn get_approved(&self, _token_id: uint256) -> Result<address> {294		// TODO: Not implemetable295		Err("not implemented".into())296	}297298	/// Not implemented299	fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {300		// TODO: Not implemetable301		Err("not implemented".into())302	}303}304305#[solidity_interface(name = "ERC721Burnable")]306impl<T: Config> NonfungibleHandle<T> {307	#[weight(<SelfWeightOf<T>>::burn_item())]308	fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {309		let caller = T::CrossAccountId::from_eth(caller);310		let token = token_id.try_into()?;311312		<Pallet<T>>::burn(self, &caller, token).map_err(dispatch_to_evm::<T>)?;313		Ok(())314	}315}316317#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))]318impl<T: Config> NonfungibleHandle<T> {319	fn minting_finished(&self) -> Result<bool> {320		Ok(false)321	}322323	/// `token_id` should be obtained with `next_token_id` method,324	/// unlike standard, you can't specify it manually325	#[weight(<SelfWeightOf<T>>::create_item())]326	fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {327		let caller = T::CrossAccountId::from_eth(caller);328		let to = T::CrossAccountId::from_eth(to);329		let token_id: u32 = token_id.try_into()?;330		let budget = self331			.recorder332			.weight_calls_budget(<StructureWeight<T>>::find_parent());333334		if <TokensMinted<T>>::get(self.id)335			.checked_add(1)336			.ok_or("item id overflow")?337			!= token_id338		{339			return Err("item id should be next".into());340		}341342		<Pallet<T>>::create_item(343			self,344			&caller,345			CreateItemData::<T> {346				properties: BoundedVec::default(),347				owner: to,348			},349			&budget,350		)351		.map_err(dispatch_to_evm::<T>)?;352353		Ok(true)354	}355356	/// `token_id` should be obtained with `next_token_id` method,357	/// unlike standard, you can't specify it manually358	#[solidity(rename_selector = "mintWithTokenURI")]359	#[weight(<SelfWeightOf<T>>::create_item())]360	fn mint_with_token_uri(361		&mut self,362		caller: caller,363		to: address,364		token_id: uint256,365		token_uri: string,366	) -> Result<bool> {367		let key = token_uri_key();368		let permission = get_token_permission::<T>(self.id, &key)?;369		if !permission.collection_admin {370			return Err("Operation is not allowed".into());371		}372373		let caller = T::CrossAccountId::from_eth(caller);374		let to = T::CrossAccountId::from_eth(to);375		let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;376		let budget = self377			.recorder378			.weight_calls_budget(<StructureWeight<T>>::find_parent());379380		if <TokensMinted<T>>::get(self.id)381			.checked_add(1)382			.ok_or("item id overflow")?383			!= token_id384		{385			return Err("item id should be next".into());386		}387388		let mut properties = CollectionPropertiesVec::default();389		properties390			.try_push(Property {391				key,392				value: token_uri393					.into_bytes()394					.try_into()395					.map_err(|_| "token uri is too long")?,396			})397			.map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;398399		<Pallet<T>>::create_item(400			self,401			&caller,402			CreateItemData::<T> {403				properties,404				owner: to,405			},406			&budget,407		)408		.map_err(dispatch_to_evm::<T>)?;409		Ok(true)410	}411412	/// Not implemented413	fn finish_minting(&mut self, _caller: caller) -> Result<bool> {414		Err("not implementable".into())415	}416}417418fn get_token_permission<T: Config>(419	collection_id: CollectionId,420	key: &PropertyKey,421) -> Result<PropertyPermission> {422	let token_property_permissions = CollectionPropertyPermissions::<T>::try_get(collection_id)423		.map_err(|_| Error::Revert("No permissions for collection".into()))?;424	let a = token_property_permissions425		.get(key)426		.map(|p| p.clone())427		.ok_or_else(|| Error::Revert("No permission".into()))?;428	Ok(a)429}430431fn has_token_permission<T: Config>(collection_id: CollectionId, key: &PropertyKey) -> bool {432	if let Ok(token_property_permissions) =433		CollectionPropertyPermissions::<T>::try_get(collection_id)434	{435		return token_property_permissions.contains_key(key);436	}437438	false439}440441#[solidity_interface(name = "ERC721UniqueExtensions")]442impl<T: Config> NonfungibleHandle<T> {443	#[weight(<SelfWeightOf<T>>::transfer())]444	fn transfer(445		&mut self,446		caller: caller,447		to: address,448		token_id: uint256,449		_value: value,450	) -> Result<void> {451		let caller = T::CrossAccountId::from_eth(caller);452		let to = T::CrossAccountId::from_eth(to);453		let token = token_id.try_into()?;454		let budget = self455			.recorder456			.weight_calls_budget(<StructureWeight<T>>::find_parent());457458		<Pallet<T>>::transfer(self, &caller, &to, token, &budget).map_err(dispatch_to_evm::<T>)?;459		Ok(())460	}461462	#[weight(<SelfWeightOf<T>>::burn_from())]463	fn burn_from(464		&mut self,465		caller: caller,466		from: address,467		token_id: uint256,468		_value: value,469	) -> Result<void> {470		let caller = T::CrossAccountId::from_eth(caller);471		let from = T::CrossAccountId::from_eth(from);472		let token = token_id.try_into()?;473		let budget = self474			.recorder475			.weight_calls_budget(<StructureWeight<T>>::find_parent());476477		<Pallet<T>>::burn_from(self, &caller, &from, token, &budget)478			.map_err(dispatch_to_evm::<T>)?;479		Ok(())480	}481482	fn next_token_id(&self) -> Result<uint256> {483		self.consume_store_reads(1)?;484		Ok(<TokensMinted<T>>::get(self.id)485			.checked_add(1)486			.ok_or("item id overflow")?487			.into())488	}489490	#[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]491	fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {492		let caller = T::CrossAccountId::from_eth(caller);493		let to = T::CrossAccountId::from_eth(to);494		let mut expected_index = <TokensMinted<T>>::get(self.id)495			.checked_add(1)496			.ok_or("item id overflow")?;497		let budget = self498			.recorder499			.weight_calls_budget(<StructureWeight<T>>::find_parent());500501		let total_tokens = token_ids.len();502		for id in token_ids.into_iter() {503			let id: u32 = id.try_into().map_err(|_| "token id overflow")?;504			if id != expected_index {505				return Err("item id should be next".into());506			}507			expected_index = expected_index.checked_add(1).ok_or("item id overflow")?;508		}509		let data = (0..total_tokens)510			.map(|_| CreateItemData::<T> {511				properties: BoundedVec::default(),512				owner: to.clone(),513			})514			.collect();515516		<Pallet<T>>::create_multiple_items(self, &caller, data, &budget)517			.map_err(dispatch_to_evm::<T>)?;518		Ok(true)519	}520521	#[solidity(rename_selector = "mintBulkWithTokenURI")]522	#[weight(<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32))]523	fn mint_bulk_with_token_uri(524		&mut self,525		caller: caller,526		to: address,527		tokens: Vec<(uint256, string)>,528	) -> Result<bool> {529		let key = token_uri_key();530		let caller = T::CrossAccountId::from_eth(caller);531		let to = T::CrossAccountId::from_eth(to);532		let mut expected_index = <TokensMinted<T>>::get(self.id)533			.checked_add(1)534			.ok_or("item id overflow")?;535		let budget = self536			.recorder537			.weight_calls_budget(<StructureWeight<T>>::find_parent());538539		let mut data = Vec::with_capacity(tokens.len());540		for (id, token_uri) in tokens {541			let id: u32 = id.try_into().map_err(|_| "token id overflow")?;542			if id != expected_index {543				return Err("item id should be next".into());544			}545			expected_index = expected_index.checked_add(1).ok_or("item id overflow")?;546547			let mut properties = CollectionPropertiesVec::default();548			properties549				.try_push(Property {550					key: key.clone(),551					value: token_uri552						.into_bytes()553						.try_into()554						.map_err(|_| "token uri is too long")?,555				})556				.map_err(|e| Error::Revert(alloc::format!("Can't add property: {:?}", e)))?;557558			data.push(CreateItemData::<T> {559				properties,560				owner: to.clone(),561			});562		}563564		<Pallet<T>>::create_multiple_items(self, &caller, data, &budget)565			.map_err(dispatch_to_evm::<T>)?;566		Ok(true)567	}568}569570#[solidity_interface(571	name = "UniqueNFT",572	is(573		ERC721,574		ERC721Metadata,575		ERC721Enumerable,576		ERC721UniqueExtensions,577		ERC721Mintable,578		ERC721Burnable,579		via("CollectionHandle<T>", common_mut, Collection),580		TokenProperties,581	)582)]583impl<T: Config> NonfungibleHandle<T> {}584585// Not a tests, but code generators586generate_stubgen!(gen_impl, UniqueNFTCall<()>, true);587generate_stubgen!(gen_iface, UniqueNFTCall<()>, false);588589impl<T: Config> CommonEvmHandler for NonfungibleHandle<T> {590	const CODE: &'static [u8] = include_bytes!("./stubs/UniqueNFT.raw");591592	fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {593		call::<T, UniqueNFTCall<T>, _, _>(handle, self)594	}595}
modifiedpallets/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
modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
--- a/pallets/proxy-rmrk-core/src/lib.rs
+++ b/pallets/proxy-rmrk-core/src/lib.rs
@@ -414,13 +414,14 @@
 					let is_approval_required = cross_sender != spender;
 
 					if is_approval_required {
-						<PalletNft<T>>::set_allowance(
-							&collection,
-							&cross_sender,
-							nft_id,
-							Some(&spender),
-							&budget
-						).map_err(Self::map_common_err_to_proxy)?;
+						// FIXME
+						// <PalletNft<T>>::set_allowance(
+						// 	&collection,
+						// 	&cross_sender,
+						// 	nft_id,
+						// 	Some(&spender),
+						// 	&budget
+						// ).map_err(Self::map_common_err_to_proxy)?;
 
 						return Ok(());
 					}
modifiedpallets/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),
modifiedpallets/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.