difftreelog
Merge remote-tracking branch 'origin/feature/add_collection_sponsor_substrate' into develop
in: master
32 files changed
Cargo.lockdiffbeforeafterboth551055105511[[package]]5511[[package]]5512name = "pallet-common"5512name = "pallet-common"5513version = "0.1.7"5513version = "0.1.8"5514dependencies = [5514dependencies = [5515 "ethereum",5515 "ethereum",5516 "evm-coder",5516 "evm-coder",574857485749[[package]]5749[[package]]5750name = "pallet-fungible"5750name = "pallet-fungible"5751version = "0.1.3"5751version = "0.1.4"5752dependencies = [5752dependencies = [5753 "ethereum",5753 "ethereum",5754 "evm-coder",5754 "evm-coder",599059905991[[package]]5991[[package]]5992name = "pallet-nonfungible"5992name = "pallet-nonfungible"5993version = "0.1.4"5993version = "0.1.5"5994dependencies = [5994dependencies = [5995 "ethereum",5995 "ethereum",5996 "evm-coder",5996 "evm-coder",611261126113[[package]]6113[[package]]6114name = "pallet-refungible"6114name = "pallet-refungible"6115version = "0.2.3"6115version = "0.2.4"6116dependencies = [6116dependencies = [6117 "derivative",6117 "derivative",6118 "ethereum",6118 "ethereum",crates/evm-coder/CHANGELOG.mddiffbeforeafterboth1# Change Log1# Change Log223All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.45<!-- bureaucrate goes here -->4## [v0.1.2] 2022-08-196## [v0.1.2] 2022-08-19576### Added8### Addedcrates/evm-coder/src/solidity.rsdiffbeforeafterboth479 }479 }480}480}481481482#[impl_for_tuples(0, 24)]482#[impl_for_tuples(0, 48)]483impl SolidityFunctions for Tuple {483impl SolidityFunctions for Tuple {484 for_tuples!( where #( Tuple: SolidityFunctions ),* );484 for_tuples!( where #( Tuple: SolidityFunctions ),* );485485pallets/common/CHANGELOG.mddiffbeforeafterboth223All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.445## [0.1.8] - 2022-08-2467## Added8 - Eth methods for collection9 + set_collection_sponsor_substrate10 + has_collection_pending_sponsor11 + remove_collection_sponsor12 + get_collection_sponsor13- Add convert function from `uint256` to `CrossAccountId`.145## [0.1.7] - 2022-08-1915## [0.1.7] - 2022-08-196167### Added17### Addedpallets/common/Cargo.tomldiffbeforeafterboth1[package]1[package]2name = "pallet-common"2name = "pallet-common"3version = "0.1.7"3version = "0.1.8"4license = "GPLv3"4license = "GPLv3"5edition = "2021"5edition = "2021"66pallets/common/src/erc.rsdiffbeforeafterboth26use sp_std::vec::Vec;26use sp_std::vec::Vec;27use up_data_structs::{27use up_data_structs::{28 AccessMode, CollectionMode, CollectionPermissions, OwnerRestrictedSet, Property,28 AccessMode, CollectionMode, CollectionPermissions, OwnerRestrictedSet, Property,29 SponsoringRateLimit,29 SponsoringRateLimit, SponsorshipState,30};30};31use alloc::format;31use alloc::format;323233use crate::{33use crate::{34 Pallet, CollectionHandle, Config, CollectionProperties,34 Pallet, CollectionHandle, Config, CollectionProperties,35 eth::convert_substrate_address_to_cross_account_id,35 eth::{convert_cross_account_to_uint256, convert_uint256_to_cross_account},36};36};373738/// Events for ethereum collection helper.38/// Events for ethereum collection helper.63#[solidity_interface(name = Collection)]63#[solidity_interface(name = Collection)]64impl<T: Config> CollectionHandle<T>64impl<T: Config> CollectionHandle<T>65where65where66 T::AccountId: From<[u8; 32]>,66 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,67{67{68 /// Set collection property.68 /// Set collection property.69 ///69 ///128 save(self)128 save(self)129 }129 }130131 /// Set the substrate sponsor of the collection.132 ///133 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.134 ///135 /// @param sponsor Substrate address of the sponsor from whose account funds will be debited for operations with the contract.136 fn set_collection_sponsor_substrate(137 &mut self,138 caller: caller,139 sponsor: uint256,140 ) -> Result<void> {141 check_is_owner_or_admin(caller, self)?;142143 let sponsor = convert_uint256_to_cross_account::<T>(sponsor);144 self.set_sponsor(sponsor.as_sub().clone())145 .map_err(dispatch_to_evm::<T>)?;146 save(self)147 }148149 // /// Whether there is a pending sponsor.150 fn has_collection_pending_sponsor(&self) -> Result<bool> {151 Ok(matches!(152 self.collection.sponsorship,153 SponsorshipState::Unconfirmed(_)154 ))155 }130156131 /// Collection sponsorship confirmation.157 /// Collection sponsorship confirmation.132 ///158 ///142 save(self)168 save(self)143 }169 }170171 /// Remove collection sponsor.172 fn remove_collection_sponsor(&mut self, caller: caller) -> Result<void> {173 check_is_owner_or_admin(caller, self)?;174 self.remove_sponsor().map_err(dispatch_to_evm::<T>)?;175 save(self)176 }177178 /// Get current sponsor.179 ///180 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.181 fn get_collection_sponsor(&self) -> Result<(address, uint256)> {182 let sponsor = match self.collection.sponsorship.sponsor() {183 Some(sponsor) => sponsor,184 None => return Ok(Default::default()),185 };186 let sponsor = T::CrossAccountId::from_sub(sponsor.clone());187 let result: (address, uint256) = if sponsor.is_canonical_substrate() {188 let sponsor = convert_cross_account_to_uint256::<T>(&sponsor);189 (Default::default(), sponsor)190 } else {191 let sponsor = *sponsor.as_eth();192 (sponsor, Default::default())193 };194 Ok(result)195 }144196145 /// Set limits for the collection.197 /// Set limits for the collection.146 /// @dev Throws error if limit not found.198 /// @dev Throws error if limit not found.235 new_admin: uint256,287 new_admin: uint256,236 ) -> Result<void> {288 ) -> Result<void> {237 let caller = T::CrossAccountId::from_eth(caller);289 let caller = T::CrossAccountId::from_eth(caller);238 let new_admin = convert_substrate_address_to_cross_account_id::<T>(new_admin);290 let new_admin = convert_uint256_to_cross_account::<T>(new_admin);239 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;291 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;240 Ok(())292 Ok(())241 }293 }248 admin: uint256,300 admin: uint256,249 ) -> Result<void> {301 ) -> Result<void> {250 let caller = T::CrossAccountId::from_eth(caller);302 let caller = T::CrossAccountId::from_eth(caller);251 let admin = convert_substrate_address_to_cross_account_id::<T>(admin);303 let admin = convert_uint256_to_cross_account::<T>(admin);252 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;304 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;253 Ok(())305 Ok(())254 }306 }422 /// @param user account to verify474 /// @param user account to verify423 /// @return "true" if account is the owner or admin475 /// @return "true" if account is the owner or admin424 fn is_owner_or_admin_substrate(&self, user: uint256) -> Result<bool> {476 fn is_owner_or_admin_substrate(&self, user: uint256) -> Result<bool> {425 let user = convert_substrate_address_to_cross_account_id::<T>(user);477 let user = convert_uint256_to_cross_account::<T>(user);426 Ok(self.is_owner_or_admin(&user))478 Ok(self.is_owner_or_admin(&user))427 }479 }428480455 /// @param newOwner new owner substrate account507 /// @param newOwner new owner substrate account456 fn set_owner_substrate(&mut self, caller: caller, new_owner: uint256) -> Result<void> {508 fn set_owner_substrate(&mut self, caller: caller, new_owner: uint256) -> Result<void> {457 let caller = T::CrossAccountId::from_eth(caller);509 let caller = T::CrossAccountId::from_eth(caller);458 let new_owner = convert_substrate_address_to_cross_account_id::<T>(new_owner);510 let new_owner = convert_uint256_to_cross_account::<T>(new_owner);459 self.set_owner_internal(caller, new_owner)511 self.set_owner_internal(caller, new_owner)460 .map_err(dispatch_to_evm::<T>)512 .map_err(dispatch_to_evm::<T>)461 }513 }pallets/common/src/eth.rsdiffbeforeafterboth59 uint256::from_big_endian(slice)59 uint256::from_big_endian(slice)60}60}616162/// Converts Substrate address to CrossAccountId62/// Convert `uint256` to `CrossAccountId`.63pub fn convert_substrate_address_to_cross_account_id<T: Config>(63pub fn convert_uint256_to_cross_account<T: Config>(from: uint256) -> T::CrossAccountId64 address: uint256,65) -> T::CrossAccountId66where64where67 T::AccountId: From<[u8; 32]>,65 T::AccountId: From<[u8; 32]>,68{66{69 let mut address_arr: [u8; 32] = Default::default();67 let mut new_admin_arr = [0_u8; 32];70 address.to_big_endian(&mut address_arr);68 from.to_big_endian(&mut new_admin_arr);71 let account_id = T::AccountId::from(address_arr);69 let account_id = T::AccountId::from(new_admin_arr);72 T::CrossAccountId::from_sub(account_id)70 T::CrossAccountId::from_sub(account_id)73}71}7472pallets/common/src/lib.rsdiffbeforeafterboth231 Ok(true)231 Ok(true)232 }232 }233234 /// Remove collection sponsor.235 pub fn remove_sponsor(&mut self) -> DispatchResult {236 self.collection.sponsorship = SponsorshipState::Disabled;237 Ok(())238 }233239234 /// Checks that the collection was created with, and must be operated upon through **Unique API**.240 /// Checks that the collection was created with, and must be operated upon through **Unique API**.235 /// Now check only the `external_collection` flag and if it's **true**, then return [`Error::CollectionIsExternal`] error.241 /// Now check only the `external_collection` flag and if it's **true**, then return [`Error::CollectionIsExternal`] error.732738733 /// Get the effective limits for the collection.739 /// Get the effective limits for the collection.734 pub fn effective_collection_limits(collection: CollectionId) -> Option<CollectionLimits> {740 pub fn effective_collection_limits(collection: CollectionId) -> Option<CollectionLimits> {735 let collection = <CollectionById<T>>::get(collection);741 let collection = <CollectionById<T>>::get(collection)?;736 if collection.is_none() {737 return None;738 }739740 let collection = collection.unwrap();741 let limits = collection.limits;742 let limits = collection.limits;742 let effective_limits = CollectionLimits {743 let effective_limits = CollectionLimits {743 account_token_ownership_limit: Some(limits.account_token_ownership_limit()),744 account_token_ownership_limit: Some(limits.account_token_ownership_limit()),pallets/fungible/CHANGELOG.mddiffbeforeafterboth223All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.445## [v0.1.4] - 2022-08-2467### Change8 - Add bound `AsRef<[u8; 32]>` to `T::CrossAccountId`.95<!-- bureaucrate goes here -->10<!-- bureaucrate goes here -->6## [v0.1.3] 2022-08-1611## [v0.1.3] 2022-08-16712pallets/fungible/Cargo.tomldiffbeforeafterboth1[package]1[package]2name = "pallet-fungible"2name = "pallet-fungible"3version = "0.1.3"3version = "0.1.4"4license = "GPLv3"4license = "GPLv3"5edition = "2021"5edition = "2021"66pallets/fungible/src/erc.rsdiffbeforeafterboth154 Collection(common_mut, CollectionHandle<T>),154 Collection(common_mut, CollectionHandle<T>),155 )155 )156)]156)]157impl<T: Config> FungibleHandle<T> where T::AccountId: From<[u8; 32]> {}157impl<T: Config> FungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}158158159generate_stubgen!(gen_impl, UniqueFungibleCall<()>, true);159generate_stubgen!(gen_impl, UniqueFungibleCall<()>, true);160generate_stubgen!(gen_iface, UniqueFungibleCall<()>, false);160generate_stubgen!(gen_iface, UniqueFungibleCall<()>, false);161161162impl<T: Config> CommonEvmHandler for FungibleHandle<T>162impl<T: Config> CommonEvmHandler for FungibleHandle<T>163where163where164 T::AccountId: From<[u8; 32]>,164 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,165{165{166 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");166 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");167167pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth22}22}232324/// @title A contract that allows you to work with collections.24/// @title A contract that allows you to work with collections.25/// @dev the ERC-165 identifier for this interface is 0xffe4da2325/// @dev the ERC-165 identifier for this interface is 0xe54be64026contract Collection is Dummy, ERC165 {26contract Collection is Dummy, ERC165 {27 /// Set collection property.27 /// Set collection property.28 ///28 ///82 dummy = 0;82 dummy = 0;83 }83 }8485 /// Set the substrate sponsor of the collection.86 ///87 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.88 ///89 /// @param sponsor Substrate address of the sponsor from whose account funds will be debited for operations with the contract.90 /// @dev EVM selector for this function is: 0xc74d6751,91 /// or in textual repr: setCollectionSponsorSubstrate(uint256)92 function setCollectionSponsorSubstrate(uint256 sponsor) public {93 require(false, stub_error);94 sponsor;95 dummy = 0;96 }9798 /// @dev EVM selector for this function is: 0x058ac185,99 /// or in textual repr: hasCollectionPendingSponsor()100 function hasCollectionPendingSponsor() public view returns (bool) {101 require(false, stub_error);102 dummy;103 return false;104 }8410585 /// Collection sponsorship confirmation.106 /// Collection sponsorship confirmation.86 ///107 ///92 dummy = 0;113 dummy = 0;93 }114 }115116 /// Remove collection sponsor.117 /// @dev EVM selector for this function is: 0x6e0326a3,118 /// or in textual repr: removeCollectionSponsor()119 function removeCollectionSponsor() public {120 require(false, stub_error);121 dummy = 0;122 }123124 /// Get current sponsor.125 ///126 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.127 /// @dev EVM selector for this function is: 0xb66bbc14,128 /// or in textual repr: getCollectionSponsor()129 function getCollectionSponsor() public view returns (Tuple6 memory) {130 require(false, stub_error);131 dummy;132 return Tuple6(0x0000000000000000000000000000000000000000, 0);133 }9413495 /// Set limits for the collection.135 /// Set limits for the collection.96 /// @dev Throws error if limit not found.136 /// @dev Throws error if limit not found.310 }350 }311}351}352353/// @dev anonymous struct354struct Tuple6 {355 address field_0;356 uint256 field_1;357}312358313/// @dev the ERC-165 identifier for this interface is 0x79cc6790359/// @dev the ERC-165 identifier for this interface is 0x79cc6790314contract ERC20UniqueExtensions is Dummy, ERC165 {360contract ERC20UniqueExtensions is Dummy, ERC165 {pallets/nonfungible/CHANGELOG.mddiffbeforeafterboth223All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.445## [v0.1.5] - 2022-08-2467### Change8 - Add bound `AsRef<[u8; 32]>` to `T::CrossAccountId`.95<!-- bureaucrate goes here -->10<!-- bureaucrate goes here -->6## [v0.1.4] 2022-08-1611## [v0.1.4] 2022-08-16712pallets/nonfungible/Cargo.tomldiffbeforeafterboth1[package]1[package]2name = "pallet-nonfungible"2name = "pallet-nonfungible"3version = "0.1.4"3version = "0.1.5"4license = "GPLv3"4license = "GPLv3"5edition = "2021"5edition = "2021"66pallets/nonfungible/src/erc.rsdiffbeforeafterboth740 TokenProperties,740 TokenProperties,741 )741 )742)]742)]743impl<T: Config> NonfungibleHandle<T> where T::AccountId: From<[u8; 32]> {}743impl<T: Config> NonfungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}744744745// Not a tests, but code generators745// Not a tests, but code generators746generate_stubgen!(gen_impl, UniqueNFTCall<()>, true);746generate_stubgen!(gen_impl, UniqueNFTCall<()>, true);747generate_stubgen!(gen_iface, UniqueNFTCall<()>, false);747generate_stubgen!(gen_iface, UniqueNFTCall<()>, false);748748749impl<T: Config> CommonEvmHandler for NonfungibleHandle<T>749impl<T: Config> CommonEvmHandler for NonfungibleHandle<T>750where750where751 T::AccountId: From<[u8; 32]>,751 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,752{752{753 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueNFT.raw");753 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueNFT.raw");754754pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth99}99}100100101/// @title A contract that allows you to work with collections.101/// @title A contract that allows you to work with collections.102/// @dev the ERC-165 identifier for this interface is 0xffe4da23102/// @dev the ERC-165 identifier for this interface is 0xe54be640103contract Collection is Dummy, ERC165 {103contract Collection is Dummy, ERC165 {104 /// Set collection property.104 /// Set collection property.105 ///105 ///159 dummy = 0;159 dummy = 0;160 }160 }161162 /// Set the substrate sponsor of the collection.163 ///164 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.165 ///166 /// @param sponsor Substrate address of the sponsor from whose account funds will be debited for operations with the contract.167 /// @dev EVM selector for this function is: 0xc74d6751,168 /// or in textual repr: setCollectionSponsorSubstrate(uint256)169 function setCollectionSponsorSubstrate(uint256 sponsor) public {170 require(false, stub_error);171 sponsor;172 dummy = 0;173 }174175 /// @dev EVM selector for this function is: 0x058ac185,176 /// or in textual repr: hasCollectionPendingSponsor()177 function hasCollectionPendingSponsor() public view returns (bool) {178 require(false, stub_error);179 dummy;180 return false;181 }161182162 /// Collection sponsorship confirmation.183 /// Collection sponsorship confirmation.163 ///184 ///169 dummy = 0;190 dummy = 0;170 }191 }192193 /// Remove collection sponsor.194 /// @dev EVM selector for this function is: 0x6e0326a3,195 /// or in textual repr: removeCollectionSponsor()196 function removeCollectionSponsor() public {197 require(false, stub_error);198 dummy = 0;199 }200201 /// Get current sponsor.202 ///203 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.204 /// @dev EVM selector for this function is: 0xb66bbc14,205 /// or in textual repr: getCollectionSponsor()206 function getCollectionSponsor() public view returns (Tuple17 memory) {207 require(false, stub_error);208 dummy;209 return Tuple17(0x0000000000000000000000000000000000000000, 0);210 }171211172 /// Set limits for the collection.212 /// Set limits for the collection.173 /// @dev Throws error if limit not found.213 /// @dev Throws error if limit not found.387 }427 }388}428}429430/// @dev anonymous struct431struct Tuple17 {432 address field_0;433 uint256 field_1;434}389435390/// @title ERC721 Token that can be irreversibly burned (destroyed).436/// @title ERC721 Token that can be irreversibly burned (destroyed).391/// @dev the ERC-165 identifier for this interface is 0x42966c68437/// @dev the ERC-165 identifier for this interface is 0x42966c68pallets/refungible/CHANGELOG.mddiffbeforeafterboth223All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.445## [v0.2.4] - 2022-08-2467### Change8 - Add bound `AsRef<[u8; 32]>` to `T::CrossAccountId`.95<!-- bureaucrate goes here -->10<!-- bureaucrate goes here -->6## [v0.2.3] 2022-08-1611## [v0.2.3] 2022-08-16712pallets/refungible/Cargo.tomldiffbeforeafterboth1[package]1[package]2name = "pallet-refungible"2name = "pallet-refungible"3version = "0.2.3"3version = "0.2.4"4license = "GPLv3"4license = "GPLv3"5edition = "2021"5edition = "2021"66pallets/refungible/src/erc.rsdiffbeforeafterboth789 TokenProperties,789 TokenProperties,790 )790 )791)]791)]792impl<T: Config> RefungibleHandle<T> where T::AccountId: From<[u8; 32]> {}792impl<T: Config> RefungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}793793794// Not a tests, but code generators794// Not a tests, but code generators795generate_stubgen!(gen_impl, UniqueRefungibleCall<()>, true);795generate_stubgen!(gen_impl, UniqueRefungibleCall<()>, true);796generate_stubgen!(gen_iface, UniqueRefungibleCall<()>, false);796generate_stubgen!(gen_iface, UniqueRefungibleCall<()>, false);797797798impl<T: Config> CommonEvmHandler for RefungibleHandle<T>798impl<T: Config> CommonEvmHandler for RefungibleHandle<T>799where799where800 T::AccountId: From<[u8; 32]>,800 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,801{801{802 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueRefungible.raw");802 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueRefungible.raw");803 fn call(803 fn call(pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth99}99}100100101/// @title A contract that allows you to work with collections.101/// @title A contract that allows you to work with collections.102/// @dev the ERC-165 identifier for this interface is 0xffe4da23102/// @dev the ERC-165 identifier for this interface is 0xe54be640103contract Collection is Dummy, ERC165 {103contract Collection is Dummy, ERC165 {104 /// Set collection property.104 /// Set collection property.105 ///105 ///159 dummy = 0;159 dummy = 0;160 }160 }161162 /// Set the substrate sponsor of the collection.163 ///164 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.165 ///166 /// @param sponsor Substrate address of the sponsor from whose account funds will be debited for operations with the contract.167 /// @dev EVM selector for this function is: 0xc74d6751,168 /// or in textual repr: setCollectionSponsorSubstrate(uint256)169 function setCollectionSponsorSubstrate(uint256 sponsor) public {170 require(false, stub_error);171 sponsor;172 dummy = 0;173 }174175 /// @dev EVM selector for this function is: 0x058ac185,176 /// or in textual repr: hasCollectionPendingSponsor()177 function hasCollectionPendingSponsor() public view returns (bool) {178 require(false, stub_error);179 dummy;180 return false;181 }161182162 /// Collection sponsorship confirmation.183 /// Collection sponsorship confirmation.163 ///184 ///169 dummy = 0;190 dummy = 0;170 }191 }192193 /// Remove collection sponsor.194 /// @dev EVM selector for this function is: 0x6e0326a3,195 /// or in textual repr: removeCollectionSponsor()196 function removeCollectionSponsor() public {197 require(false, stub_error);198 dummy = 0;199 }200201 /// Get current sponsor.202 ///203 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.204 /// @dev EVM selector for this function is: 0xb66bbc14,205 /// or in textual repr: getCollectionSponsor()206 function getCollectionSponsor() public view returns (Tuple17 memory) {207 require(false, stub_error);208 dummy;209 return Tuple17(0x0000000000000000000000000000000000000000, 0);210 }171211172 /// Set limits for the collection.212 /// Set limits for the collection.173 /// @dev Throws error if limit not found.213 /// @dev Throws error if limit not found.387 }427 }388}428}429430/// @dev anonymous struct431struct Tuple17 {432 address field_0;433 uint256 field_1;434}389435390/// @title ERC721 Token that can be irreversibly burned (destroyed).436/// @title ERC721 Token that can be irreversibly burned (destroyed).391/// @dev the ERC-165 identifier for this interface is 0x42966c68437/// @dev the ERC-165 identifier for this interface is 0x42966c68runtime/common/dispatch.rsdiffbeforeafterboth124 + pallet_fungible::Config124 + pallet_fungible::Config125 + pallet_nonfungible::Config125 + pallet_nonfungible::Config126 + pallet_refungible::Config,126 + pallet_refungible::Config,127 T::AccountId: From<[u8; 32]>,127 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,128{128{129 fn is_reserved(target: &H160) -> bool {129 fn is_reserved(target: &H160) -> bool {130 map_eth_to_id(target).is_some()130 map_eth_to_id(target).is_some()tests/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 0xffe4da2316/// @dev the ERC-165 identifier for this interface is 0xe54be64017interface Collection is Dummy, ERC165 {17interface Collection is Dummy, ERC165 {18 /// Set collection property.18 /// Set collection property.19 ///19 ///53 /// or in textual repr: setCollectionSponsor(address)53 /// or in textual repr: setCollectionSponsor(address)54 function setCollectionSponsor(address sponsor) external;54 function setCollectionSponsor(address sponsor) external;5556 /// Set the substrate sponsor of the collection.57 ///58 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.59 ///60 /// @param sponsor Substrate address of the sponsor from whose account funds will be debited for operations with the contract.61 /// @dev EVM selector for this function is: 0xc74d6751,62 /// or in textual repr: setCollectionSponsorSubstrate(uint256)63 function setCollectionSponsorSubstrate(uint256 sponsor) external;6465 /// @dev EVM selector for this function is: 0x058ac185,66 /// or in textual repr: hasCollectionPendingSponsor()67 function hasCollectionPendingSponsor() external view returns (bool);556856 /// Collection sponsorship confirmation.69 /// Collection sponsorship confirmation.57 ///70 ///60 /// or in textual repr: confirmCollectionSponsorship()73 /// or in textual repr: confirmCollectionSponsorship()61 function confirmCollectionSponsorship() external;74 function confirmCollectionSponsorship() external;7576 /// Remove collection sponsor.77 /// @dev EVM selector for this function is: 0x6e0326a3,78 /// or in textual repr: removeCollectionSponsor()79 function removeCollectionSponsor() external;8081 /// Get current sponsor.82 ///83 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.84 /// @dev EVM selector for this function is: 0xb66bbc14,85 /// or in textual repr: getCollectionSponsor()86 function getCollectionSponsor() external view returns (Tuple6 memory);628763 /// Set limits for the collection.88 /// Set limits for the collection.64 /// @dev Throws error if limit not found.89 /// @dev Throws error if limit not found.200 function setOwnerSubstrate(uint256 newOwner) external;225 function setOwnerSubstrate(uint256 newOwner) external;201}226}227228/// @dev anonymous struct229struct Tuple6 {230 address field_0;231 uint256 field_1;232}202233203/// @dev the ERC-165 identifier for this interface is 0x79cc6790234/// @dev the ERC-165 identifier for this interface is 0x79cc6790204interface ERC20UniqueExtensions is Dummy, ERC165 {235interface ERC20UniqueExtensions is Dummy, ERC165 {tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth65}65}666667/// @title A contract that allows you to work with collections.67/// @title A contract that allows you to work with collections.68/// @dev the ERC-165 identifier for this interface is 0xffe4da2368/// @dev the ERC-165 identifier for this interface is 0xe54be64069interface Collection is Dummy, ERC165 {69interface Collection is Dummy, ERC165 {70 /// Set collection property.70 /// Set collection property.71 ///71 ///105 /// or in textual repr: setCollectionSponsor(address)105 /// or in textual repr: setCollectionSponsor(address)106 function setCollectionSponsor(address sponsor) external;106 function setCollectionSponsor(address sponsor) external;107108 /// Set the substrate sponsor of the collection.109 ///110 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.111 ///112 /// @param sponsor Substrate address of the sponsor from whose account funds will be debited for operations with the contract.113 /// @dev EVM selector for this function is: 0xc74d6751,114 /// or in textual repr: setCollectionSponsorSubstrate(uint256)115 function setCollectionSponsorSubstrate(uint256 sponsor) external;116117 /// @dev EVM selector for this function is: 0x058ac185,118 /// or in textual repr: hasCollectionPendingSponsor()119 function hasCollectionPendingSponsor() external view returns (bool);107120108 /// Collection sponsorship confirmation.121 /// Collection sponsorship confirmation.109 ///122 ///112 /// or in textual repr: confirmCollectionSponsorship()125 /// or in textual repr: confirmCollectionSponsorship()113 function confirmCollectionSponsorship() external;126 function confirmCollectionSponsorship() external;127128 /// Remove collection sponsor.129 /// @dev EVM selector for this function is: 0x6e0326a3,130 /// or in textual repr: removeCollectionSponsor()131 function removeCollectionSponsor() external;132133 /// Get current sponsor.134 ///135 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.136 /// @dev EVM selector for this function is: 0xb66bbc14,137 /// or in textual repr: getCollectionSponsor()138 function getCollectionSponsor() external view returns (Tuple17 memory);114139115 /// Set limits for the collection.140 /// Set limits for the collection.116 /// @dev Throws error if limit not found.141 /// @dev Throws error if limit not found.252 function setOwnerSubstrate(uint256 newOwner) external;277 function setOwnerSubstrate(uint256 newOwner) external;253}278}279280/// @dev anonymous struct281struct Tuple17 {282 address field_0;283 uint256 field_1;284}254285255/// @title ERC721 Token that can be irreversibly burned (destroyed).286/// @title ERC721 Token that can be irreversibly burned (destroyed).256/// @dev the ERC-165 identifier for this interface is 0x42966c68287/// @dev the ERC-165 identifier for this interface is 0x42966c68tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth65}65}666667/// @title A contract that allows you to work with collections.67/// @title A contract that allows you to work with collections.68/// @dev the ERC-165 identifier for this interface is 0xffe4da2368/// @dev the ERC-165 identifier for this interface is 0xe54be64069interface Collection is Dummy, ERC165 {69interface Collection is Dummy, ERC165 {70 /// Set collection property.70 /// Set collection property.71 ///71 ///105 /// or in textual repr: setCollectionSponsor(address)105 /// or in textual repr: setCollectionSponsor(address)106 function setCollectionSponsor(address sponsor) external;106 function setCollectionSponsor(address sponsor) external;107108 /// Set the substrate sponsor of the collection.109 ///110 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.111 ///112 /// @param sponsor Substrate address of the sponsor from whose account funds will be debited for operations with the contract.113 /// @dev EVM selector for this function is: 0xc74d6751,114 /// or in textual repr: setCollectionSponsorSubstrate(uint256)115 function setCollectionSponsorSubstrate(uint256 sponsor) external;116117 /// @dev EVM selector for this function is: 0x058ac185,118 /// or in textual repr: hasCollectionPendingSponsor()119 function hasCollectionPendingSponsor() external view returns (bool);107120108 /// Collection sponsorship confirmation.121 /// Collection sponsorship confirmation.109 ///122 ///112 /// or in textual repr: confirmCollectionSponsorship()125 /// or in textual repr: confirmCollectionSponsorship()113 function confirmCollectionSponsorship() external;126 function confirmCollectionSponsorship() external;127128 /// Remove collection sponsor.129 /// @dev EVM selector for this function is: 0x6e0326a3,130 /// or in textual repr: removeCollectionSponsor()131 function removeCollectionSponsor() external;132133 /// Get current sponsor.134 ///135 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.136 /// @dev EVM selector for this function is: 0xb66bbc14,137 /// or in textual repr: getCollectionSponsor()138 function getCollectionSponsor() external view returns (Tuple17 memory);114139115 /// Set limits for the collection.140 /// Set limits for the collection.116 /// @dev Throws error if limit not found.141 /// @dev Throws error if limit not found.252 function setOwnerSubstrate(uint256 newOwner) external;277 function setOwnerSubstrate(uint256 newOwner) external;253}278}279280/// @dev anonymous struct281struct Tuple17 {282 address field_0;283 uint256 field_1;284}254285255/// @title ERC721 Token that can be irreversibly burned (destroyed).286/// @title ERC721 Token that can be irreversibly burned (destroyed).256/// @dev the ERC-165 identifier for this interface is 0x42966c68287/// @dev the ERC-165 identifier for this interface is 0x42966c68tests/src/eth/collectionSponsoring.test.tsdiffbeforeafterboth1import {addToAllowListExpectSuccess, confirmSponsorshipExpectSuccess, createCollectionExpectSuccess, enablePublicMintingExpectSuccess, getDetailedCollectionInfo, setCollectionSponsorExpectSuccess} from '../util/helpers';1import {addToAllowListExpectSuccess, bigIntToSub, confirmSponsorshipExpectSuccess, createCollectionExpectSuccess, enablePublicMintingExpectSuccess, getDetailedCollectionInfo, setCollectionSponsorExpectSuccess} from '../util/helpers';2import {itWeb3, createEthAccount, collectionIdToAddress, GAS_ARGS, normalizeEvents, createEthAccountWithBalance, evmCollectionHelpers, getCollectionAddressFromResult, evmCollection, ethBalanceViaSub} from './util/helpers';2import {itWeb3, createEthAccount, collectionIdToAddress, GAS_ARGS, normalizeEvents, createEthAccountWithBalance, evmCollectionHelpers, getCollectionAddressFromResult, evmCollection, ethBalanceViaSub, subToEth} from './util/helpers';3import nonFungibleAbi from './nonFungibleAbi.json';3import nonFungibleAbi from './nonFungibleAbi.json';4import {expect} from 'chai';4import {expect} from 'chai';5import {evmToAddress} from '@polkadot/util-crypto';5import {evmToAddress} from '@polkadot/util-crypto';6import {submitTransactionAsync} from '../substrate/substrate-api';7import getBalance from '../substrate/get-balance';687describe('evm collection sponsoring', () => {9describe('evm collection sponsoring', () => {8 itWeb3('sponsors mint transactions', async ({web3, privateKeyWrapper}) => {10 itWeb3('sponsors mint transactions', async ({web3, privateKeyWrapper}) => {38 ]);40 ]);39 });41 });4243 itWeb3('Set substrate sponsor', async ({api, web3, privateKeyWrapper}) => {44 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);45 const collectionHelpers = evmCollectionHelpers(web3, owner);46 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();47 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);48 const sponsor = privateKeyWrapper('//Alice');49 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);5051 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;52 result = await collectionEvm.methods.setCollectionSponsorSubstrate(sponsor.addressRaw).send({from: owner});53 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;54 55 const confirmTx = await api.tx.unique.confirmSponsorship(collectionId);56 await submitTransactionAsync(sponsor, confirmTx);57 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;58 59 const sponsorTuple = await collectionEvm.methods.getCollectionSponsor().call({from: owner});60 expect(bigIntToSub(api, BigInt(sponsorTuple[1]))).to.be.eq(sponsor.address);61 });6263 itWeb3('Remove sponsor', async ({api, web3, privateKeyWrapper}) => {64 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);65 const collectionHelpers = evmCollectionHelpers(web3, owner);66 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();67 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);68 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);69 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);7071 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;72 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});73 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;74 75 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});76 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;77 78 await collectionEvm.methods.removeCollectionSponsor().send({from: owner});79 80 const sponsorTuple = await collectionEvm.methods.getCollectionSponsor().call({from: owner});81 expect(sponsorTuple.field_0).to.be.eq('0x0000000000000000000000000000000000000000');82 });408341 itWeb3('Sponsoring collection from evm address via access list', async ({api, web3, privateKeyWrapper}) => {84 itWeb3('Sponsoring collection from evm address via access list', async ({api, web3, privateKeyWrapper}) => {42 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);85 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);107 }150 }108 });151 });152153 itWeb3('Sponsoring collection from substrate address via access list', async ({api, web3, privateKeyWrapper}) => {154 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);155 const collectionHelpers = evmCollectionHelpers(web3, owner);156 const result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();157 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);158 const sponsor = privateKeyWrapper('//Alice');159 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);160161 await collectionEvm.methods.setCollectionSponsorSubstrate(sponsor.addressRaw).send({from: owner});162 163 const confirmTx = await api.tx.unique.confirmSponsorship(collectionId);164 await submitTransactionAsync(sponsor, confirmTx);165 166 const user = createEthAccount(web3);167 const nextTokenId = await collectionEvm.methods.nextTokenId().call();168 expect(nextTokenId).to.be.equal('1');169170 await collectionEvm.methods.setCollectionAccess(1 /*'AllowList'*/).send({from: owner});171 await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});172 await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});173174 const ownerBalanceBefore = await ethBalanceViaSub(api, owner);175 const sponsorBalanceBefore = (await getBalance(api, [sponsor.address]))[0];176177 {178 const nextTokenId = await collectionEvm.methods.nextTokenId().call();179 expect(nextTokenId).to.be.equal('1');180 const result = await collectionEvm.methods.mintWithTokenURI(181 user,182 nextTokenId,183 'Test URI',184 ).send({from: user});185 const events = normalizeEvents(result.events);186187 expect(events).to.be.deep.equal([188 {189 address: collectionIdAddress,190 event: 'Transfer',191 args: {192 from: '0x0000000000000000000000000000000000000000',193 to: user,194 tokenId: nextTokenId,195 },196 },197 ]);198199 const ownerBalanceAfter = await ethBalanceViaSub(api, owner);200 const sponsorBalanceAfter = (await getBalance(api, [sponsor.address]))[0];201202 expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');203 expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);204 expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;205 }206 });109207110 itWeb3('Check that transaction via EVM spend money from sponsor address', async ({api, web3, privateKeyWrapper}) => {208 itWeb3('Check that transaction via EVM spend money from sponsor address', async ({api, web3, privateKeyWrapper}) => {111 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);209 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);tests/src/eth/fungibleAbi.jsondiffbeforeafterboth150 "stateMutability": "nonpayable",150 "stateMutability": "nonpayable",151 "type": "function"151 "type": "function"152 },152 },153 {154 "inputs": [],155 "name": "getCollectionSponsor",156 "outputs": [157 {158 "components": [159 { "internalType": "address", "name": "field_0", "type": "address" },160 { "internalType": "uint256", "name": "field_1", "type": "uint256" }161 ],162 "internalType": "struct Tuple6",163 "name": "",164 "type": "tuple"165 }166 ],167 "stateMutability": "view",168 "type": "function"169 },170 {171 "inputs": [],172 "name": "hasCollectionPendingSponsor",173 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],174 "stateMutability": "view",175 "type": "function"176 },153 {177 {154 "inputs": [178 "inputs": [155 { "internalType": "address", "name": "user", "type": "address" }179 { "internalType": "address", "name": "user", "type": "address" }193 "stateMutability": "nonpayable",217 "stateMutability": "nonpayable",194 "type": "function"218 "type": "function"195 },219 },220 {221 "inputs": [],222 "name": "removeCollectionSponsor",223 "outputs": [],224 "stateMutability": "nonpayable",225 "type": "function"226 },196 {227 {197 "inputs": [228 "inputs": [198 { "internalType": "address", "name": "user", "type": "address" }229 { "internalType": "address", "name": "user", "type": "address" }276 "stateMutability": "nonpayable",307 "stateMutability": "nonpayable",277 "type": "function"308 "type": "function"278 },309 },310 {311 "inputs": [312 { "internalType": "uint256", "name": "sponsor", "type": "uint256" }313 ],314 "name": "setCollectionSponsorSubstrate",315 "outputs": [],316 "stateMutability": "nonpayable",317 "type": "function"318 },279 {319 {280 "inputs": [320 "inputs": [281 { "internalType": "address", "name": "newOwner", "type": "address" }321 { "internalType": "address", "name": "newOwner", "type": "address" }tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth199 "stateMutability": "view",199 "stateMutability": "view",200 "type": "function"200 "type": "function"201 },201 },202 {203 "inputs": [],204 "name": "getCollectionSponsor",205 "outputs": [206 {207 "components": [208 { "internalType": "address", "name": "field_0", "type": "address" },209 { "internalType": "uint256", "name": "field_1", "type": "uint256" }210 ],211 "internalType": "struct Tuple17",212 "name": "",213 "type": "tuple"214 }215 ],216 "stateMutability": "view",217 "type": "function"218 },219 {220 "inputs": [],221 "name": "hasCollectionPendingSponsor",222 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],223 "stateMutability": "view",224 "type": "function"225 },202 {226 {203 "inputs": [227 "inputs": [204 { "internalType": "address", "name": "owner", "type": "address" },228 { "internalType": "address", "name": "owner", "type": "address" },334 "stateMutability": "nonpayable",358 "stateMutability": "nonpayable",335 "type": "function"359 "type": "function"336 },360 },361 {362 "inputs": [],363 "name": "removeCollectionSponsor",364 "outputs": [],365 "stateMutability": "nonpayable",366 "type": "function"367 },337 {368 {338 "inputs": [369 "inputs": [339 { "internalType": "address", "name": "user", "type": "address" }370 { "internalType": "address", "name": "user", "type": "address" }450 "stateMutability": "nonpayable",481 "stateMutability": "nonpayable",451 "type": "function"482 "type": "function"452 },483 },484 {485 "inputs": [486 { "internalType": "uint256", "name": "sponsor", "type": "uint256" }487 ],488 "name": "setCollectionSponsorSubstrate",489 "outputs": [],490 "stateMutability": "nonpayable",491 "type": "function"492 },453 {493 {454 "inputs": [494 "inputs": [455 { "internalType": "address", "name": "newOwner", "type": "address" }495 { "internalType": "address", "name": "newOwner", "type": "address" }tests/src/eth/reFungibleAbi.jsondiffbeforeafterboth199 "stateMutability": "view",199 "stateMutability": "view",200 "type": "function"200 "type": "function"201 },201 },202 {203 "inputs": [],204 "name": "getCollectionSponsor",205 "outputs": [206 {207 "components": [208 { "internalType": "address", "name": "field_0", "type": "address" },209 { "internalType": "uint256", "name": "field_1", "type": "uint256" }210 ],211 "internalType": "struct Tuple17",212 "name": "",213 "type": "tuple"214 }215 ],216 "stateMutability": "view",217 "type": "function"218 },219 {220 "inputs": [],221 "name": "hasCollectionPendingSponsor",222 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],223 "stateMutability": "view",224 "type": "function"225 },202 {226 {203 "inputs": [227 "inputs": [204 { "internalType": "address", "name": "owner", "type": "address" },228 { "internalType": "address", "name": "owner", "type": "address" },334 "stateMutability": "nonpayable",358 "stateMutability": "nonpayable",335 "type": "function"359 "type": "function"336 },360 },361 {362 "inputs": [],363 "name": "removeCollectionSponsor",364 "outputs": [],365 "stateMutability": "nonpayable",366 "type": "function"367 },337 {368 {338 "inputs": [369 "inputs": [339 { "internalType": "address", "name": "user", "type": "address" }370 { "internalType": "address", "name": "user", "type": "address" }450 "stateMutability": "nonpayable",481 "stateMutability": "nonpayable",451 "type": "function"482 "type": "function"452 },483 },484 {485 "inputs": [486 { "internalType": "uint256", "name": "sponsor", "type": "uint256" }487 ],488 "name": "setCollectionSponsorSubstrate",489 "outputs": [],490 "stateMutability": "nonpayable",491 "type": "function"492 },453 {493 {454 "inputs": [494 "inputs": [455 { "internalType": "address", "name": "newOwner", "type": "address" }495 { "internalType": "address", "name": "newOwner", "type": "address" }tests/src/util/helpers.tsdiffbeforeafterboth99 }99 }100}100}101102export function bigIntToSub(api: ApiPromise, number: bigint) {103 return api.registry.createType('AccountId', '0x' + number.toString(16).padStart(64, '0')).toJSON();104}101105102export function normalizeAccountId(input: string | AccountId | CrossAccountId | IKeyringPair): CrossAccountId {106export function normalizeAccountId(input: string | AccountId | CrossAccountId | IKeyringPair): CrossAccountId {103 if (typeof input === 'string') {107 if (typeof input === 'string') {