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
before · tests/src/eth/nonFungibleAbi.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      {157        "components": [158          { "internalType": "address", "name": "eth", "type": "address" },159          { "internalType": "uint256", "name": "sub", "type": "uint256" }160        ],161        "internalType": "struct EthCrossAccount",162        "name": "approved",163        "type": "tuple"164      },165      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }166    ],167    "name": "approveCross",168    "outputs": [],169    "stateMutability": "nonpayable",170    "type": "function"171  },172  {173    "inputs": [174      { "internalType": "address", "name": "owner", "type": "address" }175    ],176    "name": "balanceOf",177    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],178    "stateMutability": "view",179    "type": "function"180  },181  {182    "inputs": [183      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }184    ],185    "name": "burn",186    "outputs": [],187    "stateMutability": "nonpayable",188    "type": "function"189  },190  {191    "inputs": [192      { "internalType": "address", "name": "from", "type": "address" },193      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }194    ],195    "name": "burnFrom",196    "outputs": [],197    "stateMutability": "nonpayable",198    "type": "function"199  },200  {201    "inputs": [202      {203        "components": [204          { "internalType": "address", "name": "eth", "type": "address" },205          { "internalType": "uint256", "name": "sub", "type": "uint256" }206        ],207        "internalType": "struct EthCrossAccount",208        "name": "from",209        "type": "tuple"210      },211      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }212    ],213    "name": "burnFromCross",214    "outputs": [],215    "stateMutability": "nonpayable",216    "type": "function"217  },218  {219    "inputs": [220      { "internalType": "address", "name": "newOwner", "type": "address" }221    ],222    "name": "changeCollectionOwner",223    "outputs": [],224    "stateMutability": "nonpayable",225    "type": "function"226  },227  {228    "inputs": [],229    "name": "collectionAdmins",230    "outputs": [231      {232        "components": [233          { "internalType": "address", "name": "eth", "type": "address" },234          { "internalType": "uint256", "name": "sub", "type": "uint256" }235        ],236        "internalType": "struct EthCrossAccount[]",237        "name": "",238        "type": "tuple[]"239      }240    ],241    "stateMutability": "view",242    "type": "function"243  },244  {245    "inputs": [],246    "name": "collectionOwner",247    "outputs": [248      {249        "components": [250          { "internalType": "address", "name": "eth", "type": "address" },251          { "internalType": "uint256", "name": "sub", "type": "uint256" }252        ],253        "internalType": "struct EthCrossAccount",254        "name": "",255        "type": "tuple"256      }257    ],258    "stateMutability": "view",259    "type": "function"260  },261  {262    "inputs": [263      { "internalType": "string[]", "name": "keys", "type": "string[]" }264    ],265    "name": "collectionProperties",266    "outputs": [267      {268        "components": [269          { "internalType": "string", "name": "field_0", "type": "string" },270          { "internalType": "bytes", "name": "field_1", "type": "bytes" }271        ],272        "internalType": "struct Tuple21[]",273        "name": "",274        "type": "tuple[]"275      }276    ],277    "stateMutability": "view",278    "type": "function"279  },280  {281    "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],282    "name": "collectionProperty",283    "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],284    "stateMutability": "view",285    "type": "function"286  },287  {288    "inputs": [],289    "name": "collectionSponsor",290    "outputs": [291      {292        "components": [293          { "internalType": "address", "name": "field_0", "type": "address" },294          { "internalType": "uint256", "name": "field_1", "type": "uint256" }295        ],296        "internalType": "struct Tuple24",297        "name": "",298        "type": "tuple"299      }300    ],301    "stateMutability": "view",302    "type": "function"303  },304  {305    "inputs": [],306    "name": "confirmCollectionSponsorship",307    "outputs": [],308    "stateMutability": "nonpayable",309    "type": "function"310  },311  {312    "inputs": [],313    "name": "contractAddress",314    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],315    "stateMutability": "view",316    "type": "function"317  },318  {319    "inputs": [320      { "internalType": "string[]", "name": "keys", "type": "string[]" }321    ],322    "name": "deleteCollectionProperties",323    "outputs": [],324    "stateMutability": "nonpayable",325    "type": "function"326  },327  {328    "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],329    "name": "deleteCollectionProperty",330    "outputs": [],331    "stateMutability": "nonpayable",332    "type": "function"333  },334  {335    "inputs": [336      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },337      { "internalType": "string[]", "name": "keys", "type": "string[]" }338    ],339    "name": "deleteProperties",340    "outputs": [],341    "stateMutability": "nonpayable",342    "type": "function"343  },344  {345    "inputs": [],346    "name": "finishMinting",347    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],348    "stateMutability": "nonpayable",349    "type": "function"350  },351  {352    "inputs": [353      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }354    ],355    "name": "getApproved",356    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],357    "stateMutability": "view",358    "type": "function"359  },360  {361    "inputs": [],362    "name": "hasCollectionPendingSponsor",363    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],364    "stateMutability": "view",365    "type": "function"366  },367  {368    "inputs": [369      { "internalType": "address", "name": "owner", "type": "address" },370      { "internalType": "address", "name": "operator", "type": "address" }371    ],372    "name": "isApprovedForAll",373    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],374    "stateMutability": "view",375    "type": "function"376  },377  {378    "inputs": [379      { "internalType": "address", "name": "user", "type": "address" }380    ],381    "name": "isOwnerOrAdmin",382    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],383    "stateMutability": "view",384    "type": "function"385  },386  {387    "inputs": [388      {389        "components": [390          { "internalType": "address", "name": "eth", "type": "address" },391          { "internalType": "uint256", "name": "sub", "type": "uint256" }392        ],393        "internalType": "struct EthCrossAccount",394        "name": "user",395        "type": "tuple"396      }397    ],398    "name": "isOwnerOrAdminCross",399    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],400    "stateMutability": "view",401    "type": "function"402  },403  {404    "inputs": [{ "internalType": "address", "name": "to", "type": "address" }],405    "name": "mint",406    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],407    "stateMutability": "nonpayable",408    "type": "function"409  },410  {411    "inputs": [412      { "internalType": "address", "name": "to", "type": "address" },413      { "internalType": "string", "name": "tokenUri", "type": "string" }414    ],415    "name": "mintWithTokenURI",416    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],417    "stateMutability": "nonpayable",418    "type": "function"419  },420  {421    "inputs": [],422    "name": "mintingFinished",423    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],424    "stateMutability": "view",425    "type": "function"426  },427  {428    "inputs": [],429    "name": "name",430    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],431    "stateMutability": "view",432    "type": "function"433  },434  {435    "inputs": [],436    "name": "nextTokenId",437    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],438    "stateMutability": "view",439    "type": "function"440  },441  {442    "inputs": [443      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }444    ],445    "name": "ownerOf",446    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],447    "stateMutability": "view",448    "type": "function"449  },450  {451    "inputs": [452      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },453      { "internalType": "string", "name": "key", "type": "string" }454    ],455    "name": "property",456    "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],457    "stateMutability": "view",458    "type": "function"459  },460  {461    "inputs": [462      { "internalType": "address", "name": "admin", "type": "address" }463    ],464    "name": "removeCollectionAdmin",465    "outputs": [],466    "stateMutability": "nonpayable",467    "type": "function"468  },469  {470    "inputs": [471      {472        "components": [473          { "internalType": "address", "name": "eth", "type": "address" },474          { "internalType": "uint256", "name": "sub", "type": "uint256" }475        ],476        "internalType": "struct EthCrossAccount",477        "name": "admin",478        "type": "tuple"479      }480    ],481    "name": "removeCollectionAdminCross",482    "outputs": [],483    "stateMutability": "nonpayable",484    "type": "function"485  },486  {487    "inputs": [],488    "name": "removeCollectionSponsor",489    "outputs": [],490    "stateMutability": "nonpayable",491    "type": "function"492  },493  {494    "inputs": [495      { "internalType": "address", "name": "user", "type": "address" }496    ],497    "name": "removeFromCollectionAllowList",498    "outputs": [],499    "stateMutability": "nonpayable",500    "type": "function"501  },502  {503    "inputs": [504      {505        "components": [506          { "internalType": "address", "name": "eth", "type": "address" },507          { "internalType": "uint256", "name": "sub", "type": "uint256" }508        ],509        "internalType": "struct EthCrossAccount",510        "name": "user",511        "type": "tuple"512      }513    ],514    "name": "removeFromCollectionAllowListCross",515    "outputs": [],516    "stateMutability": "nonpayable",517    "type": "function"518  },519  {520    "inputs": [521      { "internalType": "address", "name": "from", "type": "address" },522      { "internalType": "address", "name": "to", "type": "address" },523      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }524    ],525    "name": "safeTransferFrom",526    "outputs": [],527    "stateMutability": "nonpayable",528    "type": "function"529  },530  {531    "inputs": [532      { "internalType": "address", "name": "from", "type": "address" },533      { "internalType": "address", "name": "to", "type": "address" },534      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },535      { "internalType": "bytes", "name": "data", "type": "bytes" }536    ],537    "name": "safeTransferFrom",538    "outputs": [],539    "stateMutability": "nonpayable",540    "type": "function"541  },542  {543    "inputs": [544      { "internalType": "address", "name": "operator", "type": "address" },545      { "internalType": "bool", "name": "approved", "type": "bool" }546    ],547    "name": "setApprovalForAll",548    "outputs": [],549    "stateMutability": "nonpayable",550    "type": "function"551  },552  {553    "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],554    "name": "setCollectionAccess",555    "outputs": [],556    "stateMutability": "nonpayable",557    "type": "function"558  },559  {560    "inputs": [561      { "internalType": "string", "name": "limit", "type": "string" },562      { "internalType": "uint32", "name": "value", "type": "uint32" }563    ],564    "name": "setCollectionLimit",565    "outputs": [],566    "stateMutability": "nonpayable",567    "type": "function"568  },569  {570    "inputs": [571      { "internalType": "string", "name": "limit", "type": "string" },572      { "internalType": "bool", "name": "value", "type": "bool" }573    ],574    "name": "setCollectionLimit",575    "outputs": [],576    "stateMutability": "nonpayable",577    "type": "function"578  },579  {580    "inputs": [{ "internalType": "bool", "name": "mode", "type": "bool" }],581    "name": "setCollectionMintMode",582    "outputs": [],583    "stateMutability": "nonpayable",584    "type": "function"585  },586  {587    "inputs": [{ "internalType": "bool", "name": "enable", "type": "bool" }],588    "name": "setCollectionNesting",589    "outputs": [],590    "stateMutability": "nonpayable",591    "type": "function"592  },593  {594    "inputs": [595      { "internalType": "bool", "name": "enable", "type": "bool" },596      {597        "internalType": "address[]",598        "name": "collections",599        "type": "address[]"600      }601    ],602    "name": "setCollectionNesting",603    "outputs": [],604    "stateMutability": "nonpayable",605    "type": "function"606  },607  {608    "inputs": [609      {610        "components": [611          { "internalType": "string", "name": "field_0", "type": "string" },612          { "internalType": "bytes", "name": "field_1", "type": "bytes" }613        ],614        "internalType": "struct Tuple21[]",615        "name": "properties",616        "type": "tuple[]"617      }618    ],619    "name": "setCollectionProperties",620    "outputs": [],621    "stateMutability": "nonpayable",622    "type": "function"623  },624  {625    "inputs": [626      { "internalType": "string", "name": "key", "type": "string" },627      { "internalType": "bytes", "name": "value", "type": "bytes" }628    ],629    "name": "setCollectionProperty",630    "outputs": [],631    "stateMutability": "nonpayable",632    "type": "function"633  },634  {635    "inputs": [636      { "internalType": "address", "name": "sponsor", "type": "address" }637    ],638    "name": "setCollectionSponsor",639    "outputs": [],640    "stateMutability": "nonpayable",641    "type": "function"642  },643  {644    "inputs": [645      {646        "components": [647          { "internalType": "address", "name": "eth", "type": "address" },648          { "internalType": "uint256", "name": "sub", "type": "uint256" }649        ],650        "internalType": "struct EthCrossAccount",651        "name": "sponsor",652        "type": "tuple"653      }654    ],655    "name": "setCollectionSponsorCross",656    "outputs": [],657    "stateMutability": "nonpayable",658    "type": "function"659  },660  {661    "inputs": [662      {663        "components": [664          { "internalType": "address", "name": "eth", "type": "address" },665          { "internalType": "uint256", "name": "sub", "type": "uint256" }666        ],667        "internalType": "struct EthCrossAccount",668        "name": "newOwner",669        "type": "tuple"670      }671    ],672    "name": "setOwnerCross",673    "outputs": [],674    "stateMutability": "nonpayable",675    "type": "function"676  },677  {678    "inputs": [679      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },680      {681        "components": [682          { "internalType": "string", "name": "field_0", "type": "string" },683          { "internalType": "bytes", "name": "field_1", "type": "bytes" }684        ],685        "internalType": "struct Tuple21[]",686        "name": "properties",687        "type": "tuple[]"688      }689    ],690    "name": "setProperties",691    "outputs": [],692    "stateMutability": "nonpayable",693    "type": "function"694  },695  {696    "inputs": [697      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },698      { "internalType": "string", "name": "key", "type": "string" },699      { "internalType": "bytes", "name": "value", "type": "bytes" }700    ],701    "name": "setProperty",702    "outputs": [],703    "stateMutability": "nonpayable",704    "type": "function"705  },706  {707    "inputs": [708      { "internalType": "string", "name": "key", "type": "string" },709      { "internalType": "bool", "name": "isMutable", "type": "bool" },710      { "internalType": "bool", "name": "collectionAdmin", "type": "bool" },711      { "internalType": "bool", "name": "tokenOwner", "type": "bool" }712    ],713    "name": "setTokenPropertyPermission",714    "outputs": [],715    "stateMutability": "nonpayable",716    "type": "function"717  },718  {719    "inputs": [720      { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }721    ],722    "name": "supportsInterface",723    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],724    "stateMutability": "view",725    "type": "function"726  },727  {728    "inputs": [],729    "name": "symbol",730    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],731    "stateMutability": "view",732    "type": "function"733  },734  {735    "inputs": [736      { "internalType": "uint256", "name": "index", "type": "uint256" }737    ],738    "name": "tokenByIndex",739    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],740    "stateMutability": "view",741    "type": "function"742  },743  {744    "inputs": [745      { "internalType": "address", "name": "owner", "type": "address" },746      { "internalType": "uint256", "name": "index", "type": "uint256" }747    ],748    "name": "tokenOfOwnerByIndex",749    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],750    "stateMutability": "view",751    "type": "function"752  },753  {754    "inputs": [755      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }756    ],757    "name": "tokenURI",758    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],759    "stateMutability": "view",760    "type": "function"761  },762  {763    "inputs": [],764    "name": "totalSupply",765    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],766    "stateMutability": "view",767    "type": "function"768  },769  {770    "inputs": [771      { "internalType": "address", "name": "to", "type": "address" },772      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }773    ],774    "name": "transfer",775    "outputs": [],776    "stateMutability": "nonpayable",777    "type": "function"778  },779  {780    "inputs": [781      { "internalType": "address", "name": "from", "type": "address" },782      { "internalType": "address", "name": "to", "type": "address" },783      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }784    ],785    "name": "transferFrom",786    "outputs": [],787    "stateMutability": "nonpayable",788    "type": "function"789  },790  {791    "inputs": [792      {793        "components": [794          { "internalType": "address", "name": "eth", "type": "address" },795          { "internalType": "uint256", "name": "sub", "type": "uint256" }796        ],797        "internalType": "struct EthCrossAccount",798        "name": "from",799        "type": "tuple"800      },801      {802        "components": [803          { "internalType": "address", "name": "eth", "type": "address" },804          { "internalType": "uint256", "name": "sub", "type": "uint256" }805        ],806        "internalType": "struct EthCrossAccount",807        "name": "to",808        "type": "tuple"809      },810      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }811    ],812    "name": "transferFromCross",813    "outputs": [],814    "stateMutability": "nonpayable",815    "type": "function"816  },817  {818    "inputs": [],819    "name": "uniqueCollectionType",820    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],821    "stateMutability": "view",822    "type": "function"823  }824]
after · tests/src/eth/nonFungibleAbi.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      {157        "components": [158          { "internalType": "address", "name": "eth", "type": "address" },159          { "internalType": "uint256", "name": "sub", "type": "uint256" }160        ],161        "internalType": "struct EthCrossAccount",162        "name": "approved",163        "type": "tuple"164      },165      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }166    ],167    "name": "approveCross",168    "outputs": [],169    "stateMutability": "nonpayable",170    "type": "function"171  },172  {173    "inputs": [174      { "internalType": "address", "name": "owner", "type": "address" }175    ],176    "name": "balanceOf",177    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],178    "stateMutability": "view",179    "type": "function"180  },181  {182    "inputs": [183      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }184    ],185    "name": "burn",186    "outputs": [],187    "stateMutability": "nonpayable",188    "type": "function"189  },190  {191    "inputs": [192      { "internalType": "address", "name": "from", "type": "address" },193      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }194    ],195    "name": "burnFrom",196    "outputs": [],197    "stateMutability": "nonpayable",198    "type": "function"199  },200  {201    "inputs": [202      {203        "components": [204          { "internalType": "address", "name": "eth", "type": "address" },205          { "internalType": "uint256", "name": "sub", "type": "uint256" }206        ],207        "internalType": "struct EthCrossAccount",208        "name": "from",209        "type": "tuple"210      },211      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }212    ],213    "name": "burnFromCross",214    "outputs": [],215    "stateMutability": "nonpayable",216    "type": "function"217  },218  {219    "inputs": [220      { "internalType": "address", "name": "newOwner", "type": "address" }221    ],222    "name": "changeCollectionOwner",223    "outputs": [],224    "stateMutability": "nonpayable",225    "type": "function"226  },227  {228    "inputs": [],229    "name": "collectionAdmins",230    "outputs": [231      {232        "components": [233          { "internalType": "address", "name": "eth", "type": "address" },234          { "internalType": "uint256", "name": "sub", "type": "uint256" }235        ],236        "internalType": "struct EthCrossAccount[]",237        "name": "",238        "type": "tuple[]"239      }240    ],241    "stateMutability": "view",242    "type": "function"243  },244  {245    "inputs": [],246    "name": "collectionOwner",247    "outputs": [248      {249        "components": [250          { "internalType": "address", "name": "eth", "type": "address" },251          { "internalType": "uint256", "name": "sub", "type": "uint256" }252        ],253        "internalType": "struct EthCrossAccount",254        "name": "",255        "type": "tuple"256      }257    ],258    "stateMutability": "view",259    "type": "function"260  },261  {262    "inputs": [263      { "internalType": "string[]", "name": "keys", "type": "string[]" }264    ],265    "name": "collectionProperties",266    "outputs": [267      {268        "components": [269          { "internalType": "string", "name": "field_0", "type": "string" },270          { "internalType": "bytes", "name": "field_1", "type": "bytes" }271        ],272        "internalType": "struct Tuple22[]",273        "name": "",274        "type": "tuple[]"275      }276    ],277    "stateMutability": "view",278    "type": "function"279  },280  {281    "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],282    "name": "collectionProperty",283    "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],284    "stateMutability": "view",285    "type": "function"286  },287  {288    "inputs": [],289    "name": "collectionSponsor",290    "outputs": [291      {292        "components": [293          { "internalType": "address", "name": "field_0", "type": "address" },294          { "internalType": "uint256", "name": "field_1", "type": "uint256" }295        ],296        "internalType": "struct Tuple25",297        "name": "",298        "type": "tuple"299      }300    ],301    "stateMutability": "view",302    "type": "function"303  },304  {305    "inputs": [],306    "name": "confirmCollectionSponsorship",307    "outputs": [],308    "stateMutability": "nonpayable",309    "type": "function"310  },311  {312    "inputs": [],313    "name": "contractAddress",314    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],315    "stateMutability": "view",316    "type": "function"317  },318  {319    "inputs": [320      { "internalType": "string[]", "name": "keys", "type": "string[]" }321    ],322    "name": "deleteCollectionProperties",323    "outputs": [],324    "stateMutability": "nonpayable",325    "type": "function"326  },327  {328    "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],329    "name": "deleteCollectionProperty",330    "outputs": [],331    "stateMutability": "nonpayable",332    "type": "function"333  },334  {335    "inputs": [336      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },337      { "internalType": "string[]", "name": "keys", "type": "string[]" }338    ],339    "name": "deleteProperties",340    "outputs": [],341    "stateMutability": "nonpayable",342    "type": "function"343  },344  {345    "inputs": [],346    "name": "finishMinting",347    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],348    "stateMutability": "nonpayable",349    "type": "function"350  },351  {352    "inputs": [353      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }354    ],355    "name": "getApproved",356    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],357    "stateMutability": "view",358    "type": "function"359  },360  {361    "inputs": [],362    "name": "hasCollectionPendingSponsor",363    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],364    "stateMutability": "view",365    "type": "function"366  },367  {368    "inputs": [369      { "internalType": "address", "name": "owner", "type": "address" },370      { "internalType": "address", "name": "operator", "type": "address" }371    ],372    "name": "isApprovedForAll",373    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],374    "stateMutability": "view",375    "type": "function"376  },377  {378    "inputs": [379      { "internalType": "address", "name": "user", "type": "address" }380    ],381    "name": "isOwnerOrAdmin",382    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],383    "stateMutability": "view",384    "type": "function"385  },386  {387    "inputs": [388      {389        "components": [390          { "internalType": "address", "name": "eth", "type": "address" },391          { "internalType": "uint256", "name": "sub", "type": "uint256" }392        ],393        "internalType": "struct EthCrossAccount",394        "name": "user",395        "type": "tuple"396      }397    ],398    "name": "isOwnerOrAdminCross",399    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],400    "stateMutability": "view",401    "type": "function"402  },403  {404    "inputs": [{ "internalType": "address", "name": "to", "type": "address" }],405    "name": "mint",406    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],407    "stateMutability": "nonpayable",408    "type": "function"409  },410  {411    "inputs": [412      { "internalType": "address", "name": "to", "type": "address" },413      { "internalType": "string", "name": "tokenUri", "type": "string" }414    ],415    "name": "mintWithTokenURI",416    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],417    "stateMutability": "nonpayable",418    "type": "function"419  },420  {421    "inputs": [],422    "name": "mintingFinished",423    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],424    "stateMutability": "view",425    "type": "function"426  },427  {428    "inputs": [],429    "name": "name",430    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],431    "stateMutability": "view",432    "type": "function"433  },434  {435    "inputs": [],436    "name": "nextTokenId",437    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],438    "stateMutability": "view",439    "type": "function"440  },441  {442    "inputs": [443      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }444    ],445    "name": "ownerOf",446    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],447    "stateMutability": "view",448    "type": "function"449  },450  {451    "inputs": [452      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },453      { "internalType": "string", "name": "key", "type": "string" }454    ],455    "name": "property",456    "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],457    "stateMutability": "view",458    "type": "function"459  },460  {461    "inputs": [462      { "internalType": "address", "name": "admin", "type": "address" }463    ],464    "name": "removeCollectionAdmin",465    "outputs": [],466    "stateMutability": "nonpayable",467    "type": "function"468  },469  {470    "inputs": [471      {472        "components": [473          { "internalType": "address", "name": "eth", "type": "address" },474          { "internalType": "uint256", "name": "sub", "type": "uint256" }475        ],476        "internalType": "struct EthCrossAccount",477        "name": "admin",478        "type": "tuple"479      }480    ],481    "name": "removeCollectionAdminCross",482    "outputs": [],483    "stateMutability": "nonpayable",484    "type": "function"485  },486  {487    "inputs": [],488    "name": "removeCollectionSponsor",489    "outputs": [],490    "stateMutability": "nonpayable",491    "type": "function"492  },493  {494    "inputs": [495      { "internalType": "address", "name": "user", "type": "address" }496    ],497    "name": "removeFromCollectionAllowList",498    "outputs": [],499    "stateMutability": "nonpayable",500    "type": "function"501  },502  {503    "inputs": [504      {505        "components": [506          { "internalType": "address", "name": "eth", "type": "address" },507          { "internalType": "uint256", "name": "sub", "type": "uint256" }508        ],509        "internalType": "struct EthCrossAccount",510        "name": "user",511        "type": "tuple"512      }513    ],514    "name": "removeFromCollectionAllowListCross",515    "outputs": [],516    "stateMutability": "nonpayable",517    "type": "function"518  },519  {520    "inputs": [521      { "internalType": "address", "name": "from", "type": "address" },522      { "internalType": "address", "name": "to", "type": "address" },523      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }524    ],525    "name": "safeTransferFrom",526    "outputs": [],527    "stateMutability": "nonpayable",528    "type": "function"529  },530  {531    "inputs": [532      { "internalType": "address", "name": "from", "type": "address" },533      { "internalType": "address", "name": "to", "type": "address" },534      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },535      { "internalType": "bytes", "name": "data", "type": "bytes" }536    ],537    "name": "safeTransferFrom",538    "outputs": [],539    "stateMutability": "nonpayable",540    "type": "function"541  },542  {543    "inputs": [544      { "internalType": "address", "name": "operator", "type": "address" },545      { "internalType": "bool", "name": "approved", "type": "bool" }546    ],547    "name": "setApprovalForAll",548    "outputs": [],549    "stateMutability": "nonpayable",550    "type": "function"551  },552  {553    "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],554    "name": "setCollectionAccess",555    "outputs": [],556    "stateMutability": "nonpayable",557    "type": "function"558  },559  {560    "inputs": [561      { "internalType": "string", "name": "limit", "type": "string" },562      { "internalType": "uint32", "name": "value", "type": "uint32" }563    ],564    "name": "setCollectionLimit",565    "outputs": [],566    "stateMutability": "nonpayable",567    "type": "function"568  },569  {570    "inputs": [571      { "internalType": "string", "name": "limit", "type": "string" },572      { "internalType": "bool", "name": "value", "type": "bool" }573    ],574    "name": "setCollectionLimit",575    "outputs": [],576    "stateMutability": "nonpayable",577    "type": "function"578  },579  {580    "inputs": [{ "internalType": "bool", "name": "mode", "type": "bool" }],581    "name": "setCollectionMintMode",582    "outputs": [],583    "stateMutability": "nonpayable",584    "type": "function"585  },586  {587    "inputs": [{ "internalType": "bool", "name": "enable", "type": "bool" }],588    "name": "setCollectionNesting",589    "outputs": [],590    "stateMutability": "nonpayable",591    "type": "function"592  },593  {594    "inputs": [595      { "internalType": "bool", "name": "enable", "type": "bool" },596      {597        "internalType": "address[]",598        "name": "collections",599        "type": "address[]"600      }601    ],602    "name": "setCollectionNesting",603    "outputs": [],604    "stateMutability": "nonpayable",605    "type": "function"606  },607  {608    "inputs": [609      {610        "components": [611          { "internalType": "string", "name": "field_0", "type": "string" },612          { "internalType": "bytes", "name": "field_1", "type": "bytes" }613        ],614        "internalType": "struct Tuple22[]",615        "name": "properties",616        "type": "tuple[]"617      }618    ],619    "name": "setCollectionProperties",620    "outputs": [],621    "stateMutability": "nonpayable",622    "type": "function"623  },624  {625    "inputs": [626      { "internalType": "string", "name": "key", "type": "string" },627      { "internalType": "bytes", "name": "value", "type": "bytes" }628    ],629    "name": "setCollectionProperty",630    "outputs": [],631    "stateMutability": "nonpayable",632    "type": "function"633  },634  {635    "inputs": [636      { "internalType": "address", "name": "sponsor", "type": "address" }637    ],638    "name": "setCollectionSponsor",639    "outputs": [],640    "stateMutability": "nonpayable",641    "type": "function"642  },643  {644    "inputs": [645      {646        "components": [647          { "internalType": "address", "name": "eth", "type": "address" },648          { "internalType": "uint256", "name": "sub", "type": "uint256" }649        ],650        "internalType": "struct EthCrossAccount",651        "name": "sponsor",652        "type": "tuple"653      }654    ],655    "name": "setCollectionSponsorCross",656    "outputs": [],657    "stateMutability": "nonpayable",658    "type": "function"659  },660  {661    "inputs": [662      {663        "components": [664          { "internalType": "address", "name": "eth", "type": "address" },665          { "internalType": "uint256", "name": "sub", "type": "uint256" }666        ],667        "internalType": "struct EthCrossAccount",668        "name": "newOwner",669        "type": "tuple"670      }671    ],672    "name": "setOwnerCross",673    "outputs": [],674    "stateMutability": "nonpayable",675    "type": "function"676  },677  {678    "inputs": [679      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },680      {681        "components": [682          { "internalType": "string", "name": "field_0", "type": "string" },683          { "internalType": "bytes", "name": "field_1", "type": "bytes" }684        ],685        "internalType": "struct Tuple22[]",686        "name": "properties",687        "type": "tuple[]"688      }689    ],690    "name": "setProperties",691    "outputs": [],692    "stateMutability": "nonpayable",693    "type": "function"694  },695  {696    "inputs": [697      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },698      { "internalType": "string", "name": "key", "type": "string" },699      { "internalType": "bytes", "name": "value", "type": "bytes" }700    ],701    "name": "setProperty",702    "outputs": [],703    "stateMutability": "nonpayable",704    "type": "function"705  },706  {707    "inputs": [708      { "internalType": "string", "name": "key", "type": "string" },709      { "internalType": "bool", "name": "isMutable", "type": "bool" },710      { "internalType": "bool", "name": "collectionAdmin", "type": "bool" },711      { "internalType": "bool", "name": "tokenOwner", "type": "bool" }712    ],713    "name": "setTokenPropertyPermission",714    "outputs": [],715    "stateMutability": "nonpayable",716    "type": "function"717  },718  {719    "inputs": [720      { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }721    ],722    "name": "supportsInterface",723    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],724    "stateMutability": "view",725    "type": "function"726  },727  {728    "inputs": [],729    "name": "symbol",730    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],731    "stateMutability": "view",732    "type": "function"733  },734  {735    "inputs": [736      { "internalType": "uint256", "name": "index", "type": "uint256" }737    ],738    "name": "tokenByIndex",739    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],740    "stateMutability": "view",741    "type": "function"742  },743  {744    "inputs": [745      { "internalType": "address", "name": "owner", "type": "address" },746      { "internalType": "uint256", "name": "index", "type": "uint256" }747    ],748    "name": "tokenOfOwnerByIndex",749    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],750    "stateMutability": "view",751    "type": "function"752  },753  {754    "inputs": [755      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }756    ],757    "name": "tokenURI",758    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],759    "stateMutability": "view",760    "type": "function"761  },762  {763    "inputs": [],764    "name": "totalSupply",765    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],766    "stateMutability": "view",767    "type": "function"768  },769  {770    "inputs": [771      { "internalType": "address", "name": "to", "type": "address" },772      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }773    ],774    "name": "transfer",775    "outputs": [],776    "stateMutability": "nonpayable",777    "type": "function"778  },779  {780    "inputs": [781      {782        "components": [783          { "internalType": "address", "name": "eth", "type": "address" },784          { "internalType": "uint256", "name": "sub", "type": "uint256" }785        ],786        "internalType": "struct EthCrossAccount",787        "name": "to",788        "type": "tuple"789      },790      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }791    ],792    "name": "transferCross",793    "outputs": [],794    "stateMutability": "nonpayable",795    "type": "function"796  },797  {798    "inputs": [799      { "internalType": "address", "name": "from", "type": "address" },800      { "internalType": "address", "name": "to", "type": "address" },801      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }802    ],803    "name": "transferFrom",804    "outputs": [],805    "stateMutability": "nonpayable",806    "type": "function"807  },808  {809    "inputs": [810      {811        "components": [812          { "internalType": "address", "name": "eth", "type": "address" },813          { "internalType": "uint256", "name": "sub", "type": "uint256" }814        ],815        "internalType": "struct EthCrossAccount",816        "name": "from",817        "type": "tuple"818      },819      {820        "components": [821          { "internalType": "address", "name": "eth", "type": "address" },822          { "internalType": "uint256", "name": "sub", "type": "uint256" }823        ],824        "internalType": "struct EthCrossAccount",825        "name": "to",826        "type": "tuple"827      },828      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }829    ],830    "name": "transferFromCross",831    "outputs": [],832    "stateMutability": "nonpayable",833    "type": "function"834  },835  {836    "inputs": [],837    "name": "uniqueCollectionType",838    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],839    "stateMutability": "view",840    "type": "function"841  }842]
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
--- a/tests/src/eth/reFungibleAbi.json
+++ b/tests/src/eth/reFungibleAbi.json
@@ -251,7 +251,7 @@
           { "internalType": "string", "name": "field_0", "type": "string" },
           { "internalType": "bytes", "name": "field_1", "type": "bytes" }
         ],
-        "internalType": "struct Tuple20[]",
+        "internalType": "struct Tuple21[]",
         "name": "",
         "type": "tuple[]"
       }
@@ -275,7 +275,7 @@
           { "internalType": "address", "name": "field_0", "type": "address" },
           { "internalType": "uint256", "name": "field_1", "type": "uint256" }
         ],
-        "internalType": "struct Tuple23",
+        "internalType": "struct Tuple24",
         "name": "",
         "type": "tuple"
       }
@@ -593,7 +593,7 @@
           { "internalType": "string", "name": "field_0", "type": "string" },
           { "internalType": "bytes", "name": "field_1", "type": "bytes" }
         ],
-        "internalType": "struct Tuple20[]",
+        "internalType": "struct Tuple21[]",
         "name": "properties",
         "type": "tuple[]"
       }
@@ -664,7 +664,7 @@
           { "internalType": "string", "name": "field_0", "type": "string" },
           { "internalType": "bytes", "name": "field_1", "type": "bytes" }
         ],
-        "internalType": "struct Tuple20[]",
+        "internalType": "struct Tuple21[]",
         "name": "properties",
         "type": "tuple[]"
       }
@@ -769,6 +769,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" }