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

difftreelog

feature: Added `transfer_cross` in eth functions.

PraetorP2022-11-14parent: #20c695f.patch.diff
in: master

22 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6121,7 +6121,7 @@
 
 [[package]]
 name = "pallet-fungible"
-version = "0.1.6"
+version = "0.1.7"
 dependencies = [
  "ethereum",
  "evm-coder",
@@ -6376,7 +6376,7 @@
 
 [[package]]
 name = "pallet-nonfungible"
-version = "0.1.8"
+version = "0.1.9"
 dependencies = [
  "ethereum",
  "evm-coder",
@@ -6498,7 +6498,7 @@
 
 [[package]]
 name = "pallet-refungible"
-version = "0.2.7"
+version = "0.2.8"
 dependencies = [
  "derivative",
  "ethereum",
modifiedpallets/fungible/CHANGELOG.mddiffbeforeafterboth
--- a/pallets/fungible/CHANGELOG.md
+++ b/pallets/fungible/CHANGELOG.md
@@ -2,22 +2,32 @@
 
 All notable changes to this project will be documented in this file.
 
+<!-- bureaucrate goes here -->
+
+## [0.1.7] - 2022-11-14
+
+### Changed
+
+- Added `transfer_cross` in eth functions.
+
 ## [0.1.6] - 2022-11-02
+
 ### Changed
- - Use named structure `EthCrossAccount` in eth functions.
 
+- Use named structure `EthCrossAccount` in eth functions.
+
 ## [0.1.5] - 2022-08-29
 
 ### Added
 
- - Implementation of `mint` and `mint_bulk` methods for ERC20 API.
+- Implementation of `mint` and `mint_bulk` methods for ERC20 API.
 
 ## [v0.1.4] - 2022-08-24
 
 ### Change
- - Add bound `AsRef<[u8; 32]>` to `T::CrossAccountId`.
 
-<!-- bureaucrate goes here -->
+- Add bound `AsRef<[u8; 32]>` to `T::CrossAccountId`.
+
 ## [v0.1.3] 2022-08-16
 
 ### Other changes
@@ -41,11 +51,11 @@
 
 ### Fixed
 
- - Issue with ItemCreated event containing total supply of tokens instead minted amount
+- Issue with ItemCreated event containing total supply of tokens instead minted amount
 
 ## [0.1.1] - 2022-07-14
 
 ### Added
 
- - Implementation of RPC method `token_owners` returning 10 owners in no particular order.
-    This was an internal request to improve the web interface and support fractionalization event.
+- Implementation of RPC method `token_owners` returning 10 owners in no particular order.
+  This was an internal request to improve the web interface and support fractionalization event.
modifiedpallets/fungible/Cargo.tomldiffbeforeafterboth
--- a/pallets/fungible/Cargo.toml
+++ b/pallets/fungible/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "pallet-fungible"
-version = "0.1.6"
+version = "0.1.7"
 license = "GPLv3"
 edition = "2021"
 
modifiedpallets/fungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -93,6 +93,7 @@
 		<Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;
 		Ok(true)
 	}
+
 	#[weight(<SelfWeightOf<T>>::transfer_from())]
 	fn transfer_from(
 		&mut self,
@@ -238,6 +239,24 @@
 		Ok(true)
 	}
 
+	#[weight(<SelfWeightOf<T>>::transfer())]
+	fn transfer_cross(
+		&mut self,
+		caller: caller,
+		to: EthCrossAccount,
+		amount: uint256,
+	) -> Result<bool> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let to = to.into_sub_cross_account::<T>()?;
+		let amount = amount.try_into().map_err(|_| "amount overflow")?;
+		let budget = self
+			.recorder
+			.weight_calls_budget(<StructureWeight<T>>::find_parent());
+
+		<Pallet<T>>::transfer(self, &caller, &to, amount, &budget).map_err(|_| "transfer error")?;
+		Ok(true)
+	}
+
 	#[weight(<SelfWeightOf<T>>::transfer_from())]
 	fn transfer_from_cross(
 		&mut self,
modifiedpallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth
--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -38,7 +38,7 @@
 	/// @param properties Vector of properties key/value pair.
 	/// @dev EVM selector for this function is: 0x50b26b2a,
 	///  or in textual repr: setCollectionProperties((string,bytes)[])
-	function setCollectionProperties(Tuple14[] memory properties) public {
+	function setCollectionProperties(Tuple15[] memory properties) public {
 		require(false, stub_error);
 		properties;
 		dummy = 0;
@@ -87,11 +87,11 @@
 	/// @return Vector of properties key/value pairs.
 	/// @dev EVM selector for this function is: 0x285fb8e6,
 	///  or in textual repr: collectionProperties(string[])
-	function collectionProperties(string[] memory keys) public view returns (Tuple14[] memory) {
+	function collectionProperties(string[] memory keys) public view returns (Tuple15[] memory) {
 		require(false, stub_error);
 		keys;
 		dummy;
-		return new Tuple14[](0);
+		return new Tuple15[](0);
 	}
 
 	/// Set the sponsor of the collection.
@@ -439,12 +439,12 @@
 }
 
 /// @dev anonymous struct
-struct Tuple14 {
+struct Tuple15 {
 	string field_0;
 	bytes field_1;
 }
 
-/// @dev the ERC-165 identifier for this interface is 0x032e5926
+/// @dev the ERC-165 identifier for this interface is 0x29f4dcd9
 contract ERC20UniqueExtensions is Dummy, ERC165 {
 	/// @dev EVM selector for this function is: 0x0ecd0ab0,
 	///  or in textual repr: approveCross((address,uint256),uint256)
@@ -497,6 +497,16 @@
 		return false;
 	}
 
+	/// @dev EVM selector for this function is: 0x2ada85ff,
+	///  or in textual repr: transferCross((address,uint256),uint256)
+	function transferCross(EthCrossAccount memory to, uint256 amount) public returns (bool) {
+		require(false, stub_error);
+		to;
+		amount;
+		dummy = 0;
+		return false;
+	}
+
 	/// @dev EVM selector for this function is: 0xd5cf430b,
 	///  or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
 	function transferFromCross(
modifiedpallets/nonfungible/CHANGELOG.mddiffbeforeafterboth
--- a/pallets/nonfungible/CHANGELOG.md
+++ b/pallets/nonfungible/CHANGELOG.md
@@ -4,6 +4,12 @@
 
 <!-- bureaucrate goes here -->
 
+## [0.1.9] - 2022-11-14
+
+### Changed
+
+- Added `transfer_cross` in eth functions.
+
 ## [v0.1.8] - 2022-11-11
 
 ### Changed
modifiedpallets/nonfungible/Cargo.tomldiffbeforeafterboth
--- a/pallets/nonfungible/Cargo.toml
+++ b/pallets/nonfungible/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "pallet-nonfungible"
-version = "0.1.8"
+version = "0.1.9"
 license = "GPLv3"
 edition = "2021"
 
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -738,7 +738,25 @@
 		<Pallet<T>>::transfer(self, &caller, &to, token, &budget).map_err(dispatch_to_evm::<T>)?;
 		Ok(())
 	}
+	
+	/// @notice Transfer ownership of an NFT
+	/// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+	///  is the zero address. Throws if `tokenId` is not a valid NFT.
+	/// @param to The new owner
+	/// @param tokenId The NFT to transfer
+	#[weight(<SelfWeightOf<T>>::transfer())]
+	fn transfer_cross(&mut self, caller: caller, to: EthCrossAccount, token_id: uint256) -> Result<void> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let to = to.into_sub_cross_account::<T>()?;
+		let token = token_id.try_into()?;
+		let budget = self
+			.recorder
+			.weight_calls_budget(<StructureWeight<T>>::find_parent());
 
+		<Pallet<T>>::transfer(self, &caller, &to, token, &budget).map_err(dispatch_to_evm::<T>)?;
+		Ok(())
+	}
+	
 	/// @notice Transfer ownership of an NFT from cross account address to cross account address
 	/// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
 	///  is the zero address. Throws if `tokenId` is not a valid NFT.
modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -67,7 +67,7 @@
 	/// @param properties settable properties
 	/// @dev EVM selector for this function is: 0x14ed3a6e,
 	///  or in textual repr: setProperties(uint256,(string,bytes)[])
-	function setProperties(uint256 tokenId, Tuple21[] memory properties) public {
+	function setProperties(uint256 tokenId, Tuple22[] memory properties) public {
 		require(false, stub_error);
 		tokenId;
 		properties;
@@ -137,7 +137,7 @@
 	/// @param properties Vector of properties key/value pair.
 	/// @dev EVM selector for this function is: 0x50b26b2a,
 	///  or in textual repr: setCollectionProperties((string,bytes)[])
-	function setCollectionProperties(Tuple21[] memory properties) public {
+	function setCollectionProperties(Tuple22[] memory properties) public {
 		require(false, stub_error);
 		properties;
 		dummy = 0;
@@ -186,11 +186,11 @@
 	/// @return Vector of properties key/value pairs.
 	/// @dev EVM selector for this function is: 0x285fb8e6,
 	///  or in textual repr: collectionProperties(string[])
-	function collectionProperties(string[] memory keys) public view returns (Tuple21[] memory) {
+	function collectionProperties(string[] memory keys) public view returns (Tuple22[] memory) {
 		require(false, stub_error);
 		keys;
 		dummy;
-		return new Tuple21[](0);
+		return new Tuple22[](0);
 	}
 
 	/// Set the sponsor of the collection.
@@ -251,10 +251,10 @@
 	/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
 	/// @dev EVM selector for this function is: 0x6ec0a9f1,
 	///  or in textual repr: collectionSponsor()
-	function collectionSponsor() public view returns (Tuple24 memory) {
+	function collectionSponsor() public view returns (Tuple25 memory) {
 		require(false, stub_error);
 		dummy;
-		return Tuple24(0x0000000000000000000000000000000000000000, 0);
+		return Tuple25(0x0000000000000000000000000000000000000000, 0);
 	}
 
 	/// Set limits for the collection.
@@ -538,13 +538,13 @@
 }
 
 /// @dev anonymous struct
-struct Tuple24 {
+struct Tuple25 {
 	address field_0;
 	uint256 field_1;
 }
 
 /// @dev anonymous struct
-struct Tuple21 {
+struct Tuple22 {
 	string field_0;
 	bytes field_1;
 }
@@ -693,7 +693,7 @@
 }
 
 /// @title Unique extensions for ERC721.
-/// @dev the ERC-165 identifier for this interface is 0x244543ee
+/// @dev the ERC-165 identifier for this interface is 0x0e9fc611
 contract ERC721UniqueExtensions is Dummy, ERC165 {
 	/// @notice A descriptive name for a collection of NFTs in this contract
 	/// @dev EVM selector for this function is: 0x06fdde03,
@@ -742,6 +742,20 @@
 		dummy = 0;
 	}
 
+	/// @notice Transfer ownership of an NFT
+	/// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+	///  is the zero address. Throws if `tokenId` is not a valid NFT.
+	/// @param to The new owner
+	/// @param tokenId The NFT to transfer
+	/// @dev EVM selector for this function is: 0x2ada85ff,
+	///  or in textual repr: transferCross((address,uint256),uint256)
+	function transferCross(EthCrossAccount memory to, uint256 tokenId) public {
+		require(false, stub_error);
+		to;
+		tokenId;
+		dummy = 0;
+	}
+
 	/// @notice Transfer ownership of an NFT from cross account address to cross account address
 	/// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
 	///  is the zero address. Throws if `tokenId` is not a valid NFT.
@@ -822,7 +836,7 @@
 	// /// @param tokens array of pairs of token ID and token URI for minted tokens
 	// /// @dev EVM selector for this function is: 0x36543006,
 	// ///  or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
-	// function mintBulkWithTokenURI(address to, Tuple10[] memory tokens) public returns (bool) {
+	// function mintBulkWithTokenURI(address to, Tuple11[] memory tokens) public returns (bool) {
 	// 	require(false, stub_error);
 	// 	to;
 	// 	tokens;
@@ -833,7 +847,7 @@
 }
 
 /// @dev anonymous struct
-struct Tuple10 {
+struct Tuple11 {
 	uint256 field_0;
 	string field_1;
 }
modifiedpallets/refungible/CHANGELOG.mddiffbeforeafterboth
--- a/pallets/refungible/CHANGELOG.md
+++ b/pallets/refungible/CHANGELOG.md
@@ -4,6 +4,12 @@
 
 <!-- bureaucrate goes here -->
 
+## [0.2.8] - 2022-11-14
+
+### Changed
+
+- Added `transfer_cross` in eth functions.
+
 ## [v0.2.7] - 2022-11-11
 
 ### Changed
modifiedpallets/refungible/Cargo.tomldiffbeforeafterboth
--- a/pallets/refungible/Cargo.toml
+++ b/pallets/refungible/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "pallet-refungible"
-version = "0.2.7"
+version = "0.2.8"
 license = "GPLv3"
 edition = "2021"
 
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -756,6 +756,29 @@
 	/// @param to The new owner
 	/// @param tokenId The RFT to transfer
 	#[weight(<SelfWeightOf<T>>::transfer_creating_removing())]
+	fn transfer_cross(&mut self, caller: caller, to: EthCrossAccount, token_id: uint256) -> Result<void> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let to = to.into_sub_cross_account::<T>()?;
+		let token = token_id.try_into()?;
+		let budget = self
+			.recorder
+			.weight_calls_budget(<StructureWeight<T>>::find_parent());
+
+		let balance = balance(self, token, &caller)?;
+		ensure_single_owner(self, token, balance)?;
+
+		<Pallet<T>>::transfer(self, &caller, &to, token, balance, &budget)
+			.map_err(dispatch_to_evm::<T>)?;
+		Ok(())
+	}
+
+	/// @notice Transfer ownership of an RFT
+	/// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+	///  is the zero address. Throws if `tokenId` is not a valid RFT.
+	///  Throws if RFT pieces have multiple owners.
+	/// @param to The new owner
+	/// @param tokenId The RFT to transfer
+	#[weight(<SelfWeightOf<T>>::transfer_creating_removing())]
 	fn transfer_from_cross(
 		&mut self,
 		caller: caller,
modifiedpallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth
--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -67,7 +67,7 @@
 	/// @param properties settable properties
 	/// @dev EVM selector for this function is: 0x14ed3a6e,
 	///  or in textual repr: setProperties(uint256,(string,bytes)[])
-	function setProperties(uint256 tokenId, Tuple20[] memory properties) public {
+	function setProperties(uint256 tokenId, Tuple21[] memory properties) public {
 		require(false, stub_error);
 		tokenId;
 		properties;
@@ -137,7 +137,7 @@
 	/// @param properties Vector of properties key/value pair.
 	/// @dev EVM selector for this function is: 0x50b26b2a,
 	///  or in textual repr: setCollectionProperties((string,bytes)[])
-	function setCollectionProperties(Tuple20[] memory properties) public {
+	function setCollectionProperties(Tuple21[] memory properties) public {
 		require(false, stub_error);
 		properties;
 		dummy = 0;
@@ -186,11 +186,11 @@
 	/// @return Vector of properties key/value pairs.
 	/// @dev EVM selector for this function is: 0x285fb8e6,
 	///  or in textual repr: collectionProperties(string[])
-	function collectionProperties(string[] memory keys) public view returns (Tuple20[] memory) {
+	function collectionProperties(string[] memory keys) public view returns (Tuple21[] memory) {
 		require(false, stub_error);
 		keys;
 		dummy;
-		return new Tuple20[](0);
+		return new Tuple21[](0);
 	}
 
 	/// Set the sponsor of the collection.
@@ -251,10 +251,10 @@
 	/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
 	/// @dev EVM selector for this function is: 0x6ec0a9f1,
 	///  or in textual repr: collectionSponsor()
-	function collectionSponsor() public view returns (Tuple23 memory) {
+	function collectionSponsor() public view returns (Tuple24 memory) {
 		require(false, stub_error);
 		dummy;
-		return Tuple23(0x0000000000000000000000000000000000000000, 0);
+		return Tuple24(0x0000000000000000000000000000000000000000, 0);
 	}
 
 	/// Set limits for the collection.
@@ -538,13 +538,13 @@
 }
 
 /// @dev anonymous struct
-struct Tuple23 {
+struct Tuple24 {
 	address field_0;
 	uint256 field_1;
 }
 
 /// @dev anonymous struct
-struct Tuple20 {
+struct Tuple21 {
 	string field_0;
 	bytes field_1;
 }
@@ -691,7 +691,7 @@
 }
 
 /// @title Unique extensions for ERC721.
-/// @dev the ERC-165 identifier for this interface is 0x81feb398
+/// @dev the ERC-165 identifier for this interface is 0xab243667
 contract ERC721UniqueExtensions is Dummy, ERC165 {
 	/// @notice A descriptive name for a collection of NFTs in this contract
 	/// @dev EVM selector for this function is: 0x06fdde03,
@@ -732,6 +732,21 @@
 	///  Throws if RFT pieces have multiple owners.
 	/// @param to The new owner
 	/// @param tokenId The RFT to transfer
+	/// @dev EVM selector for this function is: 0x2ada85ff,
+	///  or in textual repr: transferCross((address,uint256),uint256)
+	function transferCross(EthCrossAccount memory to, uint256 tokenId) public {
+		require(false, stub_error);
+		to;
+		tokenId;
+		dummy = 0;
+	}
+
+	/// @notice Transfer ownership of an RFT
+	/// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+	///  is the zero address. Throws if `tokenId` is not a valid RFT.
+	///  Throws if RFT pieces have multiple owners.
+	/// @param to The new owner
+	/// @param tokenId The RFT to transfer
 	/// @dev EVM selector for this function is: 0xd5cf430b,
 	///  or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
 	function transferFromCross(
@@ -809,7 +824,7 @@
 	// /// @param tokens array of pairs of token ID and token URI for minted tokens
 	// /// @dev EVM selector for this function is: 0x36543006,
 	// ///  or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
-	// function mintBulkWithTokenURI(address to, Tuple9[] memory tokens) public returns (bool) {
+	// function mintBulkWithTokenURI(address to, Tuple10[] memory tokens) public returns (bool) {
 	// 	require(false, stub_error);
 	// 	to;
 	// 	tokens;
@@ -831,7 +846,7 @@
 }
 
 /// @dev anonymous struct
-struct Tuple9 {
+struct Tuple10 {
 	uint256 field_0;
 	string field_1;
 }
modifiedtests/src/eth/api/UniqueFungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -28,7 +28,7 @@
 	/// @param properties Vector of properties key/value pair.
 	/// @dev EVM selector for this function is: 0x50b26b2a,
 	///  or in textual repr: setCollectionProperties((string,bytes)[])
-	function setCollectionProperties(Tuple14[] memory properties) external;
+	function setCollectionProperties(Tuple15[] memory properties) external;
 
 	/// Delete collection property.
 	///
@@ -60,7 +60,7 @@
 	/// @return Vector of properties key/value pairs.
 	/// @dev EVM selector for this function is: 0x285fb8e6,
 	///  or in textual repr: collectionProperties(string[])
-	function collectionProperties(string[] memory keys) external view returns (Tuple14[] memory);
+	function collectionProperties(string[] memory keys) external view returns (Tuple15[] memory);
 
 	/// Set the sponsor of the collection.
 	///
@@ -287,12 +287,12 @@
 }
 
 /// @dev anonymous struct
-struct Tuple14 {
+struct Tuple15 {
 	string field_0;
 	bytes field_1;
 }
 
-/// @dev the ERC-165 identifier for this interface is 0x032e5926
+/// @dev the ERC-165 identifier for this interface is 0x29f4dcd9
 interface ERC20UniqueExtensions is Dummy, ERC165 {
 	/// @dev EVM selector for this function is: 0x0ecd0ab0,
 	///  or in textual repr: approveCross((address,uint256),uint256)
@@ -322,6 +322,10 @@
 	///  or in textual repr: mintBulk((address,uint256)[])
 	function mintBulk(Tuple8[] memory amounts) external returns (bool);
 
+	/// @dev EVM selector for this function is: 0x2ada85ff,
+	///  or in textual repr: transferCross((address,uint256),uint256)
+	function transferCross(EthCrossAccount memory to, uint256 amount) external returns (bool);
+
 	/// @dev EVM selector for this function is: 0xd5cf430b,
 	///  or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
 	function transferFromCross(
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -49,7 +49,7 @@
 	/// @param properties settable properties
 	/// @dev EVM selector for this function is: 0x14ed3a6e,
 	///  or in textual repr: setProperties(uint256,(string,bytes)[])
-	function setProperties(uint256 tokenId, Tuple21[] memory properties) external;
+	function setProperties(uint256 tokenId, Tuple22[] memory properties) external;
 
 	// /// @notice Delete token property value.
 	// /// @dev Throws error if `msg.sender` has no permission to edit the property.
@@ -93,7 +93,7 @@
 	/// @param properties Vector of properties key/value pair.
 	/// @dev EVM selector for this function is: 0x50b26b2a,
 	///  or in textual repr: setCollectionProperties((string,bytes)[])
-	function setCollectionProperties(Tuple21[] memory properties) external;
+	function setCollectionProperties(Tuple22[] memory properties) external;
 
 	/// Delete collection property.
 	///
@@ -125,7 +125,7 @@
 	/// @return Vector of properties key/value pairs.
 	/// @dev EVM selector for this function is: 0x285fb8e6,
 	///  or in textual repr: collectionProperties(string[])
-	function collectionProperties(string[] memory keys) external view returns (Tuple21[] memory);
+	function collectionProperties(string[] memory keys) external view returns (Tuple22[] memory);
 
 	/// Set the sponsor of the collection.
 	///
@@ -167,7 +167,7 @@
 	/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
 	/// @dev EVM selector for this function is: 0x6ec0a9f1,
 	///  or in textual repr: collectionSponsor()
-	function collectionSponsor() external view returns (Tuple24 memory);
+	function collectionSponsor() external view returns (Tuple25 memory);
 
 	/// Set limits for the collection.
 	/// @dev Throws error if limit not found.
@@ -352,13 +352,13 @@
 }
 
 /// @dev anonymous struct
-struct Tuple24 {
+struct Tuple25 {
 	address field_0;
 	uint256 field_1;
 }
 
 /// @dev anonymous struct
-struct Tuple21 {
+struct Tuple22 {
 	string field_0;
 	bytes field_1;
 }
@@ -458,7 +458,7 @@
 }
 
 /// @title Unique extensions for ERC721.
-/// @dev the ERC-165 identifier for this interface is 0x244543ee
+/// @dev the ERC-165 identifier for this interface is 0x0e9fc611
 interface ERC721UniqueExtensions is Dummy, ERC165 {
 	/// @notice A descriptive name for a collection of NFTs in this contract
 	/// @dev EVM selector for this function is: 0x06fdde03,
@@ -489,6 +489,15 @@
 	///  or in textual repr: transfer(address,uint256)
 	function transfer(address to, uint256 tokenId) external;
 
+	/// @notice Transfer ownership of an NFT
+	/// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+	///  is the zero address. Throws if `tokenId` is not a valid NFT.
+	/// @param to The new owner
+	/// @param tokenId The NFT to transfer
+	/// @dev EVM selector for this function is: 0x2ada85ff,
+	///  or in textual repr: transferCross((address,uint256),uint256)
+	function transferCross(EthCrossAccount memory to, uint256 tokenId) external;
+
 	/// @notice Transfer ownership of an NFT from cross account address to cross account address
 	/// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
 	///  is the zero address. Throws if `tokenId` is not a valid NFT.
@@ -543,12 +552,12 @@
 	// /// @param tokens array of pairs of token ID and token URI for minted tokens
 	// /// @dev EVM selector for this function is: 0x36543006,
 	// ///  or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
-	// function mintBulkWithTokenURI(address to, Tuple10[] memory tokens) external returns (bool);
+	// function mintBulkWithTokenURI(address to, Tuple11[] memory tokens) external returns (bool);
 
 }
 
 /// @dev anonymous struct
-struct Tuple10 {
+struct Tuple11 {
 	uint256 field_0;
 	string field_1;
 }
modifiedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -49,7 +49,7 @@
 	/// @param properties settable properties
 	/// @dev EVM selector for this function is: 0x14ed3a6e,
 	///  or in textual repr: setProperties(uint256,(string,bytes)[])
-	function setProperties(uint256 tokenId, Tuple20[] memory properties) external;
+	function setProperties(uint256 tokenId, Tuple21[] memory properties) external;
 
 	// /// @notice Delete token property value.
 	// /// @dev Throws error if `msg.sender` has no permission to edit the property.
@@ -93,7 +93,7 @@
 	/// @param properties Vector of properties key/value pair.
 	/// @dev EVM selector for this function is: 0x50b26b2a,
 	///  or in textual repr: setCollectionProperties((string,bytes)[])
-	function setCollectionProperties(Tuple20[] memory properties) external;
+	function setCollectionProperties(Tuple21[] memory properties) external;
 
 	/// Delete collection property.
 	///
@@ -125,7 +125,7 @@
 	/// @return Vector of properties key/value pairs.
 	/// @dev EVM selector for this function is: 0x285fb8e6,
 	///  or in textual repr: collectionProperties(string[])
-	function collectionProperties(string[] memory keys) external view returns (Tuple20[] memory);
+	function collectionProperties(string[] memory keys) external view returns (Tuple21[] memory);
 
 	/// Set the sponsor of the collection.
 	///
@@ -167,7 +167,7 @@
 	/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
 	/// @dev EVM selector for this function is: 0x6ec0a9f1,
 	///  or in textual repr: collectionSponsor()
-	function collectionSponsor() external view returns (Tuple23 memory);
+	function collectionSponsor() external view returns (Tuple24 memory);
 
 	/// Set limits for the collection.
 	/// @dev Throws error if limit not found.
@@ -352,13 +352,13 @@
 }
 
 /// @dev anonymous struct
-struct Tuple23 {
+struct Tuple24 {
 	address field_0;
 	uint256 field_1;
 }
 
 /// @dev anonymous struct
-struct Tuple20 {
+struct Tuple21 {
 	string field_0;
 	bytes field_1;
 }
@@ -456,7 +456,7 @@
 }
 
 /// @title Unique extensions for ERC721.
-/// @dev the ERC-165 identifier for this interface is 0x81feb398
+/// @dev the ERC-165 identifier for this interface is 0xab243667
 interface ERC721UniqueExtensions is Dummy, ERC165 {
 	/// @notice A descriptive name for a collection of NFTs in this contract
 	/// @dev EVM selector for this function is: 0x06fdde03,
@@ -484,6 +484,16 @@
 	///  Throws if RFT pieces have multiple owners.
 	/// @param to The new owner
 	/// @param tokenId The RFT to transfer
+	/// @dev EVM selector for this function is: 0x2ada85ff,
+	///  or in textual repr: transferCross((address,uint256),uint256)
+	function transferCross(EthCrossAccount memory to, uint256 tokenId) external;
+
+	/// @notice Transfer ownership of an RFT
+	/// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
+	///  is the zero address. Throws if `tokenId` is not a valid RFT.
+	///  Throws if RFT pieces have multiple owners.
+	/// @param to The new owner
+	/// @param tokenId The RFT to transfer
 	/// @dev EVM selector for this function is: 0xd5cf430b,
 	///  or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
 	function transferFromCross(
@@ -535,7 +545,7 @@
 	// /// @param tokens array of pairs of token ID and token URI for minted tokens
 	// /// @dev EVM selector for this function is: 0x36543006,
 	// ///  or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
-	// function mintBulkWithTokenURI(address to, Tuple9[] memory tokens) external returns (bool);
+	// function mintBulkWithTokenURI(address to, Tuple10[] memory tokens) external returns (bool);
 
 	/// Returns EVM address for refungible token
 	///
@@ -546,7 +556,7 @@
 }
 
 /// @dev anonymous struct
-struct Tuple9 {
+struct Tuple10 {
 	uint256 field_0;
 	string field_1;
 }
modifiedtests/src/eth/fungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/fungible.test.ts
+++ b/tests/src/eth/fungible.test.ts
@@ -230,6 +230,37 @@
     }
   });
 
+  itEth('Can perform transferCross()', async ({helper}) => {
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const receiver = await helper.eth.createAccountWithBalance(donor);
+    const to = helper.ethCrossAccount.fromAddress(receiver);
+    const collection = await helper.ft.mintCollection(alice);
+    await collection.mint(alice, 200n, {Ethereum: owner});
+
+    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);
+
+    {
+      const result = await contract.methods.transferCross(to, 50).send({from: owner});
+      
+      const event = result.events.Transfer;
+      expect(event.address).to.be.equal(collectionAddress);
+      expect(event.returnValues.from).to.be.equal(owner);
+      expect(event.returnValues.to).to.be.equal(receiver);
+      expect(event.returnValues.value).to.be.equal('50');
+    }
+
+    {
+      const balance = await contract.methods.balanceOf(owner).call();
+      expect(+balance).to.equal(150);
+    }
+
+    {
+      const balance = await contract.methods.balanceOf(receiver).call();
+      expect(+balance).to.equal(50);
+    }
+  });
+  
   itEth('Can perform transfer()', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
     const receiver = await helper.eth.createAccountWithBalance(donor);
modifiedtests/src/eth/fungibleAbi.jsondiffbeforeafterboth
--- a/tests/src/eth/fungibleAbi.json
+++ b/tests/src/eth/fungibleAbi.json
@@ -239,7 +239,7 @@
           { "internalType": "string", "name": "field_0", "type": "string" },
           { "internalType": "bytes", "name": "field_1", "type": "bytes" }
         ],
-        "internalType": "struct Tuple14[]",
+        "internalType": "struct Tuple15[]",
         "name": "",
         "type": "tuple[]"
       }
@@ -496,7 +496,7 @@
           { "internalType": "string", "name": "field_0", "type": "string" },
           { "internalType": "bytes", "name": "field_1", "type": "bytes" }
         ],
-        "internalType": "struct Tuple14[]",
+        "internalType": "struct Tuple15[]",
         "name": "properties",
         "type": "tuple[]"
       }
@@ -594,6 +594,24 @@
   },
   {
     "inputs": [
+      {
+        "components": [
+          { "internalType": "address", "name": "eth", "type": "address" },
+          { "internalType": "uint256", "name": "sub", "type": "uint256" }
+        ],
+        "internalType": "struct EthCrossAccount",
+        "name": "to",
+        "type": "tuple"
+      },
+      { "internalType": "uint256", "name": "amount", "type": "uint256" }
+    ],
+    "name": "transferCross",
+    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "inputs": [
       { "internalType": "address", "name": "from", "type": "address" },
       { "internalType": "address", "name": "to", "type": "address" },
       { "internalType": "uint256", "name": "amount", "type": "uint256" }
modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/nonFungible.test.ts
+++ b/tests/src/eth/nonFungible.test.ts
@@ -402,6 +402,37 @@
       expect(+balance).to.equal(1);
     }
   });
+  
+  itEth('Can perform transferCross()', async ({helper}) => {
+    const collection = await helper.nft.mintCollection(minter, {});
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const receiver = helper.eth.createAccount();
+    const to = helper.ethCrossAccount.fromAddress(receiver);
+    const {tokenId} = await collection.mintToken(minter, {Ethereum: owner});
+
+    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
+    {
+      const result = await contract.methods.transferCross(to, tokenId).send({from: owner});
+
+      const event = result.events.Transfer;
+      expect(event.address).to.be.equal(collectionAddress);
+      expect(event.returnValues.from).to.be.equal(owner);
+      expect(event.returnValues.to).to.be.equal(receiver);
+      expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);
+    }
+
+    {
+      const balance = await contract.methods.balanceOf(owner).call();
+      expect(+balance).to.equal(0);
+    }
+
+    {
+      const balance = await contract.methods.balanceOf(receiver).call();
+      expect(+balance).to.equal(1);
+    }
+  });
 });
 
 describe('NFT: Fees', () => {
modifiedtests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth
--- a/tests/src/eth/nonFungibleAbi.json
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -269,7 +269,7 @@
           { "internalType": "string", "name": "field_0", "type": "string" },
           { "internalType": "bytes", "name": "field_1", "type": "bytes" }
         ],
-        "internalType": "struct Tuple21[]",
+        "internalType": "struct Tuple22[]",
         "name": "",
         "type": "tuple[]"
       }
@@ -293,7 +293,7 @@
           { "internalType": "address", "name": "field_0", "type": "address" },
           { "internalType": "uint256", "name": "field_1", "type": "uint256" }
         ],
-        "internalType": "struct Tuple24",
+        "internalType": "struct Tuple25",
         "name": "",
         "type": "tuple"
       }
@@ -611,7 +611,7 @@
           { "internalType": "string", "name": "field_0", "type": "string" },
           { "internalType": "bytes", "name": "field_1", "type": "bytes" }
         ],
-        "internalType": "struct Tuple21[]",
+        "internalType": "struct Tuple22[]",
         "name": "properties",
         "type": "tuple[]"
       }
@@ -682,7 +682,7 @@
           { "internalType": "string", "name": "field_0", "type": "string" },
           { "internalType": "bytes", "name": "field_1", "type": "bytes" }
         ],
-        "internalType": "struct Tuple21[]",
+        "internalType": "struct Tuple22[]",
         "name": "properties",
         "type": "tuple[]"
       }
@@ -778,6 +778,24 @@
   },
   {
     "inputs": [
+      {
+        "components": [
+          { "internalType": "address", "name": "eth", "type": "address" },
+          { "internalType": "uint256", "name": "sub", "type": "uint256" }
+        ],
+        "internalType": "struct EthCrossAccount",
+        "name": "to",
+        "type": "tuple"
+      },
+      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
+    ],
+    "name": "transferCross",
+    "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/reFungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/reFungible.test.ts
+++ b/tests/src/eth/reFungible.test.ts
@@ -359,6 +359,37 @@
       expect(+balance).to.equal(1);
     }
   });
+  
+  itEth('Can perform transferCross()', async ({helper}) => {
+    const caller = await helper.eth.createAccountWithBalance(donor);
+    const receiver = helper.eth.createAccount();
+    const to = helper.ethCrossAccount.fromAddress(receiver);
+    const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Transferry', '6', '6');
+    const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
+
+    const result = await contract.methods.mint(caller).send();
+    const tokenId = result.events.Transfer.returnValues.tokenId;
+
+    {
+      const result = await contract.methods.transferCross(to, tokenId).send({from: caller});
+
+      const event = result.events.Transfer;
+      expect(event.address).to.equal(collectionAddress);
+      expect(event.returnValues.from).to.equal(caller);
+      expect(event.returnValues.to).to.equal(receiver);
+      expect(event.returnValues.tokenId).to.equal(tokenId.toString());
+    }
+
+    {
+      const balance = await contract.methods.balanceOf(caller).call();
+      expect(+balance).to.equal(0);
+    }
+
+    {
+      const balance = await contract.methods.balanceOf(receiver).call();
+      expect(+balance).to.equal(1);
+    }
+  });
 
   itEth('transfer event on transfer from partial ownership to full ownership', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
modifiedtests/src/eth/reFungibleAbi.jsondiffbeforeafterboth
before · tests/src/eth/reFungibleAbi.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": "approved",15        "type": "address"16      },17      {18        "indexed": true,19        "internalType": "uint256",20        "name": "tokenId",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": "owner",34        "type": "address"35      },36      {37        "indexed": true,38        "internalType": "address",39        "name": "operator",40        "type": "address"41      },42      {43        "indexed": false,44        "internalType": "bool",45        "name": "approved",46        "type": "bool"47      }48    ],49    "name": "ApprovalForAll",50    "type": "event"51  },52  {53    "anonymous": false,54    "inputs": [],55    "name": "MintingFinished",56    "type": "event"57  },58  {59    "anonymous": false,60    "inputs": [61      {62        "indexed": true,63        "internalType": "address",64        "name": "from",65        "type": "address"66      },67      {68        "indexed": true,69        "internalType": "address",70        "name": "to",71        "type": "address"72      },73      {74        "indexed": true,75        "internalType": "uint256",76        "name": "tokenId",77        "type": "uint256"78      }79    ],80    "name": "Transfer",81    "type": "event"82  },83  {84    "inputs": [85      { "internalType": "address", "name": "newAdmin", "type": "address" }86    ],87    "name": "addCollectionAdmin",88    "outputs": [],89    "stateMutability": "nonpayable",90    "type": "function"91  },92  {93    "inputs": [94      {95        "components": [96          { "internalType": "address", "name": "eth", "type": "address" },97          { "internalType": "uint256", "name": "sub", "type": "uint256" }98        ],99        "internalType": "struct EthCrossAccount",100        "name": "newAdmin",101        "type": "tuple"102      }103    ],104    "name": "addCollectionAdminCross",105    "outputs": [],106    "stateMutability": "nonpayable",107    "type": "function"108  },109  {110    "inputs": [111      { "internalType": "address", "name": "user", "type": "address" }112    ],113    "name": "addToCollectionAllowList",114    "outputs": [],115    "stateMutability": "nonpayable",116    "type": "function"117  },118  {119    "inputs": [120      {121        "components": [122          { "internalType": "address", "name": "eth", "type": "address" },123          { "internalType": "uint256", "name": "sub", "type": "uint256" }124        ],125        "internalType": "struct EthCrossAccount",126        "name": "user",127        "type": "tuple"128      }129    ],130    "name": "addToCollectionAllowListCross",131    "outputs": [],132    "stateMutability": "nonpayable",133    "type": "function"134  },135  {136    "inputs": [137      { "internalType": "address", "name": "user", "type": "address" }138    ],139    "name": "allowed",140    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],141    "stateMutability": "view",142    "type": "function"143  },144  {145    "inputs": [146      { "internalType": "address", "name": "approved", "type": "address" },147      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }148    ],149    "name": "approve",150    "outputs": [],151    "stateMutability": "nonpayable",152    "type": "function"153  },154  {155    "inputs": [156      { "internalType": "address", "name": "owner", "type": "address" }157    ],158    "name": "balanceOf",159    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],160    "stateMutability": "view",161    "type": "function"162  },163  {164    "inputs": [165      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }166    ],167    "name": "burn",168    "outputs": [],169    "stateMutability": "nonpayable",170    "type": "function"171  },172  {173    "inputs": [174      { "internalType": "address", "name": "from", "type": "address" },175      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }176    ],177    "name": "burnFrom",178    "outputs": [],179    "stateMutability": "nonpayable",180    "type": "function"181  },182  {183    "inputs": [184      {185        "components": [186          { "internalType": "address", "name": "eth", "type": "address" },187          { "internalType": "uint256", "name": "sub", "type": "uint256" }188        ],189        "internalType": "struct EthCrossAccount",190        "name": "from",191        "type": "tuple"192      },193      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }194    ],195    "name": "burnFromCross",196    "outputs": [],197    "stateMutability": "nonpayable",198    "type": "function"199  },200  {201    "inputs": [202      { "internalType": "address", "name": "newOwner", "type": "address" }203    ],204    "name": "changeCollectionOwner",205    "outputs": [],206    "stateMutability": "nonpayable",207    "type": "function"208  },209  {210    "inputs": [],211    "name": "collectionAdmins",212    "outputs": [213      {214        "components": [215          { "internalType": "address", "name": "eth", "type": "address" },216          { "internalType": "uint256", "name": "sub", "type": "uint256" }217        ],218        "internalType": "struct EthCrossAccount[]",219        "name": "",220        "type": "tuple[]"221      }222    ],223    "stateMutability": "view",224    "type": "function"225  },226  {227    "inputs": [],228    "name": "collectionOwner",229    "outputs": [230      {231        "components": [232          { "internalType": "address", "name": "eth", "type": "address" },233          { "internalType": "uint256", "name": "sub", "type": "uint256" }234        ],235        "internalType": "struct EthCrossAccount",236        "name": "",237        "type": "tuple"238      }239    ],240    "stateMutability": "view",241    "type": "function"242  },243  {244    "inputs": [245      { "internalType": "string[]", "name": "keys", "type": "string[]" }246    ],247    "name": "collectionProperties",248    "outputs": [249      {250        "components": [251          { "internalType": "string", "name": "field_0", "type": "string" },252          { "internalType": "bytes", "name": "field_1", "type": "bytes" }253        ],254        "internalType": "struct Tuple20[]",255        "name": "",256        "type": "tuple[]"257      }258    ],259    "stateMutability": "view",260    "type": "function"261  },262  {263    "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],264    "name": "collectionProperty",265    "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],266    "stateMutability": "view",267    "type": "function"268  },269  {270    "inputs": [],271    "name": "collectionSponsor",272    "outputs": [273      {274        "components": [275          { "internalType": "address", "name": "field_0", "type": "address" },276          { "internalType": "uint256", "name": "field_1", "type": "uint256" }277        ],278        "internalType": "struct Tuple23",279        "name": "",280        "type": "tuple"281      }282    ],283    "stateMutability": "view",284    "type": "function"285  },286  {287    "inputs": [],288    "name": "confirmCollectionSponsorship",289    "outputs": [],290    "stateMutability": "nonpayable",291    "type": "function"292  },293  {294    "inputs": [],295    "name": "contractAddress",296    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],297    "stateMutability": "view",298    "type": "function"299  },300  {301    "inputs": [302      { "internalType": "string[]", "name": "keys", "type": "string[]" }303    ],304    "name": "deleteCollectionProperties",305    "outputs": [],306    "stateMutability": "nonpayable",307    "type": "function"308  },309  {310    "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],311    "name": "deleteCollectionProperty",312    "outputs": [],313    "stateMutability": "nonpayable",314    "type": "function"315  },316  {317    "inputs": [318      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },319      { "internalType": "string[]", "name": "keys", "type": "string[]" }320    ],321    "name": "deleteProperties",322    "outputs": [],323    "stateMutability": "nonpayable",324    "type": "function"325  },326  {327    "inputs": [],328    "name": "finishMinting",329    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],330    "stateMutability": "nonpayable",331    "type": "function"332  },333  {334    "inputs": [335      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }336    ],337    "name": "getApproved",338    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],339    "stateMutability": "view",340    "type": "function"341  },342  {343    "inputs": [],344    "name": "hasCollectionPendingSponsor",345    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],346    "stateMutability": "view",347    "type": "function"348  },349  {350    "inputs": [351      { "internalType": "address", "name": "owner", "type": "address" },352      { "internalType": "address", "name": "operator", "type": "address" }353    ],354    "name": "isApprovedForAll",355    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],356    "stateMutability": "view",357    "type": "function"358  },359  {360    "inputs": [361      { "internalType": "address", "name": "user", "type": "address" }362    ],363    "name": "isOwnerOrAdmin",364    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],365    "stateMutability": "view",366    "type": "function"367  },368  {369    "inputs": [370      {371        "components": [372          { "internalType": "address", "name": "eth", "type": "address" },373          { "internalType": "uint256", "name": "sub", "type": "uint256" }374        ],375        "internalType": "struct EthCrossAccount",376        "name": "user",377        "type": "tuple"378      }379    ],380    "name": "isOwnerOrAdminCross",381    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],382    "stateMutability": "view",383    "type": "function"384  },385  {386    "inputs": [{ "internalType": "address", "name": "to", "type": "address" }],387    "name": "mint",388    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],389    "stateMutability": "nonpayable",390    "type": "function"391  },392  {393    "inputs": [394      { "internalType": "address", "name": "to", "type": "address" },395      { "internalType": "string", "name": "tokenUri", "type": "string" }396    ],397    "name": "mintWithTokenURI",398    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],399    "stateMutability": "nonpayable",400    "type": "function"401  },402  {403    "inputs": [],404    "name": "mintingFinished",405    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],406    "stateMutability": "view",407    "type": "function"408  },409  {410    "inputs": [],411    "name": "name",412    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],413    "stateMutability": "view",414    "type": "function"415  },416  {417    "inputs": [],418    "name": "nextTokenId",419    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],420    "stateMutability": "view",421    "type": "function"422  },423  {424    "inputs": [425      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }426    ],427    "name": "ownerOf",428    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],429    "stateMutability": "view",430    "type": "function"431  },432  {433    "inputs": [434      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },435      { "internalType": "string", "name": "key", "type": "string" }436    ],437    "name": "property",438    "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],439    "stateMutability": "view",440    "type": "function"441  },442  {443    "inputs": [444      { "internalType": "address", "name": "admin", "type": "address" }445    ],446    "name": "removeCollectionAdmin",447    "outputs": [],448    "stateMutability": "nonpayable",449    "type": "function"450  },451  {452    "inputs": [453      {454        "components": [455          { "internalType": "address", "name": "eth", "type": "address" },456          { "internalType": "uint256", "name": "sub", "type": "uint256" }457        ],458        "internalType": "struct EthCrossAccount",459        "name": "admin",460        "type": "tuple"461      }462    ],463    "name": "removeCollectionAdminCross",464    "outputs": [],465    "stateMutability": "nonpayable",466    "type": "function"467  },468  {469    "inputs": [],470    "name": "removeCollectionSponsor",471    "outputs": [],472    "stateMutability": "nonpayable",473    "type": "function"474  },475  {476    "inputs": [477      { "internalType": "address", "name": "user", "type": "address" }478    ],479    "name": "removeFromCollectionAllowList",480    "outputs": [],481    "stateMutability": "nonpayable",482    "type": "function"483  },484  {485    "inputs": [486      {487        "components": [488          { "internalType": "address", "name": "eth", "type": "address" },489          { "internalType": "uint256", "name": "sub", "type": "uint256" }490        ],491        "internalType": "struct EthCrossAccount",492        "name": "user",493        "type": "tuple"494      }495    ],496    "name": "removeFromCollectionAllowListCross",497    "outputs": [],498    "stateMutability": "nonpayable",499    "type": "function"500  },501  {502    "inputs": [503      { "internalType": "address", "name": "from", "type": "address" },504      { "internalType": "address", "name": "to", "type": "address" },505      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }506    ],507    "name": "safeTransferFrom",508    "outputs": [],509    "stateMutability": "nonpayable",510    "type": "function"511  },512  {513    "inputs": [514      { "internalType": "address", "name": "from", "type": "address" },515      { "internalType": "address", "name": "to", "type": "address" },516      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },517      { "internalType": "bytes", "name": "data", "type": "bytes" }518    ],519    "name": "safeTransferFromWithData",520    "outputs": [],521    "stateMutability": "nonpayable",522    "type": "function"523  },524  {525    "inputs": [526      { "internalType": "address", "name": "operator", "type": "address" },527      { "internalType": "bool", "name": "approved", "type": "bool" }528    ],529    "name": "setApprovalForAll",530    "outputs": [],531    "stateMutability": "nonpayable",532    "type": "function"533  },534  {535    "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],536    "name": "setCollectionAccess",537    "outputs": [],538    "stateMutability": "nonpayable",539    "type": "function"540  },541  {542    "inputs": [543      { "internalType": "string", "name": "limit", "type": "string" },544      { "internalType": "uint32", "name": "value", "type": "uint32" }545    ],546    "name": "setCollectionLimit",547    "outputs": [],548    "stateMutability": "nonpayable",549    "type": "function"550  },551  {552    "inputs": [553      { "internalType": "string", "name": "limit", "type": "string" },554      { "internalType": "bool", "name": "value", "type": "bool" }555    ],556    "name": "setCollectionLimit",557    "outputs": [],558    "stateMutability": "nonpayable",559    "type": "function"560  },561  {562    "inputs": [{ "internalType": "bool", "name": "mode", "type": "bool" }],563    "name": "setCollectionMintMode",564    "outputs": [],565    "stateMutability": "nonpayable",566    "type": "function"567  },568  {569    "inputs": [{ "internalType": "bool", "name": "enable", "type": "bool" }],570    "name": "setCollectionNesting",571    "outputs": [],572    "stateMutability": "nonpayable",573    "type": "function"574  },575  {576    "inputs": [577      { "internalType": "bool", "name": "enable", "type": "bool" },578      {579        "internalType": "address[]",580        "name": "collections",581        "type": "address[]"582      }583    ],584    "name": "setCollectionNesting",585    "outputs": [],586    "stateMutability": "nonpayable",587    "type": "function"588  },589  {590    "inputs": [591      {592        "components": [593          { "internalType": "string", "name": "field_0", "type": "string" },594          { "internalType": "bytes", "name": "field_1", "type": "bytes" }595        ],596        "internalType": "struct Tuple20[]",597        "name": "properties",598        "type": "tuple[]"599      }600    ],601    "name": "setCollectionProperties",602    "outputs": [],603    "stateMutability": "nonpayable",604    "type": "function"605  },606  {607    "inputs": [608      { "internalType": "string", "name": "key", "type": "string" },609      { "internalType": "bytes", "name": "value", "type": "bytes" }610    ],611    "name": "setCollectionProperty",612    "outputs": [],613    "stateMutability": "nonpayable",614    "type": "function"615  },616  {617    "inputs": [618      { "internalType": "address", "name": "sponsor", "type": "address" }619    ],620    "name": "setCollectionSponsor",621    "outputs": [],622    "stateMutability": "nonpayable",623    "type": "function"624  },625  {626    "inputs": [627      {628        "components": [629          { "internalType": "address", "name": "eth", "type": "address" },630          { "internalType": "uint256", "name": "sub", "type": "uint256" }631        ],632        "internalType": "struct EthCrossAccount",633        "name": "sponsor",634        "type": "tuple"635      }636    ],637    "name": "setCollectionSponsorCross",638    "outputs": [],639    "stateMutability": "nonpayable",640    "type": "function"641  },642  {643    "inputs": [644      {645        "components": [646          { "internalType": "address", "name": "eth", "type": "address" },647          { "internalType": "uint256", "name": "sub", "type": "uint256" }648        ],649        "internalType": "struct EthCrossAccount",650        "name": "newOwner",651        "type": "tuple"652      }653    ],654    "name": "setOwnerCross",655    "outputs": [],656    "stateMutability": "nonpayable",657    "type": "function"658  },659  {660    "inputs": [661      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },662      {663        "components": [664          { "internalType": "string", "name": "field_0", "type": "string" },665          { "internalType": "bytes", "name": "field_1", "type": "bytes" }666        ],667        "internalType": "struct Tuple20[]",668        "name": "properties",669        "type": "tuple[]"670      }671    ],672    "name": "setProperties",673    "outputs": [],674    "stateMutability": "nonpayable",675    "type": "function"676  },677  {678    "inputs": [679      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },680      { "internalType": "string", "name": "key", "type": "string" },681      { "internalType": "bytes", "name": "value", "type": "bytes" }682    ],683    "name": "setProperty",684    "outputs": [],685    "stateMutability": "nonpayable",686    "type": "function"687  },688  {689    "inputs": [690      { "internalType": "string", "name": "key", "type": "string" },691      { "internalType": "bool", "name": "isMutable", "type": "bool" },692      { "internalType": "bool", "name": "collectionAdmin", "type": "bool" },693      { "internalType": "bool", "name": "tokenOwner", "type": "bool" }694    ],695    "name": "setTokenPropertyPermission",696    "outputs": [],697    "stateMutability": "nonpayable",698    "type": "function"699  },700  {701    "inputs": [702      { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }703    ],704    "name": "supportsInterface",705    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],706    "stateMutability": "view",707    "type": "function"708  },709  {710    "inputs": [],711    "name": "symbol",712    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],713    "stateMutability": "view",714    "type": "function"715  },716  {717    "inputs": [718      { "internalType": "uint256", "name": "index", "type": "uint256" }719    ],720    "name": "tokenByIndex",721    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],722    "stateMutability": "view",723    "type": "function"724  },725  {726    "inputs": [727      { "internalType": "uint256", "name": "token", "type": "uint256" }728    ],729    "name": "tokenContractAddress",730    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],731    "stateMutability": "view",732    "type": "function"733  },734  {735    "inputs": [736      { "internalType": "address", "name": "owner", "type": "address" },737      { "internalType": "uint256", "name": "index", "type": "uint256" }738    ],739    "name": "tokenOfOwnerByIndex",740    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],741    "stateMutability": "view",742    "type": "function"743  },744  {745    "inputs": [746      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }747    ],748    "name": "tokenURI",749    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],750    "stateMutability": "view",751    "type": "function"752  },753  {754    "inputs": [],755    "name": "totalSupply",756    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],757    "stateMutability": "view",758    "type": "function"759  },760  {761    "inputs": [762      { "internalType": "address", "name": "to", "type": "address" },763      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }764    ],765    "name": "transfer",766    "outputs": [],767    "stateMutability": "nonpayable",768    "type": "function"769  },770  {771    "inputs": [772      { "internalType": "address", "name": "from", "type": "address" },773      { "internalType": "address", "name": "to", "type": "address" },774      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }775    ],776    "name": "transferFrom",777    "outputs": [],778    "stateMutability": "nonpayable",779    "type": "function"780  },781  {782    "inputs": [783      {784        "components": [785          { "internalType": "address", "name": "eth", "type": "address" },786          { "internalType": "uint256", "name": "sub", "type": "uint256" }787        ],788        "internalType": "struct EthCrossAccount",789        "name": "from",790        "type": "tuple"791      },792      {793        "components": [794          { "internalType": "address", "name": "eth", "type": "address" },795          { "internalType": "uint256", "name": "sub", "type": "uint256" }796        ],797        "internalType": "struct EthCrossAccount",798        "name": "to",799        "type": "tuple"800      },801      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }802    ],803    "name": "transferFromCross",804    "outputs": [],805    "stateMutability": "nonpayable",806    "type": "function"807  },808  {809    "inputs": [],810    "name": "uniqueCollectionType",811    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],812    "stateMutability": "view",813    "type": "function"814  }815]