difftreelog
Merge pull request #574 from UniqueNetwork/feature/eth_passthrought
in: master
Feature/eth passthrought
19 files changed
pallets/common/src/erc.rsdiffbeforeafterboth20 solidity_interface, solidity, ToLog,20 solidity_interface, solidity, ToLog,21 types::*,21 types::*,22 execution::{Result, Error},22 execution::{Result, Error},23 weight,23};24};24pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId};25pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId};25use pallet_evm_coder_substrate::dispatch_to_evm;26use pallet_evm_coder_substrate::dispatch_to_evm;31use alloc::format;32use alloc::format;323333use crate::{34use crate::{34 Pallet, CollectionHandle, Config, CollectionProperties,35 Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,35 eth::{convert_cross_account_to_uint256, convert_uint256_to_cross_account},36 eth::{37 convert_cross_account_to_uint256, convert_uint256_to_cross_account,38 convert_cross_account_to_tuple,39 },40 weights::WeightInfo,36};41};374238/// Events for ethereum collection helper.43/// Events for ethereum collection helper.69 ///74 ///70 /// @param key Property key.75 /// @param key Property key.71 /// @param value Propery value.76 /// @param value Propery value.77 #[weight(<SelfWeightOf<T>>::set_collection_properties(1))]72 fn set_collection_property(78 fn set_collection_property(73 &mut self,79 &mut self,74 caller: caller,80 caller: caller,88 /// Delete collection property.94 /// Delete collection property.89 ///95 ///90 /// @param key Property key.96 /// @param key Property key.97 #[weight(<SelfWeightOf<T>>::delete_collection_properties(1))]91 fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {98 fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {99 self.consume_store_reads_and_writes(1, 1)?;10092 let caller = T::CrossAccountId::from_eth(caller);101 let caller = T::CrossAccountId::from_eth(caller);93 let key = <Vec<u8>>::from(key)102 let key = <Vec<u8>>::from(key)94 .try_into()103 .try_into()120 ///129 ///121 /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.130 /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.122 fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result<void> {131 fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result<void> {132 self.consume_store_reads_and_writes(1, 1)?;133123 check_is_owner_or_admin(caller, self)?;134 check_is_owner_or_admin(caller, self)?;124135125 let sponsor = T::CrossAccountId::from_eth(sponsor);136 let sponsor = T::CrossAccountId::from_eth(sponsor);138 caller: caller,149 caller: caller,139 sponsor: uint256,150 sponsor: uint256,140 ) -> Result<void> {151 ) -> Result<void> {152 self.consume_store_reads_and_writes(1, 1)?;153141 check_is_owner_or_admin(caller, self)?;154 check_is_owner_or_admin(caller, self)?;142155143 let sponsor = convert_uint256_to_cross_account::<T>(sponsor);156 let sponsor = convert_uint256_to_cross_account::<T>(sponsor);146 save(self)159 save(self)147 }160 }148161149 // /// Whether there is a pending sponsor.162 /// Whether there is a pending sponsor.150 fn has_collection_pending_sponsor(&self) -> Result<bool> {163 fn has_collection_pending_sponsor(&self) -> Result<bool> {151 Ok(matches!(164 Ok(matches!(152 self.collection.sponsorship,165 self.collection.sponsorship,158 ///171 ///159 /// @dev After setting the sponsor for the collection, it must be confirmed with this function.172 /// @dev After setting the sponsor for the collection, it must be confirmed with this function.160 fn confirm_collection_sponsorship(&mut self, caller: caller) -> Result<void> {173 fn confirm_collection_sponsorship(&mut self, caller: caller) -> Result<void> {174 self.consume_store_writes(1)?;175161 let caller = T::CrossAccountId::from_eth(caller);176 let caller = T::CrossAccountId::from_eth(caller);162 if !self177 if !self163 .confirm_sponsorship(caller.as_sub())178 .confirm_sponsorship(caller.as_sub())170185171 /// Remove collection sponsor.186 /// Remove collection sponsor.172 fn remove_collection_sponsor(&mut self, caller: caller) -> Result<void> {187 fn remove_collection_sponsor(&mut self, caller: caller) -> Result<void> {188 self.consume_store_reads_and_writes(1, 1)?;173 check_is_owner_or_admin(caller, self)?;189 check_is_owner_or_admin(caller, self)?;174 self.remove_sponsor().map_err(dispatch_to_evm::<T>)?;190 self.remove_sponsor().map_err(dispatch_to_evm::<T>)?;175 save(self)191 save(self)206 /// @param value Value of the limit.222 /// @param value Value of the limit.207 #[solidity(rename_selector = "setCollectionLimit")]223 #[solidity(rename_selector = "setCollectionLimit")]208 fn set_int_limit(&mut self, caller: caller, limit: string, value: uint32) -> Result<void> {224 fn set_int_limit(&mut self, caller: caller, limit: string, value: uint32) -> Result<void> {225 self.consume_store_reads_and_writes(1, 1)?;226209 check_is_owner_or_admin(caller, self)?;227 check_is_owner_or_admin(caller, self)?;210 let mut limits = self.limits.clone();228 let mut limits = self.limits.clone();211229249 /// @param value Value of the limit.267 /// @param value Value of the limit.250 #[solidity(rename_selector = "setCollectionLimit")]268 #[solidity(rename_selector = "setCollectionLimit")]251 fn set_bool_limit(&mut self, caller: caller, limit: string, value: bool) -> Result<void> {269 fn set_bool_limit(&mut self, caller: caller, limit: string, value: bool) -> Result<void> {270 self.consume_store_reads_and_writes(1, 1)?;271252 check_is_owner_or_admin(caller, self)?;272 check_is_owner_or_admin(caller, self)?;253 let mut limits = self.limits.clone();273 let mut limits = self.limits.clone();254274275 }295 }276296277 /// Get contract address.297 /// Get contract address.278 fn contract_address(&self, _caller: caller) -> Result<address> {298 fn contract_address(&self) -> Result<address> {279 Ok(crate::eth::collection_id_to_address(self.id))299 Ok(crate::eth::collection_id_to_address(self.id))280 }300 }281301286 caller: caller,306 caller: caller,287 new_admin: uint256,307 new_admin: uint256,288 ) -> Result<void> {308 ) -> Result<void> {309 self.consume_store_writes(2)?;310289 let caller = T::CrossAccountId::from_eth(caller);311 let caller = T::CrossAccountId::from_eth(caller);290 let new_admin = convert_uint256_to_cross_account::<T>(new_admin);312 let new_admin = convert_uint256_to_cross_account::<T>(new_admin);291 <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>)?;299 caller: caller,321 caller: caller,300 admin: uint256,322 admin: uint256,301 ) -> Result<void> {323 ) -> Result<void> {324 self.consume_store_writes(2)?;325302 let caller = T::CrossAccountId::from_eth(caller);326 let caller = T::CrossAccountId::from_eth(caller);303 let admin = convert_uint256_to_cross_account::<T>(admin);327 let admin = convert_uint256_to_cross_account::<T>(admin);304 <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>)?;308 /// Add collection admin.332 /// Add collection admin.309 /// @param newAdmin Address of the added administrator.333 /// @param newAdmin Address of the added administrator.310 fn add_collection_admin(&mut self, caller: caller, new_admin: address) -> Result<void> {334 fn add_collection_admin(&mut self, caller: caller, new_admin: address) -> Result<void> {335 self.consume_store_writes(2)?;336311 let caller = T::CrossAccountId::from_eth(caller);337 let caller = T::CrossAccountId::from_eth(caller);312 let new_admin = T::CrossAccountId::from_eth(new_admin);338 let new_admin = T::CrossAccountId::from_eth(new_admin);313 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;339 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;318 ///344 ///319 /// @param admin Address of the removed administrator.345 /// @param admin Address of the removed administrator.320 fn remove_collection_admin(&mut self, caller: caller, admin: address) -> Result<void> {346 fn remove_collection_admin(&mut self, caller: caller, admin: address) -> Result<void> {347 self.consume_store_writes(2)?;348321 let caller = T::CrossAccountId::from_eth(caller);349 let caller = T::CrossAccountId::from_eth(caller);322 let admin = T::CrossAccountId::from_eth(admin);350 let admin = T::CrossAccountId::from_eth(admin);323 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;351 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;329 /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'357 /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'330 #[solidity(rename_selector = "setCollectionNesting")]358 #[solidity(rename_selector = "setCollectionNesting")]331 fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {359 fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {360 self.consume_store_reads_and_writes(1, 1)?;361332 check_is_owner_or_admin(caller, self)?;362 check_is_owner_or_admin(caller, self)?;333363334 let mut permissions = self.collection.permissions.clone();364 let mut permissions = self.collection.permissions.clone();358 enable: bool,388 enable: bool,359 collections: Vec<address>,389 collections: Vec<address>,360 ) -> Result<void> {390 ) -> Result<void> {391 self.consume_store_reads_and_writes(1, 1)?;392361 if collections.is_empty() {393 if collections.is_empty() {362 return Err("no addresses provided".into());394 return Err("no addresses provided".into());363 }395 }401 /// 0 for Normal433 /// 0 for Normal402 /// 1 for AllowList434 /// 1 for AllowList403 fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {435 fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {436 self.consume_store_reads_and_writes(1, 1)?;437404 check_is_owner_or_admin(caller, self)?;438 check_is_owner_or_admin(caller, self)?;405 let permissions = CollectionPermissions {439 let permissions = CollectionPermissions {406 access: Some(match mode {440 access: Some(match mode {420 save(self)454 save(self)421 }455 }422456457 /// Checks that user allowed to operate with collection.458 ///459 /// @param user User address to check.460 fn allowed(&self, user: address) -> Result<bool> {461 Ok(Pallet::<T>::allowed(462 self.id,463 T::CrossAccountId::from_eth(user),464 ))465 }466423 /// Add the user to the allowed list.467 /// Add the user to the allowed list.424 ///468 ///425 /// @param user Address of a trusted user.469 /// @param user Address of a trusted user.426 fn add_to_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {470 fn add_to_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {471 self.consume_store_writes(1)?;472427 let caller = T::CrossAccountId::from_eth(caller);473 let caller = T::CrossAccountId::from_eth(caller);428 let user = T::CrossAccountId::from_eth(user);474 let user = T::CrossAccountId::from_eth(user);429 <Pallet<T>>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;475 <Pallet<T>>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;430 Ok(())476 Ok(())431 }477 }432478479 /// Add substrate user to allowed list.480 ///481 /// @param user User substrate address.482 fn add_to_collection_allow_list_substrate(483 &mut self,484 caller: caller,485 user: uint256,486 ) -> Result<void> {487 self.consume_store_writes(1)?;488489 let caller = T::CrossAccountId::from_eth(caller);490 let user = convert_uint256_to_cross_account::<T>(user);491 Pallet::<T>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;492 Ok(())493 }494433 /// Remove the user from the allowed list.495 /// Remove the user from the allowed list.434 ///496 ///435 /// @param user Address of a removed user.497 /// @param user Address of a removed user.436 fn remove_from_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {498 fn remove_from_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {499 self.consume_store_writes(1)?;500437 let caller = T::CrossAccountId::from_eth(caller);501 let caller = T::CrossAccountId::from_eth(caller);438 let user = T::CrossAccountId::from_eth(user);502 let user = T::CrossAccountId::from_eth(user);439 <Pallet<T>>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;503 <Pallet<T>>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;440 Ok(())504 Ok(())441 }505 }442506507 /// Remove substrate user from allowed list.508 ///509 /// @param user User substrate address.510 fn remove_from_collection_allow_list_substrate(511 &mut self,512 caller: caller,513 user: uint256,514 ) -> Result<void> {515 self.consume_store_writes(1)?;516517 let caller = T::CrossAccountId::from_eth(caller);518 let user = convert_uint256_to_cross_account::<T>(user);519 Pallet::<T>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;520 Ok(())521 }522443 /// Switch permission for minting.523 /// Switch permission for minting.444 ///524 ///445 /// @param mode Enable if "true".525 /// @param mode Enable if "true".446 fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {526 fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {527 self.consume_store_reads_and_writes(1, 1)?;528447 check_is_owner_or_admin(caller, self)?;529 check_is_owner_or_admin(caller, self)?;448 let permissions = CollectionPermissions {530 let permissions = CollectionPermissions {449 mint_mode: Some(mode),531 mint_mode: Some(mode),481 /// Returns collection type563 /// Returns collection type482 ///564 ///483 /// @return `Fungible` or `NFT` or `ReFungible`565 /// @return `Fungible` or `NFT` or `ReFungible`484 fn unique_collection_type(&mut self) -> Result<string> {566 fn unique_collection_type(&self) -> Result<string> {485 let mode = match self.collection.mode {567 let mode = match self.collection.mode {486 CollectionMode::Fungible(_) => "Fungible",568 CollectionMode::Fungible(_) => "Fungible",487 CollectionMode::NFT => "NFT",569 CollectionMode::NFT => "NFT",490 Ok(mode.into())572 Ok(mode.into())491 }573 }492574575 /// Get collection owner.576 ///577 /// @return Tuble with sponsor address and his substrate mirror.578 /// If address is canonical then substrate mirror is zero and vice versa.579 fn collection_owner(&self) -> Result<(address, uint256)> {580 Ok(convert_cross_account_to_tuple::<T>(581 &T::CrossAccountId::from_sub(self.owner.clone()),582 ))583 }584493 /// Changes collection owner to another account585 /// Changes collection owner to another account494 ///586 ///495 /// @dev Owner can be changed only by current owner587 /// @dev Owner can be changed only by current owner496 /// @param newOwner new owner account588 /// @param newOwner new owner account497 fn set_owner(&mut self, caller: caller, new_owner: address) -> Result<void> {589 fn set_owner(&mut self, caller: caller, new_owner: address) -> Result<void> {590 self.consume_store_writes(1)?;591498 let caller = T::CrossAccountId::from_eth(caller);592 let caller = T::CrossAccountId::from_eth(caller);499 let new_owner = T::CrossAccountId::from_eth(new_owner);593 let new_owner = T::CrossAccountId::from_eth(new_owner);500 self.set_owner_internal(caller, new_owner)594 self.set_owner_internal(caller, new_owner)506 /// @dev Owner can be changed only by current owner600 /// @dev Owner can be changed only by current owner507 /// @param newOwner new owner substrate account601 /// @param newOwner new owner substrate account508 fn set_owner_substrate(&mut self, caller: caller, new_owner: uint256) -> Result<void> {602 fn set_owner_substrate(&mut self, caller: caller, new_owner: uint256) -> Result<void> {603 self.consume_store_writes(1)?;604509 let caller = T::CrossAccountId::from_eth(caller);605 let caller = T::CrossAccountId::from_eth(caller);510 let new_owner = convert_uint256_to_cross_account::<T>(new_owner);606 let new_owner = convert_uint256_to_cross_account::<T>(new_owner);511 self.set_owner_internal(caller, new_owner)607 self.set_owner_internal(caller, new_owner)512 .map_err(dispatch_to_evm::<T>)608 .map_err(dispatch_to_evm::<T>)513 }609 }610611 // TODO: need implement AbiWriter for &Vec<T>612 // fn collection_admins(&self) -> Result<Vec<(address, uint256)>> {613 // let result = pallet_common::IsAdmin::<T>::iter_prefix((self.id,))614 // .map(|(admin, _)| pallet_common::eth::convert_cross_account_to_tuple::<T>(&admin))615 // .collect();616 // Ok(result)617 // }514}618}515619620/// ### Note621/// Do not forget to add: `self.consume_store_reads(1)?;`516fn check_is_owner_or_admin<T: Config>(622fn check_is_owner_or_admin<T: Config>(517 caller: caller,623 caller: caller,518 collection: &CollectionHandle<T>,624 collection: &CollectionHandle<T>,524 Ok(caller)630 Ok(caller)525}631}526632633/// ### Note634/// Do not forget to add: `self.consume_store_writes(1)?;`527fn save<T: Config>(collection: &CollectionHandle<T>) -> Result<void> {635fn save<T: Config>(collection: &CollectionHandle<T>) -> Result<void> {528 // TODO possibly delete for the lack of transaction529 collection.consume_store_writes(1)?;530 collection636 collection531 .check_is_internal()637 .check_is_internal()532 .map_err(dispatch_to_evm::<T>)?;638 .map_err(dispatch_to_evm::<T>)?;pallets/common/src/eth.rsdiffbeforeafterboth--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -16,7 +16,7 @@
//! The module contains a number of functions for converting and checking ethereum identifiers.
-use evm_coder::types::uint256;
+use evm_coder::types::{uint256, address};
pub use pallet_evm::account::{Config, CrossAccountId};
use sp_core::H160;
use up_data_structs::CollectionId;
@@ -69,3 +69,19 @@
let account_id = T::AccountId::from(new_admin_arr);
T::CrossAccountId::from_sub(account_id)
}
+
+/// Convert `CrossAccountId` to `(address, uint256)`.
+pub fn convert_cross_account_to_tuple<T: Config>(
+ cross_account_id: &T::CrossAccountId,
+) -> (address, uint256)
+where
+ T::AccountId: AsRef<[u8; 32]>,
+{
+ if cross_account_id.is_canonical_substrate() {
+ let sub = convert_cross_account_to_uint256::<T>(cross_account_id);
+ (Default::default(), sub)
+ } else {
+ let eth = *cross_account_id.as_eth();
+ (eth, Default::default())
+ }
+}
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -112,7 +112,6 @@
RmrkBoundedTheme,
RmrkNftChild,
CollectionPermissions,
- SchemaVersion,
};
pub use pallet::*;
@@ -202,6 +201,21 @@
))
}
+ /// Consume gas for reading and writing.
+ pub fn consume_store_reads_and_writes(
+ &self,
+ reads: u64,
+ writes: u64,
+ ) -> evm_coder::execution::Result<()> {
+ let weight = <T as frame_system::Config>::DbWeight::get();
+ let reads = weight.read.saturating_mul(reads);
+ let writes = weight.read.saturating_mul(writes);
+ self.recorder
+ .consume_gas(T::GasWeightMapping::weight_to_gas(
+ reads.saturating_add(writes),
+ ))
+ }
+
/// Save collection to storage.
pub fn save(&self) -> DispatchResult {
<CollectionById<T>>::insert(self.id, &self.collection);
@@ -310,6 +324,8 @@
}
/// Changes collection owner to another account
+ /// #### Store read/writes
+ /// 1 writes
fn set_owner_internal(
&mut self,
caller: T::CrossAccountId,
@@ -1292,6 +1308,8 @@
}
/// Toggle `user` participation in the `collection`'s allow list.
+ /// #### Store read/writes
+ /// 1 writes
pub fn toggle_allowlist(
collection: &CollectionHandle<T>,
sender: &T::CrossAccountId,
@@ -1312,6 +1330,8 @@
}
/// Toggle `user` participation in the `collection`'s admin list.
+ /// #### Store read/writes
+ /// 2 writes
pub fn toggle_admin(
collection: &CollectionHandle<T>,
sender: &T::CrossAccountId,
pallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -172,14 +172,9 @@
fn get_sponsor(&self, contract_address: address) -> Result<(address, uint256)> {
let sponsor =
Pallet::<T>::get_sponsor(contract_address).ok_or("Contract has no sponsor")?;
- let result: (address, uint256) = if sponsor.is_canonical_substrate() {
- let sponsor = pallet_common::eth::convert_cross_account_to_uint256::<T>(&sponsor);
- (Default::default(), sponsor)
- } else {
- let sponsor = *sponsor.as_eth();
- (sponsor, Default::default())
- };
- Ok(result)
+ Ok(pallet_common::eth::convert_cross_account_to_tuple::<T>(
+ &sponsor,
+ ))
}
/// Check tat contract has confirmed sponsor.
pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -22,7 +22,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
contract Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -255,6 +255,18 @@
dummy = 0;
}
+ /// Checks that user allowed to operate with collection.
+ ///
+ /// @param user User address to check.
+ /// @dev EVM selector for this function is: 0xd63a8e11,
+ /// or in textual repr: allowed(address)
+ function allowed(address user) public view returns (bool) {
+ require(false, stub_error);
+ user;
+ dummy;
+ return false;
+ }
+
/// Add the user to the allowed list.
///
/// @param user Address of a trusted user.
@@ -266,6 +278,17 @@
dummy = 0;
}
+ /// Add substrate user to allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xd06ad267,
+ /// or in textual repr: addToCollectionAllowListSubstrate(uint256)
+ function addToCollectionAllowListSubstrate(uint256 user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
/// Remove the user from the allowed list.
///
/// @param user Address of a removed user.
@@ -277,6 +300,17 @@
dummy = 0;
}
+ /// Remove substrate user from allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xa31913ed,
+ /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+ function removeFromCollectionAllowListSubstrate(uint256 user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
/// Switch permission for minting.
///
/// @param mode Enable if "true".
@@ -325,6 +359,18 @@
return "";
}
+ /// Get collection owner.
+ ///
+ /// @return Tuble with sponsor address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0xdf727d3b,
+ /// or in textual repr: collectionOwner()
+ function collectionOwner() public view returns (Tuple6 memory) {
+ require(false, stub_error);
+ dummy;
+ return Tuple6(0x0000000000000000000000000000000000000000, 0);
+ }
+
/// Changes collection owner to another account
///
/// @dev Owner can be changed only by current owner
pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -99,7 +99,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
contract Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -332,6 +332,18 @@
dummy = 0;
}
+ /// Checks that user allowed to operate with collection.
+ ///
+ /// @param user User address to check.
+ /// @dev EVM selector for this function is: 0xd63a8e11,
+ /// or in textual repr: allowed(address)
+ function allowed(address user) public view returns (bool) {
+ require(false, stub_error);
+ user;
+ dummy;
+ return false;
+ }
+
/// Add the user to the allowed list.
///
/// @param user Address of a trusted user.
@@ -343,6 +355,17 @@
dummy = 0;
}
+ /// Add substrate user to allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xd06ad267,
+ /// or in textual repr: addToCollectionAllowListSubstrate(uint256)
+ function addToCollectionAllowListSubstrate(uint256 user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
/// Remove the user from the allowed list.
///
/// @param user Address of a removed user.
@@ -354,6 +377,17 @@
dummy = 0;
}
+ /// Remove substrate user from allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xa31913ed,
+ /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+ function removeFromCollectionAllowListSubstrate(uint256 user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
/// Switch permission for minting.
///
/// @param mode Enable if "true".
@@ -402,6 +436,18 @@
return "";
}
+ /// Get collection owner.
+ ///
+ /// @return Tuble with sponsor address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0xdf727d3b,
+ /// or in textual repr: collectionOwner()
+ function collectionOwner() public view returns (Tuple17 memory) {
+ require(false, stub_error);
+ dummy;
+ return Tuple17(0x0000000000000000000000000000000000000000, 0);
+ }
+
/// Changes collection owner to another account
///
/// @dev Owner can be changed only by current owner
pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -99,7 +99,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
contract Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -332,6 +332,18 @@
dummy = 0;
}
+ /// Checks that user allowed to operate with collection.
+ ///
+ /// @param user User address to check.
+ /// @dev EVM selector for this function is: 0xd63a8e11,
+ /// or in textual repr: allowed(address)
+ function allowed(address user) public view returns (bool) {
+ require(false, stub_error);
+ user;
+ dummy;
+ return false;
+ }
+
/// Add the user to the allowed list.
///
/// @param user Address of a trusted user.
@@ -343,6 +355,17 @@
dummy = 0;
}
+ /// Add substrate user to allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xd06ad267,
+ /// or in textual repr: addToCollectionAllowListSubstrate(uint256)
+ function addToCollectionAllowListSubstrate(uint256 user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
/// Remove the user from the allowed list.
///
/// @param user Address of a removed user.
@@ -354,6 +377,17 @@
dummy = 0;
}
+ /// Remove substrate user from allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xa31913ed,
+ /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+ function removeFromCollectionAllowListSubstrate(uint256 user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
/// Switch permission for minting.
///
/// @param mode Enable if "true".
@@ -402,6 +436,18 @@
return "";
}
+ /// Get collection owner.
+ ///
+ /// @return Tuble with sponsor address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0xdf727d3b,
+ /// or in textual repr: collectionOwner()
+ function collectionOwner() public view returns (Tuple17 memory) {
+ require(false, stub_error);
+ dummy;
+ return Tuple17(0x0000000000000000000000000000000000000000, 0);
+ }
+
/// Changes collection owner to another account
///
/// @dev Owner can be changed only by current owner
tests/src/eth/allowlist.test.tsdiffbeforeafterboth--- a/tests/src/eth/allowlist.test.ts
+++ b/tests/src/eth/allowlist.test.ts
@@ -14,10 +14,22 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+import {IKeyringPair} from '@polkadot/types/types';
import {expect} from 'chai';
-import {contractHelpers, createEthAccountWithBalance, deployFlipper, itWeb3} from './util/helpers';
+import {isAllowlisted, normalizeAccountId} from '../util/helpers';
+import {
+ contractHelpers,
+ createEthAccount,
+ createEthAccountWithBalance,
+ deployFlipper,
+ evmCollection,
+ evmCollectionHelpers,
+ getCollectionAddressFromResult,
+ itWeb3,
+} from './util/helpers';
+import {itEth, usingEthPlaygrounds} from './util/playgrounds';
-describe('EVM allowlist', () => {
+describe('EVM contract allowlist', () => {
itWeb3('Contract allowlist can be toggled', async ({api, web3, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const flipper = await deployFlipper(web3, owner);
@@ -58,3 +70,79 @@
expect(await flipper.methods.getValue().call()).to.be.false;
});
});
+
+describe('EVM collection allowlist', () => {
+ let donor: IKeyringPair;
+
+ before(async function() {
+ await usingEthPlaygrounds(async (_helper, privateKey) => {
+ donor = privateKey('//Alice');
+ });
+ });
+
+ itEth('Collection allowlist can be added and removed by [eth] address', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const user = helper.eth.createAccount();
+
+ const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
+ expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
+ await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});
+ expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;
+
+ await collectionEvm.methods.removeFromCollectionAllowList(user).send({from: owner});
+ expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
+ });
+
+ itEth('Collection allowlist can be added and removed by [sub] address', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const user = donor;
+
+ const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
+ expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;
+ await collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).send({from: owner});
+ expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;
+
+ await collectionEvm.methods.removeFromCollectionAllowListSubstrate(user.addressRaw).send({from: owner});
+ expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;
+ });
+
+ itEth('Collection allowlist can not be add and remove [eth] address by not owner', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const notOwner = await helper.eth.createAccountWithBalance(donor);
+ const user = helper.eth.createAccount();
+
+ const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
+ expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
+ await expect(collectionEvm.methods.addToCollectionAllowList(user).call({from: notOwner})).to.be.rejectedWith('NoPermission');
+ expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
+ await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});
+
+ expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;
+ await expect(collectionEvm.methods.removeFromCollectionAllowList(user).call({from: notOwner})).to.be.rejectedWith('NoPermission');
+ expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;
+ });
+
+ itEth('Collection allowlist can not be add and remove [sub] address by not owner', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const notOwner = await helper.eth.createAccountWithBalance(donor);
+ const user = donor;
+
+ const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
+ expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;
+ await expect(collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).call({from: notOwner})).to.be.rejectedWith('NoPermission');
+ expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;
+ await collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).send({from: owner});
+
+ expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;
+ await expect(collectionEvm.methods.removeFromCollectionAllowListSubstrate(user.addressRaw).call({from: notOwner})).to.be.rejectedWith('NoPermission');
+ expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;
+ });
+});
tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -13,7 +13,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
interface Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -164,6 +164,13 @@
/// or in textual repr: setCollectionAccess(uint8)
function setCollectionAccess(uint8 mode) external;
+ /// Checks that user allowed to operate with collection.
+ ///
+ /// @param user User address to check.
+ /// @dev EVM selector for this function is: 0xd63a8e11,
+ /// or in textual repr: allowed(address)
+ function allowed(address user) external view returns (bool);
+
/// Add the user to the allowed list.
///
/// @param user Address of a trusted user.
@@ -171,6 +178,13 @@
/// or in textual repr: addToCollectionAllowList(address)
function addToCollectionAllowList(address user) external;
+ /// Add substrate user to allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xd06ad267,
+ /// or in textual repr: addToCollectionAllowListSubstrate(uint256)
+ function addToCollectionAllowListSubstrate(uint256 user) external;
+
/// Remove the user from the allowed list.
///
/// @param user Address of a removed user.
@@ -178,6 +192,13 @@
/// or in textual repr: removeFromCollectionAllowList(address)
function removeFromCollectionAllowList(address user) external;
+ /// Remove substrate user from allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xa31913ed,
+ /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+ function removeFromCollectionAllowListSubstrate(uint256 user) external;
+
/// Switch permission for minting.
///
/// @param mode Enable if "true".
@@ -208,6 +229,14 @@
/// or in textual repr: uniqueCollectionType()
function uniqueCollectionType() external returns (string memory);
+ /// Get collection owner.
+ ///
+ /// @return Tuble with sponsor address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0xdf727d3b,
+ /// or in textual repr: collectionOwner()
+ function collectionOwner() external view returns (Tuple6 memory);
+
/// Changes collection owner to another account
///
/// @dev Owner can be changed only by current owner
tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -65,7 +65,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
interface Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -216,6 +216,13 @@
/// or in textual repr: setCollectionAccess(uint8)
function setCollectionAccess(uint8 mode) external;
+ /// Checks that user allowed to operate with collection.
+ ///
+ /// @param user User address to check.
+ /// @dev EVM selector for this function is: 0xd63a8e11,
+ /// or in textual repr: allowed(address)
+ function allowed(address user) external view returns (bool);
+
/// Add the user to the allowed list.
///
/// @param user Address of a trusted user.
@@ -223,6 +230,13 @@
/// or in textual repr: addToCollectionAllowList(address)
function addToCollectionAllowList(address user) external;
+ /// Add substrate user to allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xd06ad267,
+ /// or in textual repr: addToCollectionAllowListSubstrate(uint256)
+ function addToCollectionAllowListSubstrate(uint256 user) external;
+
/// Remove the user from the allowed list.
///
/// @param user Address of a removed user.
@@ -230,6 +244,13 @@
/// or in textual repr: removeFromCollectionAllowList(address)
function removeFromCollectionAllowList(address user) external;
+ /// Remove substrate user from allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xa31913ed,
+ /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+ function removeFromCollectionAllowListSubstrate(uint256 user) external;
+
/// Switch permission for minting.
///
/// @param mode Enable if "true".
@@ -260,6 +281,14 @@
/// or in textual repr: uniqueCollectionType()
function uniqueCollectionType() external returns (string memory);
+ /// Get collection owner.
+ ///
+ /// @return Tuble with sponsor address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0xdf727d3b,
+ /// or in textual repr: collectionOwner()
+ function collectionOwner() external view returns (Tuple17 memory);
+
/// Changes collection owner to another account
///
/// @dev Owner can be changed only by current owner
tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -65,7 +65,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
interface Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -216,6 +216,13 @@
/// or in textual repr: setCollectionAccess(uint8)
function setCollectionAccess(uint8 mode) external;
+ /// Checks that user allowed to operate with collection.
+ ///
+ /// @param user User address to check.
+ /// @dev EVM selector for this function is: 0xd63a8e11,
+ /// or in textual repr: allowed(address)
+ function allowed(address user) external view returns (bool);
+
/// Add the user to the allowed list.
///
/// @param user Address of a trusted user.
@@ -223,6 +230,13 @@
/// or in textual repr: addToCollectionAllowList(address)
function addToCollectionAllowList(address user) external;
+ /// Add substrate user to allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xd06ad267,
+ /// or in textual repr: addToCollectionAllowListSubstrate(uint256)
+ function addToCollectionAllowListSubstrate(uint256 user) external;
+
/// Remove the user from the allowed list.
///
/// @param user Address of a removed user.
@@ -230,6 +244,13 @@
/// or in textual repr: removeFromCollectionAllowList(address)
function removeFromCollectionAllowList(address user) external;
+ /// Remove substrate user from allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xa31913ed,
+ /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+ function removeFromCollectionAllowListSubstrate(uint256 user) external;
+
/// Switch permission for minting.
///
/// @param mode Enable if "true".
@@ -260,6 +281,14 @@
/// or in textual repr: uniqueCollectionType()
function uniqueCollectionType() external returns (string memory);
+ /// Get collection owner.
+ ///
+ /// @return Tuble with sponsor address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0xdf727d3b,
+ /// or in textual repr: collectionOwner()
+ function collectionOwner() external view returns (Tuple17 memory);
+
/// Changes collection owner to another account
///
/// @dev Owner can be changed only by current owner
tests/src/eth/fungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/fungibleAbi.json
+++ b/tests/src/eth/fungibleAbi.json
@@ -78,6 +78,15 @@
},
{
"inputs": [
+ { "internalType": "uint256", "name": "user", "type": "uint256" }
+ ],
+ "name": "addToCollectionAllowListSubstrate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "owner", "type": "address" },
{ "internalType": "address", "name": "spender", "type": "address" }
],
@@ -88,6 +97,15 @@
},
{
"inputs": [
+ { "internalType": "address", "name": "user", "type": "address" }
+ ],
+ "name": "allowed",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "spender", "type": "address" },
{ "internalType": "uint256", "name": "amount", "type": "uint256" }
],
@@ -116,6 +134,23 @@
"type": "function"
},
{
+ "inputs": [],
+ "name": "collectionOwner",
+ "outputs": [
+ {
+ "components": [
+ { "internalType": "address", "name": "field_0", "type": "address" },
+ { "internalType": "uint256", "name": "field_1", "type": "uint256" }
+ ],
+ "internalType": "struct Tuple6",
+ "name": "",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
"inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
"name": "collectionProperty",
"outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],
@@ -261,6 +296,15 @@
"type": "function"
},
{
+ "inputs": [
+ { "internalType": "uint256", "name": "user", "type": "uint256" }
+ ],
+ "name": "removeFromCollectionAllowListSubstrate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],
"name": "setCollectionAccess",
"outputs": [],
tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/nonFungibleAbi.json
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -109,6 +109,24 @@
},
{
"inputs": [
+ { "internalType": "uint256", "name": "user", "type": "uint256" }
+ ],
+ "name": "addToCollectionAllowListSubstrate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ { "internalType": "address", "name": "user", "type": "address" }
+ ],
+ "name": "allowed",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "approved", "type": "address" },
{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }
],
@@ -146,6 +164,23 @@
"type": "function"
},
{
+ "inputs": [],
+ "name": "collectionOwner",
+ "outputs": [
+ {
+ "components": [
+ { "internalType": "address", "name": "field_0", "type": "address" },
+ { "internalType": "uint256", "name": "field_1", "type": "uint256" }
+ ],
+ "internalType": "struct Tuple17",
+ "name": "",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
"inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
"name": "collectionProperty",
"outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],
@@ -376,6 +411,15 @@
},
{
"inputs": [
+ { "internalType": "uint256", "name": "user", "type": "uint256" }
+ ],
+ "name": "removeFromCollectionAllowListSubstrate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "from", "type": "address" },
{ "internalType": "address", "name": "to", "type": "address" },
{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }
tests/src/eth/reFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/reFungibleAbi.json
+++ b/tests/src/eth/reFungibleAbi.json
@@ -109,6 +109,24 @@
},
{
"inputs": [
+ { "internalType": "uint256", "name": "user", "type": "uint256" }
+ ],
+ "name": "addToCollectionAllowListSubstrate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ { "internalType": "address", "name": "user", "type": "address" }
+ ],
+ "name": "allowed",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "approved", "type": "address" },
{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }
],
@@ -146,6 +164,23 @@
"type": "function"
},
{
+ "inputs": [],
+ "name": "collectionOwner",
+ "outputs": [
+ {
+ "components": [
+ { "internalType": "address", "name": "field_0", "type": "address" },
+ { "internalType": "uint256", "name": "field_1", "type": "uint256" }
+ ],
+ "internalType": "struct Tuple17",
+ "name": "",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
"inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
"name": "collectionProperty",
"outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],
@@ -376,6 +411,15 @@
},
{
"inputs": [
+ { "internalType": "uint256", "name": "user", "type": "uint256" }
+ ],
+ "name": "removeFromCollectionAllowListSubstrate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "from", "type": "address" },
{ "internalType": "address", "name": "to", "type": "address" },
{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }
tests/src/util/helpers.tsdiffbeforeafterboth--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -1651,7 +1651,7 @@
});
}
-export async function isAllowlisted(api: ApiPromise, collectionId: number, address: string | CrossAccountId) {
+export async function isAllowlisted(api: ApiPromise, collectionId: number, address: string | CrossAccountId | IKeyringPair) {
return (await api.rpc.unique.allowed(collectionId, normalizeAccountId(address))).toJSON();
}
tests/src/util/playgrounds/unique.tsdiffbeforeafterboth--- a/tests/src/util/playgrounds/unique.ts
+++ b/tests/src/util/playgrounds/unique.ts
@@ -730,6 +730,18 @@
}
/**
+ * Check if user is in allow list.
+ *
+ * @param collectionId ID of collection
+ * @param user Account to check
+ * @example await getAdmins(1)
+ * @returns is user in allow list
+ */
+ async allowed(collectionId: number, user: ICrossAccountId): Promise<boolean> {
+ return (await this.helper.callRpc('api.rpc.unique.allowed', [collectionId, user])).toJSON();
+ }
+
+ /**
* Adds an address to allow list
* @param signer keyring of signer
* @param collectionId ID of collection