git.delta.rocks / unique-network / refs/commits / bee4854e1405

difftreelog

feat Add some collection methods to eth.

Trubnikov Sergey2022-09-08parent: #848ef93.patch.diff
in: master

17 files changed

modifiedpallets/common/src/erc.rsdiffbeforeafterboth
--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -32,7 +32,10 @@
 
 use crate::{
 	Pallet, CollectionHandle, Config, CollectionProperties,
-	eth::{convert_cross_account_to_uint256, convert_uint256_to_cross_account},
+	eth::{
+		convert_cross_account_to_uint256, convert_uint256_to_cross_account,
+		convert_cross_account_to_tuple,
+	},
 };
 
 /// Events for ethereum collection helper.
@@ -146,7 +149,7 @@
 		save(self)
 	}
 
-	// /// Whether there is a pending sponsor.
+	/// Whether there is a pending sponsor.
 	fn has_collection_pending_sponsor(&self) -> Result<bool> {
 		Ok(matches!(
 			self.collection.sponsorship,
@@ -275,7 +278,7 @@
 	}
 
 	/// Get contract address.
-	fn contract_address(&self, _caller: caller) -> Result<address> {
+	fn contract_address(&self) -> Result<address> {
 		Ok(crate::eth::collection_id_to_address(self.id))
 	}
 
@@ -420,6 +423,16 @@
 		save(self)
 	}
 
+	/// Checks that user allowed to operate with collection.
+	///
+	/// @param user User address to check.
+	fn allowed(&self, user: address) -> Result<bool> {
+		Ok(Pallet::<T>::allowed(
+			self.id,
+			T::CrossAccountId::from_eth(user),
+		))
+	}
+
 	/// Add the user to the allowed list.
 	///
 	/// @param user Address of a trusted user.
@@ -430,6 +443,20 @@
 		Ok(())
 	}
 
+	/// Add substrate user to allowed list.
+	///
+	/// @param user User substrate address.
+	fn add_to_collection_allow_list_substrate(
+		&mut self,
+		caller: caller,
+		user: uint256,
+	) -> Result<void> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let user = convert_uint256_to_cross_account::<T>(user);
+		Pallet::<T>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;
+		Ok(())
+	}
+
 	/// Remove the user from the allowed list.
 	///
 	/// @param user Address of a removed user.
@@ -440,6 +467,20 @@
 		Ok(())
 	}
 
+	/// Remove substrate user from allowed list.
+	///
+	/// @param user User substrate address.
+	fn remove_from_collection_allow_list_substrate(
+		&mut self,
+		caller: caller,
+		user: uint256,
+	) -> Result<void> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let user = convert_uint256_to_cross_account::<T>(user);
+		Pallet::<T>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;
+		Ok(())
+	}
+
 	/// Switch permission for minting.
 	///
 	/// @param mode Enable if "true".
@@ -481,7 +522,7 @@
 	/// Returns collection type
 	///
 	/// @return `Fungible` or `NFT` or `ReFungible`
-	fn unique_collection_type(&mut self) -> Result<string> {
+	fn unique_collection_type(&self) -> Result<string> {
 		let mode = match self.collection.mode {
 			CollectionMode::Fungible(_) => "Fungible",
 			CollectionMode::NFT => "NFT",
@@ -490,6 +531,16 @@
 		Ok(mode.into())
 	}
 
+	/// Get collection owner.
+	///
+	/// @return Tuble with sponsor address and his substrate mirror.
+	/// If address is canonical then substrate mirror is zero and vice versa.
+	fn collection_owner(&self) -> Result<(address, uint256)> {
+		Ok(convert_cross_account_to_tuple::<T>(
+			&T::CrossAccountId::from_sub(self.owner.clone()),
+		))
+	}
+
 	/// Changes collection owner to another account
 	///
 	/// @dev Owner can be changed only by current owner
@@ -511,6 +562,14 @@
 		self.set_owner_internal(caller, new_owner)
 			.map_err(dispatch_to_evm::<T>)
 	}
+
+	// TODO: need implement AbiWriter for &Vec<T>
+	// fn collection_admins(&self) -> Result<Vec<(address, uint256)>> {
+	// 	let result = pallet_common::IsAdmin::<T>::iter_prefix((self.id,))
+	// 		.map(|(admin, _)| pallet_common::eth::convert_cross_account_to_tuple::<T>(&admin))
+	// 		.collect();
+	// 	Ok(result)
+	// }
 }
 
 fn check_is_owner_or_admin<T: Config>(
modifiedpallets/common/src/eth.rsdiffbeforeafterboth
--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -16,7 +16,7 @@
 
 //! The module contains a number of functions for converting and checking ethereum identifiers.
 
-use evm_coder::types::uint256;
+use evm_coder::types::{uint256, address};
 pub use pallet_evm::account::{Config, CrossAccountId};
 use sp_core::H160;
 use up_data_structs::CollectionId;
@@ -69,3 +69,17 @@
 	let account_id = T::AccountId::from(new_admin_arr);
 	T::CrossAccountId::from_sub(account_id)
 }
+
+/// Convert `CrossAccountId` to `(address, uint256)`.
+pub fn convert_cross_account_to_tuple<T: Config>(cross_account_id: &T::CrossAccountId) -> (address, uint256)
+where
+	T::AccountId: AsRef<[u8; 32]>
+{
+	if cross_account_id.is_canonical_substrate() {
+		let sub = convert_cross_account_to_uint256::<T>(cross_account_id);
+		(Default::default(), sub)
+	} else {
+		let eth = *cross_account_id.as_eth();
+		(eth, Default::default())
+	}
+}
\ No newline at end of file
modifiedpallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth
--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -171,14 +171,7 @@
 	fn get_sponsor(&self, contract_address: address) -> Result<(address, uint256)> {
 		let sponsor =
 			Pallet::<T>::get_sponsor(contract_address).ok_or("Contract has no sponsor")?;
-		let result: (address, uint256) = if sponsor.is_canonical_substrate() {
-			let sponsor = pallet_common::eth::convert_cross_account_to_uint256::<T>(&sponsor);
-			(Default::default(), sponsor)
-		} else {
-			let sponsor = *sponsor.as_eth();
-			(sponsor, Default::default())
-		};
-		Ok(result)
+		Ok(pallet_common::eth::convert_cross_account_to_tuple::<T>(&sponsor))
 	}
 
 	/// Check tat contract has confirmed sponsor.
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
@@ -22,7 +22,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
 contract Collection is Dummy, ERC165 {
 	/// Set collection property.
 	///
@@ -255,6 +255,18 @@
 		dummy = 0;
 	}
 
+	/// Checks that user allowed to operate with collection.
+	///
+	/// @param user User address to check.
+	/// @dev EVM selector for this function is: 0xd63a8e11,
+	///  or in textual repr: allowed(address)
+	function allowed(address user) public view returns (bool) {
+		require(false, stub_error);
+		user;
+		dummy;
+		return false;
+	}
+
 	/// Add the user to the allowed list.
 	///
 	/// @param user Address of a trusted user.
@@ -266,6 +278,17 @@
 		dummy = 0;
 	}
 
+	/// Add substrate user to allowed list.
+	///
+	/// @param user User substrate address.
+	/// @dev EVM selector for this function is: 0xd06ad267,
+	///  or in textual repr: addToCollectionAllowListSubstrate(uint256)
+	function addToCollectionAllowListSubstrate(uint256 user) public {
+		require(false, stub_error);
+		user;
+		dummy = 0;
+	}
+
 	/// Remove the user from the allowed list.
 	///
 	/// @param user Address of a removed user.
@@ -277,6 +300,17 @@
 		dummy = 0;
 	}
 
+	/// Remove substrate user from allowed list.
+	///
+	/// @param user User substrate address.
+	/// @dev EVM selector for this function is: 0xa31913ed,
+	///  or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+	function removeFromCollectionAllowListSubstrate(uint256 user) public {
+		require(false, stub_error);
+		user;
+		dummy = 0;
+	}
+
 	/// Switch permission for minting.
 	///
 	/// @param mode Enable if "true".
@@ -325,6 +359,18 @@
 		return "";
 	}
 
+	/// Get collection owner.
+	///
+	/// @return Tuble with sponsor address and his substrate mirror.
+	/// If address is canonical then substrate mirror is zero and vice versa.
+	/// @dev EVM selector for this function is: 0xdf727d3b,
+	///  or in textual repr: collectionOwner()
+	function collectionOwner() public view returns (Tuple6 memory) {
+		require(false, stub_error);
+		dummy;
+		return Tuple6(0x0000000000000000000000000000000000000000, 0);
+	}
+
 	/// Changes collection owner to another account
 	///
 	/// @dev Owner can be changed only by current owner
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
@@ -99,7 +99,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
 contract Collection is Dummy, ERC165 {
 	/// Set collection property.
 	///
@@ -332,6 +332,18 @@
 		dummy = 0;
 	}
 
+	/// Checks that user allowed to operate with collection.
+	///
+	/// @param user User address to check.
+	/// @dev EVM selector for this function is: 0xd63a8e11,
+	///  or in textual repr: allowed(address)
+	function allowed(address user) public view returns (bool) {
+		require(false, stub_error);
+		user;
+		dummy;
+		return false;
+	}
+
 	/// Add the user to the allowed list.
 	///
 	/// @param user Address of a trusted user.
@@ -343,6 +355,17 @@
 		dummy = 0;
 	}
 
+	/// Add substrate user to allowed list.
+	///
+	/// @param user User substrate address.
+	/// @dev EVM selector for this function is: 0xd06ad267,
+	///  or in textual repr: addToCollectionAllowListSubstrate(uint256)
+	function addToCollectionAllowListSubstrate(uint256 user) public {
+		require(false, stub_error);
+		user;
+		dummy = 0;
+	}
+
 	/// Remove the user from the allowed list.
 	///
 	/// @param user Address of a removed user.
@@ -354,6 +377,17 @@
 		dummy = 0;
 	}
 
+	/// Remove substrate user from allowed list.
+	///
+	/// @param user User substrate address.
+	/// @dev EVM selector for this function is: 0xa31913ed,
+	///  or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+	function removeFromCollectionAllowListSubstrate(uint256 user) public {
+		require(false, stub_error);
+		user;
+		dummy = 0;
+	}
+
 	/// Switch permission for minting.
 	///
 	/// @param mode Enable if "true".
@@ -402,6 +436,18 @@
 		return "";
 	}
 
+	/// Get collection owner.
+	///
+	/// @return Tuble with sponsor address and his substrate mirror.
+	/// If address is canonical then substrate mirror is zero and vice versa.
+	/// @dev EVM selector for this function is: 0xdf727d3b,
+	///  or in textual repr: collectionOwner()
+	function collectionOwner() public view returns (Tuple17 memory) {
+		require(false, stub_error);
+		dummy;
+		return Tuple17(0x0000000000000000000000000000000000000000, 0);
+	}
+
 	/// Changes collection owner to another account
 	///
 	/// @dev Owner can be changed only by current owner
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
@@ -99,7 +99,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
 contract Collection is Dummy, ERC165 {
 	/// Set collection property.
 	///
@@ -332,6 +332,18 @@
 		dummy = 0;
 	}
 
+	/// Checks that user allowed to operate with collection.
+	///
+	/// @param user User address to check.
+	/// @dev EVM selector for this function is: 0xd63a8e11,
+	///  or in textual repr: allowed(address)
+	function allowed(address user) public view returns (bool) {
+		require(false, stub_error);
+		user;
+		dummy;
+		return false;
+	}
+
 	/// Add the user to the allowed list.
 	///
 	/// @param user Address of a trusted user.
@@ -343,6 +355,17 @@
 		dummy = 0;
 	}
 
+	/// Add substrate user to allowed list.
+	///
+	/// @param user User substrate address.
+	/// @dev EVM selector for this function is: 0xd06ad267,
+	///  or in textual repr: addToCollectionAllowListSubstrate(uint256)
+	function addToCollectionAllowListSubstrate(uint256 user) public {
+		require(false, stub_error);
+		user;
+		dummy = 0;
+	}
+
 	/// Remove the user from the allowed list.
 	///
 	/// @param user Address of a removed user.
@@ -354,6 +377,17 @@
 		dummy = 0;
 	}
 
+	/// Remove substrate user from allowed list.
+	///
+	/// @param user User substrate address.
+	/// @dev EVM selector for this function is: 0xa31913ed,
+	///  or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+	function removeFromCollectionAllowListSubstrate(uint256 user) public {
+		require(false, stub_error);
+		user;
+		dummy = 0;
+	}
+
 	/// Switch permission for minting.
 	///
 	/// @param mode Enable if "true".
@@ -402,6 +436,18 @@
 		return "";
 	}
 
+	/// Get collection owner.
+	///
+	/// @return Tuble with sponsor address and his substrate mirror.
+	/// If address is canonical then substrate mirror is zero and vice versa.
+	/// @dev EVM selector for this function is: 0xdf727d3b,
+	///  or in textual repr: collectionOwner()
+	function collectionOwner() public view returns (Tuple17 memory) {
+		require(false, stub_error);
+		dummy;
+		return Tuple17(0x0000000000000000000000000000000000000000, 0);
+	}
+
 	/// Changes collection owner to another account
 	///
 	/// @dev Owner can be changed only by current owner
modifiedtests/src/eth/allowlist.test.tsdiffbeforeafterboth
--- a/tests/src/eth/allowlist.test.ts
+++ b/tests/src/eth/allowlist.test.ts
@@ -15,9 +15,19 @@
 // along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
 
 import {expect} from 'chai';
-import {contractHelpers, createEthAccountWithBalance, deployFlipper, itWeb3} from './util/helpers';
+import {isAllowlisted} from '../util/helpers';
+import {
+  contractHelpers,
+  createEthAccount,
+  createEthAccountWithBalance,
+  deployFlipper,
+  evmCollection,
+  evmCollectionHelpers,
+  getCollectionAddressFromResult,
+  itWeb3,
+} from './util/helpers';
 
-describe('EVM allowlist', () => {
+describe('EVM contract allowlist', () => {
   itWeb3('Contract allowlist can be toggled', async ({api, web3, privateKeyWrapper}) => {
     const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, owner);
@@ -58,3 +68,79 @@
     expect(await flipper.methods.getValue().call()).to.be.false;
   });
 });
+
+describe('EVM collection allowlist', () => {
+  itWeb3('Collection allowlist can be added and removed by [eth] address', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const user = createEthAccount(web3);
+    
+    const collectionHelpers = evmCollectionHelpers(web3, owner);
+    const result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
+    const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
+    const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+    
+    expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
+    await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});
+    expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;
+    
+    await collectionEvm.methods.removeFromCollectionAllowList(user).send({from: owner});
+    expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
+  });
+
+  itWeb3('Collection allowlist can be added and removed by [sub] address', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const user = privateKeyWrapper('//Alice');
+    
+    const collectionHelpers = evmCollectionHelpers(web3, owner);
+    const result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
+    const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+    const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+    
+    expect(await isAllowlisted(api, collectionId, user)).to.be.false;
+    await collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).send({from: owner});
+    expect(await isAllowlisted(api, collectionId, user)).to.be.true;
+
+    await collectionEvm.methods.removeFromCollectionAllowListSubstrate(user.addressRaw).send({from: owner});
+    expect(await isAllowlisted(api, collectionId, user)).to.be.false;
+  });
+
+  itWeb3('Collection allowlist can not be add and remove [eth] address by not owner', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const user = createEthAccount(web3);
+    
+    const collectionHelpers = evmCollectionHelpers(web3, owner);
+    const result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
+    const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
+    const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+    
+    expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
+    await expect(collectionEvm.methods.addToCollectionAllowList(user).call({from: notOwner})).to.be.rejectedWith('NoPermission');
+    expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
+    await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});
+    
+    expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;
+    await expect(collectionEvm.methods.removeFromCollectionAllowList(user).call({from: notOwner})).to.be.rejectedWith('NoPermission');
+    expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;
+  });
+
+  itWeb3('Collection allowlist can not be add and remove [sub] address by not owner', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const user = privateKeyWrapper('//Alice');
+    
+    const collectionHelpers = evmCollectionHelpers(web3, owner);
+    const result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
+    const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+    const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+    
+    expect(await isAllowlisted(api, collectionId, user)).to.be.false;
+    await expect(collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).call({from: notOwner})).to.be.rejectedWith('NoPermission');
+    expect(await isAllowlisted(api, collectionId, user)).to.be.false;
+    await collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).send({from: owner});
+    
+    expect(await isAllowlisted(api, collectionId, user)).to.be.true;
+    await expect(collectionEvm.methods.removeFromCollectionAllowListSubstrate(user.addressRaw).call({from: notOwner})).to.be.rejectedWith('NoPermission');
+    expect(await isAllowlisted(api, collectionId, user)).to.be.true;
+  });
+});
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 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
 interface Collection is Dummy, ERC165 {
 	/// Set collection property.
 	///
@@ -164,6 +164,13 @@
 	///  or in textual repr: setCollectionAccess(uint8)
 	function setCollectionAccess(uint8 mode) external;
 
+	/// Checks that user allowed to operate with collection.
+	///
+	/// @param user User address to check.
+	/// @dev EVM selector for this function is: 0xd63a8e11,
+	///  or in textual repr: allowed(address)
+	function allowed(address user) external view returns (bool);
+
 	/// Add the user to the allowed list.
 	///
 	/// @param user Address of a trusted user.
@@ -171,6 +178,13 @@
 	///  or in textual repr: addToCollectionAllowList(address)
 	function addToCollectionAllowList(address user) external;
 
+	/// Add substrate user to allowed list.
+	///
+	/// @param user User substrate address.
+	/// @dev EVM selector for this function is: 0xd06ad267,
+	///  or in textual repr: addToCollectionAllowListSubstrate(uint256)
+	function addToCollectionAllowListSubstrate(uint256 user) external;
+
 	/// Remove the user from the allowed list.
 	///
 	/// @param user Address of a removed user.
@@ -178,6 +192,13 @@
 	///  or in textual repr: removeFromCollectionAllowList(address)
 	function removeFromCollectionAllowList(address user) external;
 
+	/// Remove substrate user from allowed list.
+	///
+	/// @param user User substrate address.
+	/// @dev EVM selector for this function is: 0xa31913ed,
+	///  or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+	function removeFromCollectionAllowListSubstrate(uint256 user) external;
+
 	/// Switch permission for minting.
 	///
 	/// @param mode Enable if "true".
@@ -208,6 +229,14 @@
 	///  or in textual repr: uniqueCollectionType()
 	function uniqueCollectionType() external returns (string memory);
 
+	/// Get collection owner.
+	///
+	/// @return Tuble with sponsor address and his substrate mirror.
+	/// If address is canonical then substrate mirror is zero and vice versa.
+	/// @dev EVM selector for this function is: 0xdf727d3b,
+	///  or in textual repr: collectionOwner()
+	function collectionOwner() external view returns (Tuple6 memory);
+
 	/// Changes collection owner to another account
 	///
 	/// @dev Owner can be changed only by current owner
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -65,7 +65,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
 interface Collection is Dummy, ERC165 {
 	/// Set collection property.
 	///
@@ -216,6 +216,13 @@
 	///  or in textual repr: setCollectionAccess(uint8)
 	function setCollectionAccess(uint8 mode) external;
 
+	/// Checks that user allowed to operate with collection.
+	///
+	/// @param user User address to check.
+	/// @dev EVM selector for this function is: 0xd63a8e11,
+	///  or in textual repr: allowed(address)
+	function allowed(address user) external view returns (bool);
+
 	/// Add the user to the allowed list.
 	///
 	/// @param user Address of a trusted user.
@@ -223,6 +230,13 @@
 	///  or in textual repr: addToCollectionAllowList(address)
 	function addToCollectionAllowList(address user) external;
 
+	/// Add substrate user to allowed list.
+	///
+	/// @param user User substrate address.
+	/// @dev EVM selector for this function is: 0xd06ad267,
+	///  or in textual repr: addToCollectionAllowListSubstrate(uint256)
+	function addToCollectionAllowListSubstrate(uint256 user) external;
+
 	/// Remove the user from the allowed list.
 	///
 	/// @param user Address of a removed user.
@@ -230,6 +244,13 @@
 	///  or in textual repr: removeFromCollectionAllowList(address)
 	function removeFromCollectionAllowList(address user) external;
 
+	/// Remove substrate user from allowed list.
+	///
+	/// @param user User substrate address.
+	/// @dev EVM selector for this function is: 0xa31913ed,
+	///  or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+	function removeFromCollectionAllowListSubstrate(uint256 user) external;
+
 	/// Switch permission for minting.
 	///
 	/// @param mode Enable if "true".
@@ -260,6 +281,14 @@
 	///  or in textual repr: uniqueCollectionType()
 	function uniqueCollectionType() external returns (string memory);
 
+	/// Get collection owner.
+	///
+	/// @return Tuble with sponsor address and his substrate mirror.
+	/// If address is canonical then substrate mirror is zero and vice versa.
+	/// @dev EVM selector for this function is: 0xdf727d3b,
+	///  or in textual repr: collectionOwner()
+	function collectionOwner() external view returns (Tuple17 memory);
+
 	/// Changes collection owner to another account
 	///
 	/// @dev Owner can be changed only by current owner
modifiedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -65,7 +65,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
 interface Collection is Dummy, ERC165 {
 	/// Set collection property.
 	///
@@ -216,6 +216,13 @@
 	///  or in textual repr: setCollectionAccess(uint8)
 	function setCollectionAccess(uint8 mode) external;
 
+	/// Checks that user allowed to operate with collection.
+	///
+	/// @param user User address to check.
+	/// @dev EVM selector for this function is: 0xd63a8e11,
+	///  or in textual repr: allowed(address)
+	function allowed(address user) external view returns (bool);
+
 	/// Add the user to the allowed list.
 	///
 	/// @param user Address of a trusted user.
@@ -223,6 +230,13 @@
 	///  or in textual repr: addToCollectionAllowList(address)
 	function addToCollectionAllowList(address user) external;
 
+	/// Add substrate user to allowed list.
+	///
+	/// @param user User substrate address.
+	/// @dev EVM selector for this function is: 0xd06ad267,
+	///  or in textual repr: addToCollectionAllowListSubstrate(uint256)
+	function addToCollectionAllowListSubstrate(uint256 user) external;
+
 	/// Remove the user from the allowed list.
 	///
 	/// @param user Address of a removed user.
@@ -230,6 +244,13 @@
 	///  or in textual repr: removeFromCollectionAllowList(address)
 	function removeFromCollectionAllowList(address user) external;
 
+	/// Remove substrate user from allowed list.
+	///
+	/// @param user User substrate address.
+	/// @dev EVM selector for this function is: 0xa31913ed,
+	///  or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+	function removeFromCollectionAllowListSubstrate(uint256 user) external;
+
 	/// Switch permission for minting.
 	///
 	/// @param mode Enable if "true".
@@ -260,6 +281,14 @@
 	///  or in textual repr: uniqueCollectionType()
 	function uniqueCollectionType() external returns (string memory);
 
+	/// Get collection owner.
+	///
+	/// @return Tuble with sponsor address and his substrate mirror.
+	/// If address is canonical then substrate mirror is zero and vice versa.
+	/// @dev EVM selector for this function is: 0xdf727d3b,
+	///  or in textual repr: collectionOwner()
+	function collectionOwner() external view returns (Tuple17 memory);
+
 	/// Changes collection owner to another account
 	///
 	/// @dev Owner can be changed only by current owner
modifiedtests/src/eth/fungibleAbi.jsondiffbeforeafterboth
before · tests/src/eth/fungibleAbi.json
1[2  {3    "anonymous": false,4    "inputs": [5      {6        "indexed": true,7        "internalType": "address",8        "name": "owner",9        "type": "address"10      },11      {12        "indexed": true,13        "internalType": "address",14        "name": "spender",15        "type": "address"16      },17      {18        "indexed": false,19        "internalType": "uint256",20        "name": "value",21        "type": "uint256"22      }23    ],24    "name": "Approval",25    "type": "event"26  },27  {28    "anonymous": false,29    "inputs": [30      {31        "indexed": true,32        "internalType": "address",33        "name": "from",34        "type": "address"35      },36      {37        "indexed": true,38        "internalType": "address",39        "name": "to",40        "type": "address"41      },42      {43        "indexed": false,44        "internalType": "uint256",45        "name": "value",46        "type": "uint256"47      }48    ],49    "name": "Transfer",50    "type": "event"51  },52  {53    "inputs": [54      { "internalType": "address", "name": "newAdmin", "type": "address" }55    ],56    "name": "addCollectionAdmin",57    "outputs": [],58    "stateMutability": "nonpayable",59    "type": "function"60  },61  {62    "inputs": [63      { "internalType": "uint256", "name": "newAdmin", "type": "uint256" }64    ],65    "name": "addCollectionAdminSubstrate",66    "outputs": [],67    "stateMutability": "nonpayable",68    "type": "function"69  },70  {71    "inputs": [72      { "internalType": "address", "name": "user", "type": "address" }73    ],74    "name": "addToCollectionAllowList",75    "outputs": [],76    "stateMutability": "nonpayable",77    "type": "function"78  },79  {80    "inputs": [81      { "internalType": "address", "name": "owner", "type": "address" },82      { "internalType": "address", "name": "spender", "type": "address" }83    ],84    "name": "allowance",85    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],86    "stateMutability": "view",87    "type": "function"88  },89  {90    "inputs": [91      { "internalType": "address", "name": "spender", "type": "address" },92      { "internalType": "uint256", "name": "amount", "type": "uint256" }93    ],94    "name": "approve",95    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],96    "stateMutability": "nonpayable",97    "type": "function"98  },99  {100    "inputs": [101      { "internalType": "address", "name": "owner", "type": "address" }102    ],103    "name": "balanceOf",104    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],105    "stateMutability": "view",106    "type": "function"107  },108  {109    "inputs": [110      { "internalType": "address", "name": "from", "type": "address" },111      { "internalType": "uint256", "name": "amount", "type": "uint256" }112    ],113    "name": "burnFrom",114    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],115    "stateMutability": "nonpayable",116    "type": "function"117  },118  {119    "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],120    "name": "collectionProperty",121    "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],122    "stateMutability": "view",123    "type": "function"124  },125  {126    "inputs": [],127    "name": "confirmCollectionSponsorship",128    "outputs": [],129    "stateMutability": "nonpayable",130    "type": "function"131  },132  {133    "inputs": [],134    "name": "contractAddress",135    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],136    "stateMutability": "view",137    "type": "function"138  },139  {140    "inputs": [],141    "name": "decimals",142    "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],143    "stateMutability": "view",144    "type": "function"145  },146  {147    "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],148    "name": "deleteCollectionProperty",149    "outputs": [],150    "stateMutability": "nonpayable",151    "type": "function"152  },153  {154    "inputs": [],155    "name": "getCollectionSponsor",156    "outputs": [157      {158        "components": [159          { "internalType": "address", "name": "field_0", "type": "address" },160          { "internalType": "uint256", "name": "field_1", "type": "uint256" }161        ],162        "internalType": "struct Tuple6",163        "name": "",164        "type": "tuple"165      }166    ],167    "stateMutability": "view",168    "type": "function"169  },170  {171    "inputs": [],172    "name": "hasCollectionPendingSponsor",173    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],174    "stateMutability": "view",175    "type": "function"176  },177  {178    "inputs": [179      { "internalType": "address", "name": "user", "type": "address" }180    ],181    "name": "isOwnerOrAdmin",182    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],183    "stateMutability": "view",184    "type": "function"185  },186  {187    "inputs": [188      { "internalType": "uint256", "name": "user", "type": "uint256" }189    ],190    "name": "isOwnerOrAdminSubstrate",191    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],192    "stateMutability": "view",193    "type": "function"194  },195  {196    "inputs": [197      { "internalType": "address", "name": "to", "type": "address" },198      { "internalType": "uint256", "name": "amount", "type": "uint256" }199    ],200    "name": "mint",201    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],202    "stateMutability": "nonpayable",203    "type": "function"204  },205  {206    "inputs": [207      {208        "components": [209          { "internalType": "address", "name": "field_0", "type": "address" },210          { "internalType": "uint256", "name": "field_1", "type": "uint256" }211        ],212        "internalType": "struct Tuple6[]",213        "name": "amounts",214        "type": "tuple[]"215      }216    ],217    "name": "mintBulk",218    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],219    "stateMutability": "nonpayable",220    "type": "function"221  },222  {223    "inputs": [],224    "name": "name",225    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],226    "stateMutability": "view",227    "type": "function"228  },229  {230    "inputs": [231      { "internalType": "address", "name": "admin", "type": "address" }232    ],233    "name": "removeCollectionAdmin",234    "outputs": [],235    "stateMutability": "nonpayable",236    "type": "function"237  },238  {239    "inputs": [240      { "internalType": "uint256", "name": "admin", "type": "uint256" }241    ],242    "name": "removeCollectionAdminSubstrate",243    "outputs": [],244    "stateMutability": "nonpayable",245    "type": "function"246  },247  {248    "inputs": [],249    "name": "removeCollectionSponsor",250    "outputs": [],251    "stateMutability": "nonpayable",252    "type": "function"253  },254  {255    "inputs": [256      { "internalType": "address", "name": "user", "type": "address" }257    ],258    "name": "removeFromCollectionAllowList",259    "outputs": [],260    "stateMutability": "nonpayable",261    "type": "function"262  },263  {264    "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],265    "name": "setCollectionAccess",266    "outputs": [],267    "stateMutability": "nonpayable",268    "type": "function"269  },270  {271    "inputs": [272      { "internalType": "string", "name": "limit", "type": "string" },273      { "internalType": "uint32", "name": "value", "type": "uint32" }274    ],275    "name": "setCollectionLimit",276    "outputs": [],277    "stateMutability": "nonpayable",278    "type": "function"279  },280  {281    "inputs": [282      { "internalType": "string", "name": "limit", "type": "string" },283      { "internalType": "bool", "name": "value", "type": "bool" }284    ],285    "name": "setCollectionLimit",286    "outputs": [],287    "stateMutability": "nonpayable",288    "type": "function"289  },290  {291    "inputs": [{ "internalType": "bool", "name": "mode", "type": "bool" }],292    "name": "setCollectionMintMode",293    "outputs": [],294    "stateMutability": "nonpayable",295    "type": "function"296  },297  {298    "inputs": [{ "internalType": "bool", "name": "enable", "type": "bool" }],299    "name": "setCollectionNesting",300    "outputs": [],301    "stateMutability": "nonpayable",302    "type": "function"303  },304  {305    "inputs": [306      { "internalType": "bool", "name": "enable", "type": "bool" },307      {308        "internalType": "address[]",309        "name": "collections",310        "type": "address[]"311      }312    ],313    "name": "setCollectionNesting",314    "outputs": [],315    "stateMutability": "nonpayable",316    "type": "function"317  },318  {319    "inputs": [320      { "internalType": "string", "name": "key", "type": "string" },321      { "internalType": "bytes", "name": "value", "type": "bytes" }322    ],323    "name": "setCollectionProperty",324    "outputs": [],325    "stateMutability": "nonpayable",326    "type": "function"327  },328  {329    "inputs": [330      { "internalType": "address", "name": "sponsor", "type": "address" }331    ],332    "name": "setCollectionSponsor",333    "outputs": [],334    "stateMutability": "nonpayable",335    "type": "function"336  },337  {338    "inputs": [339      { "internalType": "uint256", "name": "sponsor", "type": "uint256" }340    ],341    "name": "setCollectionSponsorSubstrate",342    "outputs": [],343    "stateMutability": "nonpayable",344    "type": "function"345  },346  {347    "inputs": [348      { "internalType": "address", "name": "newOwner", "type": "address" }349    ],350    "name": "setOwner",351    "outputs": [],352    "stateMutability": "nonpayable",353    "type": "function"354  },355  {356    "inputs": [357      { "internalType": "uint256", "name": "newOwner", "type": "uint256" }358    ],359    "name": "setOwnerSubstrate",360    "outputs": [],361    "stateMutability": "nonpayable",362    "type": "function"363  },364  {365    "inputs": [366      { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }367    ],368    "name": "supportsInterface",369    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],370    "stateMutability": "view",371    "type": "function"372  },373  {374    "inputs": [],375    "name": "symbol",376    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],377    "stateMutability": "view",378    "type": "function"379  },380  {381    "inputs": [],382    "name": "totalSupply",383    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],384    "stateMutability": "view",385    "type": "function"386  },387  {388    "inputs": [389      { "internalType": "address", "name": "to", "type": "address" },390      { "internalType": "uint256", "name": "amount", "type": "uint256" }391    ],392    "name": "transfer",393    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],394    "stateMutability": "nonpayable",395    "type": "function"396  },397  {398    "inputs": [399      { "internalType": "address", "name": "from", "type": "address" },400      { "internalType": "address", "name": "to", "type": "address" },401      { "internalType": "uint256", "name": "amount", "type": "uint256" }402    ],403    "name": "transferFrom",404    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],405    "stateMutability": "nonpayable",406    "type": "function"407  },408  {409    "inputs": [],410    "name": "uniqueCollectionType",411    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],412    "stateMutability": "nonpayable",413    "type": "function"414  }415]
after · tests/src/eth/fungibleAbi.json
1[2  {3    "anonymous": false,4    "inputs": [5      {6        "indexed": true,7        "internalType": "address",8        "name": "owner",9        "type": "address"10      },11      {12        "indexed": true,13        "internalType": "address",14        "name": "spender",15        "type": "address"16      },17      {18        "indexed": false,19        "internalType": "uint256",20        "name": "value",21        "type": "uint256"22      }23    ],24    "name": "Approval",25    "type": "event"26  },27  {28    "anonymous": false,29    "inputs": [30      {31        "indexed": true,32        "internalType": "address",33        "name": "from",34        "type": "address"35      },36      {37        "indexed": true,38        "internalType": "address",39        "name": "to",40        "type": "address"41      },42      {43        "indexed": false,44        "internalType": "uint256",45        "name": "value",46        "type": "uint256"47      }48    ],49    "name": "Transfer",50    "type": "event"51  },52  {53    "inputs": [54      { "internalType": "address", "name": "newAdmin", "type": "address" }55    ],56    "name": "addCollectionAdmin",57    "outputs": [],58    "stateMutability": "nonpayable",59    "type": "function"60  },61  {62    "inputs": [63      { "internalType": "uint256", "name": "newAdmin", "type": "uint256" }64    ],65    "name": "addCollectionAdminSubstrate",66    "outputs": [],67    "stateMutability": "nonpayable",68    "type": "function"69  },70  {71    "inputs": [72      { "internalType": "address", "name": "user", "type": "address" }73    ],74    "name": "addToCollectionAllowList",75    "outputs": [],76    "stateMutability": "nonpayable",77    "type": "function"78  },79  {80    "inputs": [81      { "internalType": "uint256", "name": "user", "type": "uint256" }82    ],83    "name": "addToCollectionAllowListSubstrate",84    "outputs": [],85    "stateMutability": "nonpayable",86    "type": "function"87  },88  {89    "inputs": [90      { "internalType": "address", "name": "owner", "type": "address" },91      { "internalType": "address", "name": "spender", "type": "address" }92    ],93    "name": "allowance",94    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],95    "stateMutability": "view",96    "type": "function"97  },98  {99    "inputs": [100      { "internalType": "address", "name": "user", "type": "address" }101    ],102    "name": "allowed",103    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],104    "stateMutability": "view",105    "type": "function"106  },107  {108    "inputs": [109      { "internalType": "address", "name": "spender", "type": "address" },110      { "internalType": "uint256", "name": "amount", "type": "uint256" }111    ],112    "name": "approve",113    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],114    "stateMutability": "nonpayable",115    "type": "function"116  },117  {118    "inputs": [119      { "internalType": "address", "name": "owner", "type": "address" }120    ],121    "name": "balanceOf",122    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],123    "stateMutability": "view",124    "type": "function"125  },126  {127    "inputs": [128      { "internalType": "address", "name": "from", "type": "address" },129      { "internalType": "uint256", "name": "amount", "type": "uint256" }130    ],131    "name": "burnFrom",132    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],133    "stateMutability": "nonpayable",134    "type": "function"135  },136  {137    "inputs": [],138    "name": "collectionOwner",139    "outputs": [140      {141        "components": [142          { "internalType": "address", "name": "field_0", "type": "address" },143          { "internalType": "uint256", "name": "field_1", "type": "uint256" }144        ],145        "internalType": "struct Tuple6",146        "name": "",147        "type": "tuple"148      }149    ],150    "stateMutability": "view",151    "type": "function"152  },153  {154    "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],155    "name": "collectionProperty",156    "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],157    "stateMutability": "view",158    "type": "function"159  },160  {161    "inputs": [],162    "name": "confirmCollectionSponsorship",163    "outputs": [],164    "stateMutability": "nonpayable",165    "type": "function"166  },167  {168    "inputs": [],169    "name": "contractAddress",170    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],171    "stateMutability": "view",172    "type": "function"173  },174  {175    "inputs": [],176    "name": "decimals",177    "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }],178    "stateMutability": "view",179    "type": "function"180  },181  {182    "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],183    "name": "deleteCollectionProperty",184    "outputs": [],185    "stateMutability": "nonpayable",186    "type": "function"187  },188  {189    "inputs": [],190    "name": "getCollectionSponsor",191    "outputs": [192      {193        "components": [194          { "internalType": "address", "name": "field_0", "type": "address" },195          { "internalType": "uint256", "name": "field_1", "type": "uint256" }196        ],197        "internalType": "struct Tuple6",198        "name": "",199        "type": "tuple"200      }201    ],202    "stateMutability": "view",203    "type": "function"204  },205  {206    "inputs": [],207    "name": "hasCollectionPendingSponsor",208    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],209    "stateMutability": "view",210    "type": "function"211  },212  {213    "inputs": [214      { "internalType": "address", "name": "user", "type": "address" }215    ],216    "name": "isOwnerOrAdmin",217    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],218    "stateMutability": "view",219    "type": "function"220  },221  {222    "inputs": [223      { "internalType": "uint256", "name": "user", "type": "uint256" }224    ],225    "name": "isOwnerOrAdminSubstrate",226    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],227    "stateMutability": "view",228    "type": "function"229  },230  {231    "inputs": [232      { "internalType": "address", "name": "to", "type": "address" },233      { "internalType": "uint256", "name": "amount", "type": "uint256" }234    ],235    "name": "mint",236    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],237    "stateMutability": "nonpayable",238    "type": "function"239  },240  {241    "inputs": [242      {243        "components": [244          { "internalType": "address", "name": "field_0", "type": "address" },245          { "internalType": "uint256", "name": "field_1", "type": "uint256" }246        ],247        "internalType": "struct Tuple6[]",248        "name": "amounts",249        "type": "tuple[]"250      }251    ],252    "name": "mintBulk",253    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],254    "stateMutability": "nonpayable",255    "type": "function"256  },257  {258    "inputs": [],259    "name": "name",260    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],261    "stateMutability": "view",262    "type": "function"263  },264  {265    "inputs": [266      { "internalType": "address", "name": "admin", "type": "address" }267    ],268    "name": "removeCollectionAdmin",269    "outputs": [],270    "stateMutability": "nonpayable",271    "type": "function"272  },273  {274    "inputs": [275      { "internalType": "uint256", "name": "admin", "type": "uint256" }276    ],277    "name": "removeCollectionAdminSubstrate",278    "outputs": [],279    "stateMutability": "nonpayable",280    "type": "function"281  },282  {283    "inputs": [],284    "name": "removeCollectionSponsor",285    "outputs": [],286    "stateMutability": "nonpayable",287    "type": "function"288  },289  {290    "inputs": [291      { "internalType": "address", "name": "user", "type": "address" }292    ],293    "name": "removeFromCollectionAllowList",294    "outputs": [],295    "stateMutability": "nonpayable",296    "type": "function"297  },298  {299    "inputs": [300      { "internalType": "uint256", "name": "user", "type": "uint256" }301    ],302    "name": "removeFromCollectionAllowListSubstrate",303    "outputs": [],304    "stateMutability": "nonpayable",305    "type": "function"306  },307  {308    "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],309    "name": "setCollectionAccess",310    "outputs": [],311    "stateMutability": "nonpayable",312    "type": "function"313  },314  {315    "inputs": [316      { "internalType": "string", "name": "limit", "type": "string" },317      { "internalType": "uint32", "name": "value", "type": "uint32" }318    ],319    "name": "setCollectionLimit",320    "outputs": [],321    "stateMutability": "nonpayable",322    "type": "function"323  },324  {325    "inputs": [326      { "internalType": "string", "name": "limit", "type": "string" },327      { "internalType": "bool", "name": "value", "type": "bool" }328    ],329    "name": "setCollectionLimit",330    "outputs": [],331    "stateMutability": "nonpayable",332    "type": "function"333  },334  {335    "inputs": [{ "internalType": "bool", "name": "mode", "type": "bool" }],336    "name": "setCollectionMintMode",337    "outputs": [],338    "stateMutability": "nonpayable",339    "type": "function"340  },341  {342    "inputs": [{ "internalType": "bool", "name": "enable", "type": "bool" }],343    "name": "setCollectionNesting",344    "outputs": [],345    "stateMutability": "nonpayable",346    "type": "function"347  },348  {349    "inputs": [350      { "internalType": "bool", "name": "enable", "type": "bool" },351      {352        "internalType": "address[]",353        "name": "collections",354        "type": "address[]"355      }356    ],357    "name": "setCollectionNesting",358    "outputs": [],359    "stateMutability": "nonpayable",360    "type": "function"361  },362  {363    "inputs": [364      { "internalType": "string", "name": "key", "type": "string" },365      { "internalType": "bytes", "name": "value", "type": "bytes" }366    ],367    "name": "setCollectionProperty",368    "outputs": [],369    "stateMutability": "nonpayable",370    "type": "function"371  },372  {373    "inputs": [374      { "internalType": "address", "name": "sponsor", "type": "address" }375    ],376    "name": "setCollectionSponsor",377    "outputs": [],378    "stateMutability": "nonpayable",379    "type": "function"380  },381  {382    "inputs": [383      { "internalType": "uint256", "name": "sponsor", "type": "uint256" }384    ],385    "name": "setCollectionSponsorSubstrate",386    "outputs": [],387    "stateMutability": "nonpayable",388    "type": "function"389  },390  {391    "inputs": [392      { "internalType": "address", "name": "newOwner", "type": "address" }393    ],394    "name": "setOwner",395    "outputs": [],396    "stateMutability": "nonpayable",397    "type": "function"398  },399  {400    "inputs": [401      { "internalType": "uint256", "name": "newOwner", "type": "uint256" }402    ],403    "name": "setOwnerSubstrate",404    "outputs": [],405    "stateMutability": "nonpayable",406    "type": "function"407  },408  {409    "inputs": [410      { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }411    ],412    "name": "supportsInterface",413    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],414    "stateMutability": "view",415    "type": "function"416  },417  {418    "inputs": [],419    "name": "symbol",420    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],421    "stateMutability": "view",422    "type": "function"423  },424  {425    "inputs": [],426    "name": "totalSupply",427    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],428    "stateMutability": "view",429    "type": "function"430  },431  {432    "inputs": [433      { "internalType": "address", "name": "to", "type": "address" },434      { "internalType": "uint256", "name": "amount", "type": "uint256" }435    ],436    "name": "transfer",437    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],438    "stateMutability": "nonpayable",439    "type": "function"440  },441  {442    "inputs": [443      { "internalType": "address", "name": "from", "type": "address" },444      { "internalType": "address", "name": "to", "type": "address" },445      { "internalType": "uint256", "name": "amount", "type": "uint256" }446    ],447    "name": "transferFrom",448    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],449    "stateMutability": "nonpayable",450    "type": "function"451  },452  {453    "inputs": [],454    "name": "uniqueCollectionType",455    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],456    "stateMutability": "nonpayable",457    "type": "function"458  }459]
modifiedtests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth
--- a/tests/src/eth/nonFungibleAbi.json
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -109,6 +109,24 @@
   },
   {
     "inputs": [
+      { "internalType": "uint256", "name": "user", "type": "uint256" }
+    ],
+    "name": "addToCollectionAllowListSubstrate",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      { "internalType": "address", "name": "user", "type": "address" }
+    ],
+    "name": "allowed",
+    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
       { "internalType": "address", "name": "approved", "type": "address" },
       { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
     ],
@@ -146,6 +164,23 @@
     "type": "function"
   },
   {
+    "inputs": [],
+    "name": "collectionOwner",
+    "outputs": [
+      {
+        "components": [
+          { "internalType": "address", "name": "field_0", "type": "address" },
+          { "internalType": "uint256", "name": "field_1", "type": "uint256" }
+        ],
+        "internalType": "struct Tuple17",
+        "name": "",
+        "type": "tuple"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
     "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
     "name": "collectionProperty",
     "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],
@@ -376,6 +411,15 @@
   },
   {
     "inputs": [
+      { "internalType": "uint256", "name": "user", "type": "uint256" }
+    ],
+    "name": "removeFromCollectionAllowListSubstrate",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
       { "internalType": "address", "name": "from", "type": "address" },
       { "internalType": "address", "name": "to", "type": "address" },
       { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
modifiedtests/src/eth/reFungibleAbi.jsondiffbeforeafterboth
--- a/tests/src/eth/reFungibleAbi.json
+++ b/tests/src/eth/reFungibleAbi.json
@@ -109,6 +109,24 @@
   },
   {
     "inputs": [
+      { "internalType": "uint256", "name": "user", "type": "uint256" }
+    ],
+    "name": "addToCollectionAllowListSubstrate",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      { "internalType": "address", "name": "user", "type": "address" }
+    ],
+    "name": "allowed",
+    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
       { "internalType": "address", "name": "approved", "type": "address" },
       { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
     ],
@@ -146,6 +164,23 @@
     "type": "function"
   },
   {
+    "inputs": [],
+    "name": "collectionOwner",
+    "outputs": [
+      {
+        "components": [
+          { "internalType": "address", "name": "field_0", "type": "address" },
+          { "internalType": "uint256", "name": "field_1", "type": "uint256" }
+        ],
+        "internalType": "struct Tuple17",
+        "name": "",
+        "type": "tuple"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
     "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
     "name": "collectionProperty",
     "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],
@@ -376,6 +411,15 @@
   },
   {
     "inputs": [
+      { "internalType": "uint256", "name": "user", "type": "uint256" }
+    ],
+    "name": "removeFromCollectionAllowListSubstrate",
+    "outputs": [],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
       { "internalType": "address", "name": "from", "type": "address" },
       { "internalType": "address", "name": "to", "type": "address" },
       { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -1651,7 +1651,7 @@
   });
 }
 
-export async function isAllowlisted(api: ApiPromise, collectionId: number, address: string | CrossAccountId) {
+export async function isAllowlisted(api: ApiPromise, collectionId: number, address: string | CrossAccountId | IKeyringPair) {
   return (await api.rpc.unique.allowed(collectionId, normalizeAccountId(address))).toJSON();
 }