difftreelog
refac: rename substrate methods to cross
in: master
27 files changed
Cargo.lockdiffbeforeafterboth107710771078[[package]]1078[[package]]1079name = "console"1079name = "console"1080version = "0.15.1"1080version = "0.15.2"1081source = "registry+https://github.com/rust-lang/crates.io-index"1081source = "registry+https://github.com/rust-lang/crates.io-index"1082checksum = "89eab4d20ce20cea182308bca13088fecea9c05f6776cf287205d41a0ed3c847"1082checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c"1083dependencies = [1083dependencies = [1084 "encode_unicode",1084 "encode_unicode",1085 "lazy_static",1085 "libc",1086 "libc",1086 "once_cell",1087 "terminal_size",1087 "terminal_size",1088 "winapi",1088 "winapi",1089]1089]187118711872[[package]]1872[[package]]1873name = "cxx"1873name = "cxx"1874version = "1.0.79"1874version = "1.0.78"1875source = "registry+https://github.com/rust-lang/crates.io-index"1875source = "registry+https://github.com/rust-lang/crates.io-index"1876checksum = "3f83d0ebf42c6eafb8d7c52f7e5f2d3003b89c7aa4fd2b79229209459a849af8"1876checksum = "19f39818dcfc97d45b03953c1292efc4e80954e1583c4aa770bac1383e2310a4"1877dependencies = [1877dependencies = [1878 "cc",1878 "cc",1879 "cxxbridge-flags",1879 "cxxbridge-flags",188318831884[[package]]1884[[package]]1885name = "cxx-build"1885name = "cxx-build"1886version = "1.0.79"1886version = "1.0.78"1887source = "registry+https://github.com/rust-lang/crates.io-index"1887source = "registry+https://github.com/rust-lang/crates.io-index"1888checksum = "07d050484b55975889284352b0ffc2ecbda25c0c55978017c132b29ba0818a86"1888checksum = "3e580d70777c116df50c390d1211993f62d40302881e54d4b79727acb83d0199"1889dependencies = [1889dependencies = [1890 "cc",1890 "cc",1891 "codespan-reporting",1891 "codespan-reporting",189818981899[[package]]1899[[package]]1900name = "cxxbridge-flags"1900name = "cxxbridge-flags"1901version = "1.0.79"1901version = "1.0.78"1902source = "registry+https://github.com/rust-lang/crates.io-index"1902source = "registry+https://github.com/rust-lang/crates.io-index"1903checksum = "99d2199b00553eda8012dfec8d3b1c75fce747cf27c169a270b3b99e3448ab78"1903checksum = "56a46460b88d1cec95112c8c363f0e2c39afdb237f60583b0b36343bf627ea9c"190419041905[[package]]1905[[package]]1906name = "cxxbridge-macro"1906name = "cxxbridge-macro"1907version = "1.0.79"1907version = "1.0.78"1908source = "registry+https://github.com/rust-lang/crates.io-index"1908source = "registry+https://github.com/rust-lang/crates.io-index"1909checksum = "dcb67a6de1f602736dd7eaead0080cf3435df806c61b24b13328db128c58868f"1909checksum = "747b608fecf06b0d72d440f27acc99288207324b793be2c17991839f3d4995ea"1910dependencies = [1910dependencies = [1911 "proc-macro2",1911 "proc-macro2",1912 "quote",1912 "quote",356135613562[[package]]3562[[package]]3563name = "iana-time-zone-haiku"3563name = "iana-time-zone-haiku"3564version = "0.1.1"3564version = "0.1.0"3565source = "registry+https://github.com/rust-lang/crates.io-index"3565source = "registry+https://github.com/rust-lang/crates.io-index"3566checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"3566checksum = "fde6edd6cef363e9359ed3c98ba64590ba9eecba2293eb5a723ab32aee8926aa"3567dependencies = [3567dependencies = [3568 "cxx",3568 "cxx",3569 "cxx-build",3569 "cxx-build",107741077410775[[package]]10775[[package]]10776name = "serde_json"10776name = "serde_json"10777version = "1.0.87"10777version = "1.0.86"10778source = "registry+https://github.com/rust-lang/crates.io-index"10778source = "registry+https://github.com/rust-lang/crates.io-index"10779checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45"10779checksum = "41feea4228a6f1cd09ec7a3593a682276702cd67b5273544757dae23c096f074"10780dependencies = [10780dependencies = [10781 "itoa",10781 "itoa",10782 "ryu",10782 "ryu",120551205512056[[package]]12056[[package]]12057name = "syn"12057name = "syn"12058version = "1.0.103"12058version = "1.0.102"12059source = "registry+https://github.com/rust-lang/crates.io-index"12059source = "registry+https://github.com/rust-lang/crates.io-index"12060checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"12060checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"12061dependencies = [12061dependencies = [12062 "proc-macro2",12062 "proc-macro2",12063 "quote",12063 "quote",pallets/common/src/erc.rsdiffbeforeafterboth34use crate::{34use crate::{35 Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,35 Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,36 eth::{36 eth::{37 convert_cross_account_to_uint256, convert_uint256_to_cross_account,37 convert_cross_account_to_uint256, convert_cross_account_to_tuple,38 convert_cross_account_to_tuple,38 convert_tuple_to_cross_account,39 },39 },40 weights::WeightInfo,40 weights::WeightInfo,41};41};139 save(self)139 save(self)140 }140 }141141142 // TODO: Temprorary off. Need refactor143 // /// Set the substrate sponsor of the collection.142 /// Set the sponsor of the collection.144 // ///143 ///145 // /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.144 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.146 // ///145 ///147 // /// @param sponsor Substrate address of the sponsor from whose account funds will be debited for operations with the contract.146 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.148 // fn set_collection_sponsor_substrate(147 fn set_collection_sponsor_cross(149 // &mut self,148 &mut self,150 // caller: caller,149 caller: caller,151 // sponsor: uint256,150 sponsor: (address, uint256),152 // ) -> Result<void> {151 ) -> Result<void> {153 // self.consume_store_reads_and_writes(1, 1)?;152 self.consume_store_reads_and_writes(1, 1)?;154153155 // check_is_owner_or_admin(caller, self)?;154 check_is_owner_or_admin(caller, self)?;156155157 // let sponsor = convert_uint256_to_cross_account::<T>(sponsor);156 let sponsor = convert_tuple_to_cross_account::<T>(sponsor)?;158 // self.set_sponsor(sponsor.as_sub().clone())157 self.set_sponsor(sponsor.as_sub().clone())159 // .map_err(dispatch_to_evm::<T>)?;158 .map_err(dispatch_to_evm::<T>)?;160 // save(self)159 save(self)161 // }160 }162161163 /// Whether there is a pending sponsor.162 /// Whether there is a pending sponsor.164 fn has_collection_pending_sponsor(&self) -> Result<bool> {163 fn has_collection_pending_sponsor(&self) -> Result<bool> {300 Ok(crate::eth::collection_id_to_address(self.id))299 Ok(crate::eth::collection_id_to_address(self.id))301 }300 }302301303 // TODO: Temprorary off. Need refactor304 // /// Add collection admin by substrate address.302 /// Add collection admin.305 // /// @param newAdmin Substrate administrator address.303 /// @param newAdmin Cross account administrator address.306 // fn add_collection_admin_substrate(304 fn add_collection_admin_cross(307 // &mut self,305 &mut self,308 // caller: caller,306 caller: caller,309 // new_admin: uint256,307 new_admin: (address, uint256),310 // ) -> Result<void> {308 ) -> Result<void> {311 // self.consume_store_writes(2)?;309 self.consume_store_writes(2)?;312310313 // let caller = T::CrossAccountId::from_eth(caller);311 let caller = T::CrossAccountId::from_eth(caller);314 // let new_admin = convert_uint256_to_cross_account::<T>(new_admin);312 let new_admin = convert_tuple_to_cross_account::<T>(new_admin)?;315 // <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;313 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;316 // Ok(())314 Ok(())317 // }315 }318316319 // TODO: Temprorary off. Need refactor320 // /// Remove collection admin by substrate address.317 /// Remove collection admin.321 // /// @param admin Substrate administrator address.318 /// @param admin Cross account administrator address.322 // fn remove_collection_admin_substrate(319 fn remove_collection_admin_cross(323 // &mut self,320 &mut self,324 // caller: caller,321 caller: caller,325 // admin: uint256,322 admin: (address, uint256),326 // ) -> Result<void> {323 ) -> Result<void> {327 // self.consume_store_writes(2)?;324 self.consume_store_writes(2)?;328325329 // let caller = T::CrossAccountId::from_eth(caller);326 let caller = T::CrossAccountId::from_eth(caller);330 // let admin = convert_uint256_to_cross_account::<T>(admin);327 let admin = convert_tuple_to_cross_account::<T>(admin)?;331 // <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;328 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;332 // Ok(())329 Ok(())333 // }330 }334331335 /// Add collection admin.332 /// Add collection admin.336 /// @param newAdmin Address of the added administrator.333 /// @param newAdmin Address of the added administrator.479 Ok(())476 Ok(())480 }477 }481478482 // TODO: Temprorary off. Need refactor483 // /// Add substrate user to allowed list.479 /// Add user to allowed list.484 // ///480 ///485 // /// @param user User substrate address.481 /// @param user User cross account address.486 // fn add_to_collection_allow_list_substrate(482 fn add_to_collection_allow_list_cross(487 // &mut self,483 &mut self,488 // caller: caller,484 caller: caller,489 // user: uint256,485 user: (address, uint256),490 // ) -> Result<void> {486 ) -> Result<void> {491 // self.consume_store_writes(1)?;487 self.consume_store_writes(1)?;492488493 // let caller = T::CrossAccountId::from_eth(caller);489 let caller = T::CrossAccountId::from_eth(caller);494 // let user = convert_uint256_to_cross_account::<T>(user);490 let user = convert_tuple_to_cross_account::<T>(user)?;495 // Pallet::<T>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;491 Pallet::<T>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;496 // Ok(())492 Ok(())497 // }493 }498494499 /// Remove the user from the allowed list.495 /// Remove the user from the allowed list.500 ///496 ///508 Ok(())504 Ok(())509 }505 }510506511 // TODO: Temprorary off. Need refactor512 // /// Remove substrate user from allowed list.507 /// Remove user from allowed list.513 // ///508 ///514 // /// @param user User substrate address.509 /// @param user User cross account address.515 // fn remove_from_collection_allow_list_substrate(510 fn remove_from_collection_allow_list_cross(516 // &mut self,511 &mut self,517 // caller: caller,512 caller: caller,518 // user: uint256,513 user: (address, uint256),519 // ) -> Result<void> {514 ) -> Result<void> {520 // self.consume_store_writes(1)?;515 self.consume_store_writes(1)?;521516522 // let caller = T::CrossAccountId::from_eth(caller);517 let caller = T::CrossAccountId::from_eth(caller);523 // let user = convert_uint256_to_cross_account::<T>(user);518 let user = convert_tuple_to_cross_account::<T>(user)?;524 // Pallet::<T>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;519 Pallet::<T>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;525 // Ok(())520 Ok(())526 // }521 }527522528 /// Switch permission for minting.523 /// Switch permission for minting.529 ///524 ///556 Ok(self.is_owner_or_admin(&user))551 Ok(self.is_owner_or_admin(&user))557 }552 }558553559 // TODO: Temprorary off. Need refactor560 // /// Check that substrate account is the owner or admin of the collection554 /// Check that account is the owner or admin of the collection561 // ///555 ///562 // /// @param user account to verify556 /// @param user User cross account to verify563 // /// @return "true" if account is the owner or admin557 /// @return "true" if account is the owner or admin564 // fn is_owner_or_admin_substrate(&self, user: uint256) -> Result<bool> {558 fn is_owner_or_admin_cross(&self, user: (address, uint256)) -> Result<bool> {565 // let user = convert_uint256_to_cross_account::<T>(user);559 let user = convert_tuple_to_cross_account::<T>(user)?;566 // Ok(self.is_owner_or_admin(&user))560 Ok(self.is_owner_or_admin(&user))567 // }561 }568562569 /// Returns collection type563 /// Returns collection type570 ///564 ///580574581 /// Get collection owner.575 /// Get collection owner.582 ///576 ///583 /// @return Tuple with sponsor address and his substrate mirror.577 /// @return Tuble with sponsor address and his substrate mirror.584 /// If address is canonical then substrate mirror is zero and vice versa.578 /// If address is canonical then substrate mirror is zero and vice versa.585 fn collection_owner(&self) -> Result<(address, uint256)> {579 fn collection_owner(&self) -> Result<(address, uint256)> {586 Ok(convert_cross_account_to_tuple::<T>(580 Ok(convert_cross_account_to_tuple::<T>(602 .map_err(dispatch_to_evm::<T>)596 .map_err(dispatch_to_evm::<T>)603 }597 }604605 // TODO: Temprorary off. Need refactor606 // /// Changes collection owner to another substrate account607 // ///608 // /// @dev Owner can be changed only by current owner609 // /// @param newOwner new owner substrate account610 // fn set_owner_substrate(&mut self, caller: caller, new_owner: uint256) -> Result<void> {611 // self.consume_store_writes(1)?;612613 // let caller = T::CrossAccountId::from_eth(caller);614 // let new_owner = convert_uint256_to_cross_account::<T>(new_owner);615 // self.set_owner_internal(caller, new_owner)616 // .map_err(dispatch_to_evm::<T>)617 // }618598619 /// Get collection administrators599 /// Get collection administrators620 ///600 ///627 Ok(result)607 Ok(result)628 }608 }609610 /// Changes collection owner to another account611 ///612 /// @dev Owner can be changed only by current owner613 /// @param newOwner new owner cross account614 fn set_owner_cross(&mut self, caller: caller, new_owner: (address, uint256)) -> Result<void> {615 self.consume_store_writes(1)?;616617 let caller = T::CrossAccountId::from_eth(caller);618 let new_owner = convert_tuple_to_cross_account::<T>(new_owner)?;619 self.set_owner_internal(caller, new_owner)620 .map_err(dispatch_to_evm::<T>)621 }629}622}630623631/// ### Note624/// ### Notepallets/common/src/eth.rsdiffbeforeafterboth86 }86 }87}87}8889/// Convert tuple `(address, uint256)` to `CrossAccountId`.90///91/// If `address` in the tuple has *default* value, then the canonical form is substrate,92/// if `uint256` has *default* value, then the ethereum form is canonical,93/// if both values are *default* or *non default*, then this is considered an invalid address and `Error` is returned.94pub fn convert_tuple_to_cross_account<T: Config>(95 eth_cross_account_id: (address, uint256),96) -> evm_coder::execution::Result<T::CrossAccountId>97where98 T::AccountId: From<[u8; 32]>,99{100 if eth_cross_account_id == Default::default() {101 Err("All fields of cross account is zeroed".into())102 } else if eth_cross_account_id.0 == Default::default() {103 Ok(convert_uint256_to_cross_account::<T>(104 eth_cross_account_id.1,105 ))106 } else if eth_cross_account_id.1 == Default::default() {107 Ok(T::CrossAccountId::from_eth(eth_cross_account_id.0))108 } else {109 Err("All fields of cross account is non zeroed".into())110 }111}88112pallets/fungible/src/erc.rsdiffbeforeafterboth19use core::char::{REPLACEMENT_CHARACTER, decode_utf16};19use core::char::{REPLACEMENT_CHARACTER, decode_utf16};20use core::convert::TryInto;20use core::convert::TryInto;21use evm_coder::{ToLog, execution::*, generate_stubgen, solidity_interface, types::*, weight};21use evm_coder::{ToLog, execution::*, generate_stubgen, solidity_interface, types::*, weight};22use pallet_common::eth::convert_tuple_to_cross_account;22use up_data_structs::CollectionMode;23use up_data_structs::CollectionMode;23use pallet_common::erc::{CommonEvmHandler, PrecompileResult};24use pallet_common::erc::{CommonEvmHandler, PrecompileResult};24use sp_std::vec::Vec;25use sp_std::vec::Vec;150151151#[solidity_interface(name = ERC20UniqueExtensions)]152#[solidity_interface(name = ERC20UniqueExtensions)]152impl<T: Config> FungibleHandle<T> {153impl<T: Config> FungibleHandle<T>154where155 T::AccountId: From<[u8; 32]>,156{157 #[weight(<SelfWeightOf<T>>::approve())]158 fn approve_cross(159 &mut self,160 caller: caller,161 spender: (address, uint256),162 amount: uint256,163 ) -> Result<bool> {164 let caller = T::CrossAccountId::from_eth(caller);165 let spender = convert_tuple_to_cross_account::<T>(spender)?;166 let amount = amount.try_into().map_err(|_| "amount overflow")?;167168 <Pallet<T>>::set_allowance(self, &caller, &spender, amount)169 .map_err(dispatch_to_evm::<T>)?;170 Ok(true)171 }172153 /// Burn tokens from account173 /// Burn tokens from account154 /// @dev Function that burns an `amount` of the tokens of a given account,174 /// @dev Function that burns an `amount` of the tokens of a given account,169 Ok(true)189 Ok(true)170 }190 }191192 /// Burn tokens from account193 /// @dev Function that burns an `amount` of the tokens of a given account,194 /// deducting from the sender's allowance for said account.195 /// @param from The account whose tokens will be burnt.196 /// @param amount The amount that will be burnt.197 #[weight(<SelfWeightOf<T>>::burn_from())]198 fn burn_from_cross(199 &mut self,200 caller: caller,201 from: (address, uint256),202 amount: uint256,203 ) -> Result<bool> {204 let caller = T::CrossAccountId::from_eth(caller);205 let from = convert_tuple_to_cross_account::<T>(from)?;206 let amount = amount.try_into().map_err(|_| "amount overflow")?;207 let budget = self208 .recorder209 .weight_calls_budget(<StructureWeight<T>>::find_parent());210211 <Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)212 .map_err(dispatch_to_evm::<T>)?;213 Ok(true)214 }171215172 /// Mint tokens for multiple accounts.216 /// Mint tokens for multiple accounts.173 /// @param amounts array of pairs of account address and amount217 /// @param amounts array of pairs of account address and amount192 Ok(true)236 Ok(true)193 }237 }238239 #[weight(<SelfWeightOf<T>>::transfer_from())]240 fn transfer_from_cross(241 &mut self,242 caller: caller,243 from: (address, uint256),244 to: (address, uint256),245 amount: uint256,246 ) -> Result<bool> {247 let caller = T::CrossAccountId::from_eth(caller);248 let from = convert_tuple_to_cross_account::<T>(from)?;249 let to = convert_tuple_to_cross_account::<T>(to)?;250 let amount = amount.try_into().map_err(|_| "amount overflow")?;251 let budget = self252 .recorder253 .weight_calls_budget(<StructureWeight<T>>::find_parent());254255 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)256 .map_err(dispatch_to_evm::<T>)?;257 Ok(true)258 }194}259}195260196#[solidity_interface(261#[solidity_interface(pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth18}18}191920/// @title A contract that allows you to work with collections.20/// @title A contract that allows you to work with collections.21/// @dev the ERC-165 identifier for this interface is 0x3af103fb21/// @dev the ERC-165 identifier for this interface is 0x25d897dc22contract Collection is Dummy, ERC165 {22contract Collection is Dummy, ERC165 {23 /// Set collection property.23 /// Set collection property.24 ///24 ///72 dummy = 0;72 dummy = 0;73 }73 }7475 /// Set the sponsor of the collection.76 ///77 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.78 ///79 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.80 /// @dev EVM selector for this function is: 0x84a1d5a8,81 /// or in textual repr: setCollectionSponsorCross((address,uint256))82 function setCollectionSponsorCross(Tuple6 memory sponsor) public {83 require(false, stub_error);84 sponsor;85 dummy = 0;86 }748775 /// Whether there is a pending sponsor.88 /// Whether there is a pending sponsor.76 /// @dev EVM selector for this function is: 0x058ac185,89 /// @dev EVM selector for this function is: 0x058ac185,154 return 0x0000000000000000000000000000000000000000;167 return 0x0000000000000000000000000000000000000000;155 }168 }169170 /// Add collection admin.171 /// @param newAdmin Cross account administrator address.172 /// @dev EVM selector for this function is: 0x859aa7d6,173 /// or in textual repr: addCollectionAdminCross((address,uint256))174 function addCollectionAdminCross(Tuple6 memory newAdmin) public {175 require(false, stub_error);176 newAdmin;177 dummy = 0;178 }179180 /// Remove collection admin.181 /// @param admin Cross account administrator address.182 /// @dev EVM selector for this function is: 0x6c0cd173,183 /// or in textual repr: removeCollectionAdminCross((address,uint256))184 function removeCollectionAdminCross(Tuple6 memory admin) public {185 require(false, stub_error);186 admin;187 dummy = 0;188 }156189157 /// Add collection admin.190 /// Add collection admin.158 /// @param newAdmin Address of the added administrator.191 /// @param newAdmin Address of the added administrator.234 dummy = 0;267 dummy = 0;235 }268 }269270 /// Add user to allowed list.271 ///272 /// @param user User cross account address.273 /// @dev EVM selector for this function is: 0xa0184a3a,274 /// or in textual repr: addToCollectionAllowListCross((address,uint256))275 function addToCollectionAllowListCross(Tuple6 memory user) public {276 require(false, stub_error);277 user;278 dummy = 0;279 }236280237 /// Remove the user from the allowed list.281 /// Remove the user from the allowed list.238 ///282 ///245 dummy = 0;289 dummy = 0;246 }290 }291292 /// Remove user from allowed list.293 ///294 /// @param user User cross account address.295 /// @dev EVM selector for this function is: 0x09ba452a,296 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))297 function removeFromCollectionAllowListCross(Tuple6 memory user) public {298 require(false, stub_error);299 user;300 dummy = 0;301 }247302248 /// Switch permission for minting.303 /// Switch permission for minting.249 ///304 ///269 return false;324 return false;270 }325 }326327 /// Check that account is the owner or admin of the collection328 ///329 /// @param user User cross account to verify330 /// @return "true" if account is the owner or admin331 /// @dev EVM selector for this function is: 0x3e75a905,332 /// or in textual repr: isOwnerOrAdminCross((address,uint256))333 function isOwnerOrAdminCross(Tuple6 memory user) public view returns (bool) {334 require(false, stub_error);335 user;336 dummy;337 return false;338 }271339272 /// Returns collection type340 /// Returns collection type273 ///341 ///282350283 /// Get collection owner.351 /// Get collection owner.284 ///352 ///285 /// @return Tuple with sponsor address and his substrate mirror.353 /// @return Tuble with sponsor address and his substrate mirror.286 /// If address is canonical then substrate mirror is zero and vice versa.354 /// If address is canonical then substrate mirror is zero and vice versa.287 /// @dev EVM selector for this function is: 0xdf727d3b,355 /// @dev EVM selector for this function is: 0xdf727d3b,288 /// or in textual repr: collectionOwner()356 /// or in textual repr: collectionOwner()316 return new Tuple6[](0);384 return new Tuple6[](0);317 }385 }386387 /// Changes collection owner to another account388 ///389 /// @dev Owner can be changed only by current owner390 /// @param newOwner new owner cross account391 /// @dev EVM selector for this function is: 0xe5c9913f,392 /// or in textual repr: setOwnerCross((address,uint256))393 function setOwnerCross(Tuple6 memory newOwner) public {394 require(false, stub_error);395 newOwner;396 dummy = 0;397 }318}398}319399320/// @dev the ERC-165 identifier for this interface is 0x63034ac5400/// @dev the ERC-165 identifier for this interface is 0x032e5926321contract ERC20UniqueExtensions is Dummy, ERC165 {401contract ERC20UniqueExtensions is Dummy, ERC165 {402 /// @dev EVM selector for this function is: 0x0ecd0ab0,403 /// or in textual repr: approveCross((address,uint256),uint256)404 function approveCross(Tuple6 memory spender, uint256 amount) public returns (bool) {405 require(false, stub_error);406 spender;407 amount;408 dummy = 0;409 return false;410 }411322 /// Burn tokens from account412 /// Burn tokens from account323 /// @dev Function that burns an `amount` of the tokens of a given account,413 /// @dev Function that burns an `amount` of the tokens of a given account,334 return false;424 return false;335 }425 }426427 /// Burn tokens from account428 /// @dev Function that burns an `amount` of the tokens of a given account,429 /// deducting from the sender's allowance for said account.430 /// @param from The account whose tokens will be burnt.431 /// @param amount The amount that will be burnt.432 /// @dev EVM selector for this function is: 0xbb2f5a58,433 /// or in textual repr: burnFromCross((address,uint256),uint256)434 function burnFromCross(Tuple6 memory from, uint256 amount) public returns (bool) {435 require(false, stub_error);436 from;437 amount;438 dummy = 0;439 return false;440 }336441337 /// Mint tokens for multiple accounts.442 /// Mint tokens for multiple accounts.338 /// @param amounts array of pairs of account address and amount443 /// @param amounts array of pairs of account address and amount345 return false;450 return false;346 }451 }452453 /// @dev EVM selector for this function is: 0xd5cf430b,454 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)455 function transferFromCross(456 Tuple6 memory from,457 Tuple6 memory to,458 uint256 amount459 ) public returns (bool) {460 require(false, stub_error);461 from;462 to;463 amount;464 dummy = 0;465 return false;466 }347}467}348468349/// @dev anonymous struct469/// @dev anonymous structpallets/nonfungible/src/erc.rsdiffbeforeafterboth35use pallet_common::{35use pallet_common::{36 erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},36 erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},37 CollectionHandle, CollectionPropertyPermissions,37 CollectionHandle, CollectionPropertyPermissions,38 eth::convert_tuple_to_cross_account,38};39};39use pallet_evm::{account::CrossAccountId, PrecompileHandle};40use pallet_evm::{account::CrossAccountId, PrecompileHandle};40use pallet_evm_coder_substrate::call;41use pallet_evm_coder_substrate::call;199/// @dev See https://eips.ethereum.org/EIPS/eip-721200/// @dev See https://eips.ethereum.org/EIPS/eip-721200#[solidity_interface(name = ERC721Metadata, expect_selector = 0x5b5e139f)]201#[solidity_interface(name = ERC721Metadata, expect_selector = 0x5b5e139f)]201impl<T: Config> NonfungibleHandle<T> {202impl<T: Config> NonfungibleHandle<T>203where204 T::AccountId: From<[u8; 32]>,205{202 /// @notice A descriptive name for a collection of NFTs in this contract206 /// @notice A descriptive name for a collection of NFTs in this contract203 /// @dev real implementation of this function lies in `ERC721UniqueExtensions`207 /// @dev real implementation of this function lies in `ERC721UniqueExtensions`604/// @title Unique extensions for ERC721.608/// @title Unique extensions for ERC721.605#[solidity_interface(name = ERC721UniqueExtensions)]609#[solidity_interface(name = ERC721UniqueExtensions)]606impl<T: Config> NonfungibleHandle<T> {610impl<T: Config> NonfungibleHandle<T>611where612 T::AccountId: From<[u8; 32]>,613{607 /// @notice A descriptive name for a collection of NFTs in this contract614 /// @notice A descriptive name for a collection of NFTs in this contract608 fn name(&self) -> Result<string> {615 fn name(&self) -> Result<string> {616 Ok(string::from_utf8_lossy(&self.token_prefix).into())623 Ok(string::from_utf8_lossy(&self.token_prefix).into())617 }624 }625626 /// @notice Set or reaffirm the approved address for an NFT627 /// @dev The zero address indicates there is no approved address.628 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized629 /// operator of the current owner.630 /// @param approved The new substrate address approved NFT controller631 /// @param tokenId The NFT to approve632 #[weight(<SelfWeightOf<T>>::approve())]633 fn approve_cross(634 &mut self,635 caller: caller,636 approved: (address, uint256),637 token_id: uint256,638 ) -> Result<void> {639 let caller = T::CrossAccountId::from_eth(caller);640 let approved = convert_tuple_to_cross_account::<T>(approved)?;641 let token = token_id.try_into()?;642643 <Pallet<T>>::set_allowance(self, &caller, token, Some(&approved))644 .map_err(dispatch_to_evm::<T>)?;645 Ok(())646 }618647619 /// @notice Transfer ownership of an NFT648 /// @notice Transfer ownership of an NFT620 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`649 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`634 Ok(())663 Ok(())635 }664 }665666 /// @notice Transfer ownership of an NFT from cross account address to cross account address667 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`668 /// is the zero address. Throws if `tokenId` is not a valid NFT.669 /// @param from Cross acccount address of current owner670 /// @param to Cross acccount address of new owner671 /// @param tokenId The NFT to transfer672 #[weight(<SelfWeightOf<T>>::transfer())]673 fn transfer_from_cross(674 &mut self,675 caller: caller,676 from: (address, uint256),677 to: (address, uint256),678 token_id: uint256,679 ) -> Result<void> {680 let caller = T::CrossAccountId::from_eth(caller);681 let from = convert_tuple_to_cross_account::<T>(from)?;682 let to = convert_tuple_to_cross_account::<T>(to)?;683 let token_id = token_id.try_into()?;684 let budget = self685 .recorder686 .weight_calls_budget(<StructureWeight<T>>::find_parent());687 Pallet::<T>::transfer_from(self, &caller, &from, &to, token_id, &budget)688 .map_err(dispatch_to_evm::<T>)?;689 Ok(())690 }636691637 /// @notice Burns a specific ERC721 token.692 /// @notice Burns a specific ERC721 token.638 /// @dev Throws unless `msg.sender` is the current owner or an authorized693 /// @dev Throws unless `msg.sender` is the current owner or an authorized654 Ok(())709 Ok(())655 }710 }711712 /// @notice Burns a specific ERC721 token.713 /// @dev Throws unless `msg.sender` is the current owner or an authorized714 /// operator for this NFT. Throws if `from` is not the current owner. Throws715 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.716 /// @param from The current owner of the NFT717 /// @param tokenId The NFT to transfer718 #[weight(<SelfWeightOf<T>>::burn_from())]719 fn burn_from_cross(720 &mut self,721 caller: caller,722 from: (address, uint256),723 token_id: uint256,724 ) -> Result<void> {725 let caller = T::CrossAccountId::from_eth(caller);726 let from = convert_tuple_to_cross_account::<T>(from)?;727 let token = token_id.try_into()?;728 let budget = self729 .recorder730 .weight_calls_budget(<StructureWeight<T>>::find_parent());731732 <Pallet<T>>::burn_from(self, &caller, &from, token, &budget)733 .map_err(dispatch_to_evm::<T>)?;734 Ok(())735 }656736657 /// @notice Returns next free NFT ID.737 /// @notice Returns next free NFT ID.658 fn next_token_id(&self) -> Result<uint256> {738 fn next_token_id(&self) -> Result<uint256> {pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth91}91}929293/// @title A contract that allows you to work with collections.93/// @title A contract that allows you to work with collections.94/// @dev the ERC-165 identifier for this interface is 0x3af103fb94/// @dev the ERC-165 identifier for this interface is 0x25d897dc95contract Collection is Dummy, ERC165 {95contract Collection is Dummy, ERC165 {96 /// Set collection property.96 /// Set collection property.97 ///97 ///145 dummy = 0;145 dummy = 0;146 }146 }147148 /// Set the sponsor of the collection.149 ///150 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.151 ///152 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.153 /// @dev EVM selector for this function is: 0x84a1d5a8,154 /// or in textual repr: setCollectionSponsorCross((address,uint256))155 function setCollectionSponsorCross(Tuple6 memory sponsor) public {156 require(false, stub_error);157 sponsor;158 dummy = 0;159 }147160148 /// Whether there is a pending sponsor.161 /// Whether there is a pending sponsor.149 /// @dev EVM selector for this function is: 0x058ac185,162 /// @dev EVM selector for this function is: 0x058ac185,177 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.190 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.178 /// @dev EVM selector for this function is: 0x6ec0a9f1,191 /// @dev EVM selector for this function is: 0x6ec0a9f1,179 /// or in textual repr: collectionSponsor()192 /// or in textual repr: collectionSponsor()180 function collectionSponsor() public view returns (Tuple17 memory) {193 function collectionSponsor() public view returns (Tuple6 memory) {181 require(false, stub_error);194 require(false, stub_error);182 dummy;195 dummy;183 return Tuple17(0x0000000000000000000000000000000000000000, 0);196 return Tuple6(0x0000000000000000000000000000000000000000, 0);184 }197 }185198186 /// Set limits for the collection.199 /// Set limits for the collection.227 return 0x0000000000000000000000000000000000000000;240 return 0x0000000000000000000000000000000000000000;228 }241 }242243 /// Add collection admin.244 /// @param newAdmin Cross account administrator address.245 /// @dev EVM selector for this function is: 0x859aa7d6,246 /// or in textual repr: addCollectionAdminCross((address,uint256))247 function addCollectionAdminCross(Tuple6 memory newAdmin) public {248 require(false, stub_error);249 newAdmin;250 dummy = 0;251 }252253 /// Remove collection admin.254 /// @param admin Cross account administrator address.255 /// @dev EVM selector for this function is: 0x6c0cd173,256 /// or in textual repr: removeCollectionAdminCross((address,uint256))257 function removeCollectionAdminCross(Tuple6 memory admin) public {258 require(false, stub_error);259 admin;260 dummy = 0;261 }229262230 /// Add collection admin.263 /// Add collection admin.231 /// @param newAdmin Address of the added administrator.264 /// @param newAdmin Address of the added administrator.307 dummy = 0;340 dummy = 0;308 }341 }342343 /// Add user to allowed list.344 ///345 /// @param user User cross account address.346 /// @dev EVM selector for this function is: 0xa0184a3a,347 /// or in textual repr: addToCollectionAllowListCross((address,uint256))348 function addToCollectionAllowListCross(Tuple6 memory user) public {349 require(false, stub_error);350 user;351 dummy = 0;352 }309353310 /// Remove the user from the allowed list.354 /// Remove the user from the allowed list.311 ///355 ///318 dummy = 0;362 dummy = 0;319 }363 }364365 /// Remove user from allowed list.366 ///367 /// @param user User cross account address.368 /// @dev EVM selector for this function is: 0x09ba452a,369 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))370 function removeFromCollectionAllowListCross(Tuple6 memory user) public {371 require(false, stub_error);372 user;373 dummy = 0;374 }320375321 /// Switch permission for minting.376 /// Switch permission for minting.322 ///377 ///342 return false;397 return false;343 }398 }399400 /// Check that account is the owner or admin of the collection401 ///402 /// @param user User cross account to verify403 /// @return "true" if account is the owner or admin404 /// @dev EVM selector for this function is: 0x3e75a905,405 /// or in textual repr: isOwnerOrAdminCross((address,uint256))406 function isOwnerOrAdminCross(Tuple6 memory user) public view returns (bool) {407 require(false, stub_error);408 user;409 dummy;410 return false;411 }344412345 /// Returns collection type413 /// Returns collection type346 ///414 ///355423356 /// Get collection owner.424 /// Get collection owner.357 ///425 ///358 /// @return Tuple with sponsor address and his substrate mirror.426 /// @return Tuble with sponsor address and his substrate mirror.359 /// If address is canonical then substrate mirror is zero and vice versa.427 /// If address is canonical then substrate mirror is zero and vice versa.360 /// @dev EVM selector for this function is: 0xdf727d3b,428 /// @dev EVM selector for this function is: 0xdf727d3b,361 /// or in textual repr: collectionOwner()429 /// or in textual repr: collectionOwner()362 function collectionOwner() public view returns (Tuple17 memory) {430 function collectionOwner() public view returns (Tuple6 memory) {363 require(false, stub_error);431 require(false, stub_error);364 dummy;432 dummy;365 return Tuple17(0x0000000000000000000000000000000000000000, 0);433 return Tuple6(0x0000000000000000000000000000000000000000, 0);366 }434 }367435368 /// Changes collection owner to another account436 /// Changes collection owner to another account383 /// If address is canonical then substrate mirror is zero and vice versa.451 /// If address is canonical then substrate mirror is zero and vice versa.384 /// @dev EVM selector for this function is: 0x5813216b,452 /// @dev EVM selector for this function is: 0x5813216b,385 /// or in textual repr: collectionAdmins()453 /// or in textual repr: collectionAdmins()386 function collectionAdmins() public view returns (Tuple17[] memory) {454 function collectionAdmins() public view returns (Tuple6[] memory) {387 require(false, stub_error);455 require(false, stub_error);388 dummy;456 dummy;389 return new Tuple17[](0);457 return new Tuple6[](0);390 }458 }459460 /// Changes collection owner to another account461 ///462 /// @dev Owner can be changed only by current owner463 /// @param newOwner new owner cross account464 /// @dev EVM selector for this function is: 0xe5c9913f,465 /// or in textual repr: setOwnerCross((address,uint256))466 function setOwnerCross(Tuple6 memory newOwner) public {467 require(false, stub_error);468 newOwner;469 dummy = 0;470 }391}471}392393/// @dev anonymous struct394struct Tuple17 {395 address field_0;396 uint256 field_1;397}398472399/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension473/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension400/// @dev See https://eips.ethereum.org/EIPS/eip-721474/// @dev See https://eips.ethereum.org/EIPS/eip-721540}614}541615542/// @title Unique extensions for ERC721.616/// @title Unique extensions for ERC721.543/// @dev the ERC-165 identifier for this interface is 0x4468500d617/// @dev the ERC-165 identifier for this interface is 0x244543ee544contract ERC721UniqueExtensions is Dummy, ERC165 {618contract ERC721UniqueExtensions is Dummy, ERC165 {545 /// @notice A descriptive name for a collection of NFTs in this contract619 /// @notice A descriptive name for a collection of NFTs in this contract546 /// @dev EVM selector for this function is: 0x06fdde03,620 /// @dev EVM selector for this function is: 0x06fdde03,560 return "";634 return "";561 }635 }636637 /// @notice Set or reaffirm the approved address for an NFT638 /// @dev The zero address indicates there is no approved address.639 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized640 /// operator of the current owner.641 /// @param approved The new substrate address approved NFT controller642 /// @param tokenId The NFT to approve643 /// @dev EVM selector for this function is: 0x0ecd0ab0,644 /// or in textual repr: approveCross((address,uint256),uint256)645 function approveCross(Tuple6 memory approved, uint256 tokenId) public {646 require(false, stub_error);647 approved;648 tokenId;649 dummy = 0;650 }562651563 /// @notice Transfer ownership of an NFT652 /// @notice Transfer ownership of an NFT564 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`653 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`574 dummy = 0;663 dummy = 0;575 }664 }665666 /// @notice Transfer ownership of an NFT from cross account address to cross account address667 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`668 /// is the zero address. Throws if `tokenId` is not a valid NFT.669 /// @param from Cross acccount address of current owner670 /// @param to Cross acccount address of new owner671 /// @param tokenId The NFT to transfer672 /// @dev EVM selector for this function is: 0xd5cf430b,673 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)674 function transferFromCross(675 Tuple6 memory from,676 Tuple6 memory to,677 uint256 tokenId678 ) public {679 require(false, stub_error);680 from;681 to;682 tokenId;683 dummy = 0;684 }576685577 /// @notice Burns a specific ERC721 token.686 /// @notice Burns a specific ERC721 token.578 /// @dev Throws unless `msg.sender` is the current owner or an authorized687 /// @dev Throws unless `msg.sender` is the current owner or an authorized589 dummy = 0;698 dummy = 0;590 }699 }700701 /// @notice Burns a specific ERC721 token.702 /// @dev Throws unless `msg.sender` is the current owner or an authorized703 /// operator for this NFT. Throws if `from` is not the current owner. Throws704 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.705 /// @param from The current owner of the NFT706 /// @param tokenId The NFT to transfer707 /// @dev EVM selector for this function is: 0xbb2f5a58,708 /// or in textual repr: burnFromCross((address,uint256),uint256)709 function burnFromCross(Tuple6 memory from, uint256 tokenId) public {710 require(false, stub_error);711 from;712 tokenId;713 dummy = 0;714 }591715592 /// @notice Returns next free NFT ID.716 /// @notice Returns next free NFT ID.593 /// @dev EVM selector for this function is: 0x75794a3c,717 /// @dev EVM selector for this function is: 0x75794a3c,619 // /// @param tokens array of pairs of token ID and token URI for minted tokens743 // /// @param tokens array of pairs of token ID and token URI for minted tokens620 // /// @dev EVM selector for this function is: 0x36543006,744 // /// @dev EVM selector for this function is: 0x36543006,621 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])745 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])622 // function mintBulkWithTokenURI(address to, Tuple6[] memory tokens) public returns (bool) {746 // function mintBulkWithTokenURI(address to, Tuple8[] memory tokens) public returns (bool) {623 // require(false, stub_error);747 // require(false, stub_error);624 // to;748 // to;625 // tokens;749 // tokens;630}754}631755632/// @dev anonymous struct756/// @dev anonymous struct633struct Tuple6 {757struct Tuple8 {634 uint256 field_0;758 uint256 field_0;635 string field_1;759 string field_1;636}760}761762/// @dev anonymous struct763struct Tuple6 {764 address field_0;765 uint256 field_1;766}637767638/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension768/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension639/// @dev See https://eips.ethereum.org/EIPS/eip-721769/// @dev See https://eips.ethereum.org/EIPS/eip-721pallets/refungible/src/erc.rsdiffbeforeafterboth30use pallet_common::{30use pallet_common::{31 CollectionHandle, CollectionPropertyPermissions,31 CollectionHandle, CollectionPropertyPermissions,32 erc::{CommonEvmHandler, CollectionCall, static_property::key},32 erc::{CommonEvmHandler, CollectionCall, static_property::key},33 eth::convert_tuple_to_cross_account,33};34};34use pallet_evm::{account::CrossAccountId, PrecompileHandle};35use pallet_evm::{account::CrossAccountId, PrecompileHandle};35use pallet_evm_coder_substrate::{call, dispatch_to_evm};36use pallet_evm_coder_substrate::{call, dispatch_to_evm};195196196#[solidity_interface(name = ERC721Metadata)]197#[solidity_interface(name = ERC721Metadata)]197impl<T: Config> RefungibleHandle<T> {198impl<T: Config> RefungibleHandle<T>199where200 T::AccountId: From<[u8; 32]>,201{198 /// @notice A descriptive name for a collection of NFTs in this contract202 /// @notice A descriptive name for a collection of NFTs in this contract199 /// @dev real implementation of this function lies in `ERC721UniqueExtensions`203 /// @dev real implementation of this function lies in `ERC721UniqueExtensions`632/// @title Unique extensions for ERC721.636/// @title Unique extensions for ERC721.633#[solidity_interface(name = ERC721UniqueExtensions)]637#[solidity_interface(name = ERC721UniqueExtensions)]634impl<T: Config> RefungibleHandle<T> {638impl<T: Config> RefungibleHandle<T>639where640 T::AccountId: From<[u8; 32]>,641{635 /// @notice A descriptive name for a collection of NFTs in this contract642 /// @notice A descriptive name for a collection of NFTs in this contract636 fn name(&self) -> Result<string> {643 fn name(&self) -> Result<string> {659 .recorder666 .recorder660 .weight_calls_budget(<StructureWeight<T>>::find_parent());667 .weight_calls_budget(<StructureWeight<T>>::find_parent());661668662 let balance = balance(&self, token, &caller)?;669 let balance = balance(self, token, &caller)?;663 ensure_single_owner(&self, token, balance)?;670 ensure_single_owner(self, token, balance)?;664671665 <Pallet<T>>::transfer(self, &caller, &to, token, balance, &budget)672 <Pallet<T>>::transfer(self, &caller, &to, token, balance, &budget)666 .map_err(dispatch_to_evm::<T>)?;673 .map_err(dispatch_to_evm::<T>)?;667 Ok(())674 Ok(())668 }675 }676677 /// @notice Transfer ownership of an RFT678 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`679 /// is the zero address. Throws if `tokenId` is not a valid RFT.680 /// Throws if RFT pieces have multiple owners.681 /// @param to The new owner682 /// @param tokenId The RFT to transfer683 #[weight(<SelfWeightOf<T>>::transfer_creating_removing())]684 fn transfer_from_cross(685 &mut self,686 caller: caller,687 from: (address, uint256),688 to: (address, uint256),689 token_id: uint256,690 ) -> Result<void> {691 let caller = T::CrossAccountId::from_eth(caller);692 let from = convert_tuple_to_cross_account::<T>(from)?;693 let to = convert_tuple_to_cross_account::<T>(to)?;694 let token_id = token_id.try_into()?;695 let budget = self696 .recorder697 .weight_calls_budget(<StructureWeight<T>>::find_parent());698699 let balance = balance(self, token_id, &from)?;700 ensure_single_owner(self, token_id, balance)?;701702 Pallet::<T>::transfer_from(self, &caller, &from, &to, token_id, balance, &budget)703 .map_err(dispatch_to_evm::<T>)?;704 Ok(())705 }669706670 /// @notice Burns a specific ERC721 token.707 /// @notice Burns a specific ERC721 token.671 /// @dev Throws unless `msg.sender` is the current owner or an authorized708 /// @dev Throws unless `msg.sender` is the current owner or an authorized683 .recorder720 .recorder684 .weight_calls_budget(<StructureWeight<T>>::find_parent());721 .weight_calls_budget(<StructureWeight<T>>::find_parent());685722686 let balance = balance(&self, token, &caller)?;723 let balance = balance(self, token, &from)?;687 ensure_single_owner(&self, token, balance)?;724 ensure_single_owner(self, token, balance)?;688725689 <Pallet<T>>::burn_from(self, &caller, &from, token, balance, &budget)726 <Pallet<T>>::burn_from(self, &caller, &from, token, balance, &budget)690 .map_err(dispatch_to_evm::<T>)?;727 .map_err(dispatch_to_evm::<T>)?;691 Ok(())728 Ok(())692 }729 }730731 /// @notice Burns a specific ERC721 token.732 /// @dev Throws unless `msg.sender` is the current owner or an authorized733 /// operator for this RFT. Throws if `from` is not the current owner. Throws734 /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.735 /// Throws if RFT pieces have multiple owners.736 /// @param from The current owner of the RFT737 /// @param tokenId The RFT to transfer738 #[weight(<SelfWeightOf<T>>::burn_from())]739 fn burn_from_cross(740 &mut self,741 caller: caller,742 from: (address, uint256),743 token_id: uint256,744 ) -> Result<void> {745 let caller = T::CrossAccountId::from_eth(caller);746 let from = convert_tuple_to_cross_account::<T>(from)?;747 let token = token_id.try_into()?;748 let budget = self749 .recorder750 .weight_calls_budget(<StructureWeight<T>>::find_parent());751752 let balance = balance(self, token, &from)?;753 ensure_single_owner(self, token, balance)?;754755 <Pallet<T>>::burn_from(self, &caller, &from, token, balance, &budget)756 .map_err(dispatch_to_evm::<T>)?;757 Ok(())758 }693759694 /// @notice Returns next free RFT ID.760 /// @notice Returns next free RFT ID.695 fn next_token_id(&self) -> Result<uint256> {761 fn next_token_id(&self) -> Result<uint256> {pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth91}91}929293/// @title A contract that allows you to work with collections.93/// @title A contract that allows you to work with collections.94/// @dev the ERC-165 identifier for this interface is 0x3af103fb94/// @dev the ERC-165 identifier for this interface is 0x25d897dc95contract Collection is Dummy, ERC165 {95contract Collection is Dummy, ERC165 {96 /// Set collection property.96 /// Set collection property.97 ///97 ///145 dummy = 0;145 dummy = 0;146 }146 }147148 /// Set the sponsor of the collection.149 ///150 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.151 ///152 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.153 /// @dev EVM selector for this function is: 0x84a1d5a8,154 /// or in textual repr: setCollectionSponsorCross((address,uint256))155 function setCollectionSponsorCross(Tuple6 memory sponsor) public {156 require(false, stub_error);157 sponsor;158 dummy = 0;159 }147160148 /// Whether there is a pending sponsor.161 /// Whether there is a pending sponsor.149 /// @dev EVM selector for this function is: 0x058ac185,162 /// @dev EVM selector for this function is: 0x058ac185,177 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.190 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.178 /// @dev EVM selector for this function is: 0x6ec0a9f1,191 /// @dev EVM selector for this function is: 0x6ec0a9f1,179 /// or in textual repr: collectionSponsor()192 /// or in textual repr: collectionSponsor()180 function collectionSponsor() public view returns (Tuple17 memory) {193 function collectionSponsor() public view returns (Tuple6 memory) {181 require(false, stub_error);194 require(false, stub_error);182 dummy;195 dummy;183 return Tuple17(0x0000000000000000000000000000000000000000, 0);196 return Tuple6(0x0000000000000000000000000000000000000000, 0);184 }197 }185198186 /// Set limits for the collection.199 /// Set limits for the collection.227 return 0x0000000000000000000000000000000000000000;240 return 0x0000000000000000000000000000000000000000;228 }241 }242243 /// Add collection admin.244 /// @param newAdmin Cross account administrator address.245 /// @dev EVM selector for this function is: 0x859aa7d6,246 /// or in textual repr: addCollectionAdminCross((address,uint256))247 function addCollectionAdminCross(Tuple6 memory newAdmin) public {248 require(false, stub_error);249 newAdmin;250 dummy = 0;251 }252253 /// Remove collection admin.254 /// @param admin Cross account administrator address.255 /// @dev EVM selector for this function is: 0x6c0cd173,256 /// or in textual repr: removeCollectionAdminCross((address,uint256))257 function removeCollectionAdminCross(Tuple6 memory admin) public {258 require(false, stub_error);259 admin;260 dummy = 0;261 }229262230 /// Add collection admin.263 /// Add collection admin.231 /// @param newAdmin Address of the added administrator.264 /// @param newAdmin Address of the added administrator.307 dummy = 0;340 dummy = 0;308 }341 }342343 /// Add user to allowed list.344 ///345 /// @param user User cross account address.346 /// @dev EVM selector for this function is: 0xa0184a3a,347 /// or in textual repr: addToCollectionAllowListCross((address,uint256))348 function addToCollectionAllowListCross(Tuple6 memory user) public {349 require(false, stub_error);350 user;351 dummy = 0;352 }309353310 /// Remove the user from the allowed list.354 /// Remove the user from the allowed list.311 ///355 ///318 dummy = 0;362 dummy = 0;319 }363 }364365 /// Remove user from allowed list.366 ///367 /// @param user User cross account address.368 /// @dev EVM selector for this function is: 0x09ba452a,369 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))370 function removeFromCollectionAllowListCross(Tuple6 memory user) public {371 require(false, stub_error);372 user;373 dummy = 0;374 }320375321 /// Switch permission for minting.376 /// Switch permission for minting.322 ///377 ///342 return false;397 return false;343 }398 }399400 /// Check that account is the owner or admin of the collection401 ///402 /// @param user User cross account to verify403 /// @return "true" if account is the owner or admin404 /// @dev EVM selector for this function is: 0x3e75a905,405 /// or in textual repr: isOwnerOrAdminCross((address,uint256))406 function isOwnerOrAdminCross(Tuple6 memory user) public view returns (bool) {407 require(false, stub_error);408 user;409 dummy;410 return false;411 }344412345 /// Returns collection type413 /// Returns collection type346 ///414 ///355423356 /// Get collection owner.424 /// Get collection owner.357 ///425 ///358 /// @return Tuple with sponsor address and his substrate mirror.426 /// @return Tuble with sponsor address and his substrate mirror.359 /// If address is canonical then substrate mirror is zero and vice versa.427 /// If address is canonical then substrate mirror is zero and vice versa.360 /// @dev EVM selector for this function is: 0xdf727d3b,428 /// @dev EVM selector for this function is: 0xdf727d3b,361 /// or in textual repr: collectionOwner()429 /// or in textual repr: collectionOwner()362 function collectionOwner() public view returns (Tuple17 memory) {430 function collectionOwner() public view returns (Tuple6 memory) {363 require(false, stub_error);431 require(false, stub_error);364 dummy;432 dummy;365 return Tuple17(0x0000000000000000000000000000000000000000, 0);433 return Tuple6(0x0000000000000000000000000000000000000000, 0);366 }434 }367435368 /// Changes collection owner to another account436 /// Changes collection owner to another account383 /// If address is canonical then substrate mirror is zero and vice versa.451 /// If address is canonical then substrate mirror is zero and vice versa.384 /// @dev EVM selector for this function is: 0x5813216b,452 /// @dev EVM selector for this function is: 0x5813216b,385 /// or in textual repr: collectionAdmins()453 /// or in textual repr: collectionAdmins()386 function collectionAdmins() public view returns (Tuple17[] memory) {454 function collectionAdmins() public view returns (Tuple6[] memory) {387 require(false, stub_error);455 require(false, stub_error);388 dummy;456 dummy;389 return new Tuple17[](0);457 return new Tuple6[](0);390 }458 }459460 /// Changes collection owner to another account461 ///462 /// @dev Owner can be changed only by current owner463 /// @param newOwner new owner cross account464 /// @dev EVM selector for this function is: 0xe5c9913f,465 /// or in textual repr: setOwnerCross((address,uint256))466 function setOwnerCross(Tuple6 memory newOwner) public {467 require(false, stub_error);468 newOwner;469 dummy = 0;470 }391}471}392393/// @dev anonymous struct394struct Tuple17 {395 address field_0;396 uint256 field_1;397}398472399/// @dev the ERC-165 identifier for this interface is 0x5b5e139f473/// @dev the ERC-165 identifier for this interface is 0x5b5e139f400contract ERC721Metadata is Dummy, ERC165 {474contract ERC721Metadata is Dummy, ERC165 {538}612}539613540/// @title Unique extensions for ERC721.614/// @title Unique extensions for ERC721.541/// @dev the ERC-165 identifier for this interface is 0xef1eaacb615/// @dev the ERC-165 identifier for this interface is 0x81feb398542contract ERC721UniqueExtensions is Dummy, ERC165 {616contract ERC721UniqueExtensions is Dummy, ERC165 {543 /// @notice A descriptive name for a collection of NFTs in this contract617 /// @notice A descriptive name for a collection of NFTs in this contract544 /// @dev EVM selector for this function is: 0x06fdde03,618 /// @dev EVM selector for this function is: 0x06fdde03,573 dummy = 0;647 dummy = 0;574 }648 }649650 /// @notice Transfer ownership of an RFT651 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`652 /// is the zero address. Throws if `tokenId` is not a valid RFT.653 /// Throws if RFT pieces have multiple owners.654 /// @param to The new owner655 /// @param tokenId The RFT to transfer656 /// @dev EVM selector for this function is: 0xd5cf430b,657 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)658 function transferFromCross(659 Tuple6 memory from,660 Tuple6 memory to,661 uint256 tokenId662 ) public {663 require(false, stub_error);664 from;665 to;666 tokenId;667 dummy = 0;668 }575669576 /// @notice Burns a specific ERC721 token.670 /// @notice Burns a specific ERC721 token.577 /// @dev Throws unless `msg.sender` is the current owner or an authorized671 /// @dev Throws unless `msg.sender` is the current owner or an authorized589 dummy = 0;683 dummy = 0;590 }684 }685686 /// @notice Burns a specific ERC721 token.687 /// @dev Throws unless `msg.sender` is the current owner or an authorized688 /// operator for this RFT. Throws if `from` is not the current owner. Throws689 /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.690 /// Throws if RFT pieces have multiple owners.691 /// @param from The current owner of the RFT692 /// @param tokenId The RFT to transfer693 /// @dev EVM selector for this function is: 0xbb2f5a58,694 /// or in textual repr: burnFromCross((address,uint256),uint256)695 function burnFromCross(Tuple6 memory from, uint256 tokenId) public {696 require(false, stub_error);697 from;698 tokenId;699 dummy = 0;700 }591701592 /// @notice Returns next free RFT ID.702 /// @notice Returns next free RFT ID.593 /// @dev EVM selector for this function is: 0x75794a3c,703 /// @dev EVM selector for this function is: 0x75794a3c,620 // /// @param tokens array of pairs of token ID and token URI for minted tokens730 // /// @param tokens array of pairs of token ID and token URI for minted tokens621 // /// @dev EVM selector for this function is: 0x36543006,731 // /// @dev EVM selector for this function is: 0x36543006,622 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])732 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])623 // function mintBulkWithTokenURI(address to, Tuple6[] memory tokens) public returns (bool) {733 // function mintBulkWithTokenURI(address to, Tuple8[] memory tokens) public returns (bool) {624 // require(false, stub_error);734 // require(false, stub_error);625 // to;735 // to;626 // tokens;736 // tokens;642}752}643753644/// @dev anonymous struct754/// @dev anonymous struct645struct Tuple6 {755struct Tuple8 {646 uint256 field_0;756 uint256 field_0;647 string field_1;757 string field_1;648}758}759760/// @dev anonymous struct761struct Tuple6 {762 address field_0;763 uint256 field_1;764}649765650/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension766/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension651/// @dev See https://eips.ethereum.org/EIPS/eip-721767/// @dev See https://eips.ethereum.org/EIPS/eip-721tests/src/eth/allowlist.test.tsdiffbeforeafterboth89 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;89 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;90 });90 });919192 // TODO: Temprorary off. Need refactor93 // itEth('Collection allowlist can be added and removed by [sub] address', async ({helper}) => {92 //itEth('Collection allowlist can be added and removed by [cross] address', async ({helper}) => {94 // const owner = await helper.eth.createAccountWithBalance(donor);93 // const owner = await helper.eth.createAccountWithBalance(donor);95 // const user = donor;94 // const user = donor;9695 // 97 // const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');96 // const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');98 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);97 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);9998 // const userCross = helper.ethCrossAccount.fromKeyringPair(user);99 // 100 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;100 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;101 // await collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).send({from: owner});101 // await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner});102 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;102 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;103103 // 104 // await collectionEvm.methods.removeFromCollectionAllowListSubstrate(user.addressRaw).send({from: owner});104 // await collectionEvm.methods.removeFromCollectionAllowListCross(userCross).send({from: owner});105 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;105 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;106 // });106 //});107107108 itEth('Collection allowlist can not be add and remove [eth] address by not owner', async ({helper}) => {108 itEth('Collection allowlist can not be add and remove [eth] address by not owner', async ({helper}) => {109 const owner = await helper.eth.createAccountWithBalance(donor);109 const owner = await helper.eth.createAccountWithBalance(donor);123 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;122 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;124 });123 });125124126 // TODO: Temprorary off. Need refactor127 // itEth('Collection allowlist can not be add and remove [sub] address by not owner', async ({helper}) => {125 //itEth('Collection allowlist can not be add and remove [cross] address by not owner', async ({helper}) => {128 // const owner = await helper.eth.createAccountWithBalance(donor);126 // const owner = await helper.eth.createAccountWithBalance(donor);129 // const notOwner = await helper.eth.createAccountWithBalance(donor);127 // const notOwner = await helper.eth.createAccountWithBalance(donor);130 // const user = donor;128 // const user = donor;131129 // 132 // const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');130 // const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');133 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);131 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);134132 // 135 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;133 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;134 // const userCross = helper.ethCrossAccount.fromKeyringPair(user);136 // await expect(collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).call({from: notOwner})).to.be.rejectedWith('NoPermission');135 // await expect(collectionEvm.methods.addToCollectionAllowListCross(userCross).call({from: notOwner})).to.be.rejectedWith('NoPermission');137 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;136 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;138 // await collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).send({from: owner});137 // await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner});139138 // 140 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;139 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;141 // await expect(collectionEvm.methods.removeFromCollectionAllowListSubstrate(user.addressRaw).call({from: notOwner})).to.be.rejectedWith('NoPermission');140 // await expect(collectionEvm.methods.removeFromCollectionAllowListCross(userCross).call({from: notOwner})).to.be.rejectedWith('NoPermission');142 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;141 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;143 // });142 //});144});143});145144tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth13}13}141415/// @title A contract that allows you to work with collections.15/// @title A contract that allows you to work with collections.16/// @dev the ERC-165 identifier for this interface is 0x3af103fb16/// @dev the ERC-165 identifier for this interface is 0x25d897dc17interface Collection is Dummy, ERC165 {17interface Collection is Dummy, ERC165 {18 /// Set collection property.18 /// Set collection property.19 ///19 ///49 /// or in textual repr: setCollectionSponsor(address)49 /// or in textual repr: setCollectionSponsor(address)50 function setCollectionSponsor(address sponsor) external;50 function setCollectionSponsor(address sponsor) external;5152 /// Set the sponsor of the collection.53 ///54 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.55 ///56 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.57 /// @dev EVM selector for this function is: 0x84a1d5a8,58 /// or in textual repr: setCollectionSponsorCross((address,uint256))59 function setCollectionSponsorCross(Tuple6 memory sponsor) external;516052 /// Whether there is a pending sponsor.61 /// Whether there is a pending sponsor.53 /// @dev EVM selector for this function is: 0x058ac185,62 /// @dev EVM selector for this function is: 0x058ac185,103 /// or in textual repr: contractAddress()112 /// or in textual repr: contractAddress()104 function contractAddress() external view returns (address);113 function contractAddress() external view returns (address);114115 /// Add collection admin.116 /// @param newAdmin Cross account administrator address.117 /// @dev EVM selector for this function is: 0x859aa7d6,118 /// or in textual repr: addCollectionAdminCross((address,uint256))119 function addCollectionAdminCross(Tuple6 memory newAdmin) external;120121 /// Remove collection admin.122 /// @param admin Cross account administrator address.123 /// @dev EVM selector for this function is: 0x6c0cd173,124 /// or in textual repr: removeCollectionAdminCross((address,uint256))125 function removeCollectionAdminCross(Tuple6 memory admin) external;105126106 /// Add collection admin.127 /// Add collection admin.107 /// @param newAdmin Address of the added administrator.128 /// @param newAdmin Address of the added administrator.153 /// or in textual repr: addToCollectionAllowList(address)174 /// or in textual repr: addToCollectionAllowList(address)154 function addToCollectionAllowList(address user) external;175 function addToCollectionAllowList(address user) external;176177 /// Add user to allowed list.178 ///179 /// @param user User cross account address.180 /// @dev EVM selector for this function is: 0xa0184a3a,181 /// or in textual repr: addToCollectionAllowListCross((address,uint256))182 function addToCollectionAllowListCross(Tuple6 memory user) external;155183156 /// Remove the user from the allowed list.184 /// Remove the user from the allowed list.157 ///185 ///160 /// or in textual repr: removeFromCollectionAllowList(address)188 /// or in textual repr: removeFromCollectionAllowList(address)161 function removeFromCollectionAllowList(address user) external;189 function removeFromCollectionAllowList(address user) external;190191 /// Remove user from allowed list.192 ///193 /// @param user User cross account address.194 /// @dev EVM selector for this function is: 0x09ba452a,195 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))196 function removeFromCollectionAllowListCross(Tuple6 memory user) external;162197163 /// Switch permission for minting.198 /// Switch permission for minting.164 ///199 ///175 /// or in textual repr: isOwnerOrAdmin(address)210 /// or in textual repr: isOwnerOrAdmin(address)176 function isOwnerOrAdmin(address user) external view returns (bool);211 function isOwnerOrAdmin(address user) external view returns (bool);212213 /// Check that account is the owner or admin of the collection214 ///215 /// @param user User cross account to verify216 /// @return "true" if account is the owner or admin217 /// @dev EVM selector for this function is: 0x3e75a905,218 /// or in textual repr: isOwnerOrAdminCross((address,uint256))219 function isOwnerOrAdminCross(Tuple6 memory user) external view returns (bool);177220178 /// Returns collection type221 /// Returns collection type179 ///222 ///184227185 /// Get collection owner.228 /// Get collection owner.186 ///229 ///187 /// @return Tuple with sponsor address and his substrate mirror.230 /// @return Tuble with sponsor address and his substrate mirror.188 /// If address is canonical then substrate mirror is zero and vice versa.231 /// If address is canonical then substrate mirror is zero and vice versa.189 /// @dev EVM selector for this function is: 0xdf727d3b,232 /// @dev EVM selector for this function is: 0xdf727d3b,190 /// or in textual repr: collectionOwner()233 /// or in textual repr: collectionOwner()206 /// or in textual repr: collectionAdmins()249 /// or in textual repr: collectionAdmins()207 function collectionAdmins() external view returns (Tuple6[] memory);250 function collectionAdmins() external view returns (Tuple6[] memory);251252 /// Changes collection owner to another account253 ///254 /// @dev Owner can be changed only by current owner255 /// @param newOwner new owner cross account256 /// @dev EVM selector for this function is: 0xe5c9913f,257 /// or in textual repr: setOwnerCross((address,uint256))258 function setOwnerCross(Tuple6 memory newOwner) external;208}259}209260210/// @dev the ERC-165 identifier for this interface is 0x63034ac5261/// @dev the ERC-165 identifier for this interface is 0x032e5926211interface ERC20UniqueExtensions is Dummy, ERC165 {262interface ERC20UniqueExtensions is Dummy, ERC165 {263 /// @dev EVM selector for this function is: 0x0ecd0ab0,264 /// or in textual repr: approveCross((address,uint256),uint256)265 function approveCross(Tuple6 memory spender, uint256 amount) external returns (bool);266212 /// Burn tokens from account267 /// Burn tokens from account213 /// @dev Function that burns an `amount` of the tokens of a given account,268 /// @dev Function that burns an `amount` of the tokens of a given account,218 /// or in textual repr: burnFrom(address,uint256)273 /// or in textual repr: burnFrom(address,uint256)219 function burnFrom(address from, uint256 amount) external returns (bool);274 function burnFrom(address from, uint256 amount) external returns (bool);275276 /// Burn tokens from account277 /// @dev Function that burns an `amount` of the tokens of a given account,278 /// deducting from the sender's allowance for said account.279 /// @param from The account whose tokens will be burnt.280 /// @param amount The amount that will be burnt.281 /// @dev EVM selector for this function is: 0xbb2f5a58,282 /// or in textual repr: burnFromCross((address,uint256),uint256)283 function burnFromCross(Tuple6 memory from, uint256 amount) external returns (bool);220284221 /// Mint tokens for multiple accounts.285 /// Mint tokens for multiple accounts.222 /// @param amounts array of pairs of account address and amount286 /// @param amounts array of pairs of account address and amount223 /// @dev EVM selector for this function is: 0x1acf2d55,287 /// @dev EVM selector for this function is: 0x1acf2d55,224 /// or in textual repr: mintBulk((address,uint256)[])288 /// or in textual repr: mintBulk((address,uint256)[])225 function mintBulk(Tuple6[] memory amounts) external returns (bool);289 function mintBulk(Tuple6[] memory amounts) external returns (bool);290291 /// @dev EVM selector for this function is: 0xd5cf430b,292 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)293 function transferFromCross(294 Tuple6 memory from,295 Tuple6 memory to,296 uint256 amount297 ) external returns (bool);226}298}227299228/// @dev anonymous struct300/// @dev anonymous structtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth62}62}636364/// @title A contract that allows you to work with collections.64/// @title A contract that allows you to work with collections.65/// @dev the ERC-165 identifier for this interface is 0x3af103fb65/// @dev the ERC-165 identifier for this interface is 0x25d897dc66interface Collection is Dummy, ERC165 {66interface Collection is Dummy, ERC165 {67 /// Set collection property.67 /// Set collection property.68 ///68 ///98 /// or in textual repr: setCollectionSponsor(address)98 /// or in textual repr: setCollectionSponsor(address)99 function setCollectionSponsor(address sponsor) external;99 function setCollectionSponsor(address sponsor) external;100101 /// Set the sponsor of the collection.102 ///103 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.104 ///105 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.106 /// @dev EVM selector for this function is: 0x84a1d5a8,107 /// or in textual repr: setCollectionSponsorCross((address,uint256))108 function setCollectionSponsorCross(Tuple6 memory sponsor) external;100109101 /// Whether there is a pending sponsor.110 /// Whether there is a pending sponsor.102 /// @dev EVM selector for this function is: 0x058ac185,111 /// @dev EVM selector for this function is: 0x058ac185,120 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.129 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.121 /// @dev EVM selector for this function is: 0x6ec0a9f1,130 /// @dev EVM selector for this function is: 0x6ec0a9f1,122 /// or in textual repr: collectionSponsor()131 /// or in textual repr: collectionSponsor()123 function collectionSponsor() external view returns (Tuple17 memory);132 function collectionSponsor() external view returns (Tuple6 memory);124133125 /// Set limits for the collection.134 /// Set limits for the collection.126 /// @dev Throws error if limit not found.135 /// @dev Throws error if limit not found.152 /// or in textual repr: contractAddress()161 /// or in textual repr: contractAddress()153 function contractAddress() external view returns (address);162 function contractAddress() external view returns (address);163164 /// Add collection admin.165 /// @param newAdmin Cross account administrator address.166 /// @dev EVM selector for this function is: 0x859aa7d6,167 /// or in textual repr: addCollectionAdminCross((address,uint256))168 function addCollectionAdminCross(Tuple6 memory newAdmin) external;169170 /// Remove collection admin.171 /// @param admin Cross account administrator address.172 /// @dev EVM selector for this function is: 0x6c0cd173,173 /// or in textual repr: removeCollectionAdminCross((address,uint256))174 function removeCollectionAdminCross(Tuple6 memory admin) external;154175155 /// Add collection admin.176 /// Add collection admin.156 /// @param newAdmin Address of the added administrator.177 /// @param newAdmin Address of the added administrator.202 /// or in textual repr: addToCollectionAllowList(address)223 /// or in textual repr: addToCollectionAllowList(address)203 function addToCollectionAllowList(address user) external;224 function addToCollectionAllowList(address user) external;225226 /// Add user to allowed list.227 ///228 /// @param user User cross account address.229 /// @dev EVM selector for this function is: 0xa0184a3a,230 /// or in textual repr: addToCollectionAllowListCross((address,uint256))231 function addToCollectionAllowListCross(Tuple6 memory user) external;204232205 /// Remove the user from the allowed list.233 /// Remove the user from the allowed list.206 ///234 ///209 /// or in textual repr: removeFromCollectionAllowList(address)237 /// or in textual repr: removeFromCollectionAllowList(address)210 function removeFromCollectionAllowList(address user) external;238 function removeFromCollectionAllowList(address user) external;239240 /// Remove user from allowed list.241 ///242 /// @param user User cross account address.243 /// @dev EVM selector for this function is: 0x09ba452a,244 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))245 function removeFromCollectionAllowListCross(Tuple6 memory user) external;211246212 /// Switch permission for minting.247 /// Switch permission for minting.213 ///248 ///224 /// or in textual repr: isOwnerOrAdmin(address)259 /// or in textual repr: isOwnerOrAdmin(address)225 function isOwnerOrAdmin(address user) external view returns (bool);260 function isOwnerOrAdmin(address user) external view returns (bool);261262 /// Check that account is the owner or admin of the collection263 ///264 /// @param user User cross account to verify265 /// @return "true" if account is the owner or admin266 /// @dev EVM selector for this function is: 0x3e75a905,267 /// or in textual repr: isOwnerOrAdminCross((address,uint256))268 function isOwnerOrAdminCross(Tuple6 memory user) external view returns (bool);226269227 /// Returns collection type270 /// Returns collection type228 ///271 ///233276234 /// Get collection owner.277 /// Get collection owner.235 ///278 ///236 /// @return Tuple with sponsor address and his substrate mirror.279 /// @return Tuble with sponsor address and his substrate mirror.237 /// If address is canonical then substrate mirror is zero and vice versa.280 /// If address is canonical then substrate mirror is zero and vice versa.238 /// @dev EVM selector for this function is: 0xdf727d3b,281 /// @dev EVM selector for this function is: 0xdf727d3b,239 /// or in textual repr: collectionOwner()282 /// or in textual repr: collectionOwner()240 function collectionOwner() external view returns (Tuple17 memory);283 function collectionOwner() external view returns (Tuple6 memory);241284242 /// Changes collection owner to another account285 /// Changes collection owner to another account243 ///286 ///253 /// If address is canonical then substrate mirror is zero and vice versa.296 /// If address is canonical then substrate mirror is zero and vice versa.254 /// @dev EVM selector for this function is: 0x5813216b,297 /// @dev EVM selector for this function is: 0x5813216b,255 /// or in textual repr: collectionAdmins()298 /// or in textual repr: collectionAdmins()256 function collectionAdmins() external view returns (Tuple17[] memory);299 function collectionAdmins() external view returns (Tuple6[] memory);300301 /// Changes collection owner to another account302 ///303 /// @dev Owner can be changed only by current owner304 /// @param newOwner new owner cross account305 /// @dev EVM selector for this function is: 0xe5c9913f,306 /// or in textual repr: setOwnerCross((address,uint256))307 function setOwnerCross(Tuple6 memory newOwner) external;257}308}258259/// @dev anonymous struct260struct Tuple17 {261 address field_0;262 uint256 field_1;263}264309265/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension310/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension266/// @dev See https://eips.ethereum.org/EIPS/eip-721311/// @dev See https://eips.ethereum.org/EIPS/eip-721357}402}358403359/// @title Unique extensions for ERC721.404/// @title Unique extensions for ERC721.360/// @dev the ERC-165 identifier for this interface is 0x4468500d405/// @dev the ERC-165 identifier for this interface is 0x244543ee361interface ERC721UniqueExtensions is Dummy, ERC165 {406interface ERC721UniqueExtensions is Dummy, ERC165 {362 /// @notice A descriptive name for a collection of NFTs in this contract407 /// @notice A descriptive name for a collection of NFTs in this contract363 /// @dev EVM selector for this function is: 0x06fdde03,408 /// @dev EVM selector for this function is: 0x06fdde03,369 /// or in textual repr: symbol()414 /// or in textual repr: symbol()370 function symbol() external view returns (string memory);415 function symbol() external view returns (string memory);416417 /// @notice Set or reaffirm the approved address for an NFT418 /// @dev The zero address indicates there is no approved address.419 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized420 /// operator of the current owner.421 /// @param approved The new substrate address approved NFT controller422 /// @param tokenId The NFT to approve423 /// @dev EVM selector for this function is: 0x0ecd0ab0,424 /// or in textual repr: approveCross((address,uint256),uint256)425 function approveCross(Tuple6 memory approved, uint256 tokenId) external;371426372 /// @notice Transfer ownership of an NFT427 /// @notice Transfer ownership of an NFT373 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`428 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`378 /// or in textual repr: transfer(address,uint256)433 /// or in textual repr: transfer(address,uint256)379 function transfer(address to, uint256 tokenId) external;434 function transfer(address to, uint256 tokenId) external;435436 /// @notice Transfer ownership of an NFT from cross account address to cross account address437 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`438 /// is the zero address. Throws if `tokenId` is not a valid NFT.439 /// @param from Cross acccount address of current owner440 /// @param to Cross acccount address of new owner441 /// @param tokenId The NFT to transfer442 /// @dev EVM selector for this function is: 0xd5cf430b,443 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)444 function transferFromCross(445 Tuple6 memory from,446 Tuple6 memory to,447 uint256 tokenId448 ) external;380449381 /// @notice Burns a specific ERC721 token.450 /// @notice Burns a specific ERC721 token.382 /// @dev Throws unless `msg.sender` is the current owner or an authorized451 /// @dev Throws unless `msg.sender` is the current owner or an authorized388 /// or in textual repr: burnFrom(address,uint256)457 /// or in textual repr: burnFrom(address,uint256)389 function burnFrom(address from, uint256 tokenId) external;458 function burnFrom(address from, uint256 tokenId) external;459460 /// @notice Burns a specific ERC721 token.461 /// @dev Throws unless `msg.sender` is the current owner or an authorized462 /// operator for this NFT. Throws if `from` is not the current owner. Throws463 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.464 /// @param from The current owner of the NFT465 /// @param tokenId The NFT to transfer466 /// @dev EVM selector for this function is: 0xbb2f5a58,467 /// or in textual repr: burnFromCross((address,uint256),uint256)468 function burnFromCross(Tuple6 memory from, uint256 tokenId) external;390469391 /// @notice Returns next free NFT ID.470 /// @notice Returns next free NFT ID.392 /// @dev EVM selector for this function is: 0x75794a3c,471 /// @dev EVM selector for this function is: 0x75794a3c,408 // /// @param tokens array of pairs of token ID and token URI for minted tokens487 // /// @param tokens array of pairs of token ID and token URI for minted tokens409 // /// @dev EVM selector for this function is: 0x36543006,488 // /// @dev EVM selector for this function is: 0x36543006,410 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])489 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])411 // function mintBulkWithTokenURI(address to, Tuple6[] memory tokens) external returns (bool);490 // function mintBulkWithTokenURI(address to, Tuple8[] memory tokens) external returns (bool);412491413}492}414493415/// @dev anonymous struct494/// @dev anonymous struct416struct Tuple6 {495struct Tuple8 {417 uint256 field_0;496 uint256 field_0;418 string field_1;497 string field_1;419}498}499500/// @dev anonymous struct501struct Tuple6 {502 address field_0;503 uint256 field_1;504}420505421/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension506/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension422/// @dev See https://eips.ethereum.org/EIPS/eip-721507/// @dev See https://eips.ethereum.org/EIPS/eip-721tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth62}62}636364/// @title A contract that allows you to work with collections.64/// @title A contract that allows you to work with collections.65/// @dev the ERC-165 identifier for this interface is 0x3af103fb65/// @dev the ERC-165 identifier for this interface is 0x25d897dc66interface Collection is Dummy, ERC165 {66interface Collection is Dummy, ERC165 {67 /// Set collection property.67 /// Set collection property.68 ///68 ///98 /// or in textual repr: setCollectionSponsor(address)98 /// or in textual repr: setCollectionSponsor(address)99 function setCollectionSponsor(address sponsor) external;99 function setCollectionSponsor(address sponsor) external;100101 /// Set the sponsor of the collection.102 ///103 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.104 ///105 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.106 /// @dev EVM selector for this function is: 0x84a1d5a8,107 /// or in textual repr: setCollectionSponsorCross((address,uint256))108 function setCollectionSponsorCross(Tuple6 memory sponsor) external;100109101 /// Whether there is a pending sponsor.110 /// Whether there is a pending sponsor.102 /// @dev EVM selector for this function is: 0x058ac185,111 /// @dev EVM selector for this function is: 0x058ac185,120 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.129 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.121 /// @dev EVM selector for this function is: 0x6ec0a9f1,130 /// @dev EVM selector for this function is: 0x6ec0a9f1,122 /// or in textual repr: collectionSponsor()131 /// or in textual repr: collectionSponsor()123 function collectionSponsor() external view returns (Tuple17 memory);132 function collectionSponsor() external view returns (Tuple6 memory);124133125 /// Set limits for the collection.134 /// Set limits for the collection.126 /// @dev Throws error if limit not found.135 /// @dev Throws error if limit not found.152 /// or in textual repr: contractAddress()161 /// or in textual repr: contractAddress()153 function contractAddress() external view returns (address);162 function contractAddress() external view returns (address);163164 /// Add collection admin.165 /// @param newAdmin Cross account administrator address.166 /// @dev EVM selector for this function is: 0x859aa7d6,167 /// or in textual repr: addCollectionAdminCross((address,uint256))168 function addCollectionAdminCross(Tuple6 memory newAdmin) external;169170 /// Remove collection admin.171 /// @param admin Cross account administrator address.172 /// @dev EVM selector for this function is: 0x6c0cd173,173 /// or in textual repr: removeCollectionAdminCross((address,uint256))174 function removeCollectionAdminCross(Tuple6 memory admin) external;154175155 /// Add collection admin.176 /// Add collection admin.156 /// @param newAdmin Address of the added administrator.177 /// @param newAdmin Address of the added administrator.202 /// or in textual repr: addToCollectionAllowList(address)223 /// or in textual repr: addToCollectionAllowList(address)203 function addToCollectionAllowList(address user) external;224 function addToCollectionAllowList(address user) external;225226 /// Add user to allowed list.227 ///228 /// @param user User cross account address.229 /// @dev EVM selector for this function is: 0xa0184a3a,230 /// or in textual repr: addToCollectionAllowListCross((address,uint256))231 function addToCollectionAllowListCross(Tuple6 memory user) external;204232205 /// Remove the user from the allowed list.233 /// Remove the user from the allowed list.206 ///234 ///209 /// or in textual repr: removeFromCollectionAllowList(address)237 /// or in textual repr: removeFromCollectionAllowList(address)210 function removeFromCollectionAllowList(address user) external;238 function removeFromCollectionAllowList(address user) external;239240 /// Remove user from allowed list.241 ///242 /// @param user User cross account address.243 /// @dev EVM selector for this function is: 0x09ba452a,244 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))245 function removeFromCollectionAllowListCross(Tuple6 memory user) external;211246212 /// Switch permission for minting.247 /// Switch permission for minting.213 ///248 ///224 /// or in textual repr: isOwnerOrAdmin(address)259 /// or in textual repr: isOwnerOrAdmin(address)225 function isOwnerOrAdmin(address user) external view returns (bool);260 function isOwnerOrAdmin(address user) external view returns (bool);261262 /// Check that account is the owner or admin of the collection263 ///264 /// @param user User cross account to verify265 /// @return "true" if account is the owner or admin266 /// @dev EVM selector for this function is: 0x3e75a905,267 /// or in textual repr: isOwnerOrAdminCross((address,uint256))268 function isOwnerOrAdminCross(Tuple6 memory user) external view returns (bool);226269227 /// Returns collection type270 /// Returns collection type228 ///271 ///233276234 /// Get collection owner.277 /// Get collection owner.235 ///278 ///236 /// @return Tuple with sponsor address and his substrate mirror.279 /// @return Tuble with sponsor address and his substrate mirror.237 /// If address is canonical then substrate mirror is zero and vice versa.280 /// If address is canonical then substrate mirror is zero and vice versa.238 /// @dev EVM selector for this function is: 0xdf727d3b,281 /// @dev EVM selector for this function is: 0xdf727d3b,239 /// or in textual repr: collectionOwner()282 /// or in textual repr: collectionOwner()240 function collectionOwner() external view returns (Tuple17 memory);283 function collectionOwner() external view returns (Tuple6 memory);241284242 /// Changes collection owner to another account285 /// Changes collection owner to another account243 ///286 ///253 /// If address is canonical then substrate mirror is zero and vice versa.296 /// If address is canonical then substrate mirror is zero and vice versa.254 /// @dev EVM selector for this function is: 0x5813216b,297 /// @dev EVM selector for this function is: 0x5813216b,255 /// or in textual repr: collectionAdmins()298 /// or in textual repr: collectionAdmins()256 function collectionAdmins() external view returns (Tuple17[] memory);299 function collectionAdmins() external view returns (Tuple6[] memory);300301 /// Changes collection owner to another account302 ///303 /// @dev Owner can be changed only by current owner304 /// @param newOwner new owner cross account305 /// @dev EVM selector for this function is: 0xe5c9913f,306 /// or in textual repr: setOwnerCross((address,uint256))307 function setOwnerCross(Tuple6 memory newOwner) external;257}308}258259/// @dev anonymous struct260struct Tuple17 {261 address field_0;262 uint256 field_1;263}264309265/// @dev the ERC-165 identifier for this interface is 0x5b5e139f310/// @dev the ERC-165 identifier for this interface is 0x5b5e139f266interface ERC721Metadata is Dummy, ERC165 {311interface ERC721Metadata is Dummy, ERC165 {355}400}356401357/// @title Unique extensions for ERC721.402/// @title Unique extensions for ERC721.358/// @dev the ERC-165 identifier for this interface is 0xef1eaacb403/// @dev the ERC-165 identifier for this interface is 0x81feb398359interface ERC721UniqueExtensions is Dummy, ERC165 {404interface ERC721UniqueExtensions is Dummy, ERC165 {360 /// @notice A descriptive name for a collection of NFTs in this contract405 /// @notice A descriptive name for a collection of NFTs in this contract361 /// @dev EVM selector for this function is: 0x06fdde03,406 /// @dev EVM selector for this function is: 0x06fdde03,377 /// or in textual repr: transfer(address,uint256)422 /// or in textual repr: transfer(address,uint256)378 function transfer(address to, uint256 tokenId) external;423 function transfer(address to, uint256 tokenId) external;424425 /// @notice Transfer ownership of an RFT426 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`427 /// is the zero address. Throws if `tokenId` is not a valid RFT.428 /// Throws if RFT pieces have multiple owners.429 /// @param to The new owner430 /// @param tokenId The RFT to transfer431 /// @dev EVM selector for this function is: 0xd5cf430b,432 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)433 function transferFromCross(434 Tuple6 memory from,435 Tuple6 memory to,436 uint256 tokenId437 ) external;379438380 /// @notice Burns a specific ERC721 token.439 /// @notice Burns a specific ERC721 token.381 /// @dev Throws unless `msg.sender` is the current owner or an authorized440 /// @dev Throws unless `msg.sender` is the current owner or an authorized388 /// or in textual repr: burnFrom(address,uint256)447 /// or in textual repr: burnFrom(address,uint256)389 function burnFrom(address from, uint256 tokenId) external;448 function burnFrom(address from, uint256 tokenId) external;449450 /// @notice Burns a specific ERC721 token.451 /// @dev Throws unless `msg.sender` is the current owner or an authorized452 /// operator for this RFT. Throws if `from` is not the current owner. Throws453 /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.454 /// Throws if RFT pieces have multiple owners.455 /// @param from The current owner of the RFT456 /// @param tokenId The RFT to transfer457 /// @dev EVM selector for this function is: 0xbb2f5a58,458 /// or in textual repr: burnFromCross((address,uint256),uint256)459 function burnFromCross(Tuple6 memory from, uint256 tokenId) external;390460391 /// @notice Returns next free RFT ID.461 /// @notice Returns next free RFT ID.392 /// @dev EVM selector for this function is: 0x75794a3c,462 /// @dev EVM selector for this function is: 0x75794a3c,409 // /// @param tokens array of pairs of token ID and token URI for minted tokens479 // /// @param tokens array of pairs of token ID and token URI for minted tokens410 // /// @dev EVM selector for this function is: 0x36543006,480 // /// @dev EVM selector for this function is: 0x36543006,411 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])481 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])412 // function mintBulkWithTokenURI(address to, Tuple6[] memory tokens) external returns (bool);482 // function mintBulkWithTokenURI(address to, Tuple8[] memory tokens) external returns (bool);413483414 /// Returns EVM address for refungible token484 /// Returns EVM address for refungible token415 ///485 ///420}490}421491422/// @dev anonymous struct492/// @dev anonymous struct423struct Tuple6 {493struct Tuple8 {424 uint256 field_0;494 uint256 field_0;425 string field_1;495 string field_1;426}496}497498/// @dev anonymous struct499struct Tuple6 {500 address field_0;501 uint256 field_1;502}427503428/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension504/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension429/// @dev See https://eips.ethereum.org/EIPS/eip-721505/// @dev See https://eips.ethereum.org/EIPS/eip-721tests/src/eth/base.test.tsdiffbeforeafterboth116 await checkInterface(helper, '0x780e9d63', true, true);116 await checkInterface(helper, '0x780e9d63', true, true);117 });117 });118118119 itEth('ERC721UniqueExtensions - 0x4468500d - support', async ({helper}) => {119 itEth('ERC721UniqueExtensions - 0x244543ee - support', async ({helper}) => {120 await checkInterface(helper, '0x4468500d', true, true);120 await checkInterface(helper, '0x244543ee', true, true);121 });121 });122122123 itEth('ERC721Burnable - 0x42966c68 - support', async ({helper}) => {123 itEth('ERC721Burnable - 0x42966c68 - support', async ({helper}) => {tests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth50 .to.be.eq(newAdmin.toLocaleLowerCase());50 .to.be.eq(newAdmin.toLocaleLowerCase());51 });51 });525253 itEth.skip('Add substrate admin by owner', async ({helper}) => {53 itEth('Add cross account admin by owner', async ({helper, privateKey}) => {54 const owner = await helper.eth.createAccountWithBalance(donor);54 const owner = await helper.eth.createAccountWithBalance(donor);55 55 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');56 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');56 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);57 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);5758 59 const newAdmin = await privateKey('//Bob');58 const [newAdmin] = await helper.arrange.createAccounts([10n], donor);60 const newAdminCross = helper.ethCrossAccount.fromKeyringPair(newAdmin);59 await collectionEvm.methods.addCollectionAdminSubstrate(newAdmin.addressRaw).send();61 await collectionEvm.methods.addCollectionAdminCross(newAdminCross).send();606261 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);63 const adminList = await helper.collection.getAdmins(collectionId);62 expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())64 expect(adminList).to.be.like([{Substrate: newAdmin.address}]);63 .to.be.eq(newAdmin.address.toLocaleLowerCase());64 });65 });656666 itEth('Verify owner or admin', async ({helper}) => {67 itEth('Verify owner or admin', async ({helper}) => {tests/src/eth/fractionalizer/Fractionalizer.soldiffbeforeafterbothno syntactic changes
tests/src/eth/fungible.test.tsdiffbeforeafterboth148 }148 }149 });149 });150151 itEth('Can perform burnFromCross()', async ({helper, privateKey}) => {152 const alice = await privateKey('//Alice');153 const sender = await helper.eth.createAccountWithBalance(alice, 100n);154155 const collection = await helper.ft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);156157 await collection.mint(alice, 200n, {Substrate: alice.address});158 await collection.approveTokens(alice, {Ethereum: sender}, 100n);159160 const address = helper.ethAddress.fromCollectionId(collection.collectionId);161 const contract = helper.ethNativeContract.collection(address, 'ft');162163 const fromBalanceBefore = await collection.getBalance({Substrate: alice.address});164 165 const ownerCross = helper.ethCrossAccount.fromKeyringPair(alice);166 const result = await contract.methods.burnFromCross(ownerCross, 49).send({from: sender});167 const events = result.events;168169 expect(events).to.be.like({170 Transfer: {171 address: helper.ethAddress.fromCollectionId(collection.collectionId),172 event: 'Transfer',173 returnValues: {174 from: helper.address.substrateToEth(alice.address),175 to: '0x0000000000000000000000000000000000000000',176 value: '49',177 },178 },179 Approval: {180 address: helper.ethAddress.fromCollectionId(collection.collectionId),181 returnValues: {182 owner: helper.address.substrateToEth(alice.address),183 spender: sender,184 value: '51',185 },186 event: 'Approval',187 },188 });189190 const fromBalanceAfter = await collection.getBalance({Substrate: alice.address});191 expect(fromBalanceBefore - fromBalanceAfter).to.be.eq(49n);192 });150193151 itEth('Can perform transferFrom()', async ({helper}) => {194 itEth('Can perform transferFrom()', async ({helper}) => {152 const owner = await helper.eth.createAccountWithBalance(donor);195 const owner = await helper.eth.createAccountWithBalance(donor);217 }260 }218 });261 });262263 itEth('Can perform transferFromCross()', async ({helper, privateKey}) => {264 const alice = await privateKey('//Alice');265 const sender = await helper.eth.createAccountWithBalance(alice, 100n);266267 const collection = await helper.ft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);268269 const receiver = helper.eth.createAccount();270271 await collection.mint(alice, 200n, {Substrate: alice.address});272 await collection.approveTokens(alice, {Ethereum: sender}, 100n);273274 const address = helper.ethAddress.fromCollectionId(collection.collectionId);275 const contract = helper.ethNativeContract.collection(address, 'ft');276277 const from = helper.ethCrossAccount.fromKeyringPair(alice);278 const to = helper.ethCrossAccount.fromAddress(receiver);279280 const fromBalanceBefore = await collection.getBalance({Substrate: alice.address});281 const toBalanceBefore = await collection.getBalance({Ethereum: receiver});282 283 const result = await contract.methods.transferFromCross(from, to, 51).send({from: sender});284285 expect(result.events).to.be.like({286 Transfer: {287 address,288 event: 'Transfer',289 returnValues: {290 from: helper.address.substrateToEth(alice.address),291 to: receiver,292 value: '51',293 },294 },295 Approval: {296 address,297 event: 'Approval',298 returnValues: {299 owner: helper.address.substrateToEth(alice.address),300 spender: sender,301 value: '49',302 },303 }});304305 const fromBalanceAfter = await collection.getBalance({Substrate: alice.address});306 expect(fromBalanceBefore - fromBalanceAfter).to.be.eq(51n);307 const toBalanceAfter = await collection.getBalance({Ethereum: receiver});308 expect(toBalanceAfter - toBalanceBefore).to.be.eq(51n);309 });219});310});220311221describe('Fungible: Fees', () => {312describe('Fungible: Fees', () => {363 expect(event.returnValues.value).to.be.equal('51');454 expect(event.returnValues.value).to.be.equal('51');364 });455 });456457 itEth('Events emitted for transferFromCross()', async ({helper, privateKey}) => {458 const alice = await privateKey('//Alice');459 const sender = await helper.eth.createAccountWithBalance(alice, 100n);460461 const collection = await helper.ft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);462463 const receiver = helper.eth.createAccount();464465 await collection.mint(alice, 200n, {Substrate: alice.address});466 await collection.approveTokens(alice, {Ethereum: sender}, 100n);467468 const address = helper.ethAddress.fromCollectionId(collection.collectionId);469 const contract = helper.ethNativeContract.collection(address, 'ft');470471 const from = helper.ethCrossAccount.fromKeyringPair(alice);472 const to = helper.ethCrossAccount.fromAddress(receiver);473 474 const result = await contract.methods.transferFromCross(from, to, 51).send({from: sender});475476 expect(result.events).to.be.like({477 Transfer: {478 address,479 event: 'Transfer',480 returnValues: {481 from: helper.address.substrateToEth(alice.address),482 to: receiver,483 value: '51',484 },485 },486 Approval: {487 address,488 event: 'Approval',489 returnValues: {490 owner: helper.address.substrateToEth(alice.address),491 spender: sender,492 value: '49',493 },494 }});495 });365});496});366497tests/src/eth/fungibleAbi.jsondiffbeforeafterboth58 "stateMutability": "nonpayable",58 "stateMutability": "nonpayable",59 "type": "function"59 "type": "function"60 },60 },61 {62 "inputs": [63 {64 "components": [65 { "internalType": "address", "name": "field_0", "type": "address" },66 { "internalType": "uint256", "name": "field_1", "type": "uint256" }67 ],68 "internalType": "struct Tuple6",69 "name": "newAdmin",70 "type": "tuple"71 }72 ],73 "name": "addCollectionAdminCross",74 "outputs": [],75 "stateMutability": "nonpayable",76 "type": "function"77 },61 {78 {62 "inputs": [79 "inputs": [63 { "internalType": "address", "name": "user", "type": "address" }80 { "internalType": "address", "name": "user", "type": "address" }67 "stateMutability": "nonpayable",84 "stateMutability": "nonpayable",68 "type": "function"85 "type": "function"69 },86 },87 {88 "inputs": [89 {90 "components": [91 { "internalType": "address", "name": "field_0", "type": "address" },92 { "internalType": "uint256", "name": "field_1", "type": "uint256" }93 ],94 "internalType": "struct Tuple6",95 "name": "user",96 "type": "tuple"97 }98 ],99 "name": "addToCollectionAllowListCross",100 "outputs": [],101 "stateMutability": "nonpayable",102 "type": "function"103 },70 {104 {71 "inputs": [105 "inputs": [72 { "internalType": "address", "name": "owner", "type": "address" },106 { "internalType": "address", "name": "owner", "type": "address" },96 "stateMutability": "nonpayable",130 "stateMutability": "nonpayable",97 "type": "function"131 "type": "function"98 },132 },133 {134 "inputs": [135 {136 "components": [137 { "internalType": "address", "name": "field_0", "type": "address" },138 { "internalType": "uint256", "name": "field_1", "type": "uint256" }139 ],140 "internalType": "struct Tuple6",141 "name": "spender",142 "type": "tuple"143 },144 { "internalType": "uint256", "name": "amount", "type": "uint256" }145 ],146 "name": "approveCross",147 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],148 "stateMutability": "nonpayable",149 "type": "function"150 },99 {151 {100 "inputs": [152 "inputs": [101 { "internalType": "address", "name": "owner", "type": "address" }153 { "internalType": "address", "name": "owner", "type": "address" }115 "stateMutability": "nonpayable",167 "stateMutability": "nonpayable",116 "type": "function"168 "type": "function"117 },169 },170 {171 "inputs": [172 {173 "components": [174 { "internalType": "address", "name": "field_0", "type": "address" },175 { "internalType": "uint256", "name": "field_1", "type": "uint256" }176 ],177 "internalType": "struct Tuple6",178 "name": "from",179 "type": "tuple"180 },181 { "internalType": "uint256", "name": "amount", "type": "uint256" }182 ],183 "name": "burnFromCross",184 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],185 "stateMutability": "nonpayable",186 "type": "function"187 },118 {188 {119 "inputs": [189 "inputs": [120 { "internalType": "address", "name": "newOwner", "type": "address" }190 { "internalType": "address", "name": "newOwner", "type": "address" }226 "stateMutability": "view",296 "stateMutability": "view",227 "type": "function"297 "type": "function"228 },298 },299 {300 "inputs": [301 {302 "components": [303 { "internalType": "address", "name": "field_0", "type": "address" },304 { "internalType": "uint256", "name": "field_1", "type": "uint256" }305 ],306 "internalType": "struct Tuple6",307 "name": "user",308 "type": "tuple"309 }310 ],311 "name": "isOwnerOrAdminCross",312 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],313 "stateMutability": "view",314 "type": "function"315 },229 {316 {230 "inputs": [317 "inputs": [231 { "internalType": "address", "name": "to", "type": "address" },318 { "internalType": "address", "name": "to", "type": "address" },269 "stateMutability": "nonpayable",356 "stateMutability": "nonpayable",270 "type": "function"357 "type": "function"271 },358 },359 {360 "inputs": [361 {362 "components": [363 { "internalType": "address", "name": "field_0", "type": "address" },364 { "internalType": "uint256", "name": "field_1", "type": "uint256" }365 ],366 "internalType": "struct Tuple6",367 "name": "admin",368 "type": "tuple"369 }370 ],371 "name": "removeCollectionAdminCross",372 "outputs": [],373 "stateMutability": "nonpayable",374 "type": "function"375 },272 {376 {273 "inputs": [],377 "inputs": [],274 "name": "removeCollectionSponsor",378 "name": "removeCollectionSponsor",285 "stateMutability": "nonpayable",389 "stateMutability": "nonpayable",286 "type": "function"390 "type": "function"287 },391 },392 {393 "inputs": [394 {395 "components": [396 { "internalType": "address", "name": "field_0", "type": "address" },397 { "internalType": "uint256", "name": "field_1", "type": "uint256" }398 ],399 "internalType": "struct Tuple6",400 "name": "user",401 "type": "tuple"402 }403 ],404 "name": "removeFromCollectionAllowListCross",405 "outputs": [],406 "stateMutability": "nonpayable",407 "type": "function"408 },288 {409 {289 "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],410 "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],290 "name": "setCollectionAccess",411 "name": "setCollectionAccess",359 "stateMutability": "nonpayable",480 "stateMutability": "nonpayable",360 "type": "function"481 "type": "function"361 },482 },483 {484 "inputs": [485 {486 "components": [487 { "internalType": "address", "name": "field_0", "type": "address" },488 { "internalType": "uint256", "name": "field_1", "type": "uint256" }489 ],490 "internalType": "struct Tuple6",491 "name": "sponsor",492 "type": "tuple"493 }494 ],495 "name": "setCollectionSponsorCross",496 "outputs": [],497 "stateMutability": "nonpayable",498 "type": "function"499 },500 {501 "inputs": [502 {503 "components": [504 { "internalType": "address", "name": "field_0", "type": "address" },505 { "internalType": "uint256", "name": "field_1", "type": "uint256" }506 ],507 "internalType": "struct Tuple6",508 "name": "newOwner",509 "type": "tuple"510 }511 ],512 "name": "setOwnerCross",513 "outputs": [],514 "stateMutability": "nonpayable",515 "type": "function"516 },362 {517 {363 "inputs": [518 "inputs": [364 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }519 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }403 "stateMutability": "nonpayable",558 "stateMutability": "nonpayable",404 "type": "function"559 "type": "function"405 },560 },561 {562 "inputs": [563 {564 "components": [565 { "internalType": "address", "name": "field_0", "type": "address" },566 { "internalType": "uint256", "name": "field_1", "type": "uint256" }567 ],568 "internalType": "struct Tuple6",569 "name": "from",570 "type": "tuple"571 },572 {573 "components": [574 { "internalType": "address", "name": "field_0", "type": "address" },575 { "internalType": "uint256", "name": "field_1", "type": "uint256" }576 ],577 "internalType": "struct Tuple6",578 "name": "to",579 "type": "tuple"580 },581 { "internalType": "uint256", "name": "amount", "type": "uint256" }582 ],583 "name": "transferFromCross",584 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],585 "stateMutability": "nonpayable",586 "type": "function"587 },406 {588 {407 "inputs": [],589 "inputs": [],408 "name": "uniqueCollectionType",590 "name": "uniqueCollectionType",tests/src/eth/nonFungible.test.tsdiffbeforeafterboth246 }246 }247 });247 });248249 itEth('Can perform burnFromCross()', async ({helper, privateKey}) => {250 const alice = await privateKey('//Alice');251 const collection = await helper.nft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'});252253 const owner = await privateKey('//Bob');254 const spender = await helper.eth.createAccountWithBalance(alice, 100n);255256 const token = await collection.mintToken(alice, {Substrate: owner.address});257258 const address = helper.ethAddress.fromCollectionId(collection.collectionId);259 const contract = helper.ethNativeContract.collection(address, 'nft');260261 {262 await token.approve(owner, {Ethereum: spender});263 const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);264 const result = await contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender});265 const events = result.events.Transfer;266267 expect(events).to.be.like({268 address,269 event: 'Transfer',270 returnValues: {271 from: helper.address.substrateToEth(owner.address),272 to: '0x0000000000000000000000000000000000000000',273 tokenId: token.tokenId.toString(),274 },275 });276 }277 });278279 itEth('Can perform approveCross()', async ({helper, privateKey}) => {280 const alice = await privateKey('//Alice');281 const collection = await helper.nft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'});282283 const owner = await helper.eth.createAccountWithBalance(alice, 100n);284 const receiver = await privateKey('//Charlie');285286 const token = await collection.mintToken(alice, {Ethereum: owner});287288 const address = helper.ethAddress.fromCollectionId(collection.collectionId);289 const contract = helper.ethNativeContract.collection(address, 'nft');290291 {292 const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);293 const result = await contract.methods.approveCross(recieverCross, token.tokenId).send({from: owner});294 const event = result.events.Approval;295 expect(event).to.be.like({296 address: helper.ethAddress.fromCollectionId(collection.collectionId),297 event: 'Approval',298 returnValues: {299 owner,300 approved: helper.address.substrateToEth(receiver.address),301 tokenId: token.tokenId.toString(),302 },303 });304 }305 });248306249 itEth('Can perform transferFrom()', async ({helper}) => {307 itEth('Can perform transferFrom()', async ({helper}) => {250 const owner = await helper.eth.createAccountWithBalance(donor);308 const owner = await helper.eth.createAccountWithBalance(donor);351 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));409 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));352 });410 });411412 itEth('Can perform transferFromCross()', async ({helper, privateKey}) => {413 const alice = await privateKey('//Alice');414 const collection = await helper.nft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'});415416 const owner = await privateKey('//Bob');417 const spender = await helper.eth.createAccountWithBalance(alice, 100n);418 const receiver = await privateKey('//Charlie');419420 const token = await collection.mintToken(alice, {Substrate: owner.address});421422 const address = helper.ethAddress.fromCollectionId(collection.collectionId);423 const contract = helper.ethNativeContract.collection(address, 'nft');424425 await token.approve(owner, {Ethereum: spender});426427 {428 const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);429 const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);430 const result = await contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender});431 const event = result.events.Transfer;432 expect(event).to.be.like({433 address: helper.ethAddress.fromCollectionId(collection.collectionId),434 event: 'Transfer',435 returnValues: {436 from: helper.address.substrateToEth(owner.address),437 to: helper.address.substrateToEth(receiver.address),438 tokenId: token.tokenId.toString(),439 },440 });441 }442443 expect(await token.getOwner()).to.be.like({Substrate: receiver.address});444 });353445354 itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {446 itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {355 const owner = await helper.eth.createAccountWithBalance(donor);447 const owner = await helper.eth.createAccountWithBalance(donor);tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth89 "stateMutability": "nonpayable",89 "stateMutability": "nonpayable",90 "type": "function"90 "type": "function"91 },91 },92 {93 "inputs": [94 {95 "components": [96 { "internalType": "address", "name": "field_0", "type": "address" },97 { "internalType": "uint256", "name": "field_1", "type": "uint256" }98 ],99 "internalType": "struct Tuple6",100 "name": "newAdmin",101 "type": "tuple"102 }103 ],104 "name": "addCollectionAdminCross",105 "outputs": [],106 "stateMutability": "nonpayable",107 "type": "function"108 },92 {109 {93 "inputs": [110 "inputs": [94 { "internalType": "address", "name": "user", "type": "address" }111 { "internalType": "address", "name": "user", "type": "address" }98 "stateMutability": "nonpayable",115 "stateMutability": "nonpayable",99 "type": "function"116 "type": "function"100 },117 },118 {119 "inputs": [120 {121 "components": [122 { "internalType": "address", "name": "field_0", "type": "address" },123 { "internalType": "uint256", "name": "field_1", "type": "uint256" }124 ],125 "internalType": "struct Tuple6",126 "name": "user",127 "type": "tuple"128 }129 ],130 "name": "addToCollectionAllowListCross",131 "outputs": [],132 "stateMutability": "nonpayable",133 "type": "function"134 },101 {135 {102 "inputs": [136 "inputs": [103 { "internalType": "address", "name": "user", "type": "address" }137 { "internalType": "address", "name": "user", "type": "address" }117 "stateMutability": "nonpayable",151 "stateMutability": "nonpayable",118 "type": "function"152 "type": "function"119 },153 },154 {155 "inputs": [156 {157 "components": [158 { "internalType": "address", "name": "field_0", "type": "address" },159 { "internalType": "uint256", "name": "field_1", "type": "uint256" }160 ],161 "internalType": "struct Tuple6",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 },120 {172 {121 "inputs": [173 "inputs": [122 { "internalType": "address", "name": "owner", "type": "address" }174 { "internalType": "address", "name": "owner", "type": "address" }145 "stateMutability": "nonpayable",197 "stateMutability": "nonpayable",146 "type": "function"198 "type": "function"147 },199 },200 {201 "inputs": [202 {203 "components": [204 { "internalType": "address", "name": "field_0", "type": "address" },205 { "internalType": "uint256", "name": "field_1", "type": "uint256" }206 ],207 "internalType": "struct Tuple6",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 },148 {218 {149 "inputs": [219 "inputs": [150 { "internalType": "address", "name": "newOwner", "type": "address" }220 { "internalType": "address", "name": "newOwner", "type": "address" }163 { "internalType": "address", "name": "field_0", "type": "address" },233 { "internalType": "address", "name": "field_0", "type": "address" },164 { "internalType": "uint256", "name": "field_1", "type": "uint256" }234 { "internalType": "uint256", "name": "field_1", "type": "uint256" }165 ],235 ],166 "internalType": "struct Tuple17[]",236 "internalType": "struct Tuple6[]",167 "name": "",237 "name": "",168 "type": "tuple[]"238 "type": "tuple[]"169 }239 }180 { "internalType": "address", "name": "field_0", "type": "address" },250 { "internalType": "address", "name": "field_0", "type": "address" },181 { "internalType": "uint256", "name": "field_1", "type": "uint256" }251 { "internalType": "uint256", "name": "field_1", "type": "uint256" }182 ],252 ],183 "internalType": "struct Tuple17",253 "internalType": "struct Tuple6",184 "name": "",254 "name": "",185 "type": "tuple"255 "type": "tuple"186 }256 }204 { "internalType": "address", "name": "field_0", "type": "address" },274 { "internalType": "address", "name": "field_0", "type": "address" },205 { "internalType": "uint256", "name": "field_1", "type": "uint256" }275 { "internalType": "uint256", "name": "field_1", "type": "uint256" }206 ],276 ],207 "internalType": "struct Tuple17",277 "internalType": "struct Tuple6",208 "name": "",278 "name": "",209 "type": "tuple"279 "type": "tuple"210 }280 }285 "stateMutability": "view",355 "stateMutability": "view",286 "type": "function"356 "type": "function"287 },357 },358 {359 "inputs": [360 {361 "components": [362 { "internalType": "address", "name": "field_0", "type": "address" },363 { "internalType": "uint256", "name": "field_1", "type": "uint256" }364 ],365 "internalType": "struct Tuple6",366 "name": "user",367 "type": "tuple"368 }369 ],370 "name": "isOwnerOrAdminCross",371 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],372 "stateMutability": "view",373 "type": "function"374 },288 {375 {289 "inputs": [{ "internalType": "address", "name": "to", "type": "address" }],376 "inputs": [{ "internalType": "address", "name": "to", "type": "address" }],290 "name": "mint",377 "name": "mint",351 "stateMutability": "nonpayable",438 "stateMutability": "nonpayable",352 "type": "function"439 "type": "function"353 },440 },441 {442 "inputs": [443 {444 "components": [445 { "internalType": "address", "name": "field_0", "type": "address" },446 { "internalType": "uint256", "name": "field_1", "type": "uint256" }447 ],448 "internalType": "struct Tuple6",449 "name": "admin",450 "type": "tuple"451 }452 ],453 "name": "removeCollectionAdminCross",454 "outputs": [],455 "stateMutability": "nonpayable",456 "type": "function"457 },354 {458 {355 "inputs": [],459 "inputs": [],356 "name": "removeCollectionSponsor",460 "name": "removeCollectionSponsor",367 "stateMutability": "nonpayable",471 "stateMutability": "nonpayable",368 "type": "function"472 "type": "function"369 },473 },474 {475 "inputs": [476 {477 "components": [478 { "internalType": "address", "name": "field_0", "type": "address" },479 { "internalType": "uint256", "name": "field_1", "type": "uint256" }480 ],481 "internalType": "struct Tuple6",482 "name": "user",483 "type": "tuple"484 }485 ],486 "name": "removeFromCollectionAllowListCross",487 "outputs": [],488 "stateMutability": "nonpayable",489 "type": "function"490 },370 {491 {371 "inputs": [492 "inputs": [372 { "internalType": "address", "name": "from", "type": "address" },493 { "internalType": "address", "name": "from", "type": "address" },474 "stateMutability": "nonpayable",595 "stateMutability": "nonpayable",475 "type": "function"596 "type": "function"476 },597 },598 {599 "inputs": [600 {601 "components": [602 { "internalType": "address", "name": "field_0", "type": "address" },603 { "internalType": "uint256", "name": "field_1", "type": "uint256" }604 ],605 "internalType": "struct Tuple6",606 "name": "sponsor",607 "type": "tuple"608 }609 ],610 "name": "setCollectionSponsorCross",611 "outputs": [],612 "stateMutability": "nonpayable",613 "type": "function"614 },615 {616 "inputs": [617 {618 "components": [619 { "internalType": "address", "name": "field_0", "type": "address" },620 { "internalType": "uint256", "name": "field_1", "type": "uint256" }621 ],622 "internalType": "struct Tuple6",623 "name": "newOwner",624 "type": "tuple"625 }626 ],627 "name": "setOwnerCross",628 "outputs": [],629 "stateMutability": "nonpayable",630 "type": "function"631 },477 {632 {478 "inputs": [633 "inputs": [479 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },634 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },569 "stateMutability": "nonpayable",724 "stateMutability": "nonpayable",570 "type": "function"725 "type": "function"571 },726 },727 {728 "inputs": [729 {730 "components": [731 { "internalType": "address", "name": "field_0", "type": "address" },732 { "internalType": "uint256", "name": "field_1", "type": "uint256" }733 ],734 "internalType": "struct Tuple6",735 "name": "from",736 "type": "tuple"737 },738 {739 "components": [740 { "internalType": "address", "name": "field_0", "type": "address" },741 { "internalType": "uint256", "name": "field_1", "type": "uint256" }742 ],743 "internalType": "struct Tuple6",744 "name": "to",745 "type": "tuple"746 },747 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }748 ],749 "name": "transferFromCross",750 "outputs": [],751 "stateMutability": "nonpayable",752 "type": "function"753 },572 {754 {573 "inputs": [],755 "inputs": [],574 "name": "uniqueCollectionType",756 "name": "uniqueCollectionType",tests/src/eth/reFungible.test.tsdiffbeforeafterboth227 }227 }228 });228 });229230 itEth('Can perform burnFrom()', async ({helper, privateKey}) => {231 const alice = await privateKey('//Alice');232 const collection = await helper.rft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'});233234 const owner = await helper.eth.createAccountWithBalance(alice, 100n);235 const spender = await helper.eth.createAccountWithBalance(alice, 100n);236237 const token = await collection.mintToken(alice, 100n, {Ethereum: owner});238239 const address = helper.ethAddress.fromCollectionId(collection.collectionId);240 const contract = helper.ethNativeContract.collection(address, 'rft');241242 const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId);243 const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, owner);244 await tokenContract.methods.repartition(15).send();245 await tokenContract.methods.approve(spender, 15).send();246247 {248 const result = await contract.methods.burnFrom(owner, token.tokenId).send({from: spender});249 const event = result.events.Transfer;250 expect(event).to.be.like({251 address: helper.ethAddress.fromCollectionId(collection.collectionId),252 event: 'Transfer',253 returnValues: {254 from: owner,255 to: '0x0000000000000000000000000000000000000000',256 tokenId: token.tokenId.toString(),257 },258 });259 }260261 expect(await collection.getTokenBalance(token.tokenId, {Ethereum: owner})).to.be.eq(0n);262 });263264 itEth('Can perform burnFromCross()', async ({helper, privateKey}) => {265 const alice = await privateKey('//Alice');266 const collection = await helper.rft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'});267268 const owner = await privateKey('//Bob');269 const spender = await helper.eth.createAccountWithBalance(alice, 100n);270271 const token = await collection.mintToken(alice, 100n, {Substrate: owner.address});272273 const address = helper.ethAddress.fromCollectionId(collection.collectionId);274 const contract = helper.ethNativeContract.collection(address, 'rft');275276 await token.repartition(owner, 15n);277 await token.approve(owner, {Ethereum: spender}, 15n);278279 {280 const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);281 const result = await contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender});282 const event = result.events.Transfer;283 expect(event).to.be.like({284 address: helper.ethAddress.fromCollectionId(collection.collectionId),285 event: 'Transfer',286 returnValues: {287 from: helper.address.substrateToEth(owner.address),288 to: '0x0000000000000000000000000000000000000000',289 tokenId: token.tokenId.toString(),290 },291 });292 }293294 expect(await collection.getTokenBalance(token.tokenId, {Substrate: owner.address})).to.be.eq(0n);295 });296297 itEth('Can perform transferFromCross()', async ({helper, privateKey}) => {298 const alice = await privateKey('//Alice');299 const collection = await helper.rft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'});300301 const owner = await privateKey('//Bob');302 const spender = await helper.eth.createAccountWithBalance(alice, 100n);303 const receiver = await privateKey('//Charlie');304305 const token = await collection.mintToken(alice, 100n, {Substrate: owner.address});306307 const address = helper.ethAddress.fromCollectionId(collection.collectionId);308 const contract = helper.ethNativeContract.collection(address, 'rft');309310 await token.repartition(owner, 15n);311 await token.approve(owner, {Ethereum: spender}, 15n);312313 {314 const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);315 const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);316 const result = await contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender});317 const event = result.events.Transfer;318 expect(event).to.be.like({319 address: helper.ethAddress.fromCollectionId(collection.collectionId),320 event: 'Transfer',321 returnValues: {322 from: helper.address.substrateToEth(owner.address),323 to: helper.address.substrateToEth(receiver.address),324 tokenId: token.tokenId.toString(),325 },326 });327 }328329 expect(await token.getTop10Owners()).to.be.like([{Substrate: receiver.address}]);330 });229331230 itEth('Can perform transfer()', async ({helper}) => {332 itEth('Can perform transfer()', async ({helper}) => {231 const caller = await helper.eth.createAccountWithBalance(donor);333 const caller = await helper.eth.createAccountWithBalance(donor);tests/src/eth/reFungibleAbi.jsondiffbeforeafterboth89 "stateMutability": "nonpayable",89 "stateMutability": "nonpayable",90 "type": "function"90 "type": "function"91 },91 },92 {93 "inputs": [94 {95 "components": [96 { "internalType": "address", "name": "field_0", "type": "address" },97 { "internalType": "uint256", "name": "field_1", "type": "uint256" }98 ],99 "internalType": "struct Tuple6",100 "name": "newAdmin",101 "type": "tuple"102 }103 ],104 "name": "addCollectionAdminCross",105 "outputs": [],106 "stateMutability": "nonpayable",107 "type": "function"108 },92 {109 {93 "inputs": [110 "inputs": [94 { "internalType": "address", "name": "user", "type": "address" }111 { "internalType": "address", "name": "user", "type": "address" }98 "stateMutability": "nonpayable",115 "stateMutability": "nonpayable",99 "type": "function"116 "type": "function"100 },117 },118 {119 "inputs": [120 {121 "components": [122 { "internalType": "address", "name": "field_0", "type": "address" },123 { "internalType": "uint256", "name": "field_1", "type": "uint256" }124 ],125 "internalType": "struct Tuple6",126 "name": "user",127 "type": "tuple"128 }129 ],130 "name": "addToCollectionAllowListCross",131 "outputs": [],132 "stateMutability": "nonpayable",133 "type": "function"134 },101 {135 {102 "inputs": [136 "inputs": [103 { "internalType": "address", "name": "user", "type": "address" }137 { "internalType": "address", "name": "user", "type": "address" }145 "stateMutability": "nonpayable",179 "stateMutability": "nonpayable",146 "type": "function"180 "type": "function"147 },181 },182 {183 "inputs": [184 {185 "components": [186 { "internalType": "address", "name": "field_0", "type": "address" },187 { "internalType": "uint256", "name": "field_1", "type": "uint256" }188 ],189 "internalType": "struct Tuple6",190 "name": "from",191 "type": "tuple"192 },193 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }194 ],195 "name": "burnFromCross",196 "outputs": [],197 "stateMutability": "nonpayable",198 "type": "function"199 },148 {200 {149 "inputs": [201 "inputs": [150 { "internalType": "address", "name": "newOwner", "type": "address" }202 { "internalType": "address", "name": "newOwner", "type": "address" }163 { "internalType": "address", "name": "field_0", "type": "address" },215 { "internalType": "address", "name": "field_0", "type": "address" },164 { "internalType": "uint256", "name": "field_1", "type": "uint256" }216 { "internalType": "uint256", "name": "field_1", "type": "uint256" }165 ],217 ],166 "internalType": "struct Tuple17[]",218 "internalType": "struct Tuple6[]",167 "name": "",219 "name": "",168 "type": "tuple[]"220 "type": "tuple[]"169 }221 }180 { "internalType": "address", "name": "field_0", "type": "address" },232 { "internalType": "address", "name": "field_0", "type": "address" },181 { "internalType": "uint256", "name": "field_1", "type": "uint256" }233 { "internalType": "uint256", "name": "field_1", "type": "uint256" }182 ],234 ],183 "internalType": "struct Tuple17",235 "internalType": "struct Tuple6",184 "name": "",236 "name": "",185 "type": "tuple"237 "type": "tuple"186 }238 }204 { "internalType": "address", "name": "field_0", "type": "address" },256 { "internalType": "address", "name": "field_0", "type": "address" },205 { "internalType": "uint256", "name": "field_1", "type": "uint256" }257 { "internalType": "uint256", "name": "field_1", "type": "uint256" }206 ],258 ],207 "internalType": "struct Tuple17",259 "internalType": "struct Tuple6",208 "name": "",260 "name": "",209 "type": "tuple"261 "type": "tuple"210 }262 }285 "stateMutability": "view",337 "stateMutability": "view",286 "type": "function"338 "type": "function"287 },339 },340 {341 "inputs": [342 {343 "components": [344 { "internalType": "address", "name": "field_0", "type": "address" },345 { "internalType": "uint256", "name": "field_1", "type": "uint256" }346 ],347 "internalType": "struct Tuple6",348 "name": "user",349 "type": "tuple"350 }351 ],352 "name": "isOwnerOrAdminCross",353 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],354 "stateMutability": "view",355 "type": "function"356 },288 {357 {289 "inputs": [{ "internalType": "address", "name": "to", "type": "address" }],358 "inputs": [{ "internalType": "address", "name": "to", "type": "address" }],290 "name": "mint",359 "name": "mint",351 "stateMutability": "nonpayable",420 "stateMutability": "nonpayable",352 "type": "function"421 "type": "function"353 },422 },423 {424 "inputs": [425 {426 "components": [427 { "internalType": "address", "name": "field_0", "type": "address" },428 { "internalType": "uint256", "name": "field_1", "type": "uint256" }429 ],430 "internalType": "struct Tuple6",431 "name": "admin",432 "type": "tuple"433 }434 ],435 "name": "removeCollectionAdminCross",436 "outputs": [],437 "stateMutability": "nonpayable",438 "type": "function"439 },354 {440 {355 "inputs": [],441 "inputs": [],356 "name": "removeCollectionSponsor",442 "name": "removeCollectionSponsor",367 "stateMutability": "nonpayable",453 "stateMutability": "nonpayable",368 "type": "function"454 "type": "function"369 },455 },456 {457 "inputs": [458 {459 "components": [460 { "internalType": "address", "name": "field_0", "type": "address" },461 { "internalType": "uint256", "name": "field_1", "type": "uint256" }462 ],463 "internalType": "struct Tuple6",464 "name": "user",465 "type": "tuple"466 }467 ],468 "name": "removeFromCollectionAllowListCross",469 "outputs": [],470 "stateMutability": "nonpayable",471 "type": "function"472 },370 {473 {371 "inputs": [474 "inputs": [372 { "internalType": "address", "name": "from", "type": "address" },475 { "internalType": "address", "name": "from", "type": "address" },474 "stateMutability": "nonpayable",577 "stateMutability": "nonpayable",475 "type": "function"578 "type": "function"476 },579 },580 {581 "inputs": [582 {583 "components": [584 { "internalType": "address", "name": "field_0", "type": "address" },585 { "internalType": "uint256", "name": "field_1", "type": "uint256" }586 ],587 "internalType": "struct Tuple6",588 "name": "sponsor",589 "type": "tuple"590 }591 ],592 "name": "setCollectionSponsorCross",593 "outputs": [],594 "stateMutability": "nonpayable",595 "type": "function"596 },597 {598 "inputs": [599 {600 "components": [601 { "internalType": "address", "name": "field_0", "type": "address" },602 { "internalType": "uint256", "name": "field_1", "type": "uint256" }603 ],604 "internalType": "struct Tuple6",605 "name": "newOwner",606 "type": "tuple"607 }608 ],609 "name": "setOwnerCross",610 "outputs": [],611 "stateMutability": "nonpayable",612 "type": "function"613 },477 {614 {478 "inputs": [615 "inputs": [479 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },616 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },578 "stateMutability": "nonpayable",715 "stateMutability": "nonpayable",579 "type": "function"716 "type": "function"580 },717 },718 {719 "inputs": [720 {721 "components": [722 { "internalType": "address", "name": "field_0", "type": "address" },723 { "internalType": "uint256", "name": "field_1", "type": "uint256" }724 ],725 "internalType": "struct Tuple6",726 "name": "from",727 "type": "tuple"728 },729 {730 "components": [731 { "internalType": "address", "name": "field_0", "type": "address" },732 { "internalType": "uint256", "name": "field_1", "type": "uint256" }733 ],734 "internalType": "struct Tuple6",735 "name": "to",736 "type": "tuple"737 },738 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }739 ],740 "name": "transferFromCross",741 "outputs": [],742 "stateMutability": "nonpayable",743 "type": "function"744 },581 {745 {582 "inputs": [],746 "inputs": [],583 "name": "uniqueCollectionType",747 "name": "uniqueCollectionType",tests/src/eth/util/playgrounds/types.tsdiffbeforeafterboth13 event: string,13 event: string,14 args: { [key: string]: string }14 args: { [key: string]: string }15};15};16export interface TEthCrossAccount {17 readonly 0: string,18 readonly 1: string | Uint8Array,19 readonly field_0: string,20 readonly field_1: string | Uint8Array,21}1622tests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth181819import {DevUniqueHelper} from '../../../util/playgrounds/unique.dev';19import {DevUniqueHelper} from '../../../util/playgrounds/unique.dev';202021import {ContractImports, CompiledContract, NormalizedEvent} from './types';21import {ContractImports, CompiledContract, TEthCrossAccount, NormalizedEvent} from './types';222223// Native contracts ABI23// Native contracts ABI24import collectionHelpersAbi from '../../collectionHelpersAbi.json';24import collectionHelpersAbi from '../../collectionHelpersAbi.json';343343344export type EthUniqueHelperConstructor = new (...args: any[]) => EthUniqueHelper;344export type EthUniqueHelperConstructor = new (...args: any[]) => EthUniqueHelper;345346export class EthCrossAccountGroup extends EthGroupBase {347 fromAddress(address: TEthereumAccount): TEthCrossAccount {348 return {349 0: address,350 1: '0',351 field_0: address,352 field_1: '0',353 };354 }355356 fromKeyringPair(keyring: IKeyringPair): TEthCrossAccount {357 return {358 0: '0x0000000000000000000000000000000000000000',359 1: keyring.addressRaw,360 field_0: '0x0000000000000000000000000000000000000000',361 field_1: keyring.addressRaw,362 };363 }364}345365346export class EthUniqueHelper extends DevUniqueHelper {366export class EthUniqueHelper extends DevUniqueHelper {347 web3: Web3 | null = null;367 web3: Web3 | null = null;351 ethAddress: EthAddressGroup;371 ethAddress: EthAddressGroup;352 ethNativeContract: NativeContractGroup;372 ethNativeContract: NativeContractGroup;353 ethContract: ContractGroup;373 ethContract: ContractGroup;374 ethCrossAccount: EthCrossAccountGroup;354375355 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {376 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {356 options.helperBase = options.helperBase ?? EthUniqueHelper;377 options.helperBase = options.helperBase ?? EthUniqueHelper;357378358 super(logger, options);379 super(logger, options);359 this.eth = new EthGroup(this);380 this.eth = new EthGroup(this);360 this.ethAddress = new EthAddressGroup(this);381 this.ethAddress = new EthAddressGroup(this);382 this.ethCrossAccount = new EthCrossAccountGroup(this);361 this.ethNativeContract = new NativeContractGroup(this);383 this.ethNativeContract = new NativeContractGroup(this);362 this.ethContract = new ContractGroup(this);384 this.ethContract = new ContractGroup(this);363 }385 }