git.delta.rocks / unique-network / refs/commits / 3429f32311d9

difftreelog

fix PR comments

Trubnikov Sergey2023-05-17parent: #ab5c2b5.patch.diff
in: master

8 files changed

modifiedpallets/balances-adapter/src/common.rsdiffbeforeafterboth
--- a/pallets/balances-adapter/src/common.rs
+++ b/pallets/balances-adapter/src/common.rs
@@ -7,6 +7,8 @@
 use up_data_structs::TokenId;
 
 pub struct CommonWeights<T: Config>(PhantomData<T>);
+
+// All implementations with `Weight::default` used in methods that return error `UnsupportedOperation`.
 impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {
 	fn create_multiple_items(_amount: &[up_data_structs::CreateItemData]) -> Weight {
 		Weight::default()
modifiedpallets/balances-adapter/src/erc.rsdiffbeforeafterboth
before · pallets/balances-adapter/src/erc.rs
1use crate::{Config, NativeFungibleHandle, Pallet, SelfWeightOf};2use evm_coder::{abi::AbiType, ToLog, generate_stubgen, solidity_interface, types::*};3use frame_support::traits::{Currency, ExistenceRequirement};4use pallet_balances::WeightInfo;5use pallet_common::{6	consume_store_reads,7	erc::{CommonEvmHandler, CrossAccountId, PrecompileHandle, PrecompileResult},8	eth::CrossAddress,9};10use pallet_evm_coder_substrate::{11	call, dispatch_to_evm,12	execution::{PreDispatch, Result},13	frontier_contract, WithRecorder,14};15use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};16use sp_core::{U256, Get};17use sp_std::vec::Vec;1819frontier_contract! {20	macro_rules! NativeFungibleHandle_result {...}21	impl<T: Config> Contract for NativeFungibleHandle<T> {...}22}2324#[derive(ToLog)]25pub enum ERC20Events {26	Transfer {27		#[indexed]28		from: Address,29		#[indexed]30		to: Address,31		value: U256,32	},33}3435#[solidity_interface(name = ERC20, events(ERC20Events), enum(derive(PreDispatch)), enum_attr(weight), expect_selector = 0x942e8b22)]36impl<T: Config> NativeFungibleHandle<T> {37	fn allowance(&self, _owner: Address, _spender: Address) -> Result<U256> {38		Ok(U256::zero())39	}4041	// #[weight(<SelfWeightOf<T>>::approve())]42	fn approve(&mut self, _caller: Caller, _spender: Address, _amount: U256) -> Result<bool> {43		// self.consume_store_reads(1)?;44		Err("Approve not supported".into())45	}4647	fn balance_of(&self, owner: Address) -> Result<U256> {48		consume_store_reads(self, 1)?;49		let owner = T::CrossAccountId::from_eth(owner);50		let balance = <T as Config>::Currency::free_balance(owner.as_sub());51		Ok(balance.into())52	}5354	fn decimals(&self) -> Result<u8> {55		Ok(T::Decimals::get())56	}5758	fn name(&self) -> Result<String> {59		Ok(T::Name::get())60	}6162	fn symbol(&self) -> Result<String> {63		Ok(T::Symbol::get())64	}6566	fn total_supply(&self) -> Result<U256> {67		consume_store_reads(self, 1)?;68		let total = <T as Config>::Currency::total_issuance();69		Ok(total.into())70	}7172	#[weight(<SelfWeightOf<T>>::transfer())]73	fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {74		let caller = T::CrossAccountId::from_eth(caller);75		let to = T::CrossAccountId::from_eth(to);76		let amount = amount.try_into().map_err(|_| "amount overflow")?;77		let budget = self78			.recorder()79			.weight_calls_budget(<StructureWeight<T>>::find_parent());8081		<Pallet<T>>::transfer(self, &caller, &to, amount, &budget)82			.map_err(|e| dispatch_to_evm::<T>(e.error))?;83		Ok(true)84	}8586	#[weight(<SelfWeightOf<T>>::transfer())]87	fn transfer_from(88		&mut self,89		caller: Caller,90		from: Address,91		to: Address,92		amount: U256,93	) -> Result<bool> {94		let caller = T::CrossAccountId::from_eth(caller);95		let from = T::CrossAccountId::from_eth(from);96		let to = T::CrossAccountId::from_eth(to);97		let amount = amount.try_into().map_err(|_| "amount overflow")?;98		let budget = self99			.recorder()100			.weight_calls_budget(<StructureWeight<T>>::find_parent());101102		<Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)103			.map_err(|e| dispatch_to_evm::<T>(e.error))?;104		Ok(true)105	}106}107108#[solidity_interface(name = ERC20UniqueExtensions, enum(derive(PreDispatch)), enum_attr(weight))]109impl<T: Config> NativeFungibleHandle<T>110where111	T::AccountId: From<[u8; 32]>,112{113	fn balance_of_cross(&self, owner: CrossAddress) -> Result<U256> {114		consume_store_reads(self, 1)?;115		let owner = owner.into_sub_cross_account::<T>()?;116		let balance = <T as Config>::Currency::free_balance(owner.as_sub());117		Ok(balance.into())118	}119120	#[weight(<SelfWeightOf<T>>::transfer())]121	fn transfer_cross(&mut self, caller: Caller, to: CrossAddress, amount: U256) -> Result<bool> {122		let caller = T::CrossAccountId::from_eth(caller);123		let to = to.into_sub_cross_account::<T>()?;124		let amount = amount.try_into().map_err(|_| "amount overflow")?;125		// let budget = self126		// 	.recorder127		// 	.weight_calls_budget(<StructureWeight<T>>::find_parent());128129		// <Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;130		<T as Config>::Currency::transfer(131			caller.as_sub(),132			to.as_sub(),133			amount,134			ExistenceRequirement::KeepAlive,135		)136		.map_err(dispatch_to_evm::<T>)?;137		Ok(true)138	}139140	#[weight(<SelfWeightOf<T>>::transfer())]141	fn transfer_from_cross(142		&mut self,143		caller: Caller,144		from: CrossAddress,145		to: CrossAddress,146		amount: U256,147	) -> Result<bool> {148		let caller = T::CrossAccountId::from_eth(caller);149		let from = from.into_sub_cross_account::<T>()?;150		let to = to.into_sub_cross_account::<T>()?;151		let amount = amount.try_into().map_err(|_| "amount overflow")?;152153		if from != caller {154			return Err("no permission".into());155		}156157		// let budget = self158		// 	.recorder159		// 	.weight_calls_budget(<StructureWeight<T>>::find_parent());160161		// <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)162		// 	.map_err(dispatch_to_evm::<T>)?;163		<T as Config>::Currency::transfer(164			caller.as_sub(),165			to.as_sub(),166			amount,167			ExistenceRequirement::KeepAlive,168		)169		.map_err(dispatch_to_evm::<T>)?;170		Ok(true)171	}172}173174#[solidity_interface(175	name = UniqueNativeFungible,176	is(ERC20, ERC20UniqueExtensions),177	enum(derive(PreDispatch))178)]179impl<T: Config> NativeFungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}180181generate_stubgen!(gen_impl, UniqueNativeFungibleCall<()>, true);182generate_stubgen!(gen_iface, UniqueNativeFungibleCall<()>, false);183184impl<T: Config> CommonEvmHandler for NativeFungibleHandle<T>185where186	T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,187{188	const CODE: &'static [u8] = include_bytes!("./stubs/UniqueNativeFungible.raw");189190	fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {191		call::<T, UniqueNativeFungibleCall<T>, _, _>(handle, self)192	}193}
after · pallets/balances-adapter/src/erc.rs
1use crate::{Config, NativeFungibleHandle, Pallet, SelfWeightOf};2use evm_coder::{abi::AbiType, generate_stubgen, solidity_interface, types::*};3use frame_support::traits::{Currency};4use pallet_balances::WeightInfo;5use pallet_common::{6	erc::{CommonEvmHandler, CrossAccountId, PrecompileHandle, PrecompileResult},7	eth::CrossAddress,8};9use pallet_evm_coder_substrate::{10	call, dispatch_to_evm,11	execution::{PreDispatch, Result},12	frontier_contract, WithRecorder,13};14use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};15use sp_core::{U256, Get};1617frontier_contract! {18	macro_rules! NativeFungibleHandle_result {...}19	impl<T: Config> Contract for NativeFungibleHandle<T> {...}20}2122#[solidity_interface(name = ERC20, enum(derive(PreDispatch)), enum_attr(weight), expect_selector = 0x942e8b22)]23impl<T: Config> NativeFungibleHandle<T> {24	fn allowance(&self, _owner: Address, _spender: Address) -> Result<U256> {25		Ok(U256::zero())26	}2728	fn approve(&mut self, _caller: Caller, _spender: Address, _amount: U256) -> Result<bool> {29		Err("Approve not supported".into())30	}3132	fn balance_of(&self, owner: Address) -> Result<U256> {33		self.consume_store_reads(1)?;34		let owner = T::CrossAccountId::from_eth(owner);35		let balance = <T as Config>::Currency::free_balance(owner.as_sub());36		Ok(balance.into())37	}3839	fn decimals(&self) -> Result<u8> {40		Ok(T::Decimals::get())41	}4243	fn name(&self) -> Result<String> {44		Ok(T::Name::get())45	}4647	fn symbol(&self) -> Result<String> {48		Ok(T::Symbol::get())49	}5051	fn total_supply(&self) -> Result<U256> {52		self.consume_store_reads(1)?;53		let total = <T as Config>::Currency::total_issuance();54		Ok(total.into())55	}5657	#[weight(<SelfWeightOf<T>>::transfer())]58	fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {59		let caller = T::CrossAccountId::from_eth(caller);60		let to = T::CrossAccountId::from_eth(to);61		let amount = amount.try_into().map_err(|_| "amount overflow")?;62		let budget = self63			.recorder()64			.weight_calls_budget(<StructureWeight<T>>::find_parent());6566		<Pallet<T>>::transfer(self, &caller, &to, amount, &budget)67			.map_err(|e| dispatch_to_evm::<T>(e.error))?;68		Ok(true)69	}7071	#[weight(<SelfWeightOf<T>>::transfer())]72	fn transfer_from(73		&mut self,74		caller: Caller,75		from: Address,76		to: Address,77		amount: U256,78	) -> Result<bool> {79		let caller = T::CrossAccountId::from_eth(caller);80		let from = T::CrossAccountId::from_eth(from);81		let to = T::CrossAccountId::from_eth(to);82		let amount = amount.try_into().map_err(|_| "amount overflow")?;83		let budget = self84			.recorder()85			.weight_calls_budget(<StructureWeight<T>>::find_parent());8687		<Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)88			.map_err(|e| dispatch_to_evm::<T>(e.error))?;89		Ok(true)90	}91}9293#[solidity_interface(name = ERC20UniqueExtensions, enum(derive(PreDispatch)), enum_attr(weight))]94impl<T: Config> NativeFungibleHandle<T>95where96	T::AccountId: From<[u8; 32]>,97{98	fn balance_of_cross(&self, owner: CrossAddress) -> Result<U256> {99		self.consume_store_reads(1)?;100		let owner = owner.into_sub_cross_account::<T>()?;101		let balance = <T as Config>::Currency::free_balance(owner.as_sub());102		Ok(balance.into())103	}104105	#[weight(<SelfWeightOf<T>>::transfer())]106	fn transfer_cross(&mut self, caller: Caller, to: CrossAddress, amount: U256) -> Result<bool> {107		let caller = T::CrossAccountId::from_eth(caller);108		let to = to.into_sub_cross_account::<T>()?;109		let amount = amount.try_into().map_err(|_| "amount overflow")?;110		let budget = self111			.recorder()112			.weight_calls_budget(<StructureWeight<T>>::find_parent());113114		<Pallet<T>>::transfer(self, &caller, &to, amount, &budget)115			.map_err(|e| dispatch_to_evm::<T>(e.error))?;116117		Ok(true)118	}119120	#[weight(<SelfWeightOf<T>>::transfer())]121	fn transfer_from_cross(122		&mut self,123		caller: Caller,124		from: CrossAddress,125		to: CrossAddress,126		amount: U256,127	) -> Result<bool> {128		let caller = T::CrossAccountId::from_eth(caller);129		let from = from.into_sub_cross_account::<T>()?;130		let to = to.into_sub_cross_account::<T>()?;131		let amount = amount.try_into().map_err(|_| "amount overflow")?;132133		if from != caller {134			return Err("no permission".into());135		}136137		let budget = self138			.recorder()139			.weight_calls_budget(<StructureWeight<T>>::find_parent());140141		<Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)142			.map_err(|e| dispatch_to_evm::<T>(e.error))?;143144		Ok(true)145	}146}147148#[solidity_interface(149	name = UniqueNativeFungible,150	is(ERC20, ERC20UniqueExtensions),151	enum(derive(PreDispatch))152)]153impl<T: Config> NativeFungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}154155generate_stubgen!(gen_impl, UniqueNativeFungibleCall<()>, true);156generate_stubgen!(gen_iface, UniqueNativeFungibleCall<()>, false);157158impl<T: Config> CommonEvmHandler for NativeFungibleHandle<T>159where160	T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,161{162	const CODE: &'static [u8] = include_bytes!("./stubs/UniqueNativeFungible.raw");163164	fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {165		call::<T, UniqueNativeFungibleCall<T>, _, _>(handle, self)166	}167}
modifiedpallets/balances-adapter/src/lib.rsdiffbeforeafterboth
--- a/pallets/balances-adapter/src/lib.rs
+++ b/pallets/balances-adapter/src/lib.rs
@@ -1,4 +1,3 @@
-// #![doc = include_str!("../README.md")]
 #![cfg_attr(not(feature = "std"), no_std)]
 
 extern crate alloc;
@@ -12,9 +11,6 @@
 pub mod erc;
 
 pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
-
-const NATIVE_FUNGIBLE_COLLECTION_ID: up_data_structs::CollectionId =
-	up_data_structs::CollectionId(0);
 
 /// Handle for native fungible collection
 pub struct NativeFungibleHandle<T: Config>(SubstrateRecorder<T>);
@@ -57,7 +53,10 @@
 		traits::{Currency, ExistenceRequirement, Get},
 	};
 	use pallet_balances::WeightInfo;
-	use pallet_common::{erc::CrossAccountId, Error as CommonError, Pallet as PalletCommon};
+	use pallet_common::{
+		erc::CrossAccountId, Error as CommonError, Pallet as PalletCommon,
+		NATIVE_FUNGIBLE_COLLECTION_ID,
+	};
 	use pallet_structure::Pallet as PalletStructure;
 	use sp_core::U256;
 	use sp_runtime::DispatchError;
@@ -95,10 +94,9 @@
 		/// Checks if a non-owner has (enough) allowance from the owner to perform operations on the tokens.
 		/// Returns the expected remaining allowance - it should be set manually if the transaction proceeds.
 		///
-		/// - `collection`: Collection that contains the token.
 		/// - `spender`: CrossAccountId who has the allowance rights.
 		/// - `from`: The owner of the tokens who sets the allowance.
-		/// - `amount`: Amount of tokens by which the allowance sholud be reduced.
+		/// - `nesting_budget`: Limit for searching parents in-depth to check ownership.
 		fn check_allowed(
 			spender: &T::CrossAccountId,
 			from: &T::CrossAccountId,
@@ -127,10 +125,11 @@
 		/// Transfers the specified amount of tokens. Will check that
 		/// the transfer is allowed for the token.
 		///
+		/// - `collection`: Collection that contains the token.
 		/// - `from`: Owner of tokens to transfer.
 		/// - `to`: Recepient of transfered tokens.
 		/// - `amount`: Amount of tokens to transfer.
-		/// - `collection`: Collection that contains the token
+		/// - `nesting_budget`: Limit for searching parents in-depth to check ownership.
 		pub fn transfer(
 			_collection: &NativeFungibleHandle<T>,
 			from: &T::CrossAccountId,
@@ -147,7 +146,7 @@
 					amount
 						.try_into()
 						.map_err(|_| sp_runtime::ArithmeticError::Overflow)?,
-					ExistenceRequirement::KeepAlive,
+					ExistenceRequirement::AllowDeath,
 				)?;
 
 				<PalletStructure<T>>::nest_if_sent_to_token(
@@ -175,6 +174,17 @@
 			})
 		}
 
+		/// Transfer NFT token from one account to another.
+		///
+		/// Same as the [`Self::transfer`] but spender doesn't needs to be the owner of the token.
+		/// The owner should set allowance for the spender to transfer token.
+		///
+		/// - `collection`: Collection that contains the token.
+		/// - `spender`: Account that spend the money.
+		/// - `from`: Owner of tokens to transfer.
+		/// - `to`: Recepient of transfered tokens.
+		/// - `amount`: Amount of tokens to transfer.
+		/// - `nesting_budget`: Limit for searching parents in-depth to check ownership.
 		pub fn transfer_from(
 			collection: &NativeFungibleHandle<T>,
 			spender: &T::CrossAccountId,
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -77,14 +77,6 @@
 	fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult>;
 }
 
-impl CommonEvmHandler for () {
-	const CODE: &'static [u8] = &[];
-
-	fn call(self, _handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {
-		None
-	}
-}
-
 /// @title A contract that allows you to work with collections.
 #[solidity_interface(name = Collection, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> CollectionHandle<T>
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -68,7 +68,6 @@
 	dispatch::Pays,
 	transactional, fail,
 };
-use pallet_evm::GasWeightMapping;
 use up_data_structs::{
 	AccessMode, COLLECTION_NUMBER_LIMIT, Collection, RpcCollection, CollectionFlags,
 	RpcCollectionFlags, CollectionId, CreateItemData, MAX_TOKEN_PREFIX_LENGTH,
@@ -101,7 +100,7 @@
 /// Collection handle contains information about collection data and id.
 /// Also provides functionality to count consumed gas.
 ///
-/// CollectionHandle is used as a generic wrapper for collections of all types.
+/// CollectionHandle is used as a generic wrapper for collections of all types (except native fungible).
 /// It allows to perform common operations and queries on any collection type,
 /// both completely general for all, as well as their respective implementations of [`CommonCollectionOperations`].
 #[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]
@@ -153,7 +152,7 @@
 		&self,
 		reads: u64,
 	) -> pallet_evm_coder_substrate::execution::Result<()> {
-		consume_store_reads(self.recorder(), reads)
+		self.recorder().consume_store_reads(reads)
 	}
 
 	/// Consume gas for writing.
@@ -161,7 +160,7 @@
 		&self,
 		writes: u64,
 	) -> pallet_evm_coder_substrate::execution::Result<()> {
-		consume_store_writes(self.recorder(), writes)
+		self.recorder().consume_store_writes(writes)
 	}
 
 	/// Consume gas for reading and writing.
@@ -170,7 +169,8 @@
 		reads: u64,
 		writes: u64,
 	) -> pallet_evm_coder_substrate::execution::Result<()> {
-		consume_store_reads_and_writes(self.recorder(), reads, writes)
+		self.recorder()
+			.consume_store_reads_and_writes(reads, writes)
 	}
 
 	/// Save collection to storage.
@@ -441,7 +441,7 @@
 
 	const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
 	/// Collection id for native fungible collction.
-	pub const NATIVE_FINGIBLE_COLLECTION_ID: CollectionId = CollectionId(0);
+	pub const NATIVE_FUNGIBLE_COLLECTION_ID: CollectionId = CollectionId(0);
 
 	#[pallet::pallet]
 	#[pallet::storage_version(STORAGE_VERSION)]
@@ -2322,48 +2322,4 @@
 			PropertiesError::EmptyPropertyKey => Self::EmptyPropertyKey,
 		}
 	}
-}
-
-/// Consume gas for reading.
-pub fn consume_store_reads<T: Config>(
-	recorder: &SubstrateRecorder<T>,
-	reads: u64,
-) -> pallet_evm_coder_substrate::execution::Result<()> {
-	recorder.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_parts(
-		<T as frame_system::Config>::DbWeight::get()
-			.read
-			.saturating_mul(reads),
-		// TODO: measure proof
-		0,
-	)))
-}
-
-/// Consume gas for writing.
-pub fn consume_store_writes<T: Config>(
-	recorder: &SubstrateRecorder<T>,
-	writes: u64,
-) -> pallet_evm_coder_substrate::execution::Result<()> {
-	recorder.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_parts(
-		<T as frame_system::Config>::DbWeight::get()
-			.write
-			.saturating_mul(writes),
-		// TODO: measure proof
-		0,
-	)))
-}
-
-/// Consume gas for reading and writing.
-pub fn consume_store_reads_and_writes<T: Config>(
-	recorder: &SubstrateRecorder<T>,
-	reads: u64,
-	writes: u64,
-) -> pallet_evm_coder_substrate::execution::Result<()> {
-	let weight = <T as frame_system::Config>::DbWeight::get();
-	let reads = weight.read.saturating_mul(reads);
-	let writes = weight.read.saturating_mul(writes);
-	recorder.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_parts(
-		reads.saturating_add(writes),
-		// TODO: measure proof
-		0,
-	)))
 }
modifiedpallets/evm-coder-substrate/src/lib.rsdiffbeforeafterboth
--- a/pallets/evm-coder-substrate/src/lib.rs
+++ b/pallets/evm-coder-substrate/src/lib.rs
@@ -37,7 +37,7 @@
 	ExitError, ExitRevert, ExitSucceed, GasWeightMapping, PrecompileFailure, PrecompileOutput,
 	PrecompileResult, PrecompileHandle,
 };
-use sp_core::H160;
+use sp_core::{Get, H160};
 // #[cfg(feature = "runtime-benchmarks")]
 // pub mod benchmarking;
 pub mod execution;
@@ -204,6 +204,40 @@
 			Err(Error::Error(e)) => Err(e.into()),
 		})
 	}
+
+	/// Consume gas for reading.
+	pub fn consume_store_reads(&self, reads: u64) -> execution::Result<()> {
+		self.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_parts(
+			<T as frame_system::Config>::DbWeight::get()
+				.read
+				.saturating_mul(reads),
+			// TODO: measure proof
+			0,
+		)))
+	}
+
+	/// Consume gas for writing.
+	pub fn consume_store_writes(&self, writes: u64) -> execution::Result<()> {
+		self.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_parts(
+			<T as frame_system::Config>::DbWeight::get()
+				.write
+				.saturating_mul(writes),
+			// TODO: measure proof
+			0,
+		)))
+	}
+
+	/// Consume gas for reading and writing.
+	pub fn consume_store_reads_and_writes(&self, reads: u64, writes: u64) -> execution::Result<()> {
+		let weight = <T as frame_system::Config>::DbWeight::get();
+		let reads = weight.read.saturating_mul(reads);
+		let writes = weight.read.saturating_mul(writes);
+		self.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_parts(
+			reads.saturating_add(writes),
+			// TODO: measure proof
+			0,
+		)))
+	}
 }
 
 pub fn dispatch_to_evm<T: Config>(err: DispatchError) -> execution::Error {
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -440,7 +440,7 @@
 			collection_id: CollectionId,
 			address: T::CrossAccountId,
 		) -> DispatchResult {
-			if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {
+			if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 				fail!(<pallet_common::Error<T>>::UnsupportedOperation);
 			}
 
@@ -471,7 +471,7 @@
 			collection_id: CollectionId,
 			address: T::CrossAccountId,
 		) -> DispatchResult {
-			if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {
+			if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 				fail!(<pallet_common::Error<T>>::UnsupportedOperation);
 			}
 
@@ -501,7 +501,7 @@
 			collection_id: CollectionId,
 			new_owner: T::AccountId,
 		) -> DispatchResult {
-			if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {
+			if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 				fail!(<pallet_common::Error<T>>::UnsupportedOperation);
 			}
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -533,7 +533,7 @@
 			collection_id: CollectionId,
 			new_admin_id: T::CrossAccountId,
 		) -> DispatchResult {
-			if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {
+			if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 				fail!(<pallet_common::Error<T>>::UnsupportedOperation);
 			}
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -562,7 +562,7 @@
 			collection_id: CollectionId,
 			account_id: T::CrossAccountId,
 		) -> DispatchResult {
-			if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {
+			if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 				fail!(<pallet_common::Error<T>>::UnsupportedOperation);
 			}
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -590,7 +590,7 @@
 			collection_id: CollectionId,
 			new_sponsor: T::AccountId,
 		) -> DispatchResult {
-			if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {
+			if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 				fail!(<pallet_common::Error<T>>::UnsupportedOperation);
 			}
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -617,7 +617,7 @@
 			origin: OriginFor<T>,
 			collection_id: CollectionId,
 		) -> DispatchResult {
-			if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {
+			if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 				fail!(<pallet_common::Error<T>>::UnsupportedOperation);
 			}
 			let sender = ensure_signed(origin)?;
@@ -640,7 +640,7 @@
 			origin: OriginFor<T>,
 			collection_id: CollectionId,
 		) -> DispatchResult {
-			if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {
+			if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 				fail!(<pallet_common::Error<T>>::UnsupportedOperation);
 			}
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -920,7 +920,7 @@
 			collection_id: CollectionId,
 			value: bool,
 		) -> DispatchResult {
-			if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {
+			if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 				fail!(<pallet_common::Error<T>>::UnsupportedOperation);
 			}
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -1175,7 +1175,7 @@
 			collection_id: CollectionId,
 			new_limit: CollectionLimits,
 		) -> DispatchResult {
-			if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {
+			if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 				fail!(<pallet_common::Error<T>>::UnsupportedOperation);
 			}
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -1202,7 +1202,7 @@
 			collection_id: CollectionId,
 			new_permission: CollectionPermissions,
 		) -> DispatchResult {
-			if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {
+			if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 				fail!(<pallet_common::Error<T>>::UnsupportedOperation);
 			}
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -1273,7 +1273,7 @@
 			origin: OriginFor<T>,
 			collection_id: CollectionId,
 		) -> DispatchResult {
-			if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {
+			if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 				fail!(<pallet_common::Error<T>>::UnsupportedOperation);
 			}
 			ensure_root(origin)?;
modifiedruntime/common/dispatch.rsdiffbeforeafterboth
--- a/runtime/common/dispatch.rs
+++ b/runtime/common/dispatch.rs
@@ -100,12 +100,11 @@
 	}
 
 	fn destroy(sender: T::CrossAccountId, collection_id: CollectionId) -> DispatchResult {
-		if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {
+		if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 			fail!(<pallet_common::Error<T>>::UnsupportedOperation);
 		}
 
 		let collection = <CollectionHandle<T>>::try_get(collection_id)?;
-		collection.check_is_internal()?;
 
 		match collection.mode {
 			CollectionMode::ReFungible => {
@@ -122,7 +121,7 @@
 	}
 
 	fn dispatch(collection_id: CollectionId) -> Result<Self, DispatchError> {
-		if collection_id == CollectionId(0) {
+		if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 			return Ok(Self::NativeFungible(NativeFungibleHandle::new()));
 		}
 
@@ -188,7 +187,7 @@
 	}
 	fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {
 		if let Some(collection_id) = map_eth_to_id(&handle.code_address()) {
-			if collection_id == CollectionId(0) {
+			if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {
 				<NativeFungibleHandle<T>>::new().call(handle)
 			} else {
 				let collection = <CollectionHandle<T>>::new_with_gas_limit(