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

difftreelog

misk: Move TokenChanged event into ERC721 contracts

Trubnikov Sergey2023-02-02parent: #3563d09.patch.diff
in: master

16 files changed

modifiedpallets/common/src/erc.rsdiffbeforeafterboth
--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -26,7 +26,6 @@
 };
 use pallet_evm_coder_substrate::dispatch_to_evm;
 use sp_std::{vec, vec::Vec};
-use sp_core::U256;
 use up_data_structs::{
 	CollectionMode, CollectionPermissions, OwnerRestrictedSet, Property, SponsoringRateLimit,
 	SponsorshipState,
@@ -62,18 +61,9 @@
 	},
 	/// The collection has been changed.
 	CollectionChanged {
-		/// Collection ID.
-		#[indexed]
-		collection_id: Address,
-	},
-
-	/// The token has been changed.
-	TokenChanged {
 		/// Collection ID.
 		#[indexed]
 		collection_id: Address,
-		/// Token ID.
-		token_id: U256,
 	},
 }
 
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -1250,6 +1250,7 @@
 		mut stored_properties: Properties,
 		is_token_owner: impl Fn() -> Result<bool, DispatchError>,
 		set_token_properties: impl FnOnce(Properties),
+		log: evm_coder::ethereum::Log,
 	) -> DispatchResult {
 		let is_collection_admin = collection.is_owner_or_admin(sender);
 		let permissions = Self::property_permissions(collection.id);
@@ -1304,13 +1305,7 @@
 				}
 			}
 
-			<PalletEvm<T>>::deposit_log(
-				CollectionHelpersEvents::TokenChanged {
-					collection_id: eth::collection_id_to_address(collection.id),
-					token_id: token_id.into(),
-				}
-				.to_log(T::ContractAddress::get()),
-			);
+			<PalletEvm<T>>::deposit_log(log.clone());
 		}
 
 		set_token_properties(stored_properties);
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -50,13 +50,26 @@
 	TokenProperties, SelfWeightOf, weights::WeightInfo,
 };
 
+/// Nft events.
+#[derive(ToLog)]
+pub enum ERC721TokenEvent {
+	/// The token has been changed.
+	TokenChanged {
+		/// Collection ID.
+		#[indexed]
+		collection_id: Address,
+		/// Token ID.
+		token_id: U256,
+	},
+}
+
 frontier_contract! {
 	macro_rules! NonfungibleHandle_result {...}
 	impl<T: Config> Contract for NonfungibleHandle<T> {...}
 }
 
 /// @title A contract that allows to set and delete token properties and change token property permissions.
-#[solidity_interface(name = TokenProperties, enum(derive(PreDispatch)), enum_attr(weight))]
+#[solidity_interface(name = TokenProperties, events(ERC721TokenEvent), enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> NonfungibleHandle<T> {
 	/// @notice Set permissions for token property.
 	/// @dev Throws error if `msg.sender` is not admin or owner of the collection.
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -112,7 +112,7 @@
 };
 use pallet_structure::{Pallet as PalletStructure, Error as StructureError};
 use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
-use sp_core::H160;
+use sp_core::{Get, H160};
 use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};
 use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
 use core::ops::Deref;
@@ -622,6 +622,11 @@
 			stored_properties,
 			is_token_owner,
 			|properties| <TokenProperties<T>>::set((collection.id, token_id), properties),
+			erc::ERC721TokenEvent::TokenChanged {
+				collection_id: collection_id_to_address(collection.id),
+				token_id: token_id.into(),
+			}
+			.to_log(T::ContractAddress::get()),
 		)
 	}
 
modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -17,9 +17,14 @@
 	}
 }
 
+/// @dev inlined interface
+contract ERC721TokenEvent {
+	event TokenChanged(address indexed collectionId, uint256 tokenId);
+}
+
 /// @title A contract that allows to set and delete token properties and change token property permissions.
 /// @dev the ERC-165 identifier for this interface is 0xde0695c2
-contract TokenProperties is Dummy, ERC165 {
+contract TokenProperties is Dummy, ERC165, ERC721TokenEvent {
 	// /// @notice Set permissions for token property.
 	// /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
 	// /// @param key Property key.
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -59,8 +59,21 @@
 
 pub const ADDRESS_FOR_PARTIALLY_OWNED_TOKENS: H160 = H160::repeat_byte(0xff);
 
+/// Rft events.
+#[derive(ToLog)]
+pub enum ERC721TokenEvent {
+	/// The token has been changed.
+	TokenChanged {
+		/// Collection ID.
+		#[indexed]
+		collection_id: Address,
+		/// Token ID.
+		token_id: U256,
+	},
+}
+
 /// @title A contract that allows to set and delete token properties and change token property permissions.
-#[solidity_interface(name = TokenProperties, enum(derive(PreDispatch)), enum_attr(weight))]
+#[solidity_interface(name = TokenProperties, events(ERC721TokenEvent), enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> RefungibleHandle<T> {
 	/// @notice Set permissions for token property.
 	/// @dev Throws error if `msg.sender` is not admin or owner of the collection.
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -100,7 +100,7 @@
 	Event as CommonEvent, Pallet as PalletCommon,
 };
 use pallet_structure::Pallet as PalletStructure;
-use sp_core::H160;
+use sp_core::{Get, H160};
 use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};
 use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
 use up_data_structs::{
@@ -571,6 +571,11 @@
 			stored_properties,
 			is_token_owner,
 			|properties| <TokenProperties<T>>::set((collection.id, token_id), properties),
+			erc::ERC721TokenEvent::TokenChanged {
+				collection_id: collection_id_to_address(collection.id),
+				token_id: token_id.into(),
+			}
+			.to_log(T::ContractAddress::get()),
 		)
 	}
 
modifiedpallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth
--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -17,9 +17,14 @@
 	}
 }
 
+/// @dev inlined interface
+contract ERC721TokenEvent {
+	event TokenChanged(address indexed collectionId, uint256 tokenId);
+}
+
 /// @title A contract that allows to set and delete token properties and change token property permissions.
 /// @dev the ERC-165 identifier for this interface is 0xde0695c2
-contract TokenProperties is Dummy, ERC165 {
+contract TokenProperties is Dummy, ERC165, ERC721TokenEvent {
 	// /// @notice Set permissions for token property.
 	// /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
 	// /// @param key Property key.
modifiedpallets/unique/src/eth/stubs/CollectionHelpers.soldiffbeforeafterboth
--- a/pallets/unique/src/eth/stubs/CollectionHelpers.sol
+++ b/pallets/unique/src/eth/stubs/CollectionHelpers.sol
@@ -22,7 +22,6 @@
 	event CollectionCreated(address indexed owner, address indexed collectionId);
 	event CollectionDestroyed(address indexed collectionId);
 	event CollectionChanged(address indexed collectionId);
-	event TokenChanged(address indexed collectionId, uint256 tokenId);
 }
 
 /// @title Contract, which allows users to operate with collections
modifiedtests/src/eth/abi/collectionHelpers.jsondiffbeforeafterboth
--- a/tests/src/eth/abi/collectionHelpers.json
+++ b/tests/src/eth/abi/collectionHelpers.json
@@ -45,25 +45,6 @@
     "type": "event"
   },
   {
-    "anonymous": false,
-    "inputs": [
-      {
-        "indexed": true,
-        "internalType": "address",
-        "name": "collectionId",
-        "type": "address"
-      },
-      {
-        "indexed": false,
-        "internalType": "uint256",
-        "name": "tokenId",
-        "type": "uint256"
-      }
-    ],
-    "name": "TokenChanged",
-    "type": "event"
-  },
-  {
     "inputs": [
       { "internalType": "uint32", "name": "collectionId", "type": "uint32" }
     ],
modifiedtests/src/eth/abi/nonFungible.jsondiffbeforeafterboth
before · tests/src/eth/abi/nonFungible.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      {56        "indexed": true,57        "internalType": "address",58        "name": "from",59        "type": "address"60      },61      {62        "indexed": true,63        "internalType": "address",64        "name": "to",65        "type": "address"66      },67      {68        "indexed": true,69        "internalType": "uint256",70        "name": "tokenId",71        "type": "uint256"72      }73    ],74    "name": "Transfer",75    "type": "event"76  },77  {78    "inputs": [79      {80        "components": [81          { "internalType": "address", "name": "eth", "type": "address" },82          { "internalType": "uint256", "name": "sub", "type": "uint256" }83        ],84        "internalType": "struct CrossAddress",85        "name": "newAdmin",86        "type": "tuple"87      }88    ],89    "name": "addCollectionAdminCross",90    "outputs": [],91    "stateMutability": "nonpayable",92    "type": "function"93  },94  {95    "inputs": [96      {97        "components": [98          { "internalType": "address", "name": "eth", "type": "address" },99          { "internalType": "uint256", "name": "sub", "type": "uint256" }100        ],101        "internalType": "struct CrossAddress",102        "name": "user",103        "type": "tuple"104      }105    ],106    "name": "addToCollectionAllowListCross",107    "outputs": [],108    "stateMutability": "nonpayable",109    "type": "function"110  },111  {112    "inputs": [113      {114        "components": [115          { "internalType": "address", "name": "eth", "type": "address" },116          { "internalType": "uint256", "name": "sub", "type": "uint256" }117        ],118        "internalType": "struct CrossAddress",119        "name": "user",120        "type": "tuple"121      }122    ],123    "name": "allowlistedCross",124    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],125    "stateMutability": "view",126    "type": "function"127  },128  {129    "inputs": [130      { "internalType": "address", "name": "approved", "type": "address" },131      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }132    ],133    "name": "approve",134    "outputs": [],135    "stateMutability": "nonpayable",136    "type": "function"137  },138  {139    "inputs": [140      {141        "components": [142          { "internalType": "address", "name": "eth", "type": "address" },143          { "internalType": "uint256", "name": "sub", "type": "uint256" }144        ],145        "internalType": "struct CrossAddress",146        "name": "approved",147        "type": "tuple"148      },149      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }150    ],151    "name": "approveCross",152    "outputs": [],153    "stateMutability": "nonpayable",154    "type": "function"155  },156  {157    "inputs": [158      { "internalType": "address", "name": "owner", "type": "address" }159    ],160    "name": "balanceOf",161    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],162    "stateMutability": "view",163    "type": "function"164  },165  {166    "inputs": [167      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }168    ],169    "name": "burn",170    "outputs": [],171    "stateMutability": "nonpayable",172    "type": "function"173  },174  {175    "inputs": [176      {177        "components": [178          { "internalType": "address", "name": "eth", "type": "address" },179          { "internalType": "uint256", "name": "sub", "type": "uint256" }180        ],181        "internalType": "struct CrossAddress",182        "name": "from",183        "type": "tuple"184      },185      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }186    ],187    "name": "burnFromCross",188    "outputs": [],189    "stateMutability": "nonpayable",190    "type": "function"191  },192  {193    "inputs": [194      {195        "components": [196          { "internalType": "address", "name": "eth", "type": "address" },197          { "internalType": "uint256", "name": "sub", "type": "uint256" }198        ],199        "internalType": "struct CrossAddress",200        "name": "newOwner",201        "type": "tuple"202      }203    ],204    "name": "changeCollectionOwnerCross",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 CrossAddress[]",219        "name": "",220        "type": "tuple[]"221      }222    ],223    "stateMutability": "view",224    "type": "function"225  },226  {227    "inputs": [],228    "name": "collectionHelperAddress",229    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],230    "stateMutability": "view",231    "type": "function"232  },233  {234    "inputs": [],235    "name": "collectionLimits",236    "outputs": [237      {238        "components": [239          {240            "internalType": "enum CollectionLimitField",241            "name": "field",242            "type": "uint8"243          },244          {245            "components": [246              { "internalType": "bool", "name": "status", "type": "bool" },247              { "internalType": "uint256", "name": "value", "type": "uint256" }248            ],249            "internalType": "struct OptionUint256",250            "name": "value",251            "type": "tuple"252          }253        ],254        "internalType": "struct CollectionLimit[]",255        "name": "",256        "type": "tuple[]"257      }258    ],259    "stateMutability": "view",260    "type": "function"261  },262  {263    "inputs": [],264    "name": "collectionNestingPermissions",265    "outputs": [266      {267        "components": [268          {269            "internalType": "enum CollectionPermissionField",270            "name": "field",271            "type": "uint8"272          },273          { "internalType": "bool", "name": "value", "type": "bool" }274        ],275        "internalType": "struct CollectionNestingPermission[]",276        "name": "",277        "type": "tuple[]"278      }279    ],280    "stateMutability": "view",281    "type": "function"282  },283  {284    "inputs": [],285    "name": "collectionNestingRestrictedCollectionIds",286    "outputs": [287      {288        "components": [289          { "internalType": "bool", "name": "token_owner", "type": "bool" },290          { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }291        ],292        "internalType": "struct CollectionNesting",293        "name": "",294        "type": "tuple"295      }296    ],297    "stateMutability": "view",298    "type": "function"299  },300  {301    "inputs": [],302    "name": "collectionOwner",303    "outputs": [304      {305        "components": [306          { "internalType": "address", "name": "eth", "type": "address" },307          { "internalType": "uint256", "name": "sub", "type": "uint256" }308        ],309        "internalType": "struct CrossAddress",310        "name": "",311        "type": "tuple"312      }313    ],314    "stateMutability": "view",315    "type": "function"316  },317  {318    "inputs": [319      { "internalType": "string[]", "name": "keys", "type": "string[]" }320    ],321    "name": "collectionProperties",322    "outputs": [323      {324        "components": [325          { "internalType": "string", "name": "key", "type": "string" },326          { "internalType": "bytes", "name": "value", "type": "bytes" }327        ],328        "internalType": "struct Property[]",329        "name": "",330        "type": "tuple[]"331      }332    ],333    "stateMutability": "view",334    "type": "function"335  },336  {337    "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],338    "name": "collectionProperty",339    "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],340    "stateMutability": "view",341    "type": "function"342  },343  {344    "inputs": [],345    "name": "collectionSponsor",346    "outputs": [347      {348        "components": [349          { "internalType": "address", "name": "eth", "type": "address" },350          { "internalType": "uint256", "name": "sub", "type": "uint256" }351        ],352        "internalType": "struct CrossAddress",353        "name": "",354        "type": "tuple"355      }356    ],357    "stateMutability": "view",358    "type": "function"359  },360  {361    "inputs": [],362    "name": "confirmCollectionSponsorship",363    "outputs": [],364    "stateMutability": "nonpayable",365    "type": "function"366  },367  {368    "inputs": [],369    "name": "contractAddress",370    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],371    "stateMutability": "view",372    "type": "function"373  },374  {375    "inputs": [376      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }377    ],378    "name": "crossOwnerOf",379    "outputs": [380      {381        "components": [382          { "internalType": "address", "name": "eth", "type": "address" },383          { "internalType": "uint256", "name": "sub", "type": "uint256" }384        ],385        "internalType": "struct CrossAddress",386        "name": "",387        "type": "tuple"388      }389    ],390    "stateMutability": "view",391    "type": "function"392  },393  {394    "inputs": [395      { "internalType": "string[]", "name": "keys", "type": "string[]" }396    ],397    "name": "deleteCollectionProperties",398    "outputs": [],399    "stateMutability": "nonpayable",400    "type": "function"401  },402  {403    "inputs": [404      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },405      { "internalType": "string[]", "name": "keys", "type": "string[]" }406    ],407    "name": "deleteProperties",408    "outputs": [],409    "stateMutability": "nonpayable",410    "type": "function"411  },412  {413    "inputs": [],414    "name": "description",415    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],416    "stateMutability": "view",417    "type": "function"418  },419  {420    "inputs": [421      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }422    ],423    "name": "getApproved",424    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],425    "stateMutability": "view",426    "type": "function"427  },428  {429    "inputs": [],430    "name": "hasCollectionPendingSponsor",431    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],432    "stateMutability": "view",433    "type": "function"434  },435  {436    "inputs": [437      { "internalType": "address", "name": "owner", "type": "address" },438      { "internalType": "address", "name": "operator", "type": "address" }439    ],440    "name": "isApprovedForAll",441    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],442    "stateMutability": "view",443    "type": "function"444  },445  {446    "inputs": [447      {448        "components": [449          { "internalType": "address", "name": "eth", "type": "address" },450          { "internalType": "uint256", "name": "sub", "type": "uint256" }451        ],452        "internalType": "struct CrossAddress",453        "name": "user",454        "type": "tuple"455      }456    ],457    "name": "isOwnerOrAdminCross",458    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],459    "stateMutability": "view",460    "type": "function"461  },462  {463    "inputs": [{ "internalType": "address", "name": "to", "type": "address" }],464    "name": "mint",465    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],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 CrossAddress",477        "name": "to",478        "type": "tuple"479      },480      {481        "components": [482          { "internalType": "string", "name": "key", "type": "string" },483          { "internalType": "bytes", "name": "value", "type": "bytes" }484        ],485        "internalType": "struct Property[]",486        "name": "properties",487        "type": "tuple[]"488      }489    ],490    "name": "mintCross",491    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],492    "stateMutability": "nonpayable",493    "type": "function"494  },495  {496    "inputs": [497      { "internalType": "address", "name": "to", "type": "address" },498      { "internalType": "string", "name": "tokenUri", "type": "string" }499    ],500    "name": "mintWithTokenURI",501    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],502    "stateMutability": "nonpayable",503    "type": "function"504  },505  {506    "inputs": [],507    "name": "name",508    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],509    "stateMutability": "view",510    "type": "function"511  },512  {513    "inputs": [],514    "name": "nextTokenId",515    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],516    "stateMutability": "view",517    "type": "function"518  },519  {520    "inputs": [521      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }522    ],523    "name": "ownerOf",524    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],525    "stateMutability": "view",526    "type": "function"527  },528  {529    "inputs": [530      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },531      { "internalType": "string[]", "name": "keys", "type": "string[]" }532    ],533    "name": "properties",534    "outputs": [535      {536        "components": [537          { "internalType": "string", "name": "key", "type": "string" },538          { "internalType": "bytes", "name": "value", "type": "bytes" }539        ],540        "internalType": "struct Property[]",541        "name": "",542        "type": "tuple[]"543      }544    ],545    "stateMutability": "view",546    "type": "function"547  },548  {549    "inputs": [550      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },551      { "internalType": "string", "name": "key", "type": "string" }552    ],553    "name": "property",554    "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],555    "stateMutability": "view",556    "type": "function"557  },558  {559    "inputs": [560      {561        "components": [562          { "internalType": "address", "name": "eth", "type": "address" },563          { "internalType": "uint256", "name": "sub", "type": "uint256" }564        ],565        "internalType": "struct CrossAddress",566        "name": "admin",567        "type": "tuple"568      }569    ],570    "name": "removeCollectionAdminCross",571    "outputs": [],572    "stateMutability": "nonpayable",573    "type": "function"574  },575  {576    "inputs": [],577    "name": "removeCollectionSponsor",578    "outputs": [],579    "stateMutability": "nonpayable",580    "type": "function"581  },582  {583    "inputs": [584      {585        "components": [586          { "internalType": "address", "name": "eth", "type": "address" },587          { "internalType": "uint256", "name": "sub", "type": "uint256" }588        ],589        "internalType": "struct CrossAddress",590        "name": "user",591        "type": "tuple"592      }593    ],594    "name": "removeFromCollectionAllowListCross",595    "outputs": [],596    "stateMutability": "nonpayable",597    "type": "function"598  },599  {600    "inputs": [601      { "internalType": "address", "name": "from", "type": "address" },602      { "internalType": "address", "name": "to", "type": "address" },603      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }604    ],605    "name": "safeTransferFrom",606    "outputs": [],607    "stateMutability": "nonpayable",608    "type": "function"609  },610  {611    "inputs": [612      { "internalType": "address", "name": "from", "type": "address" },613      { "internalType": "address", "name": "to", "type": "address" },614      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },615      { "internalType": "bytes", "name": "data", "type": "bytes" }616    ],617    "name": "safeTransferFrom",618    "outputs": [],619    "stateMutability": "nonpayable",620    "type": "function"621  },622  {623    "inputs": [624      { "internalType": "address", "name": "operator", "type": "address" },625      { "internalType": "bool", "name": "approved", "type": "bool" }626    ],627    "name": "setApprovalForAll",628    "outputs": [],629    "stateMutability": "nonpayable",630    "type": "function"631  },632  {633    "inputs": [634      { "internalType": "enum AccessMode", "name": "mode", "type": "uint8" }635    ],636    "name": "setCollectionAccess",637    "outputs": [],638    "stateMutability": "nonpayable",639    "type": "function"640  },641  {642    "inputs": [643      {644        "components": [645          {646            "internalType": "enum CollectionLimitField",647            "name": "field",648            "type": "uint8"649          },650          {651            "components": [652              { "internalType": "bool", "name": "status", "type": "bool" },653              { "internalType": "uint256", "name": "value", "type": "uint256" }654            ],655            "internalType": "struct OptionUint256",656            "name": "value",657            "type": "tuple"658          }659        ],660        "internalType": "struct CollectionLimit",661        "name": "limit",662        "type": "tuple"663      }664    ],665    "name": "setCollectionLimit",666    "outputs": [],667    "stateMutability": "nonpayable",668    "type": "function"669  },670  {671    "inputs": [{ "internalType": "bool", "name": "mode", "type": "bool" }],672    "name": "setCollectionMintMode",673    "outputs": [],674    "stateMutability": "nonpayable",675    "type": "function"676  },677  {678    "inputs": [{ "internalType": "bool", "name": "enable", "type": "bool" }],679    "name": "setCollectionNesting",680    "outputs": [],681    "stateMutability": "nonpayable",682    "type": "function"683  },684  {685    "inputs": [686      { "internalType": "bool", "name": "enable", "type": "bool" },687      {688        "internalType": "address[]",689        "name": "collections",690        "type": "address[]"691      }692    ],693    "name": "setCollectionNesting",694    "outputs": [],695    "stateMutability": "nonpayable",696    "type": "function"697  },698  {699    "inputs": [700      {701        "components": [702          { "internalType": "string", "name": "key", "type": "string" },703          { "internalType": "bytes", "name": "value", "type": "bytes" }704        ],705        "internalType": "struct Property[]",706        "name": "properties",707        "type": "tuple[]"708      }709    ],710    "name": "setCollectionProperties",711    "outputs": [],712    "stateMutability": "nonpayable",713    "type": "function"714  },715  {716    "inputs": [717      {718        "components": [719          { "internalType": "address", "name": "eth", "type": "address" },720          { "internalType": "uint256", "name": "sub", "type": "uint256" }721        ],722        "internalType": "struct CrossAddress",723        "name": "sponsor",724        "type": "tuple"725      }726    ],727    "name": "setCollectionSponsorCross",728    "outputs": [],729    "stateMutability": "nonpayable",730    "type": "function"731  },732  {733    "inputs": [734      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },735      {736        "components": [737          { "internalType": "string", "name": "key", "type": "string" },738          { "internalType": "bytes", "name": "value", "type": "bytes" }739        ],740        "internalType": "struct Property[]",741        "name": "properties",742        "type": "tuple[]"743      }744    ],745    "name": "setProperties",746    "outputs": [],747    "stateMutability": "nonpayable",748    "type": "function"749  },750  {751    "inputs": [752      {753        "components": [754          { "internalType": "string", "name": "key", "type": "string" },755          {756            "components": [757              {758                "internalType": "enum TokenPermissionField",759                "name": "code",760                "type": "uint8"761              },762              { "internalType": "bool", "name": "value", "type": "bool" }763            ],764            "internalType": "struct PropertyPermission[]",765            "name": "permissions",766            "type": "tuple[]"767          }768        ],769        "internalType": "struct TokenPropertyPermission[]",770        "name": "permissions",771        "type": "tuple[]"772      }773    ],774    "name": "setTokenPropertyPermissions",775    "outputs": [],776    "stateMutability": "nonpayable",777    "type": "function"778  },779  {780    "inputs": [781      { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }782    ],783    "name": "supportsInterface",784    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],785    "stateMutability": "view",786    "type": "function"787  },788  {789    "inputs": [],790    "name": "symbol",791    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],792    "stateMutability": "view",793    "type": "function"794  },795  {796    "inputs": [797      { "internalType": "uint256", "name": "index", "type": "uint256" }798    ],799    "name": "tokenByIndex",800    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],801    "stateMutability": "view",802    "type": "function"803  },804  {805    "inputs": [806      { "internalType": "address", "name": "owner", "type": "address" },807      { "internalType": "uint256", "name": "index", "type": "uint256" }808    ],809    "name": "tokenOfOwnerByIndex",810    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],811    "stateMutability": "view",812    "type": "function"813  },814  {815    "inputs": [],816    "name": "tokenPropertyPermissions",817    "outputs": [818      {819        "components": [820          { "internalType": "string", "name": "key", "type": "string" },821          {822            "components": [823              {824                "internalType": "enum TokenPermissionField",825                "name": "code",826                "type": "uint8"827              },828              { "internalType": "bool", "name": "value", "type": "bool" }829            ],830            "internalType": "struct PropertyPermission[]",831            "name": "permissions",832            "type": "tuple[]"833          }834        ],835        "internalType": "struct TokenPropertyPermission[]",836        "name": "",837        "type": "tuple[]"838      }839    ],840    "stateMutability": "view",841    "type": "function"842  },843  {844    "inputs": [845      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }846    ],847    "name": "tokenURI",848    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],849    "stateMutability": "view",850    "type": "function"851  },852  {853    "inputs": [],854    "name": "totalSupply",855    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],856    "stateMutability": "view",857    "type": "function"858  },859  {860    "inputs": [861      { "internalType": "address", "name": "to", "type": "address" },862      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }863    ],864    "name": "transfer",865    "outputs": [],866    "stateMutability": "nonpayable",867    "type": "function"868  },869  {870    "inputs": [871      {872        "components": [873          { "internalType": "address", "name": "eth", "type": "address" },874          { "internalType": "uint256", "name": "sub", "type": "uint256" }875        ],876        "internalType": "struct CrossAddress",877        "name": "to",878        "type": "tuple"879      },880      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }881    ],882    "name": "transferCross",883    "outputs": [],884    "stateMutability": "nonpayable",885    "type": "function"886  },887  {888    "inputs": [889      { "internalType": "address", "name": "from", "type": "address" },890      { "internalType": "address", "name": "to", "type": "address" },891      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }892    ],893    "name": "transferFrom",894    "outputs": [],895    "stateMutability": "nonpayable",896    "type": "function"897  },898  {899    "inputs": [900      {901        "components": [902          { "internalType": "address", "name": "eth", "type": "address" },903          { "internalType": "uint256", "name": "sub", "type": "uint256" }904        ],905        "internalType": "struct CrossAddress",906        "name": "from",907        "type": "tuple"908      },909      {910        "components": [911          { "internalType": "address", "name": "eth", "type": "address" },912          { "internalType": "uint256", "name": "sub", "type": "uint256" }913        ],914        "internalType": "struct CrossAddress",915        "name": "to",916        "type": "tuple"917      },918      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }919    ],920    "name": "transferFromCross",921    "outputs": [],922    "stateMutability": "nonpayable",923    "type": "function"924  },925  {926    "inputs": [],927    "name": "uniqueCollectionType",928    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],929    "stateMutability": "view",930    "type": "function"931  }932]
after · tests/src/eth/abi/nonFungible.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      {56        "indexed": true,57        "internalType": "address",58        "name": "collectionId",59        "type": "address"60      },61      {62        "indexed": false,63        "internalType": "uint256",64        "name": "tokenId",65        "type": "uint256"66      }67    ],68    "name": "TokenChanged",69    "type": "event"70  },71  {72    "anonymous": false,73    "inputs": [74      {75        "indexed": true,76        "internalType": "address",77        "name": "from",78        "type": "address"79      },80      {81        "indexed": true,82        "internalType": "address",83        "name": "to",84        "type": "address"85      },86      {87        "indexed": true,88        "internalType": "uint256",89        "name": "tokenId",90        "type": "uint256"91      }92    ],93    "name": "Transfer",94    "type": "event"95  },96  {97    "inputs": [98      {99        "components": [100          { "internalType": "address", "name": "eth", "type": "address" },101          { "internalType": "uint256", "name": "sub", "type": "uint256" }102        ],103        "internalType": "struct CrossAddress",104        "name": "newAdmin",105        "type": "tuple"106      }107    ],108    "name": "addCollectionAdminCross",109    "outputs": [],110    "stateMutability": "nonpayable",111    "type": "function"112  },113  {114    "inputs": [115      {116        "components": [117          { "internalType": "address", "name": "eth", "type": "address" },118          { "internalType": "uint256", "name": "sub", "type": "uint256" }119        ],120        "internalType": "struct CrossAddress",121        "name": "user",122        "type": "tuple"123      }124    ],125    "name": "addToCollectionAllowListCross",126    "outputs": [],127    "stateMutability": "nonpayable",128    "type": "function"129  },130  {131    "inputs": [132      {133        "components": [134          { "internalType": "address", "name": "eth", "type": "address" },135          { "internalType": "uint256", "name": "sub", "type": "uint256" }136        ],137        "internalType": "struct CrossAddress",138        "name": "user",139        "type": "tuple"140      }141    ],142    "name": "allowlistedCross",143    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],144    "stateMutability": "view",145    "type": "function"146  },147  {148    "inputs": [149      { "internalType": "address", "name": "approved", "type": "address" },150      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }151    ],152    "name": "approve",153    "outputs": [],154    "stateMutability": "nonpayable",155    "type": "function"156  },157  {158    "inputs": [159      {160        "components": [161          { "internalType": "address", "name": "eth", "type": "address" },162          { "internalType": "uint256", "name": "sub", "type": "uint256" }163        ],164        "internalType": "struct CrossAddress",165        "name": "approved",166        "type": "tuple"167      },168      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }169    ],170    "name": "approveCross",171    "outputs": [],172    "stateMutability": "nonpayable",173    "type": "function"174  },175  {176    "inputs": [177      { "internalType": "address", "name": "owner", "type": "address" }178    ],179    "name": "balanceOf",180    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],181    "stateMutability": "view",182    "type": "function"183  },184  {185    "inputs": [186      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }187    ],188    "name": "burn",189    "outputs": [],190    "stateMutability": "nonpayable",191    "type": "function"192  },193  {194    "inputs": [195      {196        "components": [197          { "internalType": "address", "name": "eth", "type": "address" },198          { "internalType": "uint256", "name": "sub", "type": "uint256" }199        ],200        "internalType": "struct CrossAddress",201        "name": "from",202        "type": "tuple"203      },204      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }205    ],206    "name": "burnFromCross",207    "outputs": [],208    "stateMutability": "nonpayable",209    "type": "function"210  },211  {212    "inputs": [213      {214        "components": [215          { "internalType": "address", "name": "eth", "type": "address" },216          { "internalType": "uint256", "name": "sub", "type": "uint256" }217        ],218        "internalType": "struct CrossAddress",219        "name": "newOwner",220        "type": "tuple"221      }222    ],223    "name": "changeCollectionOwnerCross",224    "outputs": [],225    "stateMutability": "nonpayable",226    "type": "function"227  },228  {229    "inputs": [],230    "name": "collectionAdmins",231    "outputs": [232      {233        "components": [234          { "internalType": "address", "name": "eth", "type": "address" },235          { "internalType": "uint256", "name": "sub", "type": "uint256" }236        ],237        "internalType": "struct CrossAddress[]",238        "name": "",239        "type": "tuple[]"240      }241    ],242    "stateMutability": "view",243    "type": "function"244  },245  {246    "inputs": [],247    "name": "collectionHelperAddress",248    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],249    "stateMutability": "view",250    "type": "function"251  },252  {253    "inputs": [],254    "name": "collectionLimits",255    "outputs": [256      {257        "components": [258          {259            "internalType": "enum CollectionLimitField",260            "name": "field",261            "type": "uint8"262          },263          {264            "components": [265              { "internalType": "bool", "name": "status", "type": "bool" },266              { "internalType": "uint256", "name": "value", "type": "uint256" }267            ],268            "internalType": "struct OptionUint256",269            "name": "value",270            "type": "tuple"271          }272        ],273        "internalType": "struct CollectionLimit[]",274        "name": "",275        "type": "tuple[]"276      }277    ],278    "stateMutability": "view",279    "type": "function"280  },281  {282    "inputs": [],283    "name": "collectionNestingPermissions",284    "outputs": [285      {286        "components": [287          {288            "internalType": "enum CollectionPermissionField",289            "name": "field",290            "type": "uint8"291          },292          { "internalType": "bool", "name": "value", "type": "bool" }293        ],294        "internalType": "struct CollectionNestingPermission[]",295        "name": "",296        "type": "tuple[]"297      }298    ],299    "stateMutability": "view",300    "type": "function"301  },302  {303    "inputs": [],304    "name": "collectionNestingRestrictedCollectionIds",305    "outputs": [306      {307        "components": [308          { "internalType": "bool", "name": "token_owner", "type": "bool" },309          { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }310        ],311        "internalType": "struct CollectionNesting",312        "name": "",313        "type": "tuple"314      }315    ],316    "stateMutability": "view",317    "type": "function"318  },319  {320    "inputs": [],321    "name": "collectionOwner",322    "outputs": [323      {324        "components": [325          { "internalType": "address", "name": "eth", "type": "address" },326          { "internalType": "uint256", "name": "sub", "type": "uint256" }327        ],328        "internalType": "struct CrossAddress",329        "name": "",330        "type": "tuple"331      }332    ],333    "stateMutability": "view",334    "type": "function"335  },336  {337    "inputs": [338      { "internalType": "string[]", "name": "keys", "type": "string[]" }339    ],340    "name": "collectionProperties",341    "outputs": [342      {343        "components": [344          { "internalType": "string", "name": "key", "type": "string" },345          { "internalType": "bytes", "name": "value", "type": "bytes" }346        ],347        "internalType": "struct Property[]",348        "name": "",349        "type": "tuple[]"350      }351    ],352    "stateMutability": "view",353    "type": "function"354  },355  {356    "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],357    "name": "collectionProperty",358    "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],359    "stateMutability": "view",360    "type": "function"361  },362  {363    "inputs": [],364    "name": "collectionSponsor",365    "outputs": [366      {367        "components": [368          { "internalType": "address", "name": "eth", "type": "address" },369          { "internalType": "uint256", "name": "sub", "type": "uint256" }370        ],371        "internalType": "struct CrossAddress",372        "name": "",373        "type": "tuple"374      }375    ],376    "stateMutability": "view",377    "type": "function"378  },379  {380    "inputs": [],381    "name": "confirmCollectionSponsorship",382    "outputs": [],383    "stateMutability": "nonpayable",384    "type": "function"385  },386  {387    "inputs": [],388    "name": "contractAddress",389    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],390    "stateMutability": "view",391    "type": "function"392  },393  {394    "inputs": [395      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }396    ],397    "name": "crossOwnerOf",398    "outputs": [399      {400        "components": [401          { "internalType": "address", "name": "eth", "type": "address" },402          { "internalType": "uint256", "name": "sub", "type": "uint256" }403        ],404        "internalType": "struct CrossAddress",405        "name": "",406        "type": "tuple"407      }408    ],409    "stateMutability": "view",410    "type": "function"411  },412  {413    "inputs": [414      { "internalType": "string[]", "name": "keys", "type": "string[]" }415    ],416    "name": "deleteCollectionProperties",417    "outputs": [],418    "stateMutability": "nonpayable",419    "type": "function"420  },421  {422    "inputs": [423      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },424      { "internalType": "string[]", "name": "keys", "type": "string[]" }425    ],426    "name": "deleteProperties",427    "outputs": [],428    "stateMutability": "nonpayable",429    "type": "function"430  },431  {432    "inputs": [],433    "name": "description",434    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],435    "stateMutability": "view",436    "type": "function"437  },438  {439    "inputs": [440      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }441    ],442    "name": "getApproved",443    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],444    "stateMutability": "view",445    "type": "function"446  },447  {448    "inputs": [],449    "name": "hasCollectionPendingSponsor",450    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],451    "stateMutability": "view",452    "type": "function"453  },454  {455    "inputs": [456      { "internalType": "address", "name": "owner", "type": "address" },457      { "internalType": "address", "name": "operator", "type": "address" }458    ],459    "name": "isApprovedForAll",460    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],461    "stateMutability": "view",462    "type": "function"463  },464  {465    "inputs": [466      {467        "components": [468          { "internalType": "address", "name": "eth", "type": "address" },469          { "internalType": "uint256", "name": "sub", "type": "uint256" }470        ],471        "internalType": "struct CrossAddress",472        "name": "user",473        "type": "tuple"474      }475    ],476    "name": "isOwnerOrAdminCross",477    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],478    "stateMutability": "view",479    "type": "function"480  },481  {482    "inputs": [{ "internalType": "address", "name": "to", "type": "address" }],483    "name": "mint",484    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],485    "stateMutability": "nonpayable",486    "type": "function"487  },488  {489    "inputs": [490      {491        "components": [492          { "internalType": "address", "name": "eth", "type": "address" },493          { "internalType": "uint256", "name": "sub", "type": "uint256" }494        ],495        "internalType": "struct CrossAddress",496        "name": "to",497        "type": "tuple"498      },499      {500        "components": [501          { "internalType": "string", "name": "key", "type": "string" },502          { "internalType": "bytes", "name": "value", "type": "bytes" }503        ],504        "internalType": "struct Property[]",505        "name": "properties",506        "type": "tuple[]"507      }508    ],509    "name": "mintCross",510    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],511    "stateMutability": "nonpayable",512    "type": "function"513  },514  {515    "inputs": [516      { "internalType": "address", "name": "to", "type": "address" },517      { "internalType": "string", "name": "tokenUri", "type": "string" }518    ],519    "name": "mintWithTokenURI",520    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],521    "stateMutability": "nonpayable",522    "type": "function"523  },524  {525    "inputs": [],526    "name": "name",527    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],528    "stateMutability": "view",529    "type": "function"530  },531  {532    "inputs": [],533    "name": "nextTokenId",534    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],535    "stateMutability": "view",536    "type": "function"537  },538  {539    "inputs": [540      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }541    ],542    "name": "ownerOf",543    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],544    "stateMutability": "view",545    "type": "function"546  },547  {548    "inputs": [549      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },550      { "internalType": "string[]", "name": "keys", "type": "string[]" }551    ],552    "name": "properties",553    "outputs": [554      {555        "components": [556          { "internalType": "string", "name": "key", "type": "string" },557          { "internalType": "bytes", "name": "value", "type": "bytes" }558        ],559        "internalType": "struct Property[]",560        "name": "",561        "type": "tuple[]"562      }563    ],564    "stateMutability": "view",565    "type": "function"566  },567  {568    "inputs": [569      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },570      { "internalType": "string", "name": "key", "type": "string" }571    ],572    "name": "property",573    "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],574    "stateMutability": "view",575    "type": "function"576  },577  {578    "inputs": [579      {580        "components": [581          { "internalType": "address", "name": "eth", "type": "address" },582          { "internalType": "uint256", "name": "sub", "type": "uint256" }583        ],584        "internalType": "struct CrossAddress",585        "name": "admin",586        "type": "tuple"587      }588    ],589    "name": "removeCollectionAdminCross",590    "outputs": [],591    "stateMutability": "nonpayable",592    "type": "function"593  },594  {595    "inputs": [],596    "name": "removeCollectionSponsor",597    "outputs": [],598    "stateMutability": "nonpayable",599    "type": "function"600  },601  {602    "inputs": [603      {604        "components": [605          { "internalType": "address", "name": "eth", "type": "address" },606          { "internalType": "uint256", "name": "sub", "type": "uint256" }607        ],608        "internalType": "struct CrossAddress",609        "name": "user",610        "type": "tuple"611      }612    ],613    "name": "removeFromCollectionAllowListCross",614    "outputs": [],615    "stateMutability": "nonpayable",616    "type": "function"617  },618  {619    "inputs": [620      { "internalType": "address", "name": "from", "type": "address" },621      { "internalType": "address", "name": "to", "type": "address" },622      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }623    ],624    "name": "safeTransferFrom",625    "outputs": [],626    "stateMutability": "nonpayable",627    "type": "function"628  },629  {630    "inputs": [631      { "internalType": "address", "name": "from", "type": "address" },632      { "internalType": "address", "name": "to", "type": "address" },633      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },634      { "internalType": "bytes", "name": "data", "type": "bytes" }635    ],636    "name": "safeTransferFrom",637    "outputs": [],638    "stateMutability": "nonpayable",639    "type": "function"640  },641  {642    "inputs": [643      { "internalType": "address", "name": "operator", "type": "address" },644      { "internalType": "bool", "name": "approved", "type": "bool" }645    ],646    "name": "setApprovalForAll",647    "outputs": [],648    "stateMutability": "nonpayable",649    "type": "function"650  },651  {652    "inputs": [653      { "internalType": "enum AccessMode", "name": "mode", "type": "uint8" }654    ],655    "name": "setCollectionAccess",656    "outputs": [],657    "stateMutability": "nonpayable",658    "type": "function"659  },660  {661    "inputs": [662      {663        "components": [664          {665            "internalType": "enum CollectionLimitField",666            "name": "field",667            "type": "uint8"668          },669          {670            "components": [671              { "internalType": "bool", "name": "status", "type": "bool" },672              { "internalType": "uint256", "name": "value", "type": "uint256" }673            ],674            "internalType": "struct OptionUint256",675            "name": "value",676            "type": "tuple"677          }678        ],679        "internalType": "struct CollectionLimit",680        "name": "limit",681        "type": "tuple"682      }683    ],684    "name": "setCollectionLimit",685    "outputs": [],686    "stateMutability": "nonpayable",687    "type": "function"688  },689  {690    "inputs": [{ "internalType": "bool", "name": "mode", "type": "bool" }],691    "name": "setCollectionMintMode",692    "outputs": [],693    "stateMutability": "nonpayable",694    "type": "function"695  },696  {697    "inputs": [{ "internalType": "bool", "name": "enable", "type": "bool" }],698    "name": "setCollectionNesting",699    "outputs": [],700    "stateMutability": "nonpayable",701    "type": "function"702  },703  {704    "inputs": [705      { "internalType": "bool", "name": "enable", "type": "bool" },706      {707        "internalType": "address[]",708        "name": "collections",709        "type": "address[]"710      }711    ],712    "name": "setCollectionNesting",713    "outputs": [],714    "stateMutability": "nonpayable",715    "type": "function"716  },717  {718    "inputs": [719      {720        "components": [721          { "internalType": "string", "name": "key", "type": "string" },722          { "internalType": "bytes", "name": "value", "type": "bytes" }723        ],724        "internalType": "struct Property[]",725        "name": "properties",726        "type": "tuple[]"727      }728    ],729    "name": "setCollectionProperties",730    "outputs": [],731    "stateMutability": "nonpayable",732    "type": "function"733  },734  {735    "inputs": [736      {737        "components": [738          { "internalType": "address", "name": "eth", "type": "address" },739          { "internalType": "uint256", "name": "sub", "type": "uint256" }740        ],741        "internalType": "struct CrossAddress",742        "name": "sponsor",743        "type": "tuple"744      }745    ],746    "name": "setCollectionSponsorCross",747    "outputs": [],748    "stateMutability": "nonpayable",749    "type": "function"750  },751  {752    "inputs": [753      { "internalType": "uint256", "name": "tokenId", "type": "uint256" },754      {755        "components": [756          { "internalType": "string", "name": "key", "type": "string" },757          { "internalType": "bytes", "name": "value", "type": "bytes" }758        ],759        "internalType": "struct Property[]",760        "name": "properties",761        "type": "tuple[]"762      }763    ],764    "name": "setProperties",765    "outputs": [],766    "stateMutability": "nonpayable",767    "type": "function"768  },769  {770    "inputs": [771      {772        "components": [773          { "internalType": "string", "name": "key", "type": "string" },774          {775            "components": [776              {777                "internalType": "enum TokenPermissionField",778                "name": "code",779                "type": "uint8"780              },781              { "internalType": "bool", "name": "value", "type": "bool" }782            ],783            "internalType": "struct PropertyPermission[]",784            "name": "permissions",785            "type": "tuple[]"786          }787        ],788        "internalType": "struct TokenPropertyPermission[]",789        "name": "permissions",790        "type": "tuple[]"791      }792    ],793    "name": "setTokenPropertyPermissions",794    "outputs": [],795    "stateMutability": "nonpayable",796    "type": "function"797  },798  {799    "inputs": [800      { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }801    ],802    "name": "supportsInterface",803    "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],804    "stateMutability": "view",805    "type": "function"806  },807  {808    "inputs": [],809    "name": "symbol",810    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],811    "stateMutability": "view",812    "type": "function"813  },814  {815    "inputs": [816      { "internalType": "uint256", "name": "index", "type": "uint256" }817    ],818    "name": "tokenByIndex",819    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],820    "stateMutability": "view",821    "type": "function"822  },823  {824    "inputs": [825      { "internalType": "address", "name": "owner", "type": "address" },826      { "internalType": "uint256", "name": "index", "type": "uint256" }827    ],828    "name": "tokenOfOwnerByIndex",829    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],830    "stateMutability": "view",831    "type": "function"832  },833  {834    "inputs": [],835    "name": "tokenPropertyPermissions",836    "outputs": [837      {838        "components": [839          { "internalType": "string", "name": "key", "type": "string" },840          {841            "components": [842              {843                "internalType": "enum TokenPermissionField",844                "name": "code",845                "type": "uint8"846              },847              { "internalType": "bool", "name": "value", "type": "bool" }848            ],849            "internalType": "struct PropertyPermission[]",850            "name": "permissions",851            "type": "tuple[]"852          }853        ],854        "internalType": "struct TokenPropertyPermission[]",855        "name": "",856        "type": "tuple[]"857      }858    ],859    "stateMutability": "view",860    "type": "function"861  },862  {863    "inputs": [864      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }865    ],866    "name": "tokenURI",867    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],868    "stateMutability": "view",869    "type": "function"870  },871  {872    "inputs": [],873    "name": "totalSupply",874    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],875    "stateMutability": "view",876    "type": "function"877  },878  {879    "inputs": [880      { "internalType": "address", "name": "to", "type": "address" },881      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }882    ],883    "name": "transfer",884    "outputs": [],885    "stateMutability": "nonpayable",886    "type": "function"887  },888  {889    "inputs": [890      {891        "components": [892          { "internalType": "address", "name": "eth", "type": "address" },893          { "internalType": "uint256", "name": "sub", "type": "uint256" }894        ],895        "internalType": "struct CrossAddress",896        "name": "to",897        "type": "tuple"898      },899      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }900    ],901    "name": "transferCross",902    "outputs": [],903    "stateMutability": "nonpayable",904    "type": "function"905  },906  {907    "inputs": [908      { "internalType": "address", "name": "from", "type": "address" },909      { "internalType": "address", "name": "to", "type": "address" },910      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }911    ],912    "name": "transferFrom",913    "outputs": [],914    "stateMutability": "nonpayable",915    "type": "function"916  },917  {918    "inputs": [919      {920        "components": [921          { "internalType": "address", "name": "eth", "type": "address" },922          { "internalType": "uint256", "name": "sub", "type": "uint256" }923        ],924        "internalType": "struct CrossAddress",925        "name": "from",926        "type": "tuple"927      },928      {929        "components": [930          { "internalType": "address", "name": "eth", "type": "address" },931          { "internalType": "uint256", "name": "sub", "type": "uint256" }932        ],933        "internalType": "struct CrossAddress",934        "name": "to",935        "type": "tuple"936      },937      { "internalType": "uint256", "name": "tokenId", "type": "uint256" }938    ],939    "name": "transferFromCross",940    "outputs": [],941    "stateMutability": "nonpayable",942    "type": "function"943  },944  {945    "inputs": [],946    "name": "uniqueCollectionType",947    "outputs": [{ "internalType": "string", "name": "", "type": "string" }],948    "stateMutability": "view",949    "type": "function"950  }951]
modifiedtests/src/eth/abi/reFungible.jsondiffbeforeafterboth
--- a/tests/src/eth/abi/reFungible.json
+++ b/tests/src/eth/abi/reFungible.json
@@ -55,6 +55,25 @@
       {
         "indexed": true,
         "internalType": "address",
+        "name": "collectionId",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint256",
+        "name": "tokenId",
+        "type": "uint256"
+      }
+    ],
+    "name": "TokenChanged",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
         "name": "from",
         "type": "address"
       },
modifiedtests/src/eth/api/CollectionHelpers.soldiffbeforeafterboth
--- a/tests/src/eth/api/CollectionHelpers.sol
+++ b/tests/src/eth/api/CollectionHelpers.sol
@@ -17,7 +17,6 @@
 	event CollectionCreated(address indexed owner, address indexed collectionId);
 	event CollectionDestroyed(address indexed collectionId);
 	event CollectionChanged(address indexed collectionId);
-	event TokenChanged(address indexed collectionId, uint256 tokenId);
 }
 
 /// @title Contract, which allows users to operate with collections
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -12,9 +12,14 @@
 	function supportsInterface(bytes4 interfaceID) external view returns (bool);
 }
 
+/// @dev inlined interface
+interface ERC721TokenEvent {
+	event TokenChanged(address indexed collectionId, uint256 tokenId);
+}
+
 /// @title A contract that allows to set and delete token properties and change token property permissions.
 /// @dev the ERC-165 identifier for this interface is 0xde0695c2
-interface TokenProperties is Dummy, ERC165 {
+interface TokenProperties is Dummy, ERC165, ERC721TokenEvent {
 	// /// @notice Set permissions for token property.
 	// /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
 	// /// @param key Property key.
modifiedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -12,9 +12,14 @@
 	function supportsInterface(bytes4 interfaceID) external view returns (bool);
 }
 
+/// @dev inlined interface
+interface ERC721TokenEvent {
+	event TokenChanged(address indexed collectionId, uint256 tokenId);
+}
+
 /// @title A contract that allows to set and delete token properties and change token property permissions.
 /// @dev the ERC-165 identifier for this interface is 0xde0695c2
-interface TokenProperties is Dummy, ERC165 {
+interface TokenProperties is Dummy, ERC165, ERC721TokenEvent {
 	// /// @notice Set permissions for token property.
 	// /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
 	// /// @param key Property key.
modifiedtests/src/eth/events.test.tsdiffbeforeafterboth
--- a/tests/src/eth/events.test.ts
+++ b/tests/src/eth/events.test.ts
@@ -29,8 +29,10 @@
   });
 });
 
-function clearEvents(ethEvents: NormalizedEvent[], subEvents: IEvent[]) {
-  ethEvents.splice(0);
+function clearEvents(ethEvents: NormalizedEvent[] | null, subEvents: IEvent[]) {
+  if (ethEvents !== null) {
+    ethEvents.splice(0);
+  }
   subEvents.splice(0);
 }
 
@@ -374,7 +376,6 @@
   const owner = await helper.eth.createAccountWithBalance(donor);
   const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C');
   const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);
-  const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
   const result = await collection.methods.mint(owner).send({from: owner});
   const tokenId = result.events.Transfer.returnValues.tokenId;
   await collection.methods.setTokenPropertyPermissions([
@@ -384,38 +385,31 @@
       [TokenPermissionField.CollectionAdmin, true]],
     ],
   ]).send({from: owner});
-
 
-  const ethEvents: any = [];
-  collectionHelper.events.allEvents((_: any, event: any) => {
-    ethEvents.push(event);
-  });
   const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['TokenPropertySet', 'TokenPropertyDeleted']}]);
   {
-    await collection.methods.setProperties(tokenId, [{key: 'A', value: [1,2,3]}]).send({from: owner});
+    const result = await collection.methods.setProperties(tokenId, [{key: 'A', value: [1,2,3]}]).send({from: owner});
     await helper.wait.newBlocks(1);
-    expect(ethEvents).to.containSubset([
-      {
-        event: 'TokenChanged',
-        returnValues: {
-          collectionId: collectionAddress,
-        },
+    expect(result.events.TokenChanged).to.be.like({
+      event: 'TokenChanged',
+      returnValues: {
+        collectionId: collectionAddress,
+        tokenId: tokenId,
       },
-    ]);
+    });
     expect(subEvents).to.containSubset([{method: 'TokenPropertySet'}]);
-    clearEvents(ethEvents, subEvents);
+    clearEvents(null, subEvents);
   }
   {
-    await collection.methods.deleteProperties(tokenId, ['A']).send({from: owner});
+    const result = await collection.methods.deleteProperties(tokenId, ['A']).send({from: owner});
     await helper.wait.newBlocks(1);
-    expect(ethEvents).to.containSubset([
-      {
-        event: 'TokenChanged',
-        returnValues: {
-          collectionId: collectionAddress,
-        },
+    expect(result.events.TokenChanged).to.be.like({
+      event: 'TokenChanged',
+      returnValues: {
+        collectionId: collectionAddress,
+        tokenId: tokenId,
       },
-    ]);
+    });
     expect(subEvents).to.containSubset([{method: 'TokenPropertyDeleted'}]);
   }
   unsubscribe();