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

difftreelog

feature/setCollectionLimit Behavior of the `setCollectionLimit` method. Removed method overload: single signature `(string, uint256)` is used for both cases.

PraetorP2022-11-16parent: #78a9ca0.patch.diff
in: master

22 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5831,7 +5831,7 @@
 
 [[package]]
 name = "pallet-common"
-version = "0.1.10"
+version = "0.1.11"
 dependencies = [
  "ethereum",
  "evm-coder",
modifiedpallets/common/CHANGELOG.mddiffbeforeafterboth
--- a/pallets/common/CHANGELOG.md
+++ b/pallets/common/CHANGELOG.md
@@ -2,10 +2,22 @@
 
 All notable changes to this project will be documented in this file.
 
+<!-- bureaucrate goes here -->
+
+## [0.1.11] - 2022-11-16
+
+### Changed
+
+- Behavior of the `setCollectionLimit` method.
+  Removed method overload: single signature `(string, uint256)`
+  is used for both cases.
+
 ## [0.1.10] - 2022-11-02
+
 ### Changed
- - Use named structure `EthCrossAccount` in eth functions.
 
+- Use named structure `EthCrossAccount` in eth functions.
+
 ## [0.1.9] - 2022-10-13
 
 ## Added
@@ -34,8 +46,6 @@
 ### Added
 
 - New Ethereum API methods: changeOwner, changeOwner(Substrate) and verifyOwnerOrAdmin(Substrate).
-
-<!-- bureaucrate goes here -->
 
 ## [v0.1.5] 2022-08-16
 
modifiedpallets/common/Cargo.tomldiffbeforeafterboth
--- a/pallets/common/Cargo.toml
+++ b/pallets/common/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "pallet-common"
-version = "0.1.10"
+version = "0.1.11"
 license = "GPLv3"
 edition = "2021"
 
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
after · pallets/common/src/erc.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! This module contains the implementation of pallet methods for evm.1819use evm_coder::{20	abi::AbiType,21	solidity_interface, solidity, ToLog,22	types::*,23	types::Property as PropertyStruct,24	execution::{Result, Error},25	weight,26};27pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId};28use pallet_evm_coder_substrate::dispatch_to_evm;29use sp_std::vec::Vec;30use up_data_structs::{31	AccessMode, CollectionMode, CollectionPermissions, OwnerRestrictedSet, Property,32	SponsoringRateLimit, SponsorshipState,33};34use alloc::format;3536use crate::{37	Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,38	eth::convert_cross_account_to_uint256, weights::WeightInfo,39};4041/// Events for ethereum collection helper.42#[derive(ToLog)]43pub enum CollectionHelpersEvents {44	/// The collection has been created.45	CollectionCreated {46		/// Collection owner.47		#[indexed]48		owner: address,4950		/// Collection ID.51		#[indexed]52		collection_id: address,53	},54	/// The collection has been destroyed.55	CollectionDestroyed {56		/// Collection ID.57		#[indexed]58		collection_id: address,59	},60}6162/// Does not always represent a full collection, for RFT it is either63/// collection (Implementing ERC721), or specific collection token (Implementing ERC20).64pub trait CommonEvmHandler {65	/// Raw compiled binary code of the contract stub66	const CODE: &'static [u8];6768	/// Call precompiled handle.69	fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult>;70}7172/// @title A contract that allows you to work with collections.73#[solidity_interface(name = Collection)]74impl<T: Config> CollectionHandle<T>75where76	T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,77{78	/// Set collection property.79	///80	/// @param key Property key.81	/// @param value Propery value.82	#[solidity(hide)]83	#[weight(<SelfWeightOf<T>>::set_collection_properties(1))]84	fn set_collection_property(85		&mut self,86		caller: caller,87		key: string,88		value: bytes,89	) -> Result<void> {90		let caller = T::CrossAccountId::from_eth(caller);91		let key = <Vec<u8>>::from(key)92			.try_into()93			.map_err(|_| "key too large")?;94		let value = value.0.try_into().map_err(|_| "value too large")?;9596		<Pallet<T>>::set_collection_property(self, &caller, Property { key, value })97			.map_err(dispatch_to_evm::<T>)98	}99100	/// Set collection properties.101	///102	/// @param properties Vector of properties key/value pair.103	#[weight(<SelfWeightOf<T>>::set_collection_properties(properties.len() as u32))]104	fn set_collection_properties(105		&mut self,106		caller: caller,107		properties: Vec<PropertyStruct>,108	) -> Result<void> {109		let caller = T::CrossAccountId::from_eth(caller);110111		let properties = properties112			.into_iter()113			.map(|PropertyStruct { key, value }| {114				let key = <Vec<u8>>::from(key)115					.try_into()116					.map_err(|_| "key too large")?;117118				let value = value.0.try_into().map_err(|_| "value too large")?;119120				Ok(Property { key, value })121			})122			.collect::<Result<Vec<_>>>()?;123124		<Pallet<T>>::set_collection_properties(self, &caller, properties)125			.map_err(dispatch_to_evm::<T>)126	}127128	/// Delete collection property.129	///130	/// @param key Property key.131	#[solidity(hide)]132	#[weight(<SelfWeightOf<T>>::delete_collection_properties(1))]133	fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {134		let caller = T::CrossAccountId::from_eth(caller);135		let key = <Vec<u8>>::from(key)136			.try_into()137			.map_err(|_| "key too large")?;138139		<Pallet<T>>::delete_collection_property(self, &caller, key).map_err(dispatch_to_evm::<T>)140	}141142	/// Delete collection properties.143	///144	/// @param keys Properties keys.145	#[weight(<SelfWeightOf<T>>::delete_collection_properties(keys.len() as u32))]146	fn delete_collection_properties(&mut self, caller: caller, keys: Vec<string>) -> Result<()> {147		let caller = T::CrossAccountId::from_eth(caller);148		let keys = keys149			.into_iter()150			.map(|key| {151				<Vec<u8>>::from(key)152					.try_into()153					.map_err(|_| Error::Revert("key too large".into()))154			})155			.collect::<Result<Vec<_>>>()?;156157		<Pallet<T>>::delete_collection_properties(self, &caller, keys).map_err(dispatch_to_evm::<T>)158	}159160	/// Get collection property.161	///162	/// @dev Throws error if key not found.163	///164	/// @param key Property key.165	/// @return bytes The property corresponding to the key.166	fn collection_property(&self, key: string) -> Result<bytes> {167		let key = <Vec<u8>>::from(key)168			.try_into()169			.map_err(|_| "key too large")?;170171		let props = CollectionProperties::<T>::get(self.id);172		let prop = props.get(&key).ok_or("key not found")?;173174		Ok(bytes(prop.to_vec()))175	}176177	/// Get collection properties.178	///179	/// @param keys Properties keys. Empty keys for all propertyes.180	/// @return Vector of properties key/value pairs.181	fn collection_properties(&self, keys: Vec<string>) -> Result<Vec<(string, bytes)>> {182		let keys = keys183			.into_iter()184			.map(|key| {185				<Vec<u8>>::from(key)186					.try_into()187					.map_err(|_| Error::Revert("key too large".into()))188			})189			.collect::<Result<Vec<_>>>()?;190191		let properties = Pallet::<T>::filter_collection_properties(192			self.id,193			if keys.is_empty() { None } else { Some(keys) },194		)195		.map_err(dispatch_to_evm::<T>)?;196197		let properties = properties198			.into_iter()199			.map(|p| {200				let key =201					string::from_utf8(p.key.into()).map_err(|e| Error::Revert(format!("{}", e)))?;202				let value = bytes(p.value.to_vec());203				Ok((key, value))204			})205			.collect::<Result<Vec<_>>>()?;206		Ok(properties)207	}208209	/// Set the sponsor of the collection.210	///211	/// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.212	///213	/// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.214	#[solidity(hide)]215	fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result<void> {216		self.consume_store_reads_and_writes(1, 1)?;217218		check_is_owner_or_admin(caller, self)?;219220		let sponsor = T::CrossAccountId::from_eth(sponsor);221		self.set_sponsor(sponsor.as_sub().clone())222			.map_err(dispatch_to_evm::<T>)?;223		save(self)224	}225226	/// Set the sponsor of the collection.227	///228	/// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.229	///230	/// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.231	fn set_collection_sponsor_cross(232		&mut self,233		caller: caller,234		sponsor: EthCrossAccount,235	) -> Result<void> {236		self.consume_store_reads_and_writes(1, 1)?;237238		check_is_owner_or_admin(caller, self)?;239240		let sponsor = sponsor.into_sub_cross_account::<T>()?;241		self.set_sponsor(sponsor.as_sub().clone())242			.map_err(dispatch_to_evm::<T>)?;243		save(self)244	}245246	/// Whether there is a pending sponsor.247	fn has_collection_pending_sponsor(&self) -> Result<bool> {248		Ok(matches!(249			self.collection.sponsorship,250			SponsorshipState::Unconfirmed(_)251		))252	}253254	/// Collection sponsorship confirmation.255	///256	/// @dev After setting the sponsor for the collection, it must be confirmed with this function.257	fn confirm_collection_sponsorship(&mut self, caller: caller) -> Result<void> {258		self.consume_store_writes(1)?;259260		let caller = T::CrossAccountId::from_eth(caller);261		if !self262			.confirm_sponsorship(caller.as_sub())263			.map_err(dispatch_to_evm::<T>)?264		{265			return Err("caller is not set as sponsor".into());266		}267		save(self)268	}269270	/// Remove collection sponsor.271	fn remove_collection_sponsor(&mut self, caller: caller) -> Result<void> {272		self.consume_store_reads_and_writes(1, 1)?;273		check_is_owner_or_admin(caller, self)?;274		self.remove_sponsor().map_err(dispatch_to_evm::<T>)?;275		save(self)276	}277278	/// Get current sponsor.279	///280	/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.281	fn collection_sponsor(&self) -> Result<(address, uint256)> {282		let sponsor = match self.collection.sponsorship.sponsor() {283			Some(sponsor) => sponsor,284			None => return Ok(Default::default()),285		};286		let sponsor = T::CrossAccountId::from_sub(sponsor.clone());287		let result: (address, uint256) = if sponsor.is_canonical_substrate() {288			let sponsor = convert_cross_account_to_uint256::<T>(&sponsor);289			(Default::default(), sponsor)290		} else {291			let sponsor = *sponsor.as_eth();292			(sponsor, Default::default())293		};294		Ok(result)295	}296297	/// Set limits for the collection.298	/// @dev Throws error if limit not found.299	/// @param limit Name of the limit. Valid names:300	/// 	"accountTokenOwnershipLimit",301	/// 	"sponsoredDataSize",302	/// 	"sponsoredDataRateLimit",303	/// 	"tokenLimit",304	/// 	"sponsorTransferTimeout",305	/// 	"sponsorApproveTimeout"306	///  	"ownerCanTransfer",307	/// 	"ownerCanDestroy",308	/// 	"transfersEnabled"309	/// @param value Value of the limit.310	#[solidity(rename_selector = "setCollectionLimit")]311	fn set_int_limit(&mut self, caller: caller, limit: string, value: uint256) -> Result<void> {312		self.consume_store_reads_and_writes(1, 1)?;313314		let value = value315			.try_into()316			.map_err(|_| Error::Revert(format!("can't convert value to u32 \"{}\"", value)))?;317318		let convert_value_to_bool = || match value {319			0 => Ok(false),320			1 => Ok(true),321			_ => {322				return Err(Error::Revert(format!(323					"can't convert value to boolean \"{}\"",324					value325				)))326			}327		};328329		check_is_owner_or_admin(caller, self)?;330		let mut limits = self.limits.clone();331332		match limit.as_str() {333			"accountTokenOwnershipLimit" => {334				limits.account_token_ownership_limit = Some(value);335			}336			"sponsoredDataSize" => {337				limits.sponsored_data_size = Some(value);338			}339			"sponsoredDataRateLimit" => {340				limits.sponsored_data_rate_limit = Some(SponsoringRateLimit::Blocks(value));341			}342			"tokenLimit" => {343				limits.token_limit = Some(value);344			}345			"sponsorTransferTimeout" => {346				limits.sponsor_transfer_timeout = Some(value);347			}348			"sponsorApproveTimeout" => {349				limits.sponsor_approve_timeout = Some(value);350			}351			"ownerCanTransfer" => {352				limits.owner_can_transfer = Some(convert_value_to_bool()?);353			}354			"ownerCanDestroy" => {355				limits.owner_can_destroy = Some(convert_value_to_bool()?);356			}357			"transfersEnabled" => {358				limits.transfers_enabled = Some(convert_value_to_bool()?);359			}360			_ => return Err(Error::Revert(format!("unknown limit \"{}\"", limit))),361		}362		self.limits = <Pallet<T>>::clamp_limits(self.mode.clone(), &self.limits, limits)363			.map_err(dispatch_to_evm::<T>)?;364		save(self)365	}366367	/// Get contract address.368	fn contract_address(&self) -> Result<address> {369		Ok(crate::eth::collection_id_to_address(self.id))370	}371372	/// Add collection admin.373	/// @param newAdmin Cross account administrator address.374	fn add_collection_admin_cross(375		&mut self,376		caller: caller,377		new_admin: EthCrossAccount,378	) -> Result<void> {379		self.consume_store_writes(2)?;380381		let caller = T::CrossAccountId::from_eth(caller);382		let new_admin = new_admin.into_sub_cross_account::<T>()?;383		<Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;384		Ok(())385	}386387	/// Remove collection admin.388	/// @param admin Cross account administrator address.389	fn remove_collection_admin_cross(390		&mut self,391		caller: caller,392		admin: EthCrossAccount,393	) -> Result<void> {394		self.consume_store_writes(2)?;395396		let caller = T::CrossAccountId::from_eth(caller);397		let admin = admin.into_sub_cross_account::<T>()?;398		<Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;399		Ok(())400	}401402	/// Add collection admin.403	/// @param newAdmin Address of the added administrator.404	#[solidity(hide)]405	fn add_collection_admin(&mut self, caller: caller, new_admin: address) -> Result<void> {406		self.consume_store_writes(2)?;407408		let caller = T::CrossAccountId::from_eth(caller);409		let new_admin = T::CrossAccountId::from_eth(new_admin);410		<Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;411		Ok(())412	}413414	/// Remove collection admin.415	///416	/// @param admin Address of the removed administrator.417	#[solidity(hide)]418	fn remove_collection_admin(&mut self, caller: caller, admin: address) -> Result<void> {419		self.consume_store_writes(2)?;420421		let caller = T::CrossAccountId::from_eth(caller);422		let admin = T::CrossAccountId::from_eth(admin);423		<Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;424		Ok(())425	}426427	/// Toggle accessibility of collection nesting.428	///429	/// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'430	#[solidity(rename_selector = "setCollectionNesting")]431	fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {432		self.consume_store_reads_and_writes(1, 1)?;433434		check_is_owner_or_admin(caller, self)?;435436		let mut permissions = self.collection.permissions.clone();437		let mut nesting = permissions.nesting().clone();438		nesting.token_owner = enable;439		nesting.restricted = None;440		permissions.nesting = Some(nesting);441442		self.collection.permissions = <Pallet<T>>::clamp_permissions(443			self.collection.mode.clone(),444			&self.collection.permissions,445			permissions,446		)447		.map_err(dispatch_to_evm::<T>)?;448449		save(self)450	}451452	/// Toggle accessibility of collection nesting.453	///454	/// @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'455	/// @param collections Addresses of collections that will be available for nesting.456	#[solidity(rename_selector = "setCollectionNesting")]457	fn set_nesting(458		&mut self,459		caller: caller,460		enable: bool,461		collections: Vec<address>,462	) -> Result<void> {463		self.consume_store_reads_and_writes(1, 1)?;464465		if collections.is_empty() {466			return Err("no addresses provided".into());467		}468		check_is_owner_or_admin(caller, self)?;469470		let mut permissions = self.collection.permissions.clone();471		match enable {472			false => {473				let mut nesting = permissions.nesting().clone();474				nesting.token_owner = false;475				nesting.restricted = None;476				permissions.nesting = Some(nesting);477			}478			true => {479				let mut bv = OwnerRestrictedSet::new();480				for i in collections {481					bv.try_insert(crate::eth::map_eth_to_id(&i).ok_or_else(|| {482						Error::Revert("Can't convert address into collection id".into())483					})?)484					.map_err(|_| "too many collections")?;485				}486				let mut nesting = permissions.nesting().clone();487				nesting.token_owner = true;488				nesting.restricted = Some(bv);489				permissions.nesting = Some(nesting);490			}491		};492493		self.collection.permissions = <Pallet<T>>::clamp_permissions(494			self.collection.mode.clone(),495			&self.collection.permissions,496			permissions,497		)498		.map_err(dispatch_to_evm::<T>)?;499500		save(self)501	}502503	/// Set the collection access method.504	/// @param mode Access mode505	/// 	0 for Normal506	/// 	1 for AllowList507	fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {508		self.consume_store_reads_and_writes(1, 1)?;509510		check_is_owner_or_admin(caller, self)?;511		let permissions = CollectionPermissions {512			access: Some(match mode {513				0 => AccessMode::Normal,514				1 => AccessMode::AllowList,515				_ => return Err("not supported access mode".into()),516			}),517			..Default::default()518		};519		self.collection.permissions = <Pallet<T>>::clamp_permissions(520			self.collection.mode.clone(),521			&self.collection.permissions,522			permissions,523		)524		.map_err(dispatch_to_evm::<T>)?;525526		save(self)527	}528529	/// Checks that user allowed to operate with collection.530	///531	/// @param user User address to check.532	fn allowed(&self, user: address) -> Result<bool> {533		Ok(Pallet::<T>::allowed(534			self.id,535			T::CrossAccountId::from_eth(user),536		))537	}538539	/// Add the user to the allowed list.540	///541	/// @param user Address of a trusted user.542	#[solidity(hide)]543	fn add_to_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {544		self.consume_store_writes(1)?;545546		let caller = T::CrossAccountId::from_eth(caller);547		let user = T::CrossAccountId::from_eth(user);548		<Pallet<T>>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;549		Ok(())550	}551552	/// Add user to allowed list.553	///554	/// @param user User cross account address.555	fn add_to_collection_allow_list_cross(556		&mut self,557		caller: caller,558		user: EthCrossAccount,559	) -> Result<void> {560		self.consume_store_writes(1)?;561562		let caller = T::CrossAccountId::from_eth(caller);563		let user = user.into_sub_cross_account::<T>()?;564		Pallet::<T>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;565		Ok(())566	}567568	/// Remove the user from the allowed list.569	///570	/// @param user Address of a removed user.571	#[solidity(hide)]572	fn remove_from_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {573		self.consume_store_writes(1)?;574575		let caller = T::CrossAccountId::from_eth(caller);576		let user = T::CrossAccountId::from_eth(user);577		<Pallet<T>>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;578		Ok(())579	}580581	/// Remove user from allowed list.582	///583	/// @param user User cross account address.584	fn remove_from_collection_allow_list_cross(585		&mut self,586		caller: caller,587		user: EthCrossAccount,588	) -> Result<void> {589		self.consume_store_writes(1)?;590591		let caller = T::CrossAccountId::from_eth(caller);592		let user = user.into_sub_cross_account::<T>()?;593		Pallet::<T>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;594		Ok(())595	}596597	/// Switch permission for minting.598	///599	/// @param mode Enable if "true".600	fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {601		self.consume_store_reads_and_writes(1, 1)?;602603		check_is_owner_or_admin(caller, self)?;604		let permissions = CollectionPermissions {605			mint_mode: Some(mode),606			..Default::default()607		};608		self.collection.permissions = <Pallet<T>>::clamp_permissions(609			self.collection.mode.clone(),610			&self.collection.permissions,611			permissions,612		)613		.map_err(dispatch_to_evm::<T>)?;614615		save(self)616	}617618	/// Check that account is the owner or admin of the collection619	///620	/// @param user account to verify621	/// @return "true" if account is the owner or admin622	#[solidity(hide, rename_selector = "isOwnerOrAdmin")]623	fn is_owner_or_admin_eth(&self, user: address) -> Result<bool> {624		let user = T::CrossAccountId::from_eth(user);625		Ok(self.is_owner_or_admin(&user))626	}627628	/// Check that account is the owner or admin of the collection629	///630	/// @param user User cross account to verify631	/// @return "true" if account is the owner or admin632	fn is_owner_or_admin_cross(&self, user: EthCrossAccount) -> Result<bool> {633		let user = user.into_sub_cross_account::<T>()?;634		Ok(self.is_owner_or_admin(&user))635	}636637	/// Returns collection type638	///639	/// @return `Fungible` or `NFT` or `ReFungible`640	fn unique_collection_type(&self) -> Result<string> {641		let mode = match self.collection.mode {642			CollectionMode::Fungible(_) => "Fungible",643			CollectionMode::NFT => "NFT",644			CollectionMode::ReFungible => "ReFungible",645		};646		Ok(mode.into())647	}648649	/// Get collection owner.650	///651	/// @return Tuble with sponsor address and his substrate mirror.652	/// If address is canonical then substrate mirror is zero and vice versa.653	fn collection_owner(&self) -> Result<EthCrossAccount> {654		Ok(EthCrossAccount::from_sub_cross_account::<T>(655			&T::CrossAccountId::from_sub(self.owner.clone()),656		))657	}658659	/// Changes collection owner to another account660	///661	/// @dev Owner can be changed only by current owner662	/// @param newOwner new owner account663	#[solidity(hide, rename_selector = "changeCollectionOwner")]664	fn set_owner(&mut self, caller: caller, new_owner: address) -> Result<void> {665		self.consume_store_writes(1)?;666667		let caller = T::CrossAccountId::from_eth(caller);668		let new_owner = T::CrossAccountId::from_eth(new_owner);669		self.set_owner_internal(caller, new_owner)670			.map_err(dispatch_to_evm::<T>)671	}672673	/// Get collection administrators674	///675	/// @return Vector of tuples with admins address and his substrate mirror.676	/// If address is canonical then substrate mirror is zero and vice versa.677	fn collection_admins(&self) -> Result<Vec<EthCrossAccount>> {678		let result = crate::IsAdmin::<T>::iter_prefix((self.id,))679			.map(|(admin, _)| EthCrossAccount::from_sub_cross_account::<T>(&admin))680			.collect();681		Ok(result)682	}683684	/// Changes collection owner to another account685	///686	/// @dev Owner can be changed only by current owner687	/// @param newOwner new owner cross account688	fn change_collection_owner_cross(689		&mut self,690		caller: caller,691		new_owner: EthCrossAccount,692	) -> Result<void> {693		self.consume_store_writes(1)?;694695		let caller = T::CrossAccountId::from_eth(caller);696		let new_owner = new_owner.into_sub_cross_account::<T>()?;697		self.set_owner_internal(caller, new_owner)698			.map_err(dispatch_to_evm::<T>)699	}700}701702/// ### Note703/// Do not forget to add: `self.consume_store_reads(1)?;`704fn check_is_owner_or_admin<T: Config>(705	caller: caller,706	collection: &CollectionHandle<T>,707) -> Result<T::CrossAccountId> {708	let caller = T::CrossAccountId::from_eth(caller);709	collection710		.check_is_owner_or_admin(&caller)711		.map_err(dispatch_to_evm::<T>)?;712	Ok(caller)713}714715/// ### Note716/// Do not forget to add: `self.consume_store_writes(1)?;`717fn save<T: Config>(collection: &CollectionHandle<T>) -> Result<void> {718	collection719		.check_is_internal()720		.map_err(dispatch_to_evm::<T>)?;721	collection.save().map_err(dispatch_to_evm::<T>)?;722	Ok(())723}724725/// Contains static property keys and values.726pub mod static_property {727	use evm_coder::{728		execution::{Result, Error},729	};730	use alloc::format;731732	const EXPECT_CONVERT_ERROR: &str = "length < limit";733734	/// Keys.735	pub mod key {736		use super::*;737738		/// Key "baseURI".739		pub fn base_uri() -> up_data_structs::PropertyKey {740			property_key_from_bytes(b"baseURI").expect(EXPECT_CONVERT_ERROR)741		}742743		/// Key "url".744		pub fn url() -> up_data_structs::PropertyKey {745			property_key_from_bytes(b"URI").expect(EXPECT_CONVERT_ERROR)746		}747748		/// Key "suffix".749		pub fn suffix() -> up_data_structs::PropertyKey {750			property_key_from_bytes(b"URISuffix").expect(EXPECT_CONVERT_ERROR)751		}752753		/// Key "parentNft".754		pub fn parent_nft() -> up_data_structs::PropertyKey {755			property_key_from_bytes(b"parentNft").expect(EXPECT_CONVERT_ERROR)756		}757	}758759	/// Convert `byte` to [`PropertyKey`].760	pub fn property_key_from_bytes(bytes: &[u8]) -> Result<up_data_structs::PropertyKey> {761		bytes.to_vec().try_into().map_err(|_| {762			Error::Revert(format!(763				"Property key is too long. Max length is {}.",764				up_data_structs::PropertyKey::bound()765			))766		})767	}768769	/// Convert `bytes` to [`PropertyValue`].770	pub fn property_value_from_bytes(bytes: &[u8]) -> Result<up_data_structs::PropertyValue> {771		bytes.to_vec().try_into().map_err(|_| {772			Error::Revert(format!(773				"Property key is too long. Max length is {}.",774				up_data_structs::PropertyKey::bound()775			))776		})777	}778}
modifiedpallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth
--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -18,7 +18,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0x324a7f5b
+/// @dev the ERC-165 identifier for this interface is 0x8b91d192
 contract Collection is Dummy, ERC165 {
 	// /// Set collection property.
 	// ///
@@ -167,26 +167,13 @@
 	/// 	"tokenLimit",
 	/// 	"sponsorTransferTimeout",
 	/// 	"sponsorApproveTimeout"
-	/// @param value Value of the limit.
-	/// @dev EVM selector for this function is: 0x6a3841db,
-	///  or in textual repr: setCollectionLimit(string,uint32)
-	function setCollectionLimit(string memory limit, uint32 value) public {
-		require(false, stub_error);
-		limit;
-		value;
-		dummy = 0;
-	}
-
-	/// Set limits for the collection.
-	/// @dev Throws error if limit not found.
-	/// @param limit Name of the limit. Valid names:
-	/// 	"ownerCanTransfer",
+	///  	"ownerCanTransfer",
 	/// 	"ownerCanDestroy",
 	/// 	"transfersEnabled"
 	/// @param value Value of the limit.
-	/// @dev EVM selector for this function is: 0x993b7fba,
-	///  or in textual repr: setCollectionLimit(string,bool)
-	function setCollectionLimit(string memory limit, bool value) public {
+	/// @dev EVM selector for this function is: 0x4ad890a8,
+	///  or in textual repr: setCollectionLimit(string,uint256)
+	function setCollectionLimit(string memory limit, uint256 value) public {
 		require(false, stub_error);
 		limit;
 		value;
modifiedpallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -119,7 +119,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0x324a7f5b
+/// @dev the ERC-165 identifier for this interface is 0x8b91d192
 contract Collection is Dummy, ERC165 {
 	// /// Set collection property.
 	// ///
@@ -268,26 +268,13 @@
 	/// 	"tokenLimit",
 	/// 	"sponsorTransferTimeout",
 	/// 	"sponsorApproveTimeout"
-	/// @param value Value of the limit.
-	/// @dev EVM selector for this function is: 0x6a3841db,
-	///  or in textual repr: setCollectionLimit(string,uint32)
-	function setCollectionLimit(string memory limit, uint32 value) public {
-		require(false, stub_error);
-		limit;
-		value;
-		dummy = 0;
-	}
-
-	/// Set limits for the collection.
-	/// @dev Throws error if limit not found.
-	/// @param limit Name of the limit. Valid names:
-	/// 	"ownerCanTransfer",
+	///  	"ownerCanTransfer",
 	/// 	"ownerCanDestroy",
 	/// 	"transfersEnabled"
 	/// @param value Value of the limit.
-	/// @dev EVM selector for this function is: 0x993b7fba,
-	///  or in textual repr: setCollectionLimit(string,bool)
-	function setCollectionLimit(string memory limit, bool value) public {
+	/// @dev EVM selector for this function is: 0x4ad890a8,
+	///  or in textual repr: setCollectionLimit(string,uint256)
+	function setCollectionLimit(string memory limit, uint256 value) public {
 		require(false, stub_error);
 		limit;
 		value;
modifiedpallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth
--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -119,7 +119,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0x324a7f5b
+/// @dev the ERC-165 identifier for this interface is 0x8b91d192
 contract Collection is Dummy, ERC165 {
 	// /// Set collection property.
 	// ///
@@ -268,26 +268,13 @@
 	/// 	"tokenLimit",
 	/// 	"sponsorTransferTimeout",
 	/// 	"sponsorApproveTimeout"
-	/// @param value Value of the limit.
-	/// @dev EVM selector for this function is: 0x6a3841db,
-	///  or in textual repr: setCollectionLimit(string,uint32)
-	function setCollectionLimit(string memory limit, uint32 value) public {
-		require(false, stub_error);
-		limit;
-		value;
-		dummy = 0;
-	}
-
-	/// Set limits for the collection.
-	/// @dev Throws error if limit not found.
-	/// @param limit Name of the limit. Valid names:
-	/// 	"ownerCanTransfer",
+	///  	"ownerCanTransfer",
 	/// 	"ownerCanDestroy",
 	/// 	"transfersEnabled"
 	/// @param value Value of the limit.
-	/// @dev EVM selector for this function is: 0x993b7fba,
-	///  or in textual repr: setCollectionLimit(string,bool)
-	function setCollectionLimit(string memory limit, bool value) public {
+	/// @dev EVM selector for this function is: 0x4ad890a8,
+	///  or in textual repr: setCollectionLimit(string,uint256)
+	function setCollectionLimit(string memory limit, uint256 value) public {
 		require(false, stub_error);
 		limit;
 		value;
modifiedpallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedtests/src/eth/abi/fungible.jsondiffbeforeafterboth
--- a/tests/src/eth/abi/fungible.json
+++ b/tests/src/eth/abi/fungible.json
@@ -390,17 +390,7 @@
   {
     "inputs": [
       { "internalType": "string", "name": "limit", "type": "string" },
-      { "internalType": "uint32", "name": "value", "type": "uint32" }
-    ],
-    "name": "setCollectionLimit",
-    "outputs": [],
-    "stateMutability": "nonpayable",
-    "type": "function"
-  },
-  {
-    "inputs": [
-      { "internalType": "string", "name": "limit", "type": "string" },
-      { "internalType": "bool", "name": "value", "type": "bool" }
+      { "internalType": "uint256", "name": "value", "type": "uint256" }
     ],
     "name": "setCollectionLimit",
     "outputs": [],
modifiedtests/src/eth/abi/nonFungible.jsondiffbeforeafterboth
--- a/tests/src/eth/abi/nonFungible.json
+++ b/tests/src/eth/abi/nonFungible.json
@@ -505,17 +505,7 @@
   {
     "inputs": [
       { "internalType": "string", "name": "limit", "type": "string" },
-      { "internalType": "uint32", "name": "value", "type": "uint32" }
-    ],
-    "name": "setCollectionLimit",
-    "outputs": [],
-    "stateMutability": "nonpayable",
-    "type": "function"
-  },
-  {
-    "inputs": [
-      { "internalType": "string", "name": "limit", "type": "string" },
-      { "internalType": "bool", "name": "value", "type": "bool" }
+      { "internalType": "uint256", "name": "value", "type": "uint256" }
     ],
     "name": "setCollectionLimit",
     "outputs": [],
modifiedtests/src/eth/abi/reFungible.jsondiffbeforeafterboth
--- a/tests/src/eth/abi/reFungible.json
+++ b/tests/src/eth/abi/reFungible.json
@@ -487,17 +487,7 @@
   {
     "inputs": [
       { "internalType": "string", "name": "limit", "type": "string" },
-      { "internalType": "uint32", "name": "value", "type": "uint32" }
-    ],
-    "name": "setCollectionLimit",
-    "outputs": [],
-    "stateMutability": "nonpayable",
-    "type": "function"
-  },
-  {
-    "inputs": [
-      { "internalType": "string", "name": "limit", "type": "string" },
-      { "internalType": "bool", "name": "value", "type": "bool" }
+      { "internalType": "uint256", "name": "value", "type": "uint256" }
     ],
     "name": "setCollectionLimit",
     "outputs": [],
modifiedtests/src/eth/api/UniqueFungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -13,7 +13,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0x324a7f5b
+/// @dev the ERC-165 identifier for this interface is 0x8b91d192
 interface Collection is Dummy, ERC165 {
 	// /// Set collection property.
 	// ///
@@ -113,21 +113,13 @@
 	/// 	"tokenLimit",
 	/// 	"sponsorTransferTimeout",
 	/// 	"sponsorApproveTimeout"
-	/// @param value Value of the limit.
-	/// @dev EVM selector for this function is: 0x6a3841db,
-	///  or in textual repr: setCollectionLimit(string,uint32)
-	function setCollectionLimit(string memory limit, uint32 value) external;
-
-	/// Set limits for the collection.
-	/// @dev Throws error if limit not found.
-	/// @param limit Name of the limit. Valid names:
-	/// 	"ownerCanTransfer",
+	///  	"ownerCanTransfer",
 	/// 	"ownerCanDestroy",
 	/// 	"transfersEnabled"
 	/// @param value Value of the limit.
-	/// @dev EVM selector for this function is: 0x993b7fba,
-	///  or in textual repr: setCollectionLimit(string,bool)
-	function setCollectionLimit(string memory limit, bool value) external;
+	/// @dev EVM selector for this function is: 0x4ad890a8,
+	///  or in textual repr: setCollectionLimit(string,uint256)
+	function setCollectionLimit(string memory limit, uint256 value) external;
 
 	/// Get contract address.
 	/// @dev EVM selector for this function is: 0xf6b4dfb4,
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -80,7 +80,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0x324a7f5b
+/// @dev the ERC-165 identifier for this interface is 0x8b91d192
 interface Collection is Dummy, ERC165 {
 	// /// Set collection property.
 	// ///
@@ -180,21 +180,13 @@
 	/// 	"tokenLimit",
 	/// 	"sponsorTransferTimeout",
 	/// 	"sponsorApproveTimeout"
-	/// @param value Value of the limit.
-	/// @dev EVM selector for this function is: 0x6a3841db,
-	///  or in textual repr: setCollectionLimit(string,uint32)
-	function setCollectionLimit(string memory limit, uint32 value) external;
-
-	/// Set limits for the collection.
-	/// @dev Throws error if limit not found.
-	/// @param limit Name of the limit. Valid names:
-	/// 	"ownerCanTransfer",
+	///  	"ownerCanTransfer",
 	/// 	"ownerCanDestroy",
 	/// 	"transfersEnabled"
 	/// @param value Value of the limit.
-	/// @dev EVM selector for this function is: 0x993b7fba,
-	///  or in textual repr: setCollectionLimit(string,bool)
-	function setCollectionLimit(string memory limit, bool value) external;
+	/// @dev EVM selector for this function is: 0x4ad890a8,
+	///  or in textual repr: setCollectionLimit(string,uint256)
+	function setCollectionLimit(string memory limit, uint256 value) external;
 
 	/// Get contract address.
 	/// @dev EVM selector for this function is: 0xf6b4dfb4,
modifiedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -80,7 +80,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0x324a7f5b
+/// @dev the ERC-165 identifier for this interface is 0x8b91d192
 interface Collection is Dummy, ERC165 {
 	// /// Set collection property.
 	// ///
@@ -180,21 +180,13 @@
 	/// 	"tokenLimit",
 	/// 	"sponsorTransferTimeout",
 	/// 	"sponsorApproveTimeout"
-	/// @param value Value of the limit.
-	/// @dev EVM selector for this function is: 0x6a3841db,
-	///  or in textual repr: setCollectionLimit(string,uint32)
-	function setCollectionLimit(string memory limit, uint32 value) external;
-
-	/// Set limits for the collection.
-	/// @dev Throws error if limit not found.
-	/// @param limit Name of the limit. Valid names:
-	/// 	"ownerCanTransfer",
+	///  	"ownerCanTransfer",
 	/// 	"ownerCanDestroy",
 	/// 	"transfersEnabled"
 	/// @param value Value of the limit.
-	/// @dev EVM selector for this function is: 0x993b7fba,
-	///  or in textual repr: setCollectionLimit(string,bool)
-	function setCollectionLimit(string memory limit, bool value) external;
+	/// @dev EVM selector for this function is: 0x4ad890a8,
+	///  or in textual repr: setCollectionLimit(string,uint256)
+	function setCollectionLimit(string memory limit, uint256 value) external;
 
 	/// Get contract address.
 	/// @dev EVM selector for this function is: 0xf6b4dfb4,
modifiedtests/src/eth/createFTCollection.test.tsdiffbeforeafterboth
--- a/tests/src/eth/createFTCollection.test.ts
+++ b/tests/src/eth/createFTCollection.test.ts
@@ -85,32 +85,44 @@
       tokenLimit: 1000000,
       sponsorTransferTimeout: 6,
       sponsorApproveTimeout: 6,
+      ownerCanTransfer: 0,
+      ownerCanDestroy: 0,
+      transfersEnabled: 0,
+    };
+    
+    const expectedLimits = {
+      accountTokenOwnershipLimit: 1000,
+      sponsoredDataSize: 1024,
+      sponsoredDataRateLimit: 30,
+      tokenLimit: 1000000,
+      sponsorTransferTimeout: 6,
+      sponsorApproveTimeout: 6,
       ownerCanTransfer: false,
       ownerCanDestroy: false,
       transfersEnabled: false,
     };
-
+   
     const collection = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
-    await collection.methods['setCollectionLimit(string,uint32)']('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataSize', limits.sponsoredDataSize).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('tokenLimit', limits.tokenLimit).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();
-    await collection.methods['setCollectionLimit(string,bool)']('ownerCanTransfer', limits.ownerCanTransfer).send();
-    await collection.methods['setCollectionLimit(string,bool)']('ownerCanDestroy', limits.ownerCanDestroy).send();
-    await collection.methods['setCollectionLimit(string,bool)']('transfersEnabled', limits.transfersEnabled).send();
+    await collection.methods.setCollectionLimit('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();
+    await collection.methods.setCollectionLimit('sponsoredDataSize', limits.sponsoredDataSize).send();
+    await collection.methods.setCollectionLimit('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();
+    await collection.methods.setCollectionLimit('tokenLimit', limits.tokenLimit).send();
+    await collection.methods.setCollectionLimit('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();
+    await collection.methods.setCollectionLimit('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();
+    await collection.methods.setCollectionLimit('ownerCanTransfer', limits.ownerCanTransfer).send();
+    await collection.methods.setCollectionLimit('ownerCanDestroy', limits.ownerCanDestroy).send();
+    await collection.methods.setCollectionLimit('transfersEnabled', limits.transfersEnabled).send();
     
     const data = (await helper.rft.getData(collectionId))!;
-    expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(limits.accountTokenOwnershipLimit);
-    expect(data.raw.limits.sponsoredDataSize).to.be.eq(limits.sponsoredDataSize);
-    expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(limits.sponsoredDataRateLimit);
-    expect(data.raw.limits.tokenLimit).to.be.eq(limits.tokenLimit);
-    expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(limits.sponsorTransferTimeout);
-    expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(limits.sponsorApproveTimeout);
-    expect(data.raw.limits.ownerCanTransfer).to.be.eq(limits.ownerCanTransfer);
-    expect(data.raw.limits.ownerCanDestroy).to.be.eq(limits.ownerCanDestroy);
-    expect(data.raw.limits.transfersEnabled).to.be.eq(limits.transfersEnabled);
+    expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(expectedLimits.accountTokenOwnershipLimit);
+    expect(data.raw.limits.sponsoredDataSize).to.be.eq(expectedLimits.sponsoredDataSize);
+    expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(expectedLimits.sponsoredDataRateLimit);
+    expect(data.raw.limits.tokenLimit).to.be.eq(expectedLimits.tokenLimit);
+    expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(expectedLimits.sponsorTransferTimeout);
+    expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(expectedLimits.sponsorApproveTimeout);
+    expect(data.raw.limits.ownerCanTransfer).to.be.eq(expectedLimits.ownerCanTransfer);
+    expect(data.raw.limits.ownerCanDestroy).to.be.eq(expectedLimits.ownerCanDestroy);
+    expect(data.raw.limits.transfersEnabled).to.be.eq(expectedLimits.transfersEnabled);
   });
 
   itEth('Collection address exist', async ({helper}) => {
@@ -257,11 +269,28 @@
   });
 
   itEth('(!negative test!) Set limits', async ({helper}) => {
+
+    const invalidLimits = {
+      accountTokenOwnershipLimit: BigInt(Number.MAX_SAFE_INTEGER),
+      transfersEnabled: 3,
+    };
+
     const owner = await helper.eth.createAccountWithBalance(donor);
     const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Limits', DECIMALS, 'absolutely anything', 'ISNI');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
     await expect(collectionEvm.methods
-      .setCollectionLimit('badLimit', 'true')
-      .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');
+      .setCollectionLimit('badLimit', '1')
+      .call()).to.be.rejectedWith('unknown limit "badLimit"');
+    
+    await expect(collectionEvm.methods
+      .setCollectionLimit(Object.keys(invalidLimits)[0], invalidLimits.accountTokenOwnershipLimit)
+      .call()).to.be.rejectedWith(`can't convert value to u32 "${invalidLimits.accountTokenOwnershipLimit}"`);
+    
+    await expect(collectionEvm.methods
+      .setCollectionLimit(Object.keys(invalidLimits)[1], invalidLimits.transfersEnabled)
+      .call()).to.be.rejectedWith(`can't convert value to boolean "${invalidLimits.transfersEnabled}"`);
   });
+
+   
+    
 });
modifiedtests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth
--- a/tests/src/eth/createNFTCollection.test.ts
+++ b/tests/src/eth/createNFTCollection.test.ts
@@ -124,32 +124,44 @@
       tokenLimit: 1000000,
       sponsorTransferTimeout: 6,
       sponsorApproveTimeout: 6,
+      ownerCanTransfer: 0,
+      ownerCanDestroy: 0,
+      transfersEnabled: 0,
+    };
+    
+    const expectedLimits = {
+      accountTokenOwnershipLimit: 1000,
+      sponsoredDataSize: 1024,
+      sponsoredDataRateLimit: 30,
+      tokenLimit: 1000000,
+      sponsorTransferTimeout: 6,
+      sponsorApproveTimeout: 6,
       ownerCanTransfer: false,
       ownerCanDestroy: false,
       transfersEnabled: false,
     };
 
     const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
-    await collection.methods['setCollectionLimit(string,uint32)']('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataSize', limits.sponsoredDataSize).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('tokenLimit', limits.tokenLimit).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();
-    await collection.methods['setCollectionLimit(string,bool)']('ownerCanTransfer', limits.ownerCanTransfer).send();
-    await collection.methods['setCollectionLimit(string,bool)']('ownerCanDestroy', limits.ownerCanDestroy).send();
-    await collection.methods['setCollectionLimit(string,bool)']('transfersEnabled', limits.transfersEnabled).send();
+    await collection.methods.setCollectionLimit('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();
+    await collection.methods.setCollectionLimit('sponsoredDataSize', limits.sponsoredDataSize).send();
+    await collection.methods.setCollectionLimit('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();
+    await collection.methods.setCollectionLimit('tokenLimit', limits.tokenLimit).send();
+    await collection.methods.setCollectionLimit('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();
+    await collection.methods.setCollectionLimit('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();
+    await collection.methods.setCollectionLimit('ownerCanTransfer', limits.ownerCanTransfer).send();
+    await collection.methods.setCollectionLimit('ownerCanDestroy', limits.ownerCanDestroy).send();
+    await collection.methods.setCollectionLimit('transfersEnabled', limits.transfersEnabled).send();
 
-    const data = (await helper.nft.getData(collectionId))!;
-    expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(limits.accountTokenOwnershipLimit);
-    expect(data.raw.limits.sponsoredDataSize).to.be.eq(limits.sponsoredDataSize);
-    expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(limits.sponsoredDataRateLimit);
-    expect(data.raw.limits.tokenLimit).to.be.eq(limits.tokenLimit);
-    expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(limits.sponsorTransferTimeout);
-    expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(limits.sponsorApproveTimeout);
-    expect(data.raw.limits.ownerCanTransfer).to.be.eq(limits.ownerCanTransfer);
-    expect(data.raw.limits.ownerCanDestroy).to.be.eq(limits.ownerCanDestroy);
-    expect(data.raw.limits.transfersEnabled).to.be.eq(limits.transfersEnabled);
+    const data = (await helper.rft.getData(collectionId))!;
+    expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(expectedLimits.accountTokenOwnershipLimit);
+    expect(data.raw.limits.sponsoredDataSize).to.be.eq(expectedLimits.sponsoredDataSize);
+    expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(expectedLimits.sponsoredDataRateLimit);
+    expect(data.raw.limits.tokenLimit).to.be.eq(expectedLimits.tokenLimit);
+    expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(expectedLimits.sponsorTransferTimeout);
+    expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(expectedLimits.sponsorApproveTimeout);
+    expect(data.raw.limits.ownerCanTransfer).to.be.eq(expectedLimits.ownerCanTransfer);
+    expect(data.raw.limits.ownerCanDestroy).to.be.eq(expectedLimits.ownerCanDestroy);
+    expect(data.raw.limits.transfersEnabled).to.be.eq(expectedLimits.transfersEnabled);
   });
 
   itEth('Collection address exist', async ({helper}) => {
@@ -270,12 +282,22 @@
   });
 
   itEth('(!negative test!) Set limits', async ({helper}) => {
+    const invalidLimits = {
+      accountTokenOwnershipLimit: BigInt(Number.MAX_SAFE_INTEGER),
+      transfersEnabled: 3,
+    };
+
     const owner = await helper.eth.createAccountWithBalance(donor);
     const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+    
+    await expect(collectionEvm.methods
+      .setCollectionLimit(Object.keys(invalidLimits)[0], invalidLimits.accountTokenOwnershipLimit)
+      .call()).to.be.rejectedWith(`can't convert value to u32 "${invalidLimits.accountTokenOwnershipLimit}"`);
+    
     await expect(collectionEvm.methods
-      .setCollectionLimit('badLimit', 'true')
-      .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');
+      .setCollectionLimit(Object.keys(invalidLimits)[1], invalidLimits.transfersEnabled)
+      .call()).to.be.rejectedWith(`can't convert value to boolean "${invalidLimits.transfersEnabled}"`);
   });
 
   itEth('destroyCollection', async ({helper}) => {
modifiedtests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth
--- a/tests/src/eth/createRFTCollection.test.ts
+++ b/tests/src/eth/createRFTCollection.test.ts
@@ -159,32 +159,44 @@
       tokenLimit: 1000000,
       sponsorTransferTimeout: 6,
       sponsorApproveTimeout: 6,
+      ownerCanTransfer: 0,
+      ownerCanDestroy: 0,
+      transfersEnabled: 0,
+    };
+    
+    const expectedLimits = {
+      accountTokenOwnershipLimit: 1000,
+      sponsoredDataSize: 1024,
+      sponsoredDataRateLimit: 30,
+      tokenLimit: 1000000,
+      sponsorTransferTimeout: 6,
+      sponsorApproveTimeout: 6,
       ownerCanTransfer: false,
       ownerCanDestroy: false,
       transfersEnabled: false,
     };
-
+    
     const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
-    await collection.methods['setCollectionLimit(string,uint32)']('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataSize', limits.sponsoredDataSize).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('tokenLimit', limits.tokenLimit).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();
-    await collection.methods['setCollectionLimit(string,uint32)']('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();
-    await collection.methods['setCollectionLimit(string,bool)']('ownerCanTransfer', limits.ownerCanTransfer).send();
-    await collection.methods['setCollectionLimit(string,bool)']('ownerCanDestroy', limits.ownerCanDestroy).send();
-    await collection.methods['setCollectionLimit(string,bool)']('transfersEnabled', limits.transfersEnabled).send();
+    await collection.methods.setCollectionLimit('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();
+    await collection.methods.setCollectionLimit('sponsoredDataSize', limits.sponsoredDataSize).send();
+    await collection.methods.setCollectionLimit('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();
+    await collection.methods.setCollectionLimit('tokenLimit', limits.tokenLimit).send();
+    await collection.methods.setCollectionLimit('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();
+    await collection.methods.setCollectionLimit('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();
+    await collection.methods.setCollectionLimit('ownerCanTransfer', limits.ownerCanTransfer).send();
+    await collection.methods.setCollectionLimit('ownerCanDestroy', limits.ownerCanDestroy).send();
+    await collection.methods.setCollectionLimit('transfersEnabled', limits.transfersEnabled).send();
     
     const data = (await helper.rft.getData(collectionId))!;
-    expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(limits.accountTokenOwnershipLimit);
-    expect(data.raw.limits.sponsoredDataSize).to.be.eq(limits.sponsoredDataSize);
-    expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(limits.sponsoredDataRateLimit);
-    expect(data.raw.limits.tokenLimit).to.be.eq(limits.tokenLimit);
-    expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(limits.sponsorTransferTimeout);
-    expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(limits.sponsorApproveTimeout);
-    expect(data.raw.limits.ownerCanTransfer).to.be.eq(limits.ownerCanTransfer);
-    expect(data.raw.limits.ownerCanDestroy).to.be.eq(limits.ownerCanDestroy);
-    expect(data.raw.limits.transfersEnabled).to.be.eq(limits.transfersEnabled);
+    expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(expectedLimits.accountTokenOwnershipLimit);
+    expect(data.raw.limits.sponsoredDataSize).to.be.eq(expectedLimits.sponsoredDataSize);
+    expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(expectedLimits.sponsoredDataRateLimit);
+    expect(data.raw.limits.tokenLimit).to.be.eq(expectedLimits.tokenLimit);
+    expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(expectedLimits.sponsorTransferTimeout);
+    expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(expectedLimits.sponsorApproveTimeout);
+    expect(data.raw.limits.ownerCanTransfer).to.be.eq(expectedLimits.ownerCanTransfer);
+    expect(data.raw.limits.ownerCanDestroy).to.be.eq(expectedLimits.ownerCanDestroy);
+    expect(data.raw.limits.transfersEnabled).to.be.eq(expectedLimits.transfersEnabled);
   });
 
   itEth('Collection address exist', async ({helper}) => {
@@ -305,12 +317,22 @@
   });
 
   itEth('(!negative test!) Set limits', async ({helper}) => {
+    const invalidLimits = {
+      accountTokenOwnershipLimit: BigInt(Number.MAX_SAFE_INTEGER),
+      transfersEnabled: 3,
+    };
+
     const owner = await helper.eth.createAccountWithBalance(donor);
     const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'ISNI');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+    
+    await expect(collectionEvm.methods
+      .setCollectionLimit(Object.keys(invalidLimits)[0], invalidLimits.accountTokenOwnershipLimit)
+      .call()).to.be.rejectedWith(`can't convert value to u32 "${invalidLimits.accountTokenOwnershipLimit}"`);
+    
     await expect(collectionEvm.methods
-      .setCollectionLimit('badLimit', 'true')
-      .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');
+      .setCollectionLimit(Object.keys(invalidLimits)[1], invalidLimits.transfersEnabled)
+      .call()).to.be.rejectedWith(`can't convert value to boolean "${invalidLimits.transfersEnabled}"`);
   });
   
   itEth('destroyCollection', async ({helper}) => {