git.delta.rocks / unique-network / refs/commits / 2eb10737f56e

difftreelog

Merge branch 'develop' into feature/core-202

Igor Kozyrev2021-11-16parents: #f52edde #35c67b7.patch.diff
in: master

15 files changed

modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
before · pallets/nonfungible/src/lib.rs
1#![cfg_attr(not(feature = "std"), no_std)]23use erc::ERC721Events;4use frame_support::{BoundedVec, ensure};5use nft_data_structs::{6	AccessMode, CUSTOM_DATA_LIMIT, Collection, CollectionId, CustomDataLimit, TokenId,7};8use pallet_common::{9	Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, account::CrossAccountId,10};11use sp_core::H160;12use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};13use sp_std::{vec::Vec, vec};14use core::ops::Deref;15use sp_std::collections::btree_map::BTreeMap;16use codec::{Encode, Decode};17use scale_info::TypeInfo;1819pub use pallet::*;20#[cfg(feature = "runtime-benchmarks")]21pub mod benchmarking;22pub mod common;23pub mod erc;24pub mod weights;2526pub struct CreateItemData<T: Config> {27	pub const_data: BoundedVec<u8, CustomDataLimit>,28	pub variable_data: BoundedVec<u8, CustomDataLimit>,29	pub owner: T::CrossAccountId,30}31pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;3233#[derive(Encode, Decode, TypeInfo)]34pub struct ItemData<T: Config> {35	pub const_data: Vec<u8>,36	pub variable_data: Vec<u8>,37	pub owner: T::CrossAccountId,38}3940#[frame_support::pallet]41pub mod pallet {42	use super::*;43	use frame_support::{Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};44	use nft_data_structs::{CollectionId, TokenId};45	use super::weights::WeightInfo;4647	#[pallet::error]48	pub enum Error<T> {49		/// Not Nonfungible item data used to mint in Nonfungible collection.50		NotNonfungibleDataUsedToMintFungibleCollectionToken,51		/// Used amount > 1 with NFT52		NonfungibleItemsHaveNoAmount,53	}5455	#[pallet::config]56	pub trait Config: frame_system::Config + pallet_common::Config {57		type WeightInfo: WeightInfo;58	}5960	#[pallet::pallet]61	#[pallet::generate_store(pub(super) trait Store)]62	pub struct Pallet<T>(_);6364	#[pallet::storage]65	pub(super) type TokensMinted<T: Config> =66		StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;67	#[pallet::storage]68	pub(super) type TokensBurnt<T: Config> =69		StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;7071	#[pallet::storage]72	pub(super) type TokenData<T: Config> = StorageNMap<73		Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),74		Value = ItemData<T>,75		QueryKind = OptionQuery,76	>;7778	/// Used to enumerate tokens owned by account79	#[pallet::storage]80	pub(super) type Owned<T: Config> = StorageNMap<81		Key = (82			Key<Twox64Concat, CollectionId>,83			Key<Blake2_128Concat, T::CrossAccountId>,84			Key<Twox64Concat, TokenId>,85		),86		Value = bool,87		QueryKind = ValueQuery,88	>;8990	#[pallet::storage]91	pub(super) type AccountBalance<T: Config> = StorageNMap<92		Key = (93			Key<Twox64Concat, CollectionId>,94			Key<Blake2_128Concat, T::CrossAccountId>,95		),96		Value = u32,97		QueryKind = ValueQuery,98	>;99100	#[pallet::storage]101	pub(super) type Allowance<T: Config> = StorageNMap<102		Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),103		Value = T::CrossAccountId,104		QueryKind = OptionQuery,105	>;106}107108pub struct NonfungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);109impl<T: Config> NonfungibleHandle<T> {110	pub fn cast(inner: pallet_common::CollectionHandle<T>) -> Self {111		Self(inner)112	}113	pub fn into_inner(self) -> pallet_common::CollectionHandle<T> {114		self.0115	}116}117impl<T: Config> Deref for NonfungibleHandle<T> {118	type Target = pallet_common::CollectionHandle<T>;119120	fn deref(&self) -> &Self::Target {121		&self.0122	}123}124125impl<T: Config> Pallet<T> {126	pub fn total_supply(collection: &NonfungibleHandle<T>) -> u32 {127		<TokensMinted<T>>::get(collection.id) - <TokensBurnt<T>>::get(collection.id)128	}129	pub fn token_exists(collection: &NonfungibleHandle<T>, token: TokenId) -> bool {130		<TokenData<T>>::contains_key((collection.id, token))131	}132}133134// unchecked calls skips any permission checks135impl<T: Config> Pallet<T> {136	pub fn init_collection(data: Collection<T>) -> Result<CollectionId, DispatchError> {137		PalletCommon::init_collection(data)138	}139	pub fn destroy_collection(140		collection: NonfungibleHandle<T>,141		sender: &T::CrossAccountId,142	) -> DispatchResult {143		let id = collection.id;144145		// =========146147		PalletCommon::destroy_collection(collection.0, sender)?;148149		<TokenData<T>>::remove_prefix((id,), None);150		<Owned<T>>::remove_prefix((id,), None);151		<TokensMinted<T>>::remove(id);152		<TokensBurnt<T>>::remove(id);153		<Allowance<T>>::remove_prefix((id,), None);154		<AccountBalance<T>>::remove_prefix((id,), None);155		Ok(())156	}157158	pub fn burn(159		collection: &NonfungibleHandle<T>,160		sender: &T::CrossAccountId,161		token: TokenId,162	) -> DispatchResult {163		let token_data = <TokenData<T>>::get((collection.id, token))164			.ok_or_else(|| <CommonError<T>>::TokenNotFound)?;165		ensure!(166			&token_data.owner == sender167				|| (collection.limits.owner_can_transfer()168					&& collection.is_owner_or_admin(sender)?),169			<CommonError<T>>::NoPermission170		);171172		if collection.access == AccessMode::AllowList {173			collection.check_allowlist(sender)?;174		}175176		let burnt = <TokensBurnt<T>>::get(collection.id)177			.checked_add(1)178			.ok_or(ArithmeticError::Overflow)?;179180		// =========181182		<Owned<T>>::remove((collection.id, &token_data.owner, token));183		<TokensBurnt<T>>::insert(collection.id, burnt);184		<TokenData<T>>::remove((collection.id, token));185		let old_spender = <Allowance<T>>::take((collection.id, token));186187		if let Some(old_spender) = old_spender {188			<PalletCommon<T>>::deposit_event(CommonEvent::Approved(189				collection.id,190				token,191				sender.clone(),192				old_spender.clone(),193				0,194			));195		}196197		collection.log_infallible(ERC721Events::Transfer {198			from: *token_data.owner.as_eth(),199			to: H160::default(),200			token_id: token.into(),201		});202		<PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(203			collection.id,204			token,205			token_data.owner,206			1,207		));208		return Ok(());209	}210211	pub fn transfer(212		collection: &NonfungibleHandle<T>,213		from: &T::CrossAccountId,214		to: &T::CrossAccountId,215		token: TokenId,216	) -> DispatchResult {217		ensure!(218			collection.limits.transfers_enabled(),219			<CommonError<T>>::TransferNotAllowed220		);221222		let token_data = <TokenData<T>>::get((collection.id, token))223			.ok_or_else(|| <CommonError<T>>::TokenNotFound)?;224		ensure!(225			&token_data.owner == from226				|| (collection.limits.owner_can_transfer()227					&& collection.is_owner_or_admin(from)?),228			<CommonError<T>>::NoPermission229		);230231		if collection.access == AccessMode::AllowList {232			collection.check_allowlist(from)?;233			collection.check_allowlist(to)?;234		}235		<PalletCommon<T>>::ensure_correct_receiver(to)?;236237		let balance_from = <AccountBalance<T>>::get((collection.id, from))238			.checked_sub(1)239			.ok_or(<CommonError<T>>::TokenValueTooLow)?;240		let balance_to = if from != to {241			let balance_to = <AccountBalance<T>>::get((collection.id, to))242				.checked_add(1)243				.ok_or(ArithmeticError::Overflow)?;244245			ensure!(246				balance_to < collection.limits.account_token_ownership_limit(),247				<CommonError<T>>::AccountTokenLimitExceeded,248			);249250			Some(balance_to)251		} else {252			None253		};254255		collection.consume_sstores(4)?;256		collection.consume_log(3, 0)?;257258		// =========259260		<TokenData<T>>::insert(261			(collection.id, token),262			ItemData {263				owner: to.clone(),264				..token_data265			},266		);267268		if let Some(balance_to) = balance_to {269			// from != to270			if balance_from == 0 {271				<AccountBalance<T>>::remove((collection.id, from));272			} else {273				<AccountBalance<T>>::insert((collection.id, from), balance_from);274			}275			<AccountBalance<T>>::insert((collection.id, to), balance_to);276			<Owned<T>>::remove((collection.id, from, token));277			<Owned<T>>::insert((collection.id, to, token), true);278		}279		Self::set_allowance_unchecked(collection, from, token, None, true);280281		collection.log_infallible(ERC721Events::Transfer {282			from: *from.as_eth(),283			to: *to.as_eth(),284			token_id: token.into(),285		});286		<PalletCommon<T>>::deposit_event(CommonEvent::Transfer(287			collection.id,288			token,289			from.clone(),290			to.clone(),291			1,292		));293		Ok(())294	}295296	pub fn create_multiple_items(297		collection: &NonfungibleHandle<T>,298		sender: &T::CrossAccountId,299		data: Vec<CreateItemData<T>>,300	) -> DispatchResult {301		let unrestricted_minting = collection.is_owner_or_admin(sender)?;302		if !unrestricted_minting {303			ensure!(304				collection.mint_mode,305				<CommonError<T>>::PublicMintingNotAllowed306			);307			collection.check_allowlist(sender)?;308309			for item in data.iter() {310				collection.check_allowlist(&item.owner)?;311			}312		}313314		for data in data.iter() {315			<PalletCommon<T>>::ensure_correct_receiver(&data.owner)?;316			if !data.const_data.is_empty() {317				collection.consume_sstore()?;318			}319			if !data.variable_data.is_empty() {320				collection.consume_sstore()?;321			}322			collection.consume_sstore()?;323			collection.consume_log(3, 0)?;324		}325326		let first_token = <TokensMinted<T>>::get(collection.id);327		let tokens_minted = first_token328			.checked_add(data.len() as u32)329			.ok_or(ArithmeticError::Overflow)?;330		ensure!(331			tokens_minted < collection.limits.token_limit(),332			<CommonError<T>>::CollectionTokenLimitExceeded333		);334		collection.consume_sstore()?;335336		let mut balances = BTreeMap::new();337		for data in &data {338			let balance = balances339				.entry(&data.owner)340				.or_insert_with(|| <AccountBalance<T>>::get((collection.id, &data.owner)));341			*balance = balance.checked_add(1).ok_or(ArithmeticError::Overflow)?;342343			ensure!(344				*balance <= collection.limits.account_token_ownership_limit(),345				<CommonError<T>>::AccountTokenLimitExceeded,346			);347		}348		collection.consume_sstores(balances.len())?;349350		// =========351352		<TokensMinted<T>>::insert(collection.id, tokens_minted);353		for (account, balance) in balances {354			<AccountBalance<T>>::insert((collection.id, account), balance);355		}356		for (i, data) in data.into_iter().enumerate() {357			let token = first_token + i as u32 + 1;358359			<TokenData<T>>::insert(360				(collection.id, token),361				ItemData {362					const_data: data.const_data.into(),363					variable_data: data.variable_data.into(),364					owner: data.owner.clone(),365				},366			);367			<Owned<T>>::insert((collection.id, &data.owner, token), true);368369			collection.log_infallible(ERC721Events::Transfer {370				from: H160::default(),371				to: *data.owner.as_eth(),372				token_id: token.into(),373			});374			<PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(375				collection.id,376				TokenId(token),377				data.owner.clone(),378				1,379			));380		}381		Ok(())382	}383384	pub fn set_allowance_unchecked(385		collection: &NonfungibleHandle<T>,386		sender: &T::CrossAccountId,387		token: TokenId,388		spender: Option<&T::CrossAccountId>,389		assume_implicit_eth: bool,390	) {391		if let Some(spender) = spender {392			let old_spender = <Allowance<T>>::get((collection.id, token));393			<Allowance<T>>::insert((collection.id, token), spender);394			// In ERC721 there is only one possible approved user of token, so we set395			// approved user to spender396			collection.log_infallible(ERC721Events::Approval {397				owner: *sender.as_eth(),398				approved: *spender.as_eth(),399				token_id: token.into(),400			});401			// In Unique chain, any token can have any amount of approved users, so we need to402			// set allowance of old owner to 0, and allowance of new owner to 1403			if old_spender.as_ref() != Some(spender) {404				if let Some(old_owner) = old_spender {405					<PalletCommon<T>>::deposit_event(CommonEvent::Approved(406						collection.id,407						token,408						sender.clone(),409						old_owner.clone(),410						0,411					));412				}413				<PalletCommon<T>>::deposit_event(CommonEvent::Approved(414					collection.id,415					token,416					sender.clone(),417					spender.clone(),418					1,419				));420			}421		} else {422			let old_spender = <Allowance<T>>::take((collection.id, token));423			if !assume_implicit_eth {424				// In ERC721 there is only one possible approved user of token, so we set425				// approved user to zero address426				collection.log_infallible(ERC721Events::Approval {427					owner: *sender.as_eth(),428					approved: H160::default(),429					token_id: token.into(),430				});431			}432			// In Unique chain, any token can have any amount of approved users, so we need to433			// set allowance of old owner to 0434			if let Some(old_spender) = old_spender {435				<PalletCommon<T>>::deposit_event(CommonEvent::Approved(436					collection.id,437					token,438					sender.clone(),439					old_spender.clone(),440					0,441				));442			}443		}444	}445446	pub fn set_allowance(447		collection: &NonfungibleHandle<T>,448		sender: &T::CrossAccountId,449		token: TokenId,450		spender: Option<&T::CrossAccountId>,451	) -> DispatchResult {452		if collection.access == AccessMode::AllowList {453			collection.check_allowlist(&sender)?;454			if let Some(spender) = spender {455				collection.check_allowlist(&spender)?;456			}457		}458459		if let Some(spender) = spender {460			<PalletCommon<T>>::ensure_correct_receiver(spender)?;461		}462		let token_data =463			<TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;464		if &token_data.owner != sender {465			ensure!(466				collection.ignores_owned_amount(sender)?,467				<CommonError<T>>::CantApproveMoreThanOwned468			);469		}470471		// =========472473		Self::set_allowance_unchecked(collection, sender, token, spender, false);474		Ok(())475	}476477	pub fn transfer_from(478		collection: &NonfungibleHandle<T>,479		spender: &T::CrossAccountId,480		from: &T::CrossAccountId,481		to: &T::CrossAccountId,482		token: TokenId,483	) -> DispatchResult {484		if spender.conv_eq(from) {485			return Self::transfer(collection, from, to, token);486		}487		if collection.access == AccessMode::AllowList {488			// `from`, `to` checked in [`transfer`]489			collection.check_allowlist(spender)?;490		}491492		if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {493			ensure!(494				collection.ignores_allowance(spender)?,495				<CommonError<T>>::TokenValueNotEnough496			);497		}498499		// =========500501		Self::transfer(collection, &from, to, token)?;502		// Allowance is reset in [`transfer`]503		Ok(())504	}505506	pub fn burn_from(507		collection: &NonfungibleHandle<T>,508		spender: &T::CrossAccountId,509		from: &T::CrossAccountId,510		token: TokenId,511	) -> DispatchResult {512		if spender.conv_eq(from) {513			return Self::burn(collection, from, token);514		}515		if collection.access == AccessMode::AllowList {516			// `from` checked in [`burn`]517			collection.check_allowlist(spender)?;518		}519520		if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {521			ensure!(522				collection.ignores_allowance(spender)?,523				<CommonError<T>>::TokenValueNotEnough524			);525		}526527		// =========528529		Self::burn(collection, &from, token)530	}531532	pub fn set_variable_metadata(533		collection: &NonfungibleHandle<T>,534		sender: &T::CrossAccountId,535		token: TokenId,536		data: Vec<u8>,537	) -> DispatchResult {538		ensure!(539			data.len() as u32 <= CUSTOM_DATA_LIMIT,540			<CommonError<T>>::TokenVariableDataLimitExceeded541		);542		let token_data =543			<TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;544		collection.check_can_update_meta(sender, &token_data.owner)?;545546		collection.consume_sstore()?;547548		// =========549550		<TokenData<T>>::insert(551			(collection.id, token),552			ItemData {553				variable_data: data,554				..token_data555			},556		);557		Ok(())558	}559560	/// Delegated to `create_multiple_items`561	pub fn create_item(562		collection: &NonfungibleHandle<T>,563		sender: &T::CrossAccountId,564		data: CreateItemData<T>,565	) -> DispatchResult {566		Self::create_multiple_items(collection, sender, vec![data])567	}568}
after · pallets/nonfungible/src/lib.rs
1#![cfg_attr(not(feature = "std"), no_std)]23use erc::ERC721Events;4use frame_support::{BoundedVec, ensure};5use nft_data_structs::{6	AccessMode, CUSTOM_DATA_LIMIT, Collection, CollectionId, CustomDataLimit, TokenId,7};8use pallet_common::{9	Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, account::CrossAccountId,10};11use sp_core::H160;12use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};13use sp_std::{vec::Vec, vec};14use core::ops::Deref;15use sp_std::collections::btree_map::BTreeMap;16use codec::{Encode, Decode};17use scale_info::TypeInfo;1819pub use pallet::*;20#[cfg(feature = "runtime-benchmarks")]21pub mod benchmarking;22pub mod common;23pub mod erc;24pub mod weights;2526pub struct CreateItemData<T: Config> {27	pub const_data: BoundedVec<u8, CustomDataLimit>,28	pub variable_data: BoundedVec<u8, CustomDataLimit>,29	pub owner: T::CrossAccountId,30}31pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;3233#[derive(Encode, Decode, TypeInfo)]34pub struct ItemData<T: Config> {35	pub const_data: Vec<u8>,36	pub variable_data: Vec<u8>,37	pub owner: T::CrossAccountId,38}3940#[frame_support::pallet]41pub mod pallet {42	use super::*;43	use frame_support::{Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};44	use nft_data_structs::{CollectionId, TokenId};45	use super::weights::WeightInfo;4647	#[pallet::error]48	pub enum Error<T> {49		/// Not Nonfungible item data used to mint in Nonfungible collection.50		NotNonfungibleDataUsedToMintFungibleCollectionToken,51		/// Used amount > 1 with NFT52		NonfungibleItemsHaveNoAmount,53	}5455	#[pallet::config]56	pub trait Config: frame_system::Config + pallet_common::Config {57		type WeightInfo: WeightInfo;58	}5960	#[pallet::pallet]61	#[pallet::generate_store(pub(super) trait Store)]62	pub struct Pallet<T>(_);6364	#[pallet::storage]65	pub(super) type TokensMinted<T: Config> =66		StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;67	#[pallet::storage]68	pub(super) type TokensBurnt<T: Config> =69		StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;7071	#[pallet::storage]72	pub(super) type TokenData<T: Config> = StorageNMap<73		Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),74		Value = ItemData<T>,75		QueryKind = OptionQuery,76	>;7778	/// Used to enumerate tokens owned by account79	#[pallet::storage]80	pub(super) type Owned<T: Config> = StorageNMap<81		Key = (82			Key<Twox64Concat, CollectionId>,83			Key<Blake2_128Concat, T::CrossAccountId>,84			Key<Twox64Concat, TokenId>,85		),86		Value = bool,87		QueryKind = ValueQuery,88	>;8990	#[pallet::storage]91	pub(super) type AccountBalance<T: Config> = StorageNMap<92		Key = (93			Key<Twox64Concat, CollectionId>,94			Key<Blake2_128Concat, T::CrossAccountId>,95		),96		Value = u32,97		QueryKind = ValueQuery,98	>;99100	#[pallet::storage]101	pub(super) type Allowance<T: Config> = StorageNMap<102		Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),103		Value = T::CrossAccountId,104		QueryKind = OptionQuery,105	>;106}107108pub struct NonfungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);109impl<T: Config> NonfungibleHandle<T> {110	pub fn cast(inner: pallet_common::CollectionHandle<T>) -> Self {111		Self(inner)112	}113	pub fn into_inner(self) -> pallet_common::CollectionHandle<T> {114		self.0115	}116}117impl<T: Config> Deref for NonfungibleHandle<T> {118	type Target = pallet_common::CollectionHandle<T>;119120	fn deref(&self) -> &Self::Target {121		&self.0122	}123}124125impl<T: Config> Pallet<T> {126	pub fn total_supply(collection: &NonfungibleHandle<T>) -> u32 {127		<TokensMinted<T>>::get(collection.id) - <TokensBurnt<T>>::get(collection.id)128	}129	pub fn token_exists(collection: &NonfungibleHandle<T>, token: TokenId) -> bool {130		<TokenData<T>>::contains_key((collection.id, token))131	}132}133134// unchecked calls skips any permission checks135impl<T: Config> Pallet<T> {136	pub fn init_collection(data: Collection<T>) -> Result<CollectionId, DispatchError> {137		PalletCommon::init_collection(data)138	}139	pub fn destroy_collection(140		collection: NonfungibleHandle<T>,141		sender: &T::CrossAccountId,142	) -> DispatchResult {143		let id = collection.id;144145		// =========146147		PalletCommon::destroy_collection(collection.0, sender)?;148149		<TokenData<T>>::remove_prefix((id,), None);150		<Owned<T>>::remove_prefix((id,), None);151		<TokensMinted<T>>::remove(id);152		<TokensBurnt<T>>::remove(id);153		<Allowance<T>>::remove_prefix((id,), None);154		<AccountBalance<T>>::remove_prefix((id,), None);155		Ok(())156	}157158	pub fn burn(159		collection: &NonfungibleHandle<T>,160		sender: &T::CrossAccountId,161		token: TokenId,162	) -> DispatchResult {163		let token_data = <TokenData<T>>::get((collection.id, token))164			.ok_or_else(|| <CommonError<T>>::TokenNotFound)?;165		ensure!(166			&token_data.owner == sender167				|| (collection.limits.owner_can_transfer()168					&& collection.is_owner_or_admin(sender)?),169			<CommonError<T>>::NoPermission170		);171172		if collection.access == AccessMode::AllowList {173			collection.check_allowlist(sender)?;174		}175176		let burnt = <TokensBurnt<T>>::get(collection.id)177			.checked_add(1)178			.ok_or(ArithmeticError::Overflow)?;179180		// =========181182		<Owned<T>>::remove((collection.id, &token_data.owner, token));183		<TokensBurnt<T>>::insert(collection.id, burnt);184		<TokenData<T>>::remove((collection.id, token));185		let old_spender = <Allowance<T>>::take((collection.id, token));186187		if let Some(old_spender) = old_spender {188			<PalletCommon<T>>::deposit_event(CommonEvent::Approved(189				collection.id,190				token,191				sender.clone(),192				old_spender.clone(),193				0,194			));195		}196197		collection.log_infallible(ERC721Events::Transfer {198			from: *token_data.owner.as_eth(),199			to: H160::default(),200			token_id: token.into(),201		});202		<PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(203			collection.id,204			token,205			token_data.owner,206			1,207		));208		return Ok(());209	}210211	pub fn transfer(212		collection: &NonfungibleHandle<T>,213		from: &T::CrossAccountId,214		to: &T::CrossAccountId,215		token: TokenId,216	) -> DispatchResult {217		ensure!(218			collection.limits.transfers_enabled(),219			<CommonError<T>>::TransferNotAllowed220		);221222		let token_data = <TokenData<T>>::get((collection.id, token))223			.ok_or_else(|| <CommonError<T>>::TokenNotFound)?;224		ensure!(225			&token_data.owner == from226				|| (collection.limits.owner_can_transfer()227					&& collection.is_owner_or_admin(from)?),228			<CommonError<T>>::NoPermission229		);230231		if collection.access == AccessMode::AllowList {232			collection.check_allowlist(from)?;233			collection.check_allowlist(to)?;234		}235		<PalletCommon<T>>::ensure_correct_receiver(to)?;236237		let balance_from = <AccountBalance<T>>::get((collection.id, from))238			.checked_sub(1)239			.ok_or(<CommonError<T>>::TokenValueTooLow)?;240		let balance_to = if from != to {241			let balance_to = <AccountBalance<T>>::get((collection.id, to))242				.checked_add(1)243				.ok_or(ArithmeticError::Overflow)?;244245			ensure!(246				balance_to < collection.limits.account_token_ownership_limit(),247				<CommonError<T>>::AccountTokenLimitExceeded,248			);249250			Some(balance_to)251		} else {252			None253		};254255		collection.consume_sstores(4)?;256		collection.consume_log(3, 0)?;257258		// =========259260		<TokenData<T>>::insert(261			(collection.id, token),262			ItemData {263				owner: to.clone(),264				..token_data265			},266		);267268		if let Some(balance_to) = balance_to {269			// from != to270			if balance_from == 0 {271				<AccountBalance<T>>::remove((collection.id, from));272			} else {273				<AccountBalance<T>>::insert((collection.id, from), balance_from);274			}275			<AccountBalance<T>>::insert((collection.id, to), balance_to);276			<Owned<T>>::remove((collection.id, from, token));277			<Owned<T>>::insert((collection.id, to, token), true);278		}279		Self::set_allowance_unchecked(collection, from, token, None, true);280281		collection.log_infallible(ERC721Events::Transfer {282			from: *from.as_eth(),283			to: *to.as_eth(),284			token_id: token.into(),285		});286		<PalletCommon<T>>::deposit_event(CommonEvent::Transfer(287			collection.id,288			token,289			from.clone(),290			to.clone(),291			1,292		));293		Ok(())294	}295296	pub fn create_multiple_items(297		collection: &NonfungibleHandle<T>,298		sender: &T::CrossAccountId,299		data: Vec<CreateItemData<T>>,300	) -> DispatchResult {301		let unrestricted_minting = collection.is_owner_or_admin(sender)?;302		if !unrestricted_minting {303			ensure!(304				collection.mint_mode,305				<CommonError<T>>::PublicMintingNotAllowed306			);307			collection.check_allowlist(sender)?;308309			for item in data.iter() {310				collection.check_allowlist(&item.owner)?;311			}312		}313314		for data in data.iter() {315			<PalletCommon<T>>::ensure_correct_receiver(&data.owner)?;316			if !data.const_data.is_empty() {317				collection.consume_sstore()?;318			}319			if !data.variable_data.is_empty() {320				collection.consume_sstore()?;321			}322			collection.consume_sstore()?;323			collection.consume_log(3, 0)?;324		}325326		let first_token = <TokensMinted<T>>::get(collection.id);327		let tokens_minted = first_token328			.checked_add(data.len() as u32)329			.ok_or(ArithmeticError::Overflow)?;330		ensure!(331			tokens_minted <= collection.limits.token_limit(),332			<CommonError<T>>::CollectionTokenLimitExceeded333		);334		collection.consume_sstore()?;335336		let mut balances = BTreeMap::new();337		for data in &data {338			let balance = balances339				.entry(&data.owner)340				.or_insert_with(|| <AccountBalance<T>>::get((collection.id, &data.owner)));341			*balance = balance.checked_add(1).ok_or(ArithmeticError::Overflow)?;342343			ensure!(344				*balance <= collection.limits.account_token_ownership_limit(),345				<CommonError<T>>::AccountTokenLimitExceeded,346			);347		}348		collection.consume_sstores(balances.len())?;349350		// =========351352		<TokensMinted<T>>::insert(collection.id, tokens_minted);353		for (account, balance) in balances {354			<AccountBalance<T>>::insert((collection.id, account), balance);355		}356		for (i, data) in data.into_iter().enumerate() {357			let token = first_token + i as u32 + 1;358359			<TokenData<T>>::insert(360				(collection.id, token),361				ItemData {362					const_data: data.const_data.into(),363					variable_data: data.variable_data.into(),364					owner: data.owner.clone(),365				},366			);367			<Owned<T>>::insert((collection.id, &data.owner, token), true);368369			collection.log_infallible(ERC721Events::Transfer {370				from: H160::default(),371				to: *data.owner.as_eth(),372				token_id: token.into(),373			});374			<PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(375				collection.id,376				TokenId(token),377				data.owner.clone(),378				1,379			));380		}381		Ok(())382	}383384	pub fn set_allowance_unchecked(385		collection: &NonfungibleHandle<T>,386		sender: &T::CrossAccountId,387		token: TokenId,388		spender: Option<&T::CrossAccountId>,389		assume_implicit_eth: bool,390	) {391		if let Some(spender) = spender {392			let old_spender = <Allowance<T>>::get((collection.id, token));393			<Allowance<T>>::insert((collection.id, token), spender);394			// In ERC721 there is only one possible approved user of token, so we set395			// approved user to spender396			collection.log_infallible(ERC721Events::Approval {397				owner: *sender.as_eth(),398				approved: *spender.as_eth(),399				token_id: token.into(),400			});401			// In Unique chain, any token can have any amount of approved users, so we need to402			// set allowance of old owner to 0, and allowance of new owner to 1403			if old_spender.as_ref() != Some(spender) {404				if let Some(old_owner) = old_spender {405					<PalletCommon<T>>::deposit_event(CommonEvent::Approved(406						collection.id,407						token,408						sender.clone(),409						old_owner.clone(),410						0,411					));412				}413				<PalletCommon<T>>::deposit_event(CommonEvent::Approved(414					collection.id,415					token,416					sender.clone(),417					spender.clone(),418					1,419				));420			}421		} else {422			let old_spender = <Allowance<T>>::take((collection.id, token));423			if !assume_implicit_eth {424				// In ERC721 there is only one possible approved user of token, so we set425				// approved user to zero address426				collection.log_infallible(ERC721Events::Approval {427					owner: *sender.as_eth(),428					approved: H160::default(),429					token_id: token.into(),430				});431			}432			// In Unique chain, any token can have any amount of approved users, so we need to433			// set allowance of old owner to 0434			if let Some(old_spender) = old_spender {435				<PalletCommon<T>>::deposit_event(CommonEvent::Approved(436					collection.id,437					token,438					sender.clone(),439					old_spender.clone(),440					0,441				));442			}443		}444	}445446	pub fn set_allowance(447		collection: &NonfungibleHandle<T>,448		sender: &T::CrossAccountId,449		token: TokenId,450		spender: Option<&T::CrossAccountId>,451	) -> DispatchResult {452		if collection.access == AccessMode::AllowList {453			collection.check_allowlist(&sender)?;454			if let Some(spender) = spender {455				collection.check_allowlist(&spender)?;456			}457		}458459		if let Some(spender) = spender {460			<PalletCommon<T>>::ensure_correct_receiver(spender)?;461		}462		let token_data =463			<TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;464		if &token_data.owner != sender {465			ensure!(466				collection.ignores_owned_amount(sender)?,467				<CommonError<T>>::CantApproveMoreThanOwned468			);469		}470471		// =========472473		Self::set_allowance_unchecked(collection, sender, token, spender, false);474		Ok(())475	}476477	pub fn transfer_from(478		collection: &NonfungibleHandle<T>,479		spender: &T::CrossAccountId,480		from: &T::CrossAccountId,481		to: &T::CrossAccountId,482		token: TokenId,483	) -> DispatchResult {484		if spender.conv_eq(from) {485			return Self::transfer(collection, from, to, token);486		}487		if collection.access == AccessMode::AllowList {488			// `from`, `to` checked in [`transfer`]489			collection.check_allowlist(spender)?;490		}491492		if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {493			ensure!(494				collection.ignores_allowance(spender)?,495				<CommonError<T>>::TokenValueNotEnough496			);497		}498499		// =========500501		Self::transfer(collection, &from, to, token)?;502		// Allowance is reset in [`transfer`]503		Ok(())504	}505506	pub fn burn_from(507		collection: &NonfungibleHandle<T>,508		spender: &T::CrossAccountId,509		from: &T::CrossAccountId,510		token: TokenId,511	) -> DispatchResult {512		if spender.conv_eq(from) {513			return Self::burn(collection, from, token);514		}515		if collection.access == AccessMode::AllowList {516			// `from` checked in [`burn`]517			collection.check_allowlist(spender)?;518		}519520		if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {521			ensure!(522				collection.ignores_allowance(spender)?,523				<CommonError<T>>::TokenValueNotEnough524			);525		}526527		// =========528529		Self::burn(collection, &from, token)530	}531532	pub fn set_variable_metadata(533		collection: &NonfungibleHandle<T>,534		sender: &T::CrossAccountId,535		token: TokenId,536		data: Vec<u8>,537	) -> DispatchResult {538		ensure!(539			data.len() as u32 <= CUSTOM_DATA_LIMIT,540			<CommonError<T>>::TokenVariableDataLimitExceeded541		);542		let token_data =543			<TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;544		collection.check_can_update_meta(sender, &token_data.owner)?;545546		collection.consume_sstore()?;547548		// =========549550		<TokenData<T>>::insert(551			(collection.id, token),552			ItemData {553				variable_data: data,554				..token_data555			},556		);557		Ok(())558	}559560	/// Delegated to `create_multiple_items`561	pub fn create_item(562		collection: &NonfungibleHandle<T>,563		sender: &T::CrossAccountId,564		data: CreateItemData<T>,565	) -> DispatchResult {566		Self::create_multiple_items(collection, sender, vec![data])567	}568}
addedtests/src/eth/marketplace/MarketPlace.abidiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/marketplace/MarketPlace.abi
@@ -0,0 +1 @@
+[{"inputs":[{"internalType":"address","name":"_escrow","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_price","type":"uint256"},{"indexed":false,"internalType":"address","name":"_currencyCode","type":"address"},{"indexed":false,"internalType":"address","name":"_idCollection","type":"address"},{"indexed":false,"internalType":"uint256","name":"_idNFT","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"AddedAsk","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_idCollection","type":"address"},{"indexed":false,"internalType":"uint256","name":"_idNFT","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"orderID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"orderPrice","type":"uint256"}],"name":"BoughtNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_idCollection","type":"address"},{"indexed":false,"internalType":"uint256","name":"_idNFT","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"orderID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"orderPrice","type":"uint256"}],"name":"BoughtNFT4KSM","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_idCollection","type":"address"},{"indexed":false,"internalType":"uint256","name":"_idNFT","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"CanceledAsk","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_sender","type":"address"}],"name":"DepositedKSM","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_price","type":"uint256"},{"indexed":false,"internalType":"address","name":"_currencyCode","type":"address"},{"indexed":false,"internalType":"address","name":"_idCollection","type":"address"},{"indexed":false,"internalType":"uint256","name":"_idNFT","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"_active","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"EditedAsk","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_currencyCode","type":"address"},{"indexed":false,"internalType":"address","name":"_sender","type":"address"}],"name":"Withdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"}],"name":"WithdrawnAllKSM","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"address","name":"_currencyCode","type":"address"},{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"}],"name":"addAsk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"asks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"asksbySeller","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceKSM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"}],"name":"buy","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"},{"internalType":"address","name":"_buyer","type":"address"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"buyKSM","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"}],"name":"cancelAsk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_sender","type":"address"}],"name":"depositKSM","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"address","name":"_currencyCode","type":"address"},{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"},{"internalType":"uint8","name":"_active","type":"uint8"}],"name":"editAsk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"}],"name":"getOrder","outputs":[{"components":[{"internalType":"uint256","name":"idNFT","type":"uint256"},{"internalType":"address","name":"currencyCode","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"address","name":"idCollection","type":"address"},{"internalType":"address","name":"ownerAddr","type":"address"},{"internalType":"uint8","name":"flagActive","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"tokenURI","type":"string"}],"internalType":"struct MarketPlace.Order","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOrdersLen","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"orders","outputs":[{"internalType":"uint256","name":"idNFT","type":"uint256"},{"internalType":"address","name":"currencyCode","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"address","name":"idCollection","type":"address"},{"internalType":"address","name":"ownerAddr","type":"address"},{"internalType":"uint8","name":"flagActive","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"tokenURI","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newEscrow","type":"address"}],"name":"setEscrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_coin","type":"address"}],"name":"setNativeCoin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newEscrow","type":"address"}],"name":"setowner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_currencyCode","type":"address"},{"internalType":"address payable","name":"_sender","type":"address"}],"name":"withdraw","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"}],"name":"withdrawAllKSM","outputs":[{"internalType":"uint256","name":"lastBalance","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
\ No newline at end of file
addedtests/src/eth/marketplace/MarketPlace.bindiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/marketplace/MarketPlace.bin
@@ -0,0 +1 @@
+60806040523480156200001157600080fd5b50604051620029b8380380620029b8833981016040819052620000349162000327565b600580546001600160a01b038084166001600160a01b03199283161790925560068054821633179055604080516101408101825260008082526020808301828152838501838152606085018481526080860185815260a0870186815260c0880187815289518088018b5288815260e08a019081528a518089018c528981526101008b01528a51808901909b52888b526101208a019a909a528754600181018955978052885160099098027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563810198895595517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56487018054918e16918d1691909117905593517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56586015591517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566850155517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56784018054918b16919099161790975595517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56882018054975160ff16600160a01b026001600160a81b0319909816919098161795909517909555915180519194929362000239937f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5699091019291019062000281565b5061010082015180516200025891600784019160209091019062000281565b5061012082015180516200027791600884019160209091019062000281565b5050505062000396565b8280546200028f9062000359565b90600052602060002090601f016020900481019282620002b35760008555620002fe565b82601f10620002ce57805160ff1916838001178555620002fe565b82800160010185558215620002fe579182015b82811115620002fe578251825591602001919060010190620002e1565b506200030c92915062000310565b5090565b5b808211156200030c576000815560010162000311565b6000602082840312156200033a57600080fd5b81516001600160a01b03811681146200035257600080fd5b9392505050565b600181811c908216806200036e57607f821691505b602082108114156200039057634e487b7160e01b600052602260045260246000fd5b50919050565b61261280620003a66000396000f3fe6080604052600436106101025760003560e01c806399f2d4eb11610095578063c10c354611610064578063c10c354614610221578063cce7ec1314610378578063e22d4f7d1461038b578063edb25841146103c3578063fd8868c7146103f057610184565b806399f2d4eb146102c5578063a85c38ef146102e5578063b460af941461031b578063b4c3e8ea1461034b57610184565b80636b084b25116100d15780636b084b2514610241578063791bd866146102615780638c088f001461028157806393cdd334146102a557610184565b806337c4eb58146101bf5780633ce61756146101e157806340b8074614610201578063592bd7051461022157610184565b366101845760405162461bcd60e51b815260206004820152604160248201527f43616e277420616363657074207061796d656e7420776974686f757420636f6c60448201527f6c656374696f6e20616e64204944732c20757365206441707020746f2073656e6064820152601960fa1b608482015260a4015b60405180910390fd5b60405162461bcd60e51b815260206004820152601060248201526f27379039bab1b410333ab731ba34b7b760811b604482015260640161017b565b3480156101cb57600080fd5b506101df6101da366004612054565b610410565b005b3480156101ed57600080fd5b506101df6101fc36600461209c565b610979565b34801561020d57600080fd5b506101df61021c3660046120c0565b6109c5565b34801561022d57600080fd5b506101df61023c36600461209c565b610c27565b34801561024d57600080fd5b506101df61025c3660046120ec565b610c73565b34801561026d57600080fd5b506101df61027c366004612151565b610ee6565b34801561028d57600080fd5b506000545b6040519081526020015b60405180910390f35b3480156102b157600080fd5b506102926102c036600461209c565b610fb1565b3480156102d157600080fd5b506102926102e03660046120c0565b61105e565b3480156102f157600080fd5b50610305610300366004612181565b61108f565b60405161029c9a999897969594939291906121f6565b34801561032757600080fd5b5061033b610336366004612283565b6112a0565b604051901515815260200161029c565b34801561035757600080fd5b5061029261036636600461209c565b60026020526000908152604090205481565b61033b6103863660046120c0565b6113d2565b34801561039757600080fd5b506102926103a63660046120c0565b600360209081526000928352604080842090915290825290205481565b3480156103cf57600080fd5b506103e36103de3660046120c0565b61181b565b60405161029c91906122c5565b3480156103fc57600080fd5b506101df61040b3660046123a5565b611b0c565b6040516331a9108f60e11b8152600481018290526000906001600160a01b03841690636352211e90602401602060405180830381865afa158015610458573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047c91906123f8565b90506001600160a01b03811633146104d65760405162461bcd60e51b815260206004820152601d60248201527f4f6e6c7920746f6b656e206f776e65722063616e206d616b652061736b000000604482015260640161017b565b6060806060856001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa92505050801561053a57506040513d6000823e601f3d908101601f19168201604052610537919081019061242b565b60015b61055557604051806020016040528060008152509250610558565b92505b856001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa9250505080156105b757506040513d6000823e601f3d908101601f191682016040526105b4919081019061242b565b60015b6105d2576040518060200160405280600081525091506105d5565b91505b60405163c87b56dd60e01b8152600481018690526001600160a01b0387169063c87b56dd90602401600060405180830381865afa92505050801561063b57506040513d6000823e601f3d908101601f19168201604052610638919081019061242b565b60015b6106545750604080516020810190915260008152610657565b90505b60408051610140810182528681526001600160a01b03808a1660208084019182529383018c815242606085019081528b8416608086019081523360a08701908152600160c0880181815260e089018d81526101008a018d90526101208a018c90526000805493840181558052895160099093027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563810193845597517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56489018054918b166001600160a01b031992831617905596517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56589015594517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56688015592517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567870180549189169190961617909455517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56885018054925160ff16600160a01b026001600160a81b03199093169190961617179093559151805193949293610828937f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e569909301929190910190611fa3565b506101008201518051610845916007840191602090910190611fa3565b506101208201518051610862916008840191602090910190611fa3565b505060008054909150610877906001906124ee565b6001600160a01b03881660008181526003602090815260408083208b84528252808320859055338084526004808452828520805460018101825590865293909420909201859055516323b872dd60e01b815293945091926323b872dd926108e492909130918c9101612505565b600060405180830381600087803b1580156108fe57600080fd5b505af1158015610912573d6000803e3d6000fd5b5050604080518c81526001600160a01b038c811660208301528b1681830152606081018a90526080810185905290517f83b3a8754d705365b581ab63c329c1e55255a22aa78c67b5fcef378bfb2d9b9993509081900360a0019150a1505050505050505050565b6006546001600160a01b031633146109a35760405162461bcd60e51b815260040161017b90612529565b600780546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0382166000908152600360209081526040808320848452909152812054815490913391839081106109ff576109ff612551565b60009182526020909120600560099092020101546001600160a01b031614610a695760405162461bcd60e51b815260206004820152601d60248201527f4f6e6c7920746f6b656e206f776e65722063616e20656469742061736b000000604482015260640161017b565b60008181548110610a7c57610a7c612551565b6000918252602090912060099091020160050154600160a01b900460ff16610adb5760405162461bcd60e51b8152602060048201526012602482015271151a1a5cc8185cdac81a5cc818db1bdcd95960721b604482015260640161017b565b4260008281548110610aef57610aef612551565b9060005260206000209060090201600301819055506000808281548110610b1857610b18612551565b906000526020600020906009020160050160146101000a81548160ff021916908360ff160217905550826001600160a01b03166323b872dd3060008481548110610b6457610b64612551565b60009182526020909120600560099092020101546040516001600160e01b031960e085901b168152610ba592916001600160a01b0316908790600401612505565b600060405180830381600087803b158015610bbf57600080fd5b505af1158015610bd3573d6000803e3d6000fd5b5050604080516001600160a01b0387168152602081018690529081018490527f6330f58b476cc7f9dd8db8130a0fbb49b291ebc32531eb36e9646f56ee20174b9250606001905060405180910390a1505050565b6006546001600160a01b03163314610c515760405162461bcd60e51b815260040161017b90612529565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038316600090815260036020908152604080832085845290915281205481549091339183908110610cad57610cad612551565b60009182526020909120600560099092020101546001600160a01b031614610d175760405162461bcd60e51b815260206004820152601d60248201527f4f6e6c7920746f6b656e206f776e65722063616e20656469742061736b000000604482015260640161017b565b60008181548110610d2a57610d2a612551565b6000918252602090912060099091020160050154600160a01b900460ff16610d895760405162461bcd60e51b8152602060048201526012602482015271151a1a5cc8185cdac81a5cc818db1bdcd95960721b604482015260640161017b565b8515610db9578560008281548110610da357610da3612551565b9060005260206000209060090201600201819055505b6001600160a01b03851615610e12578460008281548110610ddc57610ddc612551565b906000526020600020906009020160010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b4260008281548110610e2657610e26612551565b9060005260206000209060090201600301819055508160008281548110610e4f57610e4f612551565b600091825260209182902060099190910201600501805460ff60a01b1916600160a01b60ff94851602179055604080518981526001600160a01b03898116938201939093529187169082015260608101859052908316608082015260a081018290527f04211d838289b72af597bf28a4ccff5a30d6056f5fce2eddb127ab4ffea0963d9060c00160405180910390a1505050505050565b6005546001600160a01b03163314610f325760405162461bcd60e51b815260206004820152600f60248201526e27b7363c9032b9b1b937bb9031b0b760891b604482015260640161017b565b6001600160a01b038116600090815260026020526040902054610f56908390612567565b6001600160a01b038216600081815260026020908152604091829020939093558051858152928301919091527f291ce0b690061cb1b3f1111bf6500efe526983251fb0f863251ec3670d035fc4910160405180910390a15050565b6005546000906001600160a01b031633146110005760405162461bcd60e51b815260206004820152600f60248201526e27b7363c9032b9b1b937bb9031b0b760891b604482015260640161017b565b506001600160a01b03811660008181526002602090815260408083208054939055805193845290830182905290917f027aeacbc6fbfa7fe735ff8f14a600469ad1a3197ce1c8c8a159641cf68fe592910160405180910390a1919050565b6004602052816000526040600020818154811061107a57600080fd5b90600052602060002001600091509150505481565b6000818154811061109f57600080fd5b600091825260209091206009909102018054600182015460028301546003840154600485015460058601546006870180549698506001600160a01b0395861697949693959283169492821693600160a01b90920460ff1692916111019061257f565b80601f016020809104026020016040519081016040528092919081815260200182805461112d9061257f565b801561117a5780601f1061114f5761010080835404028352916020019161117a565b820191906000526020600020905b81548152906001019060200180831161115d57829003601f168201915b50505050509080600701805461118f9061257f565b80601f01602080910402602001604051908101604052809291908181526020018280546111bb9061257f565b80156112085780601f106111dd57610100808354040283529160200191611208565b820191906000526020600020905b8154815290600101906020018083116111eb57829003601f168201915b50505050509080600801805461121d9061257f565b80601f01602080910402602001604051908101604052809291908181526020018280546112499061257f565b80156112965780601f1061126b57610100808354040283529160200191611296565b820191906000526020600020905b81548152906001019060200180831161127957829003601f168201915b505050505090508a565b6006546000906001600160a01b031633146112cd5760405162461bcd60e51b815260040161017b90612529565b6007546001600160a01b0384811691161461135b5760405163a9059cbb60e01b81526001600160a01b0383811660048301526024820186905284169063a9059cbb906044016020604051808303816000875af1158015611331573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135591906125ba565b50611382565b6040516001600160a01b0383169085156108fc029086906000818181858888f19450505050505b604080518581526001600160a01b03858116602083015284168183015290517fb524bace85e4ce0f8da306e32f39263c5724780ca00b7551c051c8e3dc36adaf9181900360600190a19392505050565b6001600160a01b0382166000908152600360209081526040808320848452909152812054815482918291811061140a5761140a612551565b600091825260209182902060408051610140810182526009939093029091018054835260018101546001600160a01b039081169484019490945260028101549183019190915260038101546060830152600481015483166080830152600581015492831660a0830152600160a01b90920460ff1660c082015260068201805491929160e08401919061149b9061257f565b80601f01602080910402602001604051908101604052809291908181526020018280546114c79061257f565b80156115145780601f106114e957610100808354040283529160200191611514565b820191906000526020600020905b8154815290600101906020018083116114f757829003601f168201915b5050505050815260200160078201805461152d9061257f565b80601f01602080910402602001604051908101604052809291908181526020018280546115599061257f565b80156115a65780601f1061157b576101008083540402835291602001916115a6565b820191906000526020600020905b81548152906001019060200180831161158957829003601f168201915b505050505081526020016008820180546115bf9061257f565b80601f01602080910402602001604051908101604052809291908181526020018280546115eb9061257f565b80156116385780601f1061160d57610100808354040283529160200191611638565b820191906000526020600020905b81548152906001019060200180831161161b57829003601f168201915b5050505050815250509050806040015134146116ac5760405162461bcd60e51b815260206004820152602d60248201527f4e6f7420726967687420616d6f756e742073656e742c206861766520746f206260448201526c6520657175616c20707269636560981b606482015260840161017b565b6001600160a01b0384166000908152600360209081526040808320868452909152812054815482919081106116e3576116e3612551565b906000526020600020906009020160050160146101000a81548160ff021916908360ff160217905550836001600160a01b03166323b872dd3033866040518463ffffffff1660e01b815260040161173c93929190612505565b600060405180830381600087803b15801561175657600080fd5b505af115801561176a573d6000803e3d6000fd5b505050508060a001516001600160a01b03166108fc82604001519081150290604051600060405180830381858888f16001600160a01b03891660008181526003602090815260408083208c8452825291829020548983015183519485529184018c90529183019190915260608201529096507fc220cf2a12d6492e23ed1141c55018997799699d009b00ebd5a4874c60f5c31e9450608001925061180c915050565b60405180910390a15092915050565b61188f6040518061014001604052806000815260200160006001600160a01b03168152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600060ff1681526020016060815260200160608152602001606081525090565b6001600160a01b038316600090815260036020908152604080832085845290915281205481549091908190839081106118ca576118ca612551565b600091825260209182902060408051610140810182526009939093029091018054835260018101546001600160a01b039081169484019490945260028101549183019190915260038101546060830152600481015483166080830152600581015492831660a0830152600160a01b90920460ff1660c082015260068201805491929160e08401919061195b9061257f565b80601f01602080910402602001604051908101604052809291908181526020018280546119879061257f565b80156119d45780601f106119a9576101008083540402835291602001916119d4565b820191906000526020600020905b8154815290600101906020018083116119b757829003601f168201915b505050505081526020016007820180546119ed9061257f565b80601f0160208091040260200160405190810160405280929190818152602001828054611a199061257f565b8015611a665780601f10611a3b57610100808354040283529160200191611a66565b820191906000526020600020905b815481529060010190602001808311611a4957829003601f168201915b50505050508152602001600882018054611a7f9061257f565b80601f0160208091040260200160405190810160405280929190818152602001828054611aab9061257f565b8015611af85780601f10611acd57610100808354040283529160200191611af8565b820191906000526020600020905b815481529060010190602001808311611adb57829003601f168201915b505050919092525091979650505050505050565b6001600160a01b038416600090815260036020908152604080832086845290915281205481548291908110611b4357611b43612551565b600091825260209182902060408051610140810182526009939093029091018054835260018101546001600160a01b039081169484019490945260028101549183019190915260038101546060830152600481015483166080830152600581015492831660a0830152600160a01b90920460ff1660c082015260068201805491929160e084019190611bd49061257f565b80601f0160208091040260200160405190810160405280929190818152602001828054611c009061257f565b8015611c4d5780601f10611c2257610100808354040283529160200191611c4d565b820191906000526020600020905b815481529060010190602001808311611c3057829003601f168201915b50505050508152602001600782018054611c669061257f565b80601f0160208091040260200160405190810160405280929190818152602001828054611c929061257f565b8015611cdf5780601f10611cb457610100808354040283529160200191611cdf565b820191906000526020600020905b815481529060010190602001808311611cc257829003601f168201915b50505050508152602001600882018054611cf89061257f565b80601f0160208091040260200160405190810160405280929190818152602001828054611d249061257f565b8015611d715780601f10611d4657610100808354040283529160200191611d71565b820191906000526020600020905b815481529060010190602001808311611d5457829003601f168201915b505050919092525050600554919250506001600160a01b0316331480611d9f5750336001600160a01b038416145b611df75760405162461bcd60e51b8152602060048201526024808201527f4f6e6c7920657363726f77206f722062757965722063616e2063616c6c206275604482015263794b534d60e01b606482015260840161017b565b6040808201516001600160a01b038516600090815260026020529190912054611e2091906124ee565b6001600160a01b03808516600090815260026020526040808220939093558383015160a085015190921681529190912054611e5b9190612567565b60a08201516001600160a01b039081166000908152600260209081526040808320949094559188168152600382528281208782529091529081205481548291908110611ea957611ea9612551565b906000526020600020906009020160050160146101000a81548160ff021916908360ff160217905550846001600160a01b03166323b872dd3084876040518463ffffffff1660e01b8152600401611f0293929190612505565b600060405180830381600087803b158015611f1c57600080fd5b505af1158015611f30573d6000803e3d6000fd5b505050506001600160a01b038516600081815260036020908152604080832088845282529182902054848301518351948552918401889052838301526060830152517f68bdd3548f3f05742b376651745ca73472eb18f2230f64b893d7a48e575eb0149181900360800190a15050505050565b828054611faf9061257f565b90600052602060002090601f016020900481019282611fd15760008555612017565b82601f10611fea57805160ff1916838001178555612017565b82800160010185558215612017579182015b82811115612017578251825591602001919060010190611ffc565b50612023929150612027565b5090565b5b808211156120235760008155600101612028565b6001600160a01b038116811461205157600080fd5b50565b6000806000806080858703121561206a57600080fd5b84359350602085013561207c8161203c565b9250604085013561208c8161203c565b9396929550929360600135925050565b6000602082840312156120ae57600080fd5b81356120b98161203c565b9392505050565b600080604083850312156120d357600080fd5b82356120de8161203c565b946020939093013593505050565b600080600080600060a0868803121561210457600080fd5b8535945060208601356121168161203c565b935060408601356121268161203c565b925060608601359150608086013560ff8116811461214357600080fd5b809150509295509295909350565b6000806040838503121561216457600080fd5b8235915060208301356121768161203c565b809150509250929050565b60006020828403121561219357600080fd5b5035919050565b60005b838110156121b557818101518382015260200161219d565b838111156121c4576000848401525b50505050565b600081518084526121e281602086016020860161219a565b601f01601f19169290920160200192915050565b8a81526001600160a01b038a81166020830152604082018a9052606082018990528781166080830152861660a082015260ff851660c082015261014060e08201819052600090612248838201876121ca565b905082810361010084015261225d81866121ca565b905082810361012084015261227281856121ca565b9d9c50505050505050505050505050565b60008060006060848603121561229857600080fd5b8335925060208401356122aa8161203c565b915060408401356122ba8161203c565b809150509250925092565b6020815281516020820152600060208301516122ec60408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015161231b60a08401826001600160a01b03169052565b5060a08301516001600160a01b03811660c08401525060c083015160ff811660e08401525060e0830151610140610100818186015261235e6101608601846121ca565b9250808601519050601f1961012081878603018188015261237f85846121ca565b90880151878203909201848801529350905061239b83826121ca565b9695505050505050565b600080600080608085870312156123bb57600080fd5b84356123c68161203c565b93506020850135925060408501356123dd8161203c565b915060608501356123ed8161203c565b939692955090935050565b60006020828403121561240a57600080fd5b81516120b98161203c565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561243d57600080fd5b815167ffffffffffffffff8082111561245557600080fd5b818401915084601f83011261246957600080fd5b81518181111561247b5761247b612415565b604051601f8201601f19908116603f011681019083821181831017156124a3576124a3612415565b816040528281528760208487010111156124bc57600080fd5b6124cd83602083016020880161219a565b979650505050505050565b634e487b7160e01b600052601160045260246000fd5b600082821015612500576125006124d8565b500390565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6020808252600e908201526d27b7363c9037bbb732b91031b0b760911b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6000821982111561257a5761257a6124d8565b500190565b600181811c9082168061259357607f821691505b602082108114156125b457634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156125cc57600080fd5b815180151581146120b957600080fdfea26469706673582212205a8295bbb792776496ccaaa9cb7384efe95af6490ca8015ceb6eb22e5ab3ae6b64736f6c634300080a0033
\ No newline at end of file
addedtests/src/eth/marketplace/MarketPlace.soldiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/marketplace/MarketPlace.sol
@@ -0,0 +1,390 @@
+// SPDX-License-Identifier:  Apache License
+pragma solidity >=0.8.0;
+import "../api/UniqueNFT.sol";
+
+// Inline
+interface ERC20Events {
+    event Transfer(address indexed from, address indexed to, uint256 value);
+    event Approval(
+        address indexed owner,
+        address indexed spender,
+        uint256 value
+    );
+}
+
+interface ERC20 is Dummy, ERC165, ERC20Events {
+    // Selector: name() 06fdde03
+    function name() external view returns (string memory);
+
+    // Selector: symbol() 95d89b41
+    function symbol() external view returns (string memory);
+
+    // Selector: totalSupply() 18160ddd
+    function totalSupply() external view returns (uint256);
+
+    // Selector: decimals() 313ce567
+    function decimals() external view returns (uint8);
+
+    // Selector: balanceOf(address) 70a08231
+    function balanceOf(address owner) external view returns (uint256);
+
+    // Selector: transfer(address,uint256) a9059cbb
+    function transfer(address to, uint256 amount) external returns (bool);
+
+    // Selector: transferFrom(address,address,uint256) 23b872dd
+    function transferFrom(
+        address from,
+        address to,
+        uint256 amount
+    ) external returns (bool);
+
+    // Selector: approve(address,uint256) 095ea7b3
+    function approve(address spender, uint256 amount) external returns (bool);
+
+    // Selector: allowance(address,address) dd62ed3e
+    function allowance(address owner, address spender)
+        external
+        view
+        returns (uint256);
+}
+
+interface UniqueFungible is Dummy, ERC165, ERC20 {}
+
+contract MarketPlace {
+    struct Order {
+        uint256 idNFT;
+        address currencyCode; // UNIQ tokens as address address (1); wKSM
+        uint256 price;
+        uint256 time;
+        address idCollection;
+        address ownerAddr;
+        uint8 flagActive;
+        string name;
+        string symbol;
+        string tokenURI;
+    }
+    Order[] public orders;
+    uint256 test;
+    mapping(address => uint256) public balanceKSM; //  [ownerAddr][currency] => [KSMs]
+    mapping(address => mapping(uint256 => uint256)) public asks; // [buyer][idCollection][idNFT] => idorder
+
+    mapping(address => uint256[]) public asksbySeller; // [addressSeller] =>idorder
+
+    address escrow;
+    address owner;
+    address nativecoin;
+
+    constructor(address _escrow) {
+        escrow = _escrow;
+        owner = msg.sender;
+
+        orders.push(
+            Order(0, address(0), 0, 0, address(0), address(0), 0, "", "", "")
+        );
+    }
+
+    function setowner(address _newEscrow) public onlyOwner {
+        escrow = _newEscrow;
+    }
+
+    function setEscrow(address _newEscrow) public onlyOwner {
+        escrow = _newEscrow;
+    }
+
+    function setNativeCoin(address _coin) public onlyOwner {
+        nativecoin = _coin;
+    }
+
+    modifier onlyEscrow() {
+        require(msg.sender == escrow, "Only escrow can");
+        _;
+    }
+
+    modifier onlyOwner() {
+        require(msg.sender == owner, "Only owner can");
+        _;
+    }
+
+    /**
+     * Make bids (orders) to sell NFTs
+     */
+
+    receive() external payable {
+        revert(
+            "Can't accept payment without collection and IDs, use dApp to send"
+        );
+    }
+
+    fallback() external payable {
+        revert("No such function");
+    }
+
+    event AddedAsk(
+        uint256 _price,
+        address _currencyCode,
+        address _idCollection,
+        uint256 _idNFT,
+        uint256 orderId
+    );
+    event EditedAsk(
+        uint256 _price,
+        address _currencyCode,
+        address _idCollection,
+        uint256 _idNFT,
+        uint8 _active,
+        uint256 orderId
+    );
+
+    event CanceledAsk(address _idCollection, uint256 _idNFT, uint256 orderId);
+
+    event DepositedKSM(uint256 _amount, address _sender);
+
+    event BoughtNFT4KSM(
+        address _idCollection,
+        uint256 _idNFT,
+        uint256 orderID,
+        uint256 orderPrice
+    );
+
+    event BoughtNFT(
+        address _idCollection,
+        uint256 _idNFT,
+        uint256 orderID,
+        uint256 orderPrice
+    );
+
+    event WithdrawnAllKSM(address _sender, uint256 balance);
+
+    event Withdrawn(uint256 _amount, address _currencyCode, address _sender);
+
+    function addAsk(
+        uint256 _price,
+        address _currencyCode,
+        address _idCollection,
+        uint256 _idNFT
+    ) public {
+        //
+        address ownerNFT = UniqueNFT(_idCollection).ownerOf(_idNFT);
+        require(ownerNFT == msg.sender, "Only token owner can make ask");
+        string memory nameNFT;
+        string memory symbolNFT;
+        string memory uriNFT;
+        try UniqueNFT(_idCollection).name() returns (string memory name_) {
+            nameNFT = name_;
+        } catch {
+            nameNFT = "";
+        }
+        try UniqueNFT(_idCollection).symbol() returns (string memory symbol_) {
+            symbolNFT = symbol_;
+        } catch {
+            symbolNFT = "";
+        }
+        try UniqueNFT(_idCollection).tokenURI(_idNFT) returns (
+            string memory uri_
+        ) {
+            uriNFT = uri_;
+        } catch {
+            uriNFT = "";
+        }
+        orders.push(
+            Order(
+                _idNFT,
+                _currencyCode,
+                _price,
+                block.timestamp,
+                _idCollection,
+                msg.sender,
+                1, // 1 = is active
+                nameNFT,
+                symbolNFT,
+                uriNFT
+            )
+        );
+
+        uint256 orderId = orders.length - 1;
+        asks[_idCollection][_idNFT] = orderId;
+        asksbySeller[msg.sender].push(orderId);
+        UniqueNFT(_idCollection).transferFrom(
+            msg.sender,
+            address(this),
+            _idNFT
+        );
+        emit AddedAsk(_price, _currencyCode, _idCollection, _idNFT, orderId);
+    }
+
+    function editAsk(
+        uint256 _price,
+        address _currencyCode,
+        address _idCollection,
+        uint256 _idNFT,
+        uint8 _active
+    ) public {
+        uint256 orderID = asks[_idCollection][_idNFT];
+
+        require(
+            orders[orderID].ownerAddr == msg.sender,
+            "Only token owner can edit ask"
+        );
+        require(orders[orderID].flagActive != 0, "This ask is closed");
+        if (_price > 0) {
+            orders[orderID].price = _price;
+        }
+
+        if (_currencyCode != address(0)) {
+            orders[orderID].currencyCode = _currencyCode;
+        }
+
+        orders[orderID].time = block.timestamp;
+        orders[orderID].flagActive = _active;
+
+        emit EditedAsk(
+            _price,
+            _currencyCode,
+            _idCollection,
+            _idNFT,
+            _active,
+            orderID
+        );
+    }
+
+    function cancelAsk(address _idCollection, uint256 _idNFT) public {
+        uint256 orderID = asks[_idCollection][_idNFT];
+
+        require(
+            orders[orderID].ownerAddr == msg.sender,
+            "Only token owner can edit ask"
+        );
+        require(orders[orderID].flagActive != 0, "This ask is closed");
+
+        orders[orderID].time = block.timestamp;
+        orders[orderID].flagActive = 0;
+        UniqueNFT(_idCollection).transferFrom(
+            address(this),
+            orders[orderID].ownerAddr,
+            _idNFT
+        );
+        emit CanceledAsk(_idCollection, _idNFT, orderID);
+    }
+
+    function depositKSM(uint256 _amount, address _sender) public onlyEscrow {
+        balanceKSM[_sender] = balanceKSM[_sender] + _amount;
+        emit DepositedKSM(_amount, _sender);
+    }
+
+    function buyKSM(
+        address _idCollection,
+        uint256 _idNFT,
+        address _buyer,
+        address _receiver
+    ) public {
+        Order memory order = orders[asks[_idCollection][_idNFT]];
+        require(msg.sender == escrow || msg.sender == _buyer, "Only escrow or buyer can call buyKSM" );
+        //1. reduce balance
+        balanceKSM[_buyer] = balanceKSM[_buyer] - order.price;
+        balanceKSM[order.ownerAddr] = balanceKSM[order.ownerAddr] + order.price;
+        // 2. close order
+        orders[asks[_idCollection][_idNFT]].flagActive = 0;
+        // 3. transfer NFT to buyer
+        UniqueNFT(_idCollection).transferFrom(address(this), _receiver, _idNFT);
+        emit BoughtNFT4KSM(
+            _idCollection,
+            _idNFT,
+            asks[_idCollection][_idNFT],
+            order.price
+        );
+    }
+
+    function buy(address _idCollection, uint256 _idNFT)
+        public
+        payable
+        returns (bool result)
+    {
+        //buing for UNQ like as ethers
+
+        Order memory order = orders[asks[_idCollection][_idNFT]];
+        //1. check sent amount and send to seller
+        require(
+            msg.value == order.price,
+            "Not right amount sent, have to be equal price"
+        );
+        // 2. close order
+        orders[asks[_idCollection][_idNFT]].flagActive = 0;
+
+        // 3. transfer NFT to buyer
+        UniqueNFT(_idCollection).transferFrom(
+            address(this),
+            msg.sender,
+            _idNFT
+        );
+        //uint balance  = address(this).balance;
+        result = payable(order.ownerAddr).send(order.price);
+        emit BoughtNFT(
+            _idCollection,
+            _idNFT,
+            asks[_idCollection][_idNFT],
+            order.price
+        );
+    }
+
+    /*
+        function buyOther (address _idCollection, uint256 _idNFT, address _currencyCode, uint _amount ) public  { //buy for sny token if seller wants
+
+            Order memory order = orders[ asks[_idCollection][_idNFT]];
+            //1. check sent amount and transfer from buyer to seller
+            require (order.price == _amount && order.currencyCode == _currencyCode, "Not right amount or currency sent, have to be equal currency and price" );
+            // !!! transfer have to be approved to marketplace!
+            IERC20(order.currencyCode).transferFrom(msg.sender, address(this), order.price); //to not disclojure buyer's address
+            IERC20(order.currencyCode).transfer(order.ownerAddr, order.price);
+            // 2. close order
+            orders[ asks[_idCollection][_idNFT]].flagActive = 0;
+            // 3. transfer NFT to buyer
+            IERC721ext(_idCollection).transferFrom(address(this), msg.sender, _idNFT);
+
+
+        }
+    */
+
+    function withdrawAllKSM(address _sender)
+        public
+        onlyEscrow
+        returns (uint256 lastBalance)
+    {
+        lastBalance = balanceKSM[_sender];
+        balanceKSM[_sender] = 0;
+        emit WithdrawnAllKSM(_sender, lastBalance);
+    }
+
+    function withdraw(
+        uint256 _amount,
+        address _currencyCode,
+        address payable _sender
+    ) public onlyOwner returns (bool result) {
+        if (_currencyCode != nativecoin) {
+            //erc20 compat. tokens on UNIQUE chain
+            // uint balance = IERC20(_currencyCode).balanceOf(address(this));
+            UniqueFungible(_currencyCode).transfer(_sender, _amount);
+        } else {
+            // uint balance  = address(this).balance;
+
+            result = (_sender).send(_amount); // for UNQ like as ethers
+        }
+        emit Withdrawn(_amount, _currencyCode, _sender);
+        return result;
+    }
+
+    // event GettedOrder(uint , Order);
+    function getOrder(address _idCollection, uint256 _idNFT)
+        public
+        view
+        returns (Order memory)
+    {
+        uint256 orderId = asks[_idCollection][_idNFT];
+        Order memory order = orders[orderId];
+        //       emit GettedOrder (orderId, order);
+        return order;
+    }
+
+    function getOrdersLen() public view returns (uint256) {
+        return orders.length;
+    }
+}
deletedtests/src/eth/marketplace/MarketPlaceKSM.abidiffbeforeafterboth
--- a/tests/src/eth/marketplace/MarketPlaceKSM.abi
+++ /dev/null
@@ -1 +0,0 @@
-[{"inputs":[{"internalType":"address","name":"_escrow","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"asks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"asksbySeller","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"balanceKSM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"}],"name":"buy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_currencyCode","type":"uint256"},{"internalType":"address","name":"_sender","type":"address"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_currencyCode","type":"uint256"},{"internalType":"address","name":"_sender","type":"address"}],"name":"escrowBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"offers","outputs":[{"internalType":"uint256","name":"idNFT","type":"uint256"},{"internalType":"uint256","name":"currencyCode","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"address","name":"idCollection","type":"address"},{"internalType":"address","name":"userAddr","type":"address"},{"internalType":"uint8","name":"flagActive","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_currencyCode","type":"uint256"},{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"},{"internalType":"uint8","name":"_active","type":"uint8"}],"name":"setAsk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newEscrow","type":"address"}],"name":"setEscrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newEscrow","type":"address"}],"name":"setowner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_currencyCode","type":"uint256"},{"internalType":"address","name":"_sender","type":"address"}],"name":"withdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
\ No newline at end of file
deletedtests/src/eth/marketplace/MarketPlaceKSM.bindiffbeforeafterboth
--- a/tests/src/eth/marketplace/MarketPlaceKSM.bin
+++ /dev/null
@@ -1 +0,0 @@
-608060405234801561001057600080fd5b50604051610e27380380610e2783398101604081905261002f9161005d565b600480546001600160a01b039092166001600160a01b0319928316179055600580549091163317905561008d565b60006020828403121561006f57600080fd5b81516001600160a01b038116811461008657600080fd5b9392505050565b610d8b8061009c6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c806399f2d4eb1161007157806399f2d4eb1461018e5780639df55f52146101a1578063c10c35461461010f578063cce7ec13146101b4578063db87db52146101c7578063e22d4f7d146101fa57600080fd5b80630ad58d2f146100ae57806310a5ff17146100d6578063592bd7051461010f5780638a72ea6a146101245780638dbdbe6d1461017b575b600080fd5b6100c16100bc366004610c4d565b610225565b60405190151581526020015b60405180910390f35b6101016100e4366004610bd8565b600160209081526000928352604080842090915290825290205481565b6040519081526020016100cd565b61012261011d366004610b97565b6102d8565b005b610137610132366004610c04565b610345565b6040805197885260208801969096529486019390935260608501919091526001600160a01b0390811660808501521660a083015260ff1660c082015260e0016100cd565b610122610189366004610c4d565b6103a4565b61010161019c366004610bd8565b610449565b6101226101af366004610c86565b61047a565b6101226101c2366004610bd8565b610984565b6101016101d5366004610c1d565b6001600160a01b03166000908152600160209081526040808320938352929052205490565b610101610208366004610bd8565b600260209081526000928352604080842090915290825290205481565b6004546000906001600160a01b031633146102795760405162461bcd60e51b815260206004820152600f60248201526e27b7363c9032b9b1b937bb9031b0b760891b60448201526064015b60405180910390fd5b6001600160a01b03821660009081526001602090815260408083208684529091529020546102a8908590610cfa565b6001600160a01b039290921660009081526001602081815260408084209684529590529390209190915550919050565b6005546001600160a01b031633146103235760405162461bcd60e51b815260206004820152600e60248201526d27b7363c9037bbb732b91031b0b760911b6044820152606401610270565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6000818154811061035557600080fd5b6000918252602090912060069091020180546001820154600283015460038401546004850154600590950154939550919390926001600160a01b0391821691811690600160a01b900460ff1687565b6004546001600160a01b031633146103f05760405162461bcd60e51b815260206004820152600f60248201526e27b7363c9032b9b1b937bb9031b0b760891b6044820152606401610270565b6001600160a01b038116600090815260016020908152604080832085845290915290205461041f908490610ce2565b6001600160a01b039091166000908152600160209081526040808320948352939052919091205550565b6003602052816000526040600020818154811061046557600080fd5b90600052602060002001600091509150505481565b6040516331a9108f60e11b81526004810183905233906001600160a01b03851690636352211e9060240160206040518083038186803b1580156104bc57600080fd5b505afa1580156104d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f49190610bbb565b6001600160a01b0316146105425760405162461bcd60e51b81526020600482015260156024820152742737ba103934b3b43a103a37b5b2b71037bbb732b960591b6044820152606401610270565b6001600160a01b0383166000908152600260209081526040808320858452909152812054905415806105ac575060006001600160a01b03166000828154811061058d5761058d610d27565b60009182526020909120600460069092020101546001600160a01b0316145b15610793576040805160e0810182528481526020810187815291810188815242606083019081526001600160a01b03808916608085019081523360a0860190815260ff808a1660c088019081526000805460018181018355828052995160069091027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56381019190915599517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5648b015596517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5658a015594517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56689015591517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567880180549185166001600160a01b0319909216919091179055517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56890960180549351909116600160a01b026001600160a81b031990931695909116949094171790925590546107399190610cfa565b6001600160a01b038516600090815260026020908152604080832087845282528083209390935533825260039052908120905461077890600190610cfa565b81546001810183556000928352602090922090910155610916565b6040805160e0810182526001600160a01b03861660009081526002602090815283822087835290529182205482549192839290919081106107d6576107d6610d27565b60009182526020808320600690920290910154835282810189905260408084018b90524260608501526001600160a01b0389168352600282528083208884529091528120548154608090930192811061083157610831610d27565b60009182526020808320600460069093020191909101546001600160a01b039081168452338483015260ff871660409485015288168252600281528282208783529052908120548154811061088857610888610d27565b60009182526020918290208351600690920201908155908201516001820155604082015160028201556060820151600382015560808201516004820180546001600160a01b039283166001600160a01b031990911617905560a08301516005909201805460c09094015160ff16600160a01b026001600160a81b031990941692909116919091179190911790555b6040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b038516906323b872dd90606401600060405180830381600087803b15801561096457600080fd5b505af1158015610978573d6000803e3d6000fd5b50505050505050505050565b6001600160a01b0382166000908152600260209081526040808320848452909152812054815482919081106109bb576109bb610d27565b600091825260208083206040805160e0810182526006949094029091018054845260018082015485850190815260028301548685018190526003840154606088015260048401546001600160a01b03908116608089015260059094015493841660a0880152600160a01b90930460ff1660c08701523387529084528286209051865290925290922054909250610a519190610cfa565b33600090815260016020818152604080842086830180518652908352818520959095558581015160a08701516001600160a01b031685529282528084209451845293905291902054610aa39190610ce2565b60a08201516001600160a01b0390811660009081526001602090815260408083208287015184528252808320949094559186168152600282528281208582529091529081205481548291908110610afc57610afc610d27565b60009182526020909120600560069092020101805460ff92909216600160a01b0260ff60a01b199092169190911790556040516323b872dd60e01b8152306004820152336024820152604481018390526001600160a01b038416906323b872dd90606401600060405180830381600087803b158015610b7a57600080fd5b505af1158015610b8e573d6000803e3d6000fd5b50505050505050565b600060208284031215610ba957600080fd5b8135610bb481610d3d565b9392505050565b600060208284031215610bcd57600080fd5b8151610bb481610d3d565b60008060408385031215610beb57600080fd5b8235610bf681610d3d565b946020939093013593505050565b600060208284031215610c1657600080fd5b5035919050565b60008060408385031215610c3057600080fd5b823591506020830135610c4281610d3d565b809150509250929050565b600080600060608486031215610c6257600080fd5b83359250602084013591506040840135610c7b81610d3d565b809150509250925092565b600080600080600060a08688031215610c9e57600080fd5b85359450602086013593506040860135610cb781610d3d565b925060608601359150608086013560ff81168114610cd457600080fd5b809150509295509295909350565b60008219821115610cf557610cf5610d11565b500190565b600082821015610d0c57610d0c610d11565b500390565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0381168114610d5257600080fd5b5056fea2646970667358221220d098ae4e0cc7bdbb7de1061c03402a667836f903122c1c606ca2c65db1ab78e964736f6c63430008070033
\ No newline at end of file
deletedtests/src/eth/marketplace/MarketPlaceKSM.soldiffbeforeafterboth
--- a/tests/src/eth/marketplace/MarketPlaceKSM.sol
+++ /dev/null
@@ -1,179 +0,0 @@
-// SPDX-License-Identifier:  Apache License
-pragma solidity >=0.8.0;
-
-interface IERC721 {
-    event Transfer(
-        address indexed from,
-        address indexed to,
-        uint256 indexed tokenId
-    );
-    event Approval(
-        address indexed owner,
-        address indexed approved,
-        uint256 indexed tokenId
-    );
-
-    function ownerOf(uint256 tokenId) external view returns (address owner);
-
-    function transferFrom(
-        address from,
-        address to,
-        uint256 tokenId
-    ) external;
-
-    function debug(string memory value) external;
-}
-
-interface IERC20 {
-    event Transfer(address indexed from, address indexed to, uint256 value);
-    event Approval(
-        address indexed owner,
-        address indexed spender,
-        uint256 value
-    );
-
-    function transfer(address recipient, uint256 amount)
-        external
-        returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint256 amount
-    ) external returns (bool);
-}
-
-contract MarketPlaceKSM {
-    struct Offer {
-        uint256 idNFT;
-        uint256 currencyCode;
-        uint256 price;
-        uint256 time;
-        address idCollection;
-        address userAddr;
-        uint8 flagActive;
-    }
-    Offer[] public offers;
-
-    mapping(address => mapping(uint256 => uint256)) public balanceKSM; //  [userAddr] => [KSMs]
-    mapping(address => mapping(uint256 => uint256)) public asks; // [buyer][idCollection][idNFT] => idOffer
-
-    mapping(address => uint256[]) public asksbySeller; // [addressSeller] =>idOffer
-
-    address escrow;
-    address owner;
-
-    constructor(address _escrow) {
-        escrow = _escrow;
-        owner = msg.sender;
-    }
-
-    function setowner(address _newEscrow) public onlyOwner {
-        escrow = _newEscrow;
-    }
-
-    function setEscrow(address _newEscrow) public onlyOwner {
-        escrow = _newEscrow;
-    }
-
-    modifier onlyEscrow() {
-        require(msg.sender == escrow, "Only escrow can");
-        _;
-    }
-
-    modifier onlyOwner() {
-        require(msg.sender == owner, "Only owner can");
-        _;
-    }
-
-    /**
-     * Make bids (offers) to sell NFTs
-     */
-    function setAsk(
-        uint256 _price,
-        uint256 _currencyCode,
-        address _idCollection,
-        uint256 _idNFT,
-        uint8 _active
-    ) public {
-        require(
-            IERC721(_idCollection).ownerOf(_idNFT) == msg.sender,
-            "Not right token owner"
-        );
-        uint256 offerID = asks[_idCollection][_idNFT];
-        if (offers.length == 0 || offers[offerID].idCollection == address(0)) {
-            offers.push(
-                Offer(
-                    _idNFT,
-                    _currencyCode,
-                    _price,
-                    block.timestamp,
-                    _idCollection,
-                    msg.sender,
-                    _active
-                )
-            );
-            asks[_idCollection][_idNFT] = offers.length - 1;
-            asksbySeller[msg.sender].push(offers.length - 1);
-        }
-        //edit existing offer
-        else {
-            offers[asks[_idCollection][_idNFT]] = Offer(
-                offers[asks[_idCollection][_idNFT]].idNFT,
-                _currencyCode,
-                _price,
-                block.timestamp,
-                offers[asks[_idCollection][_idNFT]].idCollection,
-                msg.sender,
-                _active
-            );
-        }
-
-        IERC721(_idCollection).transferFrom(msg.sender, address(this), _idNFT);
-    }
-
-    function deposit(
-        uint256 _amount,
-        uint256 _currencyCode,
-        address _sender
-    ) public onlyEscrow {
-        balanceKSM[_sender][_currencyCode] =
-            balanceKSM[_sender][_currencyCode] +
-            _amount;
-    }
-
-    function buy(address _idCollection, uint256 _idNFT) public {
-        Offer memory offer = offers[asks[_idCollection][_idNFT]];
-        // 1. reduce balance
-        balanceKSM[msg.sender][offer.currencyCode] =
-            balanceKSM[msg.sender][offer.currencyCode] -
-            offer.price;
-        // 2. increase balance
-        balanceKSM[offer.userAddr][offer.currencyCode] =
-            balanceKSM[offer.userAddr][offer.currencyCode] +
-            offer.price;
-        // 3. close offer
-        offers[asks[_idCollection][_idNFT]].flagActive = 0;
-        // 4. transfer NFT to buyer
-        IERC721(_idCollection).transferFrom(address(this), msg.sender, _idNFT);
-    }
-
-    function withdraw(
-        uint256 _amount,
-        uint256 _currencyCode,
-        address _sender
-    ) public onlyEscrow returns (bool) {
-        balanceKSM[_sender][_currencyCode] =
-            balanceKSM[_sender][_currencyCode] -
-            _amount;
-        return true;
-    }
-
-    function escrowBalance(uint256 _currencyCode, address _sender)
-        public
-        view
-        returns (uint256)
-    {
-        return balanceKSM[_sender][_currencyCode];
-    }
-}
deletedtests/src/eth/marketplace/MarketPlaceUNQ.abidiffbeforeafterboth
--- a/tests/src/eth/marketplace/MarketPlaceUNQ.abi
+++ /dev/null
@@ -1 +0,0 @@
-[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"asks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"asksbySeller","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"},{"internalType":"address","name":"_currencyCode","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"buy","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"}],"name":"buy","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"offers","outputs":[{"internalType":"uint256","name":"idNFT","type":"uint256"},{"internalType":"address","name":"currencyCode","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"address","name":"idCollection","type":"address"},{"internalType":"address","name":"userAddr","type":"address"},{"internalType":"uint8","name":"flagActive","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"address","name":"_currencyCode","type":"address"},{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"},{"internalType":"uint8","name":"_active","type":"uint8"}],"name":"setAsk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"setowner","outputs":[],"stateMutability":"nonpayable","type":"function"}]
\ No newline at end of file
deletedtests/src/eth/marketplace/MarketPlaceUNQ.bindiffbeforeafterboth
--- a/tests/src/eth/marketplace/MarketPlaceUNQ.bin
+++ /dev/null
@@ -1 +0,0 @@
-608060405234801561001057600080fd5b50600380546001600160a01b03191633179055610f2d806100326000396000f3fe6080604052600436106100705760003560e01c806399f2d4eb1161004e57806399f2d4eb14610120578063b3ffb7601461014e578063cce7ec1314610161578063e22d4f7d1461017457600080fd5b8063592bd705146100755780637b1d6001146100975780638a72ea6a146100b7575b600080fd5b34801561008157600080fd5b50610095610090366004610d2b565b6101ac565b005b3480156100a357600080fd5b506100956100b2366004610e1b565b61021e565b3480156100c357600080fd5b506100d76100d2366004610e02565b61073d565b604080519788526001600160a01b03968716602089015287019490945260608601929092528316608085015290911660a083015260ff1660c082015260e0015b60405180910390f35b34801561012c57600080fd5b5061014061013b366004610d6c565b6107a0565b604051908152602001610117565b61009561015c366004610d98565b6107d1565b61009561016f366004610d6c565b610b0b565b34801561018057600080fd5b5061014061018f366004610d6c565b600160209081526000928352604080842090915290825290205481565b6003546001600160a01b031633146101fc5760405162461bcd60e51b815260206004820152600e60248201526d27b7363c9037bbb732b91031b0b760911b60448201526064015b60405180910390fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6040516331a9108f60e11b81526004810183905233906001600160a01b03851690636352211e9060240160206040518083038186803b15801561026057600080fd5b505afa158015610274573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102989190610d4f565b6001600160a01b0316146102e65760405162461bcd60e51b81526020600482015260156024820152742737ba103934b3b43a103a37b5b2b71037bbb732b960591b60448201526064016101f3565b6001600160a01b038316600090815260016020908152604080832085845290915281205490541580610350575060006001600160a01b03166000828154811061033157610331610ec9565b60009182526020909120600460069092020101546001600160a01b0316145b15610542576040805160e0810182528481526001600160a01b03878116602083019081529282018981524260608401908152888316608085019081523360a0860190815260ff89811660c08801908152600080546001808201835582805299517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56360069092029182015599517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5648b0180546001600160a01b0319908116928b1692909217905596517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5658b015594517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5668a015592517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5678901805490961690871617909455517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56890960180549151969094166001600160a81b031990911617600160a01b959092169490940217905590546104e99190610ea4565b6001600160a01b0385166000908152600160208181526040808420888552825280842094909455338352600290529181209054909161052791610ea4565b815460018101835560009283526020909220909101556106d3565b6040805160e0810182526001600160a01b038616600090815260016020908152838220878352905291822054825491928392909190811061058557610585610ec9565b6000918252602080832060069092029091015483526001600160a01b03808a168483015260408085018c9052426060860152908916835260018252808320888452909152812054815460809093019281106105e2576105e2610ec9565b60009182526020808320600460069093020191909101546001600160a01b039081168452338483015260ff871660409485015288168252600181528282208783529052908120548154811061063957610639610ec9565b60009182526020918290208351600690920201908155908201516001820180546001600160a01b039283166001600160a01b031991821617909155604084015160028401556060840151600384015560808401516004840180549184169190921617905560a08301516005909201805460c09094015160ff16600160a01b026001600160a81b031990941692909116919091179190911790555b6040516323b872dd60e01b81526001600160a01b038516906323b872dd9061070390339030908890600401610e80565b600060405180830381600087803b15801561071d57600080fd5b505af1158015610731573d6000803e3d6000fd5b50505050505050505050565b6000818154811061074d57600080fd5b60009182526020909120600690910201805460018201546002830154600384015460048501546005909501549395506001600160a01b03928316949193909291821691811690600160a01b900460ff1687565b600260205281600052604060002081815481106107bc57600080fd5b90600052602060002001600091509150505481565b6001600160a01b03841660009081526001602090815260408083208684529091528120548154829190811061080857610808610ec9565b60009182526020918290206040805160e0810182526006939093029091018054835260018101546001600160a01b03908116948401949094526002810154918301829052600381015460608401526004810154841660808401526005015492831660a0830152600160a01b90920460ff1660c08201529150821480156108a35750826001600160a01b031681602001516001600160a01b0316145b6109245760405162461bcd60e51b815260206004820152604660248201527f4e6f7420726967687420616d6f756e74206f722063757272656e63792073656e60448201527f742c206861766520746f20626520657175616c2063757272656e637920616e6460648201526520707269636560d01b608482015260a4016101f3565b80602001516001600160a01b03166323b872dd333084604001516040518463ffffffff1660e01b815260040161095c93929190610e80565b602060405180830381600087803b15801561097657600080fd5b505af115801561098a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ae9190610de0565b50602081015160a0820151604080840151905163a9059cbb60e01b81526001600160a01b039283166004820152602481019190915291169063a9059cbb90604401602060405180830381600087803b158015610a0957600080fd5b505af1158015610a1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a419190610de0565b506001600160a01b038516600090815260016020908152604080832087845290915281205481548291908110610a7957610a79610ec9565b906000526020600020906006020160050160146101000a81548160ff021916908360ff160217905550846001600160a01b03166323b872dd3033876040518463ffffffff1660e01b8152600401610ad293929190610e80565b600060405180830381600087803b158015610aec57600080fd5b505af1158015610b00573d6000803e3d6000fd5b505050505050505050565b6001600160a01b038216600090815260016020908152604080832084845290915281205481548291908110610b4257610b42610ec9565b60009182526020918290206040805160e0810182526006939093029091018054835260018101546001600160a01b03908116948401949094526002810154918301829052600381015460608401526004810154841660808401526005015492831660a0830152600160a01b90920460ff1660c082015291503414610c225760405162461bcd60e51b815260206004820152603160248201527f4e6f7420726967687420616d6f756e7420554e512073656e742c206861766520604482015270746f20626520657175616c20707269636560781b60648201526084016101f3565b8060a001516001600160a01b03166108fc82604001519081150290604051600060405180830381858888f19350505050158015610c63573d6000803e3d6000fd5b506001600160a01b038316600090815260016020908152604080832085845290915281205481548291908110610c9b57610c9b610ec9565b906000526020600020906006020160050160146101000a81548160ff021916908360ff160217905550826001600160a01b03166323b872dd3033856040518463ffffffff1660e01b8152600401610cf493929190610e80565b600060405180830381600087803b158015610d0e57600080fd5b505af1158015610d22573d6000803e3d6000fd5b50505050505050565b600060208284031215610d3d57600080fd5b8135610d4881610edf565b9392505050565b600060208284031215610d6157600080fd5b8151610d4881610edf565b60008060408385031215610d7f57600080fd5b8235610d8a81610edf565b946020939093013593505050565b60008060008060808587031215610dae57600080fd5b8435610db981610edf565b9350602085013592506040850135610dd081610edf565b9396929550929360600135925050565b600060208284031215610df257600080fd5b81518015158114610d4857600080fd5b600060208284031215610e1457600080fd5b5035919050565b600080600080600060a08688031215610e3357600080fd5b853594506020860135610e4581610edf565b93506040860135610e5581610edf565b925060608601359150608086013560ff81168114610e7257600080fd5b809150509295509295909350565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600082821015610ec457634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0381168114610ef457600080fd5b5056fea2646970667358221220fbf33eb1e471c428b86ad6d948b8699fd08a127b923d5fe27ec1e1ec5f59627564736f6c63430008070033
\ No newline at end of file
deletedtests/src/eth/marketplace/MarketPlaceUNQ.soldiffbeforeafterboth
--- a/tests/src/eth/marketplace/MarketPlaceUNQ.sol
+++ /dev/null
@@ -1,163 +0,0 @@
-// SPDX-License-Identifier:  Apache License
-pragma solidity >=0.8.0;
-
-interface IERC721 {
-    event Transfer(
-        address indexed from,
-        address indexed to,
-        uint256 indexed tokenId
-    );
-    event Approval(
-        address indexed owner,
-        address indexed approved,
-        uint256 indexed tokenId
-    );
-
-    function ownerOf(uint256 tokenId) external view returns (address owner);
-
-    function transferFrom(
-        address from,
-        address to,
-        uint256 tokenId
-    ) external;
-
-    function debug(string memory value) external;
-}
-
-interface IERC20 {
-    event Transfer(address indexed from, address indexed to, uint256 value);
-    event Approval(
-        address indexed owner,
-        address indexed spender,
-        uint256 value
-    );
-
-    function transfer(address recipient, uint256 amount)
-        external
-        returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint256 amount
-    ) external returns (bool);
-}
-
-contract MarketPlaceUNQ {
-    struct Offer {
-        uint256 idNFT;
-        address currencyCode; //address of currency  token, = address(0) for UNQ
-        uint256 price;
-        uint256 time;
-        address idCollection;
-        address userAddr;
-        uint8 flagActive;
-    }
-    Offer[] public offers;
-
-    mapping(address => mapping(uint256 => uint256)) public asks; // [idCollection][idNFT] => idOffer
-
-    mapping(address => uint256[]) public asksbySeller; // [addressSeller] =>idOffer
-
-    address owner;
-
-    constructor() {
-        owner = msg.sender;
-    }
-
-    function setowner(address _newOwner) public onlyOwner {
-        owner = _newOwner;
-    }
-
-    modifier onlyOwner() {
-        require(msg.sender == owner, "Only owner can");
-        _;
-    }
-
-    /**
-     * Make bids (offers) to sell NFTs
-     */
-    function setAsk(
-        uint256 _price,
-        address _currencyCode,
-        address _idCollection,
-        uint256 _idNFT,
-        uint8 _active
-    ) public {
-        require(
-            IERC721(_idCollection).ownerOf(_idNFT) == msg.sender,
-            "Not right token owner"
-        );
-        uint256 offerID = asks[_idCollection][_idNFT];
-        if (offers.length == 0 || offers[offerID].idCollection == address(0)) {
-            offers.push(
-                Offer(
-                    _idNFT,
-                    _currencyCode,
-                    _price,
-                    block.timestamp,
-                    _idCollection,
-                    msg.sender,
-                    _active
-                )
-            );
-            asks[_idCollection][_idNFT] = offers.length - 1;
-            asksbySeller[msg.sender].push(offers.length - 1);
-        }
-        //edit existing offer
-        else {
-            offers[asks[_idCollection][_idNFT]] = Offer(
-                offers[asks[_idCollection][_idNFT]].idNFT,
-                _currencyCode,
-                _price,
-                block.timestamp,
-                offers[asks[_idCollection][_idNFT]].idCollection,
-                msg.sender,
-                _active
-            );
-        }
-
-        IERC721(_idCollection).transferFrom(msg.sender, address(this), _idNFT);
-    }
-
-    function buy(address _idCollection, uint256 _idNFT) public payable {
-        //buing for UNQ like as ethers
-        Offer memory offer = offers[asks[_idCollection][_idNFT]];
-        //1. check sent amount and send to seller
-        require(
-            msg.value == offer.price,
-            "Not right amount UNQ sent, have to be equal price"
-        );
-        payable(offer.userAddr).transfer(offer.price);
-        // 2. close offer
-        offers[asks[_idCollection][_idNFT]].flagActive = 0;
-        // 3. transfer NFT to buyer
-        IERC721(_idCollection).transferFrom(address(this), msg.sender, _idNFT);
-    }
-
-    function buy(
-        address _idCollection,
-        uint256 _idNFT,
-        address _currencyCode,
-        uint256 _amount
-    ) public payable {
-        Offer memory offer = offers[asks[_idCollection][_idNFT]];
-        //1. check sent amount and transfer from buyer to seller
-        require(
-            offer.price == _amount && offer.currencyCode == _currencyCode,
-            "Not right amount or currency sent, have to be equal currency and price"
-        );
-        // !!! transfer have to be approved to marketplace!
-        IERC20(offer.currencyCode).transferFrom(
-            msg.sender,
-            address(this),
-            offer.price
-        );
-        //to not disclojure buyer's address
-        IERC20(offer.currencyCode).transfer(offer.userAddr, offer.price);
-        // 2. close offer
-        offers[asks[_idCollection][_idNFT]].flagActive = 0;
-        // 3. transfer NFT to buyer
-        IERC721(_idCollection).transferFrom(address(this), msg.sender, _idNFT);
-    }
-}
modifiedtests/src/eth/marketplace/marketplace.test.tsdiffbeforeafterboth
--- a/tests/src/eth/marketplace/marketplace.test.ts
+++ b/tests/src/eth/marketplace/marketplace.test.ts
@@ -1,8 +1,8 @@
 import {readFile} from 'fs/promises';
 import {getBalanceSingle, transferBalanceExpectSuccess} from '../../substrate/get-balance';
 import privateKey from '../../substrate/privateKey';
-import {createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, getTokenOwner, transferExpectSuccess, transferFromExpectSuccess} from '../../util/helpers';
-import {collectionIdToAddress, createEthAccountWithBalance, executeEthTxOnSub, GAS_ARGS, itWeb3, subToEth, subToEthLowercase} from '../util/helpers';
+import {addToWhiteListExpectSuccess, confirmSponsorshipExpectSuccess, createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, getTokenOwner, setCollectionSponsorExpectSuccess, transferExpectSuccess, transferFromExpectSuccess} from '../../util/helpers';
+import {collectionIdToAddress, contractHelpers, createEthAccountWithBalance, executeEthTxOnSub, GAS_ARGS, itWeb3, subToEth, subToEthLowercase} from '../util/helpers';
 import {evmToAddress} from '@polkadot/util-crypto';
 import nonFungibleAbi from '../nonFungibleAbi.json';
 import fungibleAbi from '../fungibleAbi.json';
@@ -10,28 +10,35 @@
 
 const PRICE = 2000n;
 
-describe('Matcher contract usage', () => {
+describe.only('Matcher contract usage', () => {
   itWeb3('With UNQ', async ({api, web3}) => {
     const matcherOwner = await createEthAccountWithBalance(api, web3);
-    const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlaceUNQ.abi`)).toString()), undefined, {
+    const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {
       from: matcherOwner,
       ...GAS_ARGS,
     });
-    const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlaceUNQ.bin`)).toString()}).send({from: matcherOwner});
+    const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments:[matcherOwner]}).send({from: matcherOwner});
+    const helpers = contractHelpers(web3, matcherOwner);
+    await helpers.methods.toggleSponsoring(matcher.options.address, true).send({from: matcherOwner});
+    await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner});
 
     const alice = privateKey('//Alice');
     const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
     const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), {from: matcherOwner});
+    await setCollectionSponsorExpectSuccess(collectionId, alice.address);
+    await confirmSponsorshipExpectSuccess(collectionId);
 
+    await helpers.methods.toggleAllowed(matcher.options.address, subToEth(alice.address), true).send({from: matcherOwner});
+    await addToWhiteListExpectSuccess(alice, collectionId, evmToAddress(subToEth(alice.address)));
+
     const seller = privateKey('//Bob');
+    await helpers.methods.toggleAllowed(matcher.options.address, subToEth(seller.address), true).send({from: matcherOwner});
+    await addToWhiteListExpectSuccess(alice, collectionId, evmToAddress(subToEth(seller.address)));
 
     const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);
 
     // To transfer item to matcher it first needs to be transfered to EVM account of bob
     await transferExpectSuccess(collectionId, tokenId, seller, {Ethereum: subToEth(seller.address)});
-    // Fees will be paid from EVM account, so we should have some balance here
-    await transferBalanceExpectSuccess(api, seller, evmToAddress(subToEth(seller.address)), 10n ** 18n);
-    await transferBalanceExpectSuccess(api, alice, evmToAddress(subToEth(alice.address)), 10n ** 18n);
 
     // Token is owned by seller initially
     expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(seller.address)});
@@ -39,7 +46,7 @@
     // Ask
     {
       await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));
-      await executeEthTxOnSub(api, seller, matcher, m => m.setAsk(PRICE, '0x0000000000000000000000000000000000000000', evmCollection.options.address, tokenId, 1));
+      await executeEthTxOnSub(api, seller, matcher, m => m.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, tokenId));
     }
 
     // Token is transferred to matcher
@@ -64,13 +71,14 @@
     expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Substrate: alice.address});
   });
 
-  itWeb3('With custom ERC20', async ({api, web3}) => {
+  // selling for custom tokens excluded from release
+  itWeb3.skip('With custom ERC20', async ({api, web3}) => {
     const matcherOwner = await createEthAccountWithBalance(api, web3);
-    const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlaceUNQ.abi`)).toString()), undefined, {
+    const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {
       from: matcherOwner,
       ...GAS_ARGS,
     });
-    const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlaceUNQ.bin`)).toString()}).send({from: matcherOwner});
+    const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments: [matcherOwner]}).send({from: matcherOwner});
 
     const alice = privateKey('//Alice');
     const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
@@ -131,27 +139,33 @@
   itWeb3('With escrow', async ({api, web3}) => {
     const matcherOwner = await createEthAccountWithBalance(api, web3);
     const escrow = await createEthAccountWithBalance(api, web3);
-    const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlaceKSM.abi`)).toString()), undefined, {
+    const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {
       from: matcherOwner,
       ...GAS_ARGS,
     });
-    const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlaceKSM.bin`)).toString(), arguments: [escrow]}).send({from: matcherOwner});
-
-    const ksmToken = 11;
+    const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments: [matcherOwner]}).send({from: matcherOwner});
+    await matcher.methods.setEscrow(escrow).send({from: matcherOwner});
+    const helpers = contractHelpers(web3, matcherOwner);
+    await helpers.methods.toggleSponsoring(matcher.options.address, true).send({from: matcherOwner});
+    await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner});
 
     const alice = privateKey('//Alice');
     const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
     const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), {from: matcherOwner});
+    await setCollectionSponsorExpectSuccess(collectionId, alice.address);
+    await confirmSponsorshipExpectSuccess(collectionId);
+
+    await helpers.methods.toggleAllowed(matcher.options.address, subToEth(alice.address), true).send({from: matcherOwner});
+    await addToWhiteListExpectSuccess(alice, collectionId, evmToAddress(subToEth(alice.address)));
 
     const seller = privateKey('//Bob');
+    await helpers.methods.toggleAllowed(matcher.options.address, subToEth(seller.address), true).send({from: matcherOwner});
+    await addToWhiteListExpectSuccess(alice, collectionId, evmToAddress(subToEth(seller.address)));
 
     const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);
 
     // To transfer item to matcher it first needs to be transfered to EVM account of bob
     await transferExpectSuccess(collectionId, tokenId, seller, {Ethereum: subToEth(seller.address)});
-    // Fees will be paid from EVM account, so we should have some balance here
-    await transferBalanceExpectSuccess(api, seller, evmToAddress(subToEth(seller.address)), 10n ** 18n);
-    await transferBalanceExpectSuccess(api, alice, evmToAddress(subToEth(alice.address)), 10n ** 18n);
 
     // Token is owned by seller initially
     expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(seller.address)});
@@ -159,25 +173,25 @@
     // Ask
     {
       await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));
-      await executeEthTxOnSub(api, seller, matcher, m => m.setAsk(PRICE, ksmToken, evmCollection.options.address, tokenId, 1));
+      await executeEthTxOnSub(api, seller, matcher, m => m.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, tokenId));
     }
 
     // Token is transferred to matcher
     expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});
 
     // Give buyer KSM
-    await matcher.methods.deposit(PRICE, ksmToken, subToEth(alice.address)).send({from: escrow});
+    await matcher.methods.depositKSM(PRICE, subToEth(alice.address)).send({from: escrow});
 
     // Buy
     {
-      expect(await matcher.methods.escrowBalance(ksmToken, subToEth(seller.address)).call()).to.be.equal('0');
-      expect(await matcher.methods.escrowBalance(ksmToken, subToEth(alice.address)).call()).to.be.equal(PRICE.toString());
+      expect(await matcher.methods.balanceKSM(subToEth(seller.address)).call()).to.be.equal('0');
+      expect(await matcher.methods.balanceKSM(subToEth(alice.address)).call()).to.be.equal(PRICE.toString());
 
-      await executeEthTxOnSub(api, alice, matcher, m => m.buy(evmCollection.options.address, tokenId));
+      await executeEthTxOnSub(api, alice, matcher, m => m.buyKSM(evmCollection.options.address, tokenId, subToEth(alice.address), subToEth(alice.address)));
 
       // Price is removed from buyer balance, and added to seller
-      expect(await matcher.methods.escrowBalance(ksmToken, subToEth(alice.address)).call()).to.be.equal('0');
-      expect(await matcher.methods.escrowBalance(ksmToken, subToEth(seller.address)).call()).to.be.equal(PRICE.toString());
+      expect(await matcher.methods.balanceKSM(subToEth(alice.address)).call()).to.be.equal('0');
+      expect(await matcher.methods.balanceKSM(subToEth(seller.address)).call()).to.be.equal(PRICE.toString());
     }
 
     // Token is transferred to evm account of alice
modifiedtests/src/limits.test.tsdiffbeforeafterboth
--- a/tests/src/limits.test.ts
+++ b/tests/src/limits.test.ts
@@ -78,7 +78,7 @@
   });
 });
 
-describe('Sponsor timeout (NFT)', () => {
+describe.skip('Sponsor timeout (NFT) (only for special chain limits test)', () => {
   let alice: IKeyringPair;
   let bob: IKeyringPair;
   let charlie: IKeyringPair;
@@ -91,7 +91,7 @@
     });
   });
 
-  it('Collection limits have greater timeout value than chain limits, collection limits are enforced', async () => {
+  it.skip('Collection limits have greater timeout value than chain limits, collection limits are enforced', async () => {
     const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
     await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 7});
     const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');
@@ -141,7 +141,7 @@
   });
 });
 
-describe('Sponsor timeout (Fungible)', () => {
+describe.skip('Sponsor timeout (Fungible) (only for special chain limits test)', () => {
   let alice: IKeyringPair;
   let bob: IKeyringPair;
   let charlie: IKeyringPair;
@@ -208,7 +208,7 @@
   });
 });
 
-describe('Sponsor timeout (ReFungible)', () => {
+describe.skip('Sponsor timeout (ReFungible) (only for special chain limits test)', () => {
   let alice: IKeyringPair;
   let bob: IKeyringPair;
   let charlie: IKeyringPair;
modifiedtests/src/overflow.test.tsdiffbeforeafterboth
--- a/tests/src/overflow.test.ts
+++ b/tests/src/overflow.test.ts
@@ -13,7 +13,7 @@
 chai.use(chaiAsPromised);
 const expect = chai.expect;
 
-describe('Integration Test fungible overflows', () => {
+describe.skip('Integration Test fungible overflows', () => {
   let alice: IKeyringPair;
   let bob: IKeyringPair;
   let charlie: IKeyringPair;
modifiedtests/src/setOffchainSchema.test.tsdiffbeforeafterboth
--- a/tests/src/setOffchainSchema.test.ts
+++ b/tests/src/setOffchainSchema.test.ts
@@ -40,7 +40,7 @@
       await setOffchainSchemaExpectSuccess(alice, collectionId, DATA);
       const collection = await queryCollectionExpectSuccess(api, collectionId);
 
-      expect(collection.offchainSchema).to.be.equal('0x' + Buffer.from(DATA).toString('hex'));
+      expect('0x' + Buffer.from(collection.offchainSchema).toString('hex')).to.be.equal('0x' + Buffer.from(DATA).toString('hex'));
     });
   });
 
@@ -51,7 +51,7 @@
       await setOffchainSchemaExpectSuccess(bob, collectionId, DATA);
       const collection = await queryCollectionExpectSuccess(api, collectionId);
 
-      expect(collection.offchainSchema).to.be.equal('0x' + Buffer.from(DATA).toString('hex'));
+      expect('0x' + Buffer.from(collection.offchainSchema).toString('hex')).to.be.equal('0x' + Buffer.from(DATA).toString('hex'));
     });
   });
 });
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -905,11 +905,12 @@
   await usingApi(async (api: ApiPromise) => {
     const transferTx = api.tx.nft.transfer(normalizeAccountId(recipient.address), collectionId, tokenId, value);
     const events = await expect(submitTransactionExpectFailAsync(sender, transferTx)).to.be.rejected;
-    if (events && Array.isArray(events)) {
-      const result = getCreateCollectionResult(events);
-      // tslint:disable-next-line:no-unused-expression
-      expect(result.success).to.be.false;
-    }
+    const result = getGenericResult(events);
+    // if (events && Array.isArray(events)) {
+    //   const result = getCreateCollectionResult(events);
+    // tslint:disable-next-line:no-unused-expression
+    expect(result.success).to.be.false;
+    //}
   });
 }