git.delta.rocks / unique-network / refs/commits / 6d28dd8067cd

difftreelog

Merge branch 'develop' into tests/eth-helpers

Max Andreev2022-12-16parents: #e36664c #1e2863e.patch.diff
in: master

59 files changed

modifiedCargo.lockdiffbeforeafterboth
2274 "hash256-std-hasher",2274 "hash256-std-hasher",
2275 "rlp",2275 "rlp",
2276 "rlp-derive",2276 "rlp-derive",
2277 "sha3",2277 "sha3 0.10.6",
2278 "triehash",2278 "triehash",
2279]2279]
22802280
2292 "rlp",2292 "rlp",
2293 "scale-info",2293 "scale-info",
2294 "serde",2294 "serde",
2295 "sha3",2295 "sha3 0.10.6",
2296 "triehash",2296 "triehash",
2297]2297]
22982298
2350 "rlp",2350 "rlp",
2351 "scale-info",2351 "scale-info",
2352 "serde",2352 "serde",
2353 "sha3",2353 "sha3 0.10.6",
2354]2354]
23552355
2356[[package]]2356[[package]]
2380 "hex",2380 "hex",
2381 "proc-macro2",2381 "proc-macro2",
2382 "quote",2382 "quote",
2383 "sha3",2383 "sha3 0.10.6",
2384 "syn",2384 "syn",
2385]2385]
23862386
2415 "environmental",2415 "environmental",
2416 "evm-core",2416 "evm-core",
2417 "primitive-types 0.12.1",2417 "primitive-types 0.12.1",
2418 "sha3",2418 "sha3 0.10.6",
2419]2419]
24202420
2421[[package]]2421[[package]]
4958 "digest 0.10.6",4958 "digest 0.10.6",
4959 "multihash-derive",4959 "multihash-derive",
4960 "sha2 0.10.6",4960 "sha2 0.10.6",
4961 "sha3",4961 "sha3 0.10.6",
4962 "unsigned-varint",4962 "unsigned-varint",
4963]4963]
49644964
5280 "cumulus-primitives-utility",5280 "cumulus-primitives-utility",
5281 "derivative",5281 "derivative",
5282 "evm-coder",5282 "evm-coder",
5283 "fp-evm",
5283 "fp-evm-mapping",5284 "fp-evm-mapping",
5284 "fp-rpc",5285 "fp-rpc",
5285 "fp-self-contained",5286 "fp-self-contained",
5294 "impl-trait-for-tuples",5295 "impl-trait-for-tuples",
5295 "log",5296 "log",
5296 "logtest",5297 "logtest",
5298 "num_enum",
5297 "orml-tokens",5299 "orml-tokens",
5298 "orml-traits",5300 "orml-traits",
5299 "orml-vesting",5301 "orml-vesting",
5309 "pallet-evm-coder-substrate",5311 "pallet-evm-coder-substrate",
5310 "pallet-evm-contract-helpers",5312 "pallet-evm-contract-helpers",
5311 "pallet-evm-migration",5313 "pallet-evm-migration",
5314 "pallet-evm-precompile-simple",
5312 "pallet-evm-transaction-payment",5315 "pallet-evm-transaction-payment",
5313 "pallet-foreign-assets",5316 "pallet-foreign-assets",
5314 "pallet-fungible",5317 "pallet-fungible",
5333 "parachain-info",5336 "parachain-info",
5334 "parity-scale-codec 3.2.1",5337 "parity-scale-codec 3.2.1",
5335 "polkadot-parachain",5338 "polkadot-parachain",
5339 "precompile-utils-macro",
5336 "rmrk-rpc",5340 "rmrk-rpc",
5337 "scale-info",5341 "scale-info",
5338 "serde",5342 "serde",
6004 "sp-std",6008 "sp-std",
6005]6009]
6010
6011[[package]]
6012name = "pallet-evm-precompile-simple"
6013version = "2.0.0-dev"
6014source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.33#c37ced433a29baad45899d6ab364fe437f97570e"
6015dependencies = [
6016 "fp-evm",
6017 "ripemd",
6018 "sp-io",
6019]
60066020
6007[[package]]6021[[package]]
6008name = "pallet-evm-transaction-payment"6022name = "pallet-evm-transaction-payment"
63286342
6329[[package]]6343[[package]]
6330name = "pallet-nonfungible"6344name = "pallet-nonfungible"
6331version = "0.1.9"6345version = "0.1.11"
6332dependencies = [6346dependencies = [
6333 "ethereum 0.14.0",6347 "ethereum 0.14.0",
6334 "evm-coder",6348 "evm-coder",
64876501
6488[[package]]6502[[package]]
6489name = "pallet-refungible"6503name = "pallet-refungible"
6490version = "0.2.8"6504version = "0.2.10"
6491dependencies = [6505dependencies = [
6492 "derivative",6506 "derivative",
6493 "ethereum 0.14.0",6507 "ethereum 0.14.0",
8594source = "registry+https://github.com/rust-lang/crates.io-index"8608source = "registry+https://github.com/rust-lang/crates.io-index"
8595checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"8609checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
8610
8611[[package]]
8612name = "precompile-utils-macro"
8613version = "0.1.0"
8614dependencies = [
8615 "num_enum",
8616 "proc-macro2",
8617 "quote",
8618 "sha3 0.8.2",
8619 "syn",
8620]
85968621
8597[[package]]8622[[package]]
8598name = "predicates"8623name = "predicates"
8850 "cumulus-primitives-utility",8875 "cumulus-primitives-utility",
8851 "derivative",8876 "derivative",
8852 "evm-coder",8877 "evm-coder",
8878 "fp-evm",
8853 "fp-evm-mapping",8879 "fp-evm-mapping",
8854 "fp-rpc",8880 "fp-rpc",
8855 "fp-self-contained",8881 "fp-self-contained",
8864 "impl-trait-for-tuples",8890 "impl-trait-for-tuples",
8865 "log",8891 "log",
8866 "logtest",8892 "logtest",
8893 "num_enum",
8867 "orml-tokens",8894 "orml-tokens",
8868 "orml-traits",8895 "orml-traits",
8869 "orml-vesting",8896 "orml-vesting",
8879 "pallet-evm-coder-substrate",8906 "pallet-evm-coder-substrate",
8880 "pallet-evm-contract-helpers",8907 "pallet-evm-contract-helpers",
8881 "pallet-evm-migration",8908 "pallet-evm-migration",
8909 "pallet-evm-precompile-simple",
8882 "pallet-evm-transaction-payment",8910 "pallet-evm-transaction-payment",
8883 "pallet-foreign-assets",8911 "pallet-foreign-assets",
8884 "pallet-fungible",8912 "pallet-fungible",
8901 "parachain-info",8929 "parachain-info",
8902 "parity-scale-codec 3.2.1",8930 "parity-scale-codec 3.2.1",
8903 "polkadot-parachain",8931 "polkadot-parachain",
8932 "precompile-utils-macro",
8904 "rmrk-rpc",8933 "rmrk-rpc",
8905 "scale-info",8934 "scale-info",
8906 "serde",8935 "serde",
9248 "winapi",9277 "winapi",
9249]9278]
9279
9280[[package]]
9281name = "ripemd"
9282version = "0.1.3"
9283source = "registry+https://github.com/rust-lang/crates.io-index"
9284checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f"
9285dependencies = [
9286 "digest 0.10.6",
9287]
92509288
9251[[package]]9289[[package]]
9252name = "rlp"9290name = "rlp"
10959 "digest 0.10.6",10997 "digest 0.10.6",
10960]10998]
10999
11000[[package]]
11001name = "sha3"
11002version = "0.8.2"
11003source = "registry+https://github.com/rust-lang/crates.io-index"
11004checksum = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf"
11005dependencies = [
11006 "block-buffer 0.7.3",
11007 "byte-tools",
11008 "digest 0.8.1",
11009 "keccak",
11010 "opaque-debug 0.2.3",
11011]
1096111012
10962[[package]]11013[[package]]
10963name = "sha3"11014name = "sha3"
11396 "byteorder",11447 "byteorder",
11397 "digest 0.10.6",11448 "digest 0.10.6",
11398 "sha2 0.10.6",11449 "sha2 0.10.6",
11399 "sha3",11450 "sha3 0.10.6",
11400 "sp-std",11451 "sp-std",
11401 "twox-hash",11452 "twox-hash",
11402]11453]
13026 "cumulus-primitives-utility",13077 "cumulus-primitives-utility",
13027 "derivative",13078 "derivative",
13028 "evm-coder",13079 "evm-coder",
13080 "fp-evm",
13029 "fp-evm-mapping",13081 "fp-evm-mapping",
13030 "fp-rpc",13082 "fp-rpc",
13031 "fp-self-contained",13083 "fp-self-contained",
13040 "impl-trait-for-tuples",13092 "impl-trait-for-tuples",
13041 "log",13093 "log",
13042 "logtest",13094 "logtest",
13095 "num_enum",
13043 "orml-tokens",13096 "orml-tokens",
13044 "orml-traits",13097 "orml-traits",
13045 "orml-vesting",13098 "orml-vesting",
13055 "pallet-evm-coder-substrate",13108 "pallet-evm-coder-substrate",
13056 "pallet-evm-contract-helpers",13109 "pallet-evm-contract-helpers",
13057 "pallet-evm-migration",13110 "pallet-evm-migration",
13111 "pallet-evm-precompile-simple",
13058 "pallet-evm-transaction-payment",13112 "pallet-evm-transaction-payment",
13059 "pallet-foreign-assets",13113 "pallet-foreign-assets",
13060 "pallet-fungible",13114 "pallet-fungible",
13077 "parachain-info",13131 "parachain-info",
13078 "parity-scale-codec 3.2.1",13132 "parity-scale-codec 3.2.1",
13079 "polkadot-parachain",13133 "polkadot-parachain",
13134 "precompile-utils-macro",
13080 "rmrk-rpc",13135 "rmrk-rpc",
13081 "scale-info",13136 "scale-info",
13082 "serde",13137 "serde",
modifiedcrates/evm-coder/tests/abi_derive_generation.rsdiffbeforeafterboth
740 /// Some docs740 /// Some docs
741 /// At multi741 /// At multi
742 /// line742 /// line
743 #[derive(AbiCoder, Debug, PartialEq, Default)]743 #[derive(AbiCoder, Debug, PartialEq, Default, Clone, Copy)]
744 #[repr(u8)]744 #[repr(u8)]
745 enum Color {745 enum Color {
746 /// Docs for Red746 /// Docs for Red
modifiedpallets/app-promotion/src/lib.rsdiffbeforeafterboth
564 /// # Arguments564 /// # Arguments
565 ///565 ///
566 /// * `stakers_number`: the number of stakers for which recalculation will be performed566 /// * `stakers_number`: the number of stakers for which recalculation will be performed
567 #[pallet::weight(<T as Config>::WeightInfo::payout_stakers(stakers_number.unwrap_or(20) as u32))]567 #[pallet::weight(<T as Config>::WeightInfo::payout_stakers(stakers_number.unwrap_or(DEFAULT_NUMBER_PAYOUTS) as u32))]
568 pub fn payout_stakers(admin: OriginFor<T>, stakers_number: Option<u8>) -> DispatchResult {568 pub fn payout_stakers(admin: OriginFor<T>, stakers_number: Option<u8>) -> DispatchResult {
569 let admin_id = ensure_signed(admin)?;569 let admin_id = ensure_signed(admin)?;
570570
modifiedpallets/common/src/eth.rsdiffbeforeafterboth
163 TokenOwner,163 TokenOwner,
164}164}
165
166/// Ethereum representation of TokenPermissions (see [`up_data_structs::PropertyPermission`]) fields as an enumeration.
167#[derive(AbiCoder, Copy, Clone, Default, Debug)]
168#[repr(u8)]
169pub enum EthTokenPermissions {
170 /// Permission to change the property and property permission. See [`up_data_structs::PropertyPermission::mutable`]
171 #[default]
172 Mutable,
173
174 /// Change permission for the collection administrator. See [`up_data_structs::PropertyPermission::token_owner`]
175 TokenOwner,
176
177 /// Permission to change the property for the owner of the token. See [`up_data_structs::PropertyPermission::collection_admin`]
178 CollectionAdmin,
179}
165180
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
1222 Ok(())1222 Ok(())
1223 }1223 }
12241224
1225 /// Set scouped collection property.1225 /// Set a scoped collection property, where the scope is a special prefix
1226 /// prohibiting a user to change the property.
1226 ///1227 ///
1227 /// * `collection_id` - ID of the collection for which the property is being set.1228 /// * `collection_id` - ID of the collection for which the property is being set.
1228 /// * `scope` - Property scope.1229 /// * `scope` - Property scope.
1240 Ok(())1241 Ok(())
1241 }1242 }
12421243
1243 /// Set scouped collection properties.1244 /// Set scoped collection properties, where the scope is a special prefix
1245 /// prohibiting a user to change the properties.
1244 ///1246 ///
1245 /// * `collection_id` - ID of the collection for which the properties is being set.1247 /// * `collection_id` - ID of the collection for which the properties is being set.
1246 /// * `scope` - Property scope.1248 /// * `scope` - Property scope.
modifiedpallets/configuration/src/lib.rsdiffbeforeafterboth
52 type DefaultMinGasPrice: Get<u64>;52 type DefaultMinGasPrice: Get<u64>;
5353
54 #[pallet::constant]54 #[pallet::constant]
55 type MaxOverridedAllowedLocations: Get<u32>;55 type MaxXcmAllowedLocations: Get<u32>;
56 #[pallet::constant]56 #[pallet::constant]
57 type AppPromotionDailyRate: Get<Perbill>;57 type AppPromotionDailyRate: Get<Perbill>;
58 #[pallet::constant]58 #[pallet::constant]
7777
78 #[pallet::storage]78 #[pallet::storage]
79 pub type XcmAllowedLocationsOverride<T: Config> = StorageValue<79 pub type XcmAllowedLocationsOverride<T: Config> = StorageValue<
80 Value = BoundedVec<MultiLocation, T::MaxOverridedAllowedLocations>,80 Value = BoundedVec<MultiLocation, T::MaxXcmAllowedLocations>,
81 QueryKind = OptionQuery,81 QueryKind = OptionQuery,
82 >;82 >;
8383
118 #[pallet::weight(T::DbWeight::get().writes(1))]118 #[pallet::weight(T::DbWeight::get().writes(1))]
119 pub fn set_xcm_allowed_locations(119 pub fn set_xcm_allowed_locations(
120 origin: OriginFor<T>,120 origin: OriginFor<T>,
121 locations: Option<BoundedVec<MultiLocation, T::MaxOverridedAllowedLocations>>,121 locations: Option<BoundedVec<MultiLocation, T::MaxXcmAllowedLocations>>,
122 ) -> DispatchResult {122 ) -> DispatchResult {
123 ensure_root(origin)?;123 ensure_root(origin)?;
124 <XcmAllowedLocationsOverride<T>>::set(locations);124 <XcmAllowedLocationsOverride<T>>::set(locations);
modifiedpallets/fungible/src/common.rsdiffbeforeafterboth
19use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, traits::Get};19use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, traits::Get};
20use up_data_structs::{TokenId, CollectionId, CreateItemExData, budget::Budget, CreateItemData};20use up_data_structs::{TokenId, CollectionId, CreateItemExData, budget::Budget, CreateItemData};
21use pallet_common::{CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight};21use pallet_common::{
22 CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight,
23 weights::WeightInfo as _,
24};
22use pallet_structure::Error as StructureError;25use pallet_structure::Error as StructureError;
23use sp_runtime::ArithmeticError;26use sp_runtime::ArithmeticError;
53 <SelfWeightOf<T>>::burn_item()56 <SelfWeightOf<T>>::burn_item()
54 }57 }
5558
56 fn set_collection_properties(_amount: u32) -> Weight {59 fn set_collection_properties(amount: u32) -> Weight {
57 // Error
58 Weight::zero()60 <pallet_common::SelfWeightOf<T>>::set_collection_properties(amount)
59 }61 }
6062
61 fn delete_collection_properties(_amount: u32) -> Weight {63 fn delete_collection_properties(amount: u32) -> Weight {
62 // Error
63 Weight::zero()64 <pallet_common::SelfWeightOf<T>>::delete_collection_properties(amount)
64 }65 }
6566
66 fn set_token_properties(_amount: u32) -> Weight {67 fn set_token_properties(_amount: u32) -> Weight {
294295
295 fn set_collection_properties(296 fn set_collection_properties(
296 &self,297 &self,
297 _sender: T::CrossAccountId,298 sender: T::CrossAccountId,
298 _property: Vec<Property>,299 properties: Vec<Property>,
299 ) -> DispatchResultWithPostInfo {300 ) -> DispatchResultWithPostInfo {
301 let weight = <CommonWeights<T>>::set_collection_properties(properties.len() as u32);
302
300 fail!(<Error<T>>::SettingPropertiesNotAllowed)303 with_weight(
304 <Pallet<T>>::set_collection_properties(self, &sender, properties),
305 weight,
306 )
301 }307 }
302308
303 fn delete_collection_properties(309 fn delete_collection_properties(
304 &self,310 &self,
305 _sender: &T::CrossAccountId,311 sender: &T::CrossAccountId,
306 _property_keys: Vec<PropertyKey>,312 property_keys: Vec<PropertyKey>,
307 ) -> DispatchResultWithPostInfo {313 ) -> DispatchResultWithPostInfo {
314 let weight = <CommonWeights<T>>::delete_collection_properties(property_keys.len() as u32);
315
308 fail!(<Error<T>>::SettingPropertiesNotAllowed)316 with_weight(
317 <Pallet<T>>::delete_collection_properties(self, sender, property_keys),
318 weight,
319 )
309 }320 }
310321
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
8080
81use core::ops::Deref;81use core::ops::Deref;
82use evm_coder::ToLog;82use evm_coder::ToLog;
83use frame_support::{ensure};83use frame_support::ensure;
84use pallet_evm::account::CrossAccountId;84use pallet_evm::account::CrossAccountId;
85use up_data_structs::{85use up_data_structs::{
86 AccessMode, CollectionId, CollectionFlags, TokenId, CreateCollectionData,86 AccessMode, CollectionId, CollectionFlags, TokenId, CreateCollectionData,
87 mapping::TokenAddressMapping, budget::Budget,87 mapping::TokenAddressMapping, budget::Budget, PropertyKey, Property,
88};88};
89use pallet_common::{89use pallet_common::{
90 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,90 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,
260 Ok(())260 Ok(())
261 }261 }
262
263 /// Add properties to the collection.
264 pub fn set_collection_properties(
265 collection: &FungibleHandle<T>,
266 sender: &T::CrossAccountId,
267 properties: Vec<Property>,
268 ) -> DispatchResult {
269 <PalletCommon<T>>::set_collection_properties(collection, sender, properties)
270 }
271
272 /// Delete properties of the collection, associated with the provided keys.
273 pub fn delete_collection_properties(
274 collection: &FungibleHandle<T>,
275 sender: &T::CrossAccountId,
276 property_keys: Vec<PropertyKey>,
277 ) -> DispatchResult {
278 <PalletCommon<T>>::delete_collection_properties(collection, sender, property_keys)
279 }
262280
263 ///Checks if collection has tokens. Return `true` if it has.281 /// Checks if collection has tokens. Return `true` if it has.
264 fn collection_has_tokens(collection_id: CollectionId) -> bool {282 fn collection_has_tokens(collection_id: CollectionId) -> bool {
265 <TotalSupply<T>>::get(collection_id) != 0283 <TotalSupply<T>>::get(collection_id) != 0
266 }284 }
modifiedpallets/nonfungible/CHANGELOG.mddiffbeforeafterboth
44
5<!-- bureaucrate goes here -->5<!-- bureaucrate goes here -->
66
7## [0.1.11] - 2022-12-16
8
9### Added
10
11- The function `tokenPropertyPermissions` and `setTokenPropertyPermissions` to `TokenProperties` interface.
12
13### Changed
14
15- Hide `setTokenPropertyPermission` function in `TokenProperties` interface.
16
7## [0.1.10] - 2022-11-1817## [0.1.10] - 2022-11-18
818
9### Added19### Added
modifiedpallets/nonfungible/Cargo.tomldiffbeforeafterboth
1[package]1[package]
2name = "pallet-nonfungible"2name = "pallet-nonfungible"
3version = "0.1.9"3version = "0.1.11"
4license = "GPLv3"4license = "GPLv3"
5edition = "2021"5edition = "2021"
66
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
34 CollectionPropertiesVec,34 CollectionPropertiesVec,
35};35};
36use pallet_evm_coder_substrate::dispatch_to_evm;36use pallet_evm_coder_substrate::dispatch_to_evm;
37use sp_std::vec::Vec;37use sp_std::{vec::Vec, vec};
38use pallet_common::{38use pallet_common::{
39 CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,39 CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,
40 erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},40 erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},
41 eth::EthCrossAccount,41 eth::{EthCrossAccount, EthTokenPermissions},
42};42};
43use pallet_evm::{account::CrossAccountId, PrecompileHandle};43use pallet_evm::{account::CrossAccountId, PrecompileHandle};
44use pallet_evm_coder_substrate::call;44use pallet_evm_coder_substrate::call;
60 /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.60 /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
61 /// @param tokenOwner Permission to mutate property by token owner if property is mutable.61 /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
62 #[weight(<SelfWeightOf<T>>::set_token_property_permissions(1))]62 #[weight(<SelfWeightOf<T>>::set_token_property_permissions(1))]
63 #[solidity(hide)]
63 fn set_token_property_permission(64 fn set_token_property_permission(
64 &mut self,65 &mut self,
65 caller: caller,66 caller: caller,
69 token_owner: bool,70 token_owner: bool,
70 ) -> Result<()> {71 ) -> Result<()> {
71 let caller = T::CrossAccountId::from_eth(caller);72 let caller = T::CrossAccountId::from_eth(caller);
72 <Pallet<T>>::set_property_permission(73 <Pallet<T>>::set_token_property_permissions(
73 self,74 self,
74 &caller,75 &caller,
75 PropertyKeyPermission {76 vec![PropertyKeyPermission {
76 key: <Vec<u8>>::from(key)77 key: <Vec<u8>>::from(key)
77 .try_into()78 .try_into()
78 .map_err(|_| "too long key")?,79 .map_err(|_| "too long key")?,
79 permission: PropertyPermission {80 permission: PropertyPermission {
80 mutable: is_mutable,81 mutable: is_mutable,
81 collection_admin,82 collection_admin,
82 token_owner,83 token_owner,
83 },84 },
84 },85 }],
85 )86 )
86 .map_err(dispatch_to_evm::<T>)87 .map_err(dispatch_to_evm::<T>)
87 }88 }
89
90 /// @notice Set permissions for token property.
91 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
92 /// @param permissions Permissions for keys.
93 #[weight(<SelfWeightOf<T>>::set_token_property_permissions(permissions.len() as u32))]
94 fn set_token_property_permissions(
95 &mut self,
96 caller: caller,
97 permissions: Vec<(string, Vec<(EthTokenPermissions, bool)>)>,
98 ) -> Result<()> {
99 let caller = T::CrossAccountId::from_eth(caller);
100 const PERMISSIONS_FIELDS_COUNT: usize = 3;
101
102 let mut perms = Vec::new();
103
104 for (key, pp) in permissions {
105 if pp.len() > PERMISSIONS_FIELDS_COUNT {
106 return Err(alloc::format!(
107 "Actual number of fields {} for {}, which exceeds the maximum value of {}",
108 pp.len(),
109 stringify!(EthTokenPermissions),
110 PERMISSIONS_FIELDS_COUNT
111 )
112 .as_str()
113 .into());
114 }
115
116 let mut token_permission = PropertyPermission::default();
117
118 for (perm, value) in pp {
119 match perm {
120 EthTokenPermissions::Mutable => token_permission.mutable = value,
121 EthTokenPermissions::TokenOwner => token_permission.token_owner = value,
122 EthTokenPermissions::CollectionAdmin => {
123 token_permission.collection_admin = value
124 }
125 }
126 }
127
128 perms.push(PropertyKeyPermission {
129 key: key.into_bytes().try_into().map_err(|_| "too long key")?,
130 permission: token_permission,
131 });
132 }
133
134 <Pallet<T>>::set_token_property_permissions(self, &caller, perms)
135 .map_err(dispatch_to_evm::<T>)
136 }
137
138 /// @notice Get permissions for token properties.
139 fn token_property_permissions(
140 &self,
141 ) -> Result<Vec<(string, Vec<(EthTokenPermissions, bool)>)>> {
142 let perms = <Pallet<T>>::token_property_permission(self.id);
143 Ok(perms
144 .into_iter()
145 .map(|(key, pp)| {
146 let key = string::from_utf8(key.into_inner()).expect("Stored key must be valid");
147 let pp = vec![
148 (EthTokenPermissions::Mutable, pp.mutable),
149 (EthTokenPermissions::TokenOwner, pp.token_owner),
150 (EthTokenPermissions::CollectionAdmin, pp.collection_admin),
151 ];
152 (key, pp)
153 })
154 .collect())
155 }
88156
89 /// @notice Set token property value.157 /// @notice Set token property value.
90 /// @dev Throws error if `msg.sender` has no permission to edit the property.158 /// @dev Throws error if `msg.sender` has no permission to edit the property.
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
103 AccessMode, CollectionId, CollectionFlags, CustomDataLimit, TokenId, CreateCollectionData,103 AccessMode, CollectionId, CollectionFlags, CustomDataLimit, TokenId, CreateCollectionData,
104 CreateNftExData, mapping::TokenAddressMapping, budget::Budget, Property, PropertyPermission,104 CreateNftExData, mapping::TokenAddressMapping, budget::Budget, Property, PropertyPermission,
105 PropertyKey, PropertyValue, PropertyKeyPermission, Properties, PropertyScope, TrySetProperty,105 PropertyKey, PropertyValue, PropertyKeyPermission, Properties, PropertyScope, TrySetProperty,
106 TokenChild, AuxPropertyValue,106 TokenChild, AuxPropertyValue, PropertiesPermissionMap,
107};107};
108use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};108use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
109use pallet_common::{109use pallet_common::{
824 )824 )
825 }825 }
826826
827 /// Set property permissions for the collection.
828 ///
829 /// Sender should be the owner or admin of the collection.
830 pub fn set_property_permission(827 pub fn token_property_permission(collection_id: CollectionId) -> PropertiesPermissionMap {
831 collection: &CollectionHandle<T>,
832 sender: &T::CrossAccountId,
833 permission: PropertyKeyPermission,
834 ) -> DispatchResult {
835 <PalletCommon<T>>::set_property_permission(collection, sender, permission)828 <PalletCommon<T>>::property_permissions(collection_id)
836 }829 }
837830
838 pub fn check_token_immediate_ownership(831 pub fn check_token_immediate_ownership(
modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
18}18}
1919
20/// @title A contract that allows to set and delete token properties and change token property permissions.20/// @title A contract that allows to set and delete token properties and change token property permissions.
21/// @dev the ERC-165 identifier for this interface is 0x91a97a6821/// @dev the ERC-165 identifier for this interface is 0xde0695c2
22contract TokenProperties is Dummy, ERC165 {22contract TokenProperties is Dummy, ERC165 {
23 // /// @notice Set permissions for token property.
24 // /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
25 // /// @param key Property key.
26 // /// @param isMutable Permission to mutate property.
27 // /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
28 // /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
29 // /// @dev EVM selector for this function is: 0x222d97fa,
30 // /// or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)
31 // function setTokenPropertyPermission(string memory key, bool isMutable, bool collectionAdmin, bool tokenOwner) public {
32 // require(false, stub_error);
33 // key;
34 // isMutable;
35 // collectionAdmin;
36 // tokenOwner;
37 // dummy = 0;
38 // }
39
23 /// @notice Set permissions for token property.40 /// @notice Set permissions for token property.
24 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.41 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
25 /// @param key Property key.42 /// @param permissions Permissions for keys.
26 /// @param isMutable Permission to mutate property.
27 /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
28 /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
29 /// @dev EVM selector for this function is: 0x222d97fa,43 /// @dev EVM selector for this function is: 0xbd92983a,
30 /// or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)44 /// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
31 function setTokenPropertyPermission(45 function setTokenPropertyPermissions(Tuple48[] memory permissions) public {
32 string memory key,
33 bool isMutable,
34 bool collectionAdmin,
35 bool tokenOwner
36 ) public {
37 require(false, stub_error);46 require(false, stub_error);
38 key;47 permissions;
39 isMutable;
40 collectionAdmin;
41 tokenOwner;
42 dummy = 0;48 dummy = 0;
43 }49 }
50
51 /// @dev EVM selector for this function is: 0xf23d7790,
52 /// or in textual repr: tokenPropertyPermissions()
53 function tokenPropertyPermissions() public view returns (Tuple48[] memory) {
54 require(false, stub_error);
55 dummy;
56 return new Tuple48[](0);
57 }
4458
45 // /// @notice Set token property value.59 // /// @notice Set token property value.
46 // /// @dev Throws error if `msg.sender` has no permission to edit the property.60 // /// @dev Throws error if `msg.sender` has no permission to edit the property.
118 bytes value;132 bytes value;
119}133}
134
135enum EthTokenPermissions {
136 Mutable,
137 TokenOwner,
138 CollectionAdmin
139}
140
141/// @dev anonymous struct
142struct Tuple48 {
143 string field_0;
144 Tuple46[] field_1;
145}
146
147/// @dev anonymous struct
148struct Tuple46 {
149 EthTokenPermissions field_0;
150 bool field_1;
151}
120152
121/// @title A contract that allows you to work with collections.153/// @title A contract that allows you to work with collections.
122/// @dev the ERC-165 identifier for this interface is 0xb5e1747f154/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
modifiedpallets/refungible/CHANGELOG.mddiffbeforeafterboth
44
5<!-- bureaucrate goes here -->5<!-- bureaucrate goes here -->
66
7## [0.2.10] - 2022-12-16
8
9### Added
10
11- The function `tokenPropertyPermissions` and `setTokenPropertyPermissions` to `TokenProperties` interface.
12
13### Changed
14
15- Hide `setTokenPropertyPermission` function in `TokenProperties` interface.
16
7## [0.2.9] - 2022-11-1817## [0.2.9] - 2022-11-18
818
9### Added19### Added
modifiedpallets/refungible/Cargo.tomldiffbeforeafterboth
1[package]1[package]
2name = "pallet-refungible"2name = "pallet-refungible"
3version = "0.2.8"3version = "0.2.10"
4license = "GPLv3"4license = "GPLv3"
5edition = "2021"5edition = "2021"
66
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
33use pallet_common::{33use pallet_common::{
34 CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,34 CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,
35 erc::{CommonEvmHandler, CollectionCall, static_property::key},35 erc::{CommonEvmHandler, CollectionCall, static_property::key},
36 eth::EthCrossAccount,36 eth::{EthCrossAccount, EthTokenPermissions},
37 Error as CommonError,37 Error as CommonError,
38};38};
39use pallet_evm::{account::CrossAccountId, PrecompileHandle};39use pallet_evm::{account::CrossAccountId, PrecompileHandle};
63 /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.63 /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
64 /// @param tokenOwner Permission to mutate property by token owner if property is mutable.64 /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
65 #[weight(<SelfWeightOf<T>>::set_token_property_permissions(1))]65 #[weight(<SelfWeightOf<T>>::set_token_property_permissions(1))]
66 #[solidity(hide)]
66 fn set_token_property_permission(67 fn set_token_property_permission(
67 &mut self,68 &mut self,
68 caller: caller,69 caller: caller,
89 .map_err(dispatch_to_evm::<T>)90 .map_err(dispatch_to_evm::<T>)
90 }91 }
92
93 /// @notice Set permissions for token property.
94 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
95 /// @param permissions Permissions for keys.
96 #[weight(<SelfWeightOf<T>>::set_token_property_permissions(permissions.len() as u32))]
97 fn set_token_property_permissions(
98 &mut self,
99 caller: caller,
100 permissions: Vec<(string, Vec<(EthTokenPermissions, bool)>)>,
101 ) -> Result<()> {
102 let caller = T::CrossAccountId::from_eth(caller);
103 const PERMISSIONS_FIELDS_COUNT: usize = 3;
104
105 let mut perms = Vec::new();
106
107 for (key, pp) in permissions {
108 if pp.len() > PERMISSIONS_FIELDS_COUNT {
109 return Err(alloc::format!(
110 "Actual number of fields {} for {}, which exceeds the maximum value of {}",
111 pp.len(),
112 stringify!(EthTokenPermissions),
113 PERMISSIONS_FIELDS_COUNT
114 )
115 .as_str()
116 .into());
117 }
118
119 let mut token_permission = PropertyPermission {
120 mutable: false,
121 collection_admin: false,
122 token_owner: false,
123 };
124
125 for (perm, value) in pp {
126 match perm {
127 EthTokenPermissions::Mutable => token_permission.mutable = value,
128 EthTokenPermissions::TokenOwner => token_permission.token_owner = value,
129 EthTokenPermissions::CollectionAdmin => {
130 token_permission.collection_admin = value
131 }
132 }
133 }
134
135 perms.push(PropertyKeyPermission {
136 key: key.into_bytes().try_into().map_err(|_| "too long key")?,
137 permission: token_permission,
138 });
139 }
140
141 <Pallet<T>>::set_token_property_permissions(self, &caller, perms)
142 .map_err(dispatch_to_evm::<T>)
143 }
144
145 /// @notice Get permissions for token properties.
146 fn token_property_permissions(
147 &self,
148 ) -> Result<Vec<(string, Vec<(EthTokenPermissions, bool)>)>> {
149 let perms = <Pallet<T>>::token_property_permission(self.id);
150 Ok(perms
151 .into_iter()
152 .map(|(key, pp)| {
153 let key = string::from_utf8(key.into_inner()).expect("Stored key must be valid");
154 let pp = vec![
155 (EthTokenPermissions::Mutable, pp.mutable),
156 (EthTokenPermissions::TokenOwner, pp.token_owner),
157 (EthTokenPermissions::CollectionAdmin, pp.collection_admin),
158 ];
159 (key, pp)
160 })
161 .collect())
162 }
91163
92 /// @notice Set token property value.164 /// @notice Set token property value.
93 /// @dev Throws error if `msg.sender` has no permission to edit the property.165 /// @dev Throws error if `msg.sender` has no permission to edit the property.
modifiedpallets/refungible/src/erc_token.rsdiffbeforeafterboth
19//! Provides ERC-20 standart support implementation and EVM API for unique extensions for Refungible Pallet.19//! Provides ERC-20 standart support implementation and EVM API for unique extensions for Refungible Pallet.
20//! Method implementations are mostly doing parameter conversion and calling Nonfungible Pallet methods.20//! Method implementations are mostly doing parameter conversion and calling Nonfungible Pallet methods.
21
22extern crate alloc;
23
24#[cfg(not(feature = "std"))]
25use alloc::format;
2621
27use core::{22use core::{
28 char::{REPLACEMENT_CHARACTER, decode_utf16},23 char::{REPLACEMENT_CHARACTER, decode_utf16},
35use pallet_common::{30use pallet_common::{
36 CommonWeightInfo,31 CommonWeightInfo,
37 erc::{CommonEvmHandler, PrecompileResult},32 erc::{CommonEvmHandler, PrecompileResult},
38 eth::collection_id_to_address,33 eth::{collection_id_to_address, EthCrossAccount},
39};34};
40use pallet_evm::{account::CrossAccountId, PrecompileHandle};35use pallet_evm::{account::CrossAccountId, PrecompileHandle};
41use pallet_evm_coder_substrate::{call, dispatch_to_evm, WithRecorder};36use pallet_evm_coder_substrate::{call, dispatch_to_evm, WithRecorder};
200195
201#[solidity_interface(name = ERC20UniqueExtensions)]196#[solidity_interface(name = ERC20UniqueExtensions)]
202impl<T: Config> RefungibleTokenHandle<T> {197impl<T: Config> RefungibleTokenHandle<T>
198where
199 T::AccountId: From<[u8; 32]>,
200{
203 /// @dev Function that burns an amount of the token of a given account,201 /// @dev Function that burns an amount of the token of a given account,
204 /// deducting from the sender's allowance for said account.202 /// deducting from the sender's allowance for said account.
218 Ok(true)216 Ok(true)
219 }217 }
220218
219 /// @dev Function that burns an amount of the token of a given account,
220 /// deducting from the sender's allowance for said account.
221 /// @param from The account whose tokens will be burnt.
222 /// @param amount The amount that will be burnt.
223 #[weight(<SelfWeightOf<T>>::burn_from())]
224 fn burn_from_cross(
225 &mut self,
226 caller: caller,
227 from: EthCrossAccount,
228 amount: uint256,
229 ) -> Result<bool> {
230 let caller = T::CrossAccountId::from_eth(caller);
231 let from = from.into_sub_cross_account::<T>()?;
232 let amount = amount.try_into().map_err(|_| "amount overflow")?;
233 let budget = self
234 .recorder
235 .weight_calls_budget(<StructureWeight<T>>::find_parent());
236
237 <Pallet<T>>::burn_from(self, &caller, &from, self.1, amount, &budget)
238 .map_err(dispatch_to_evm::<T>)?;
239 Ok(true)
240 }
241
242 /// @dev Approve the passed address to spend the specified amount of tokens on behalf of `msg.sender`.
243 /// Beware that changing an allowance with this method brings the risk that someone may use both the old
244 /// and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
245 /// race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
246 /// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
247 /// @param spender The crossaccount which will spend the funds.
248 /// @param amount The amount of tokens to be spent.
249 #[weight(<SelfWeightOf<T>>::approve())]
250 fn approve_cross(
251 &mut self,
252 caller: caller,
253 spender: EthCrossAccount,
254 amount: uint256,
255 ) -> Result<bool> {
256 let caller = T::CrossAccountId::from_eth(caller);
257 let spender = spender.into_sub_cross_account::<T>()?;
258 let amount = amount.try_into().map_err(|_| "amount overflow")?;
259
260 <Pallet<T>>::set_allowance(self, &caller, &spender, self.1, amount)
261 .map_err(dispatch_to_evm::<T>)?;
262 Ok(true)
263 }
221 /// @dev Function that changes total amount of the tokens.264 /// @dev Function that changes total amount of the tokens.
222 /// Throws if `msg.sender` doesn't owns all of the tokens.265 /// Throws if `msg.sender` doesn't owns all of the tokens.
223 /// @param amount New total amount of the tokens.266 /// @param amount New total amount of the tokens.
230 Ok(true)273 Ok(true)
231 }274 }
275
276 /// @dev Transfer token for a specified address
277 /// @param to The crossaccount to transfer to.
278 /// @param amount The amount to be transferred.
279 #[weight(<CommonWeights<T>>::transfer())]
280 fn transfer_cross(
281 &mut self,
282 caller: caller,
283 to: EthCrossAccount,
284 amount: uint256,
285 ) -> Result<bool> {
286 let caller = T::CrossAccountId::from_eth(caller);
287 let to = to.into_sub_cross_account::<T>()?;
288 let amount = amount.try_into().map_err(|_| "amount overflow")?;
289 let budget = self
290 .recorder
291 .weight_calls_budget(<StructureWeight<T>>::find_parent());
292
293 <Pallet<T>>::transfer(self, &caller, &to, self.1, amount, &budget)
294 .map_err(dispatch_to_evm::<T>)?;
295 Ok(true)
296 }
297
298 /// @dev Transfer tokens from one address to another
299 /// @param from The address which you want to send tokens from
300 /// @param to The address which you want to transfer to
301 /// @param amount the amount of tokens to be transferred
302 #[weight(<CommonWeights<T>>::transfer_from())]
303 fn transfer_from_cross(
304 &mut self,
305 caller: caller,
306 from: EthCrossAccount,
307 to: EthCrossAccount,
308 amount: uint256,
309 ) -> Result<bool> {
310 let caller = T::CrossAccountId::from_eth(caller);
311 let from = from.into_sub_cross_account::<T>()?;
312 let to = to.into_sub_cross_account::<T>()?;
313 let amount = amount.try_into().map_err(|_| "amount overflow")?;
314 let budget = self
315 .recorder
316 .weight_calls_budget(<StructureWeight<T>>::find_parent());
317
318 <Pallet<T>>::transfer_from(self, &caller, &from, &to, self.1, amount, &budget)
319 .map_err(dispatch_to_evm::<T>)?;
320 Ok(true)
321 }
232}322}
233323
234impl<T: Config> RefungibleTokenHandle<T> {324impl<T: Config> RefungibleTokenHandle<T> {
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
113 AccessMode, budget::Budget, CollectionId, CollectionFlags, CollectionPropertiesVec,113 AccessMode, budget::Budget, CollectionId, CollectionFlags, CollectionPropertiesVec,
114 CreateCollectionData, CustomDataLimit, mapping::TokenAddressMapping, MAX_ITEMS_PER_BATCH,114 CreateCollectionData, CustomDataLimit, mapping::TokenAddressMapping, MAX_ITEMS_PER_BATCH,
115 MAX_REFUNGIBLE_PIECES, Property, PropertyKey, PropertyKeyPermission, PropertyPermission,115 MAX_REFUNGIBLE_PIECES, Property, PropertyKey, PropertyKeyPermission, PropertyPermission,
116 PropertyScope, PropertyValue, TokenId, TrySetProperty,116 PropertyScope, PropertyValue, TokenId, TrySetProperty, PropertiesPermissionMap,
117};117};
118118
119pub use pallet::*;119pub use pallet::*;
1378 <PalletCommon<T>>::set_token_property_permissions(collection, sender, property_permissions)1378 <PalletCommon<T>>::set_token_property_permissions(collection, sender, property_permissions)
1379 }1379 }
1380
1381 pub fn token_property_permission(collection_id: CollectionId) -> PropertiesPermissionMap {
1382 <PalletCommon<T>>::property_permissions(collection_id)
1383 }
13801384
1381 pub fn set_scoped_token_property_permissions(1385 pub fn set_scoped_token_property_permissions(
1382 collection: &RefungibleHandle<T>,1386 collection: &RefungibleHandle<T>,
modifiedpallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth
18}18}
1919
20/// @title A contract that allows to set and delete token properties and change token property permissions.20/// @title A contract that allows to set and delete token properties and change token property permissions.
21/// @dev the ERC-165 identifier for this interface is 0x91a97a6821/// @dev the ERC-165 identifier for this interface is 0xde0695c2
22contract TokenProperties is Dummy, ERC165 {22contract TokenProperties is Dummy, ERC165 {
23 // /// @notice Set permissions for token property.
24 // /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
25 // /// @param key Property key.
26 // /// @param isMutable Permission to mutate property.
27 // /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
28 // /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
29 // /// @dev EVM selector for this function is: 0x222d97fa,
30 // /// or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)
31 // function setTokenPropertyPermission(string memory key, bool isMutable, bool collectionAdmin, bool tokenOwner) public {
32 // require(false, stub_error);
33 // key;
34 // isMutable;
35 // collectionAdmin;
36 // tokenOwner;
37 // dummy = 0;
38 // }
39
23 /// @notice Set permissions for token property.40 /// @notice Set permissions for token property.
24 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.41 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
25 /// @param key Property key.42 /// @param permissions Permissions for keys.
26 /// @param isMutable Permission to mutate property.
27 /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
28 /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
29 /// @dev EVM selector for this function is: 0x222d97fa,43 /// @dev EVM selector for this function is: 0xbd92983a,
30 /// or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)44 /// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
31 function setTokenPropertyPermission(45 function setTokenPropertyPermissions(Tuple53[] memory permissions) public {
32 string memory key,
33 bool isMutable,
34 bool collectionAdmin,
35 bool tokenOwner
36 ) public {
37 require(false, stub_error);46 require(false, stub_error);
38 key;47 permissions;
39 isMutable;
40 collectionAdmin;
41 tokenOwner;
42 dummy = 0;48 dummy = 0;
43 }49 }
50
51 /// @notice Get permissions for token properties.
52 /// @dev EVM selector for this function is: 0xf23d7790,
53 /// or in textual repr: tokenPropertyPermissions()
54 function tokenPropertyPermissions() public view returns (Tuple53[] memory) {
55 require(false, stub_error);
56 dummy;
57 return new Tuple53[](0);
58 }
4459
45 // /// @notice Set token property value.60 // /// @notice Set token property value.
46 // /// @dev Throws error if `msg.sender` has no permission to edit the property.61 // /// @dev Throws error if `msg.sender` has no permission to edit the property.
118 bytes value;133 bytes value;
119}134}
135
136enum EthTokenPermissions {
137 Mutable,
138 TokenOwner,
139 CollectionAdmin
140}
141
142/// @dev anonymous struct
143struct Tuple53 {
144 string field_0;
145 Tuple51[] field_1;
146}
147
148/// @dev anonymous struct
149struct Tuple51 {
150 EthTokenPermissions field_0;
151 bool field_1;
152}
120153
121/// @title A contract that allows you to work with collections.154/// @title A contract that allows you to work with collections.
122/// @dev the ERC-165 identifier for this interface is 0xb5e1747f155/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
modifiedpallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/refungible/src/stubs/UniqueRefungibleToken.soldiffbeforeafterboth
36 }36 }
37}37}
3838
39/// @dev the ERC-165 identifier for this interface is 0xab8deb3739/// @dev the ERC-165 identifier for this interface is 0xe17a7d2b
40contract ERC20UniqueExtensions is Dummy, ERC165 {40contract ERC20UniqueExtensions is Dummy, ERC165 {
41 /// @dev Function that burns an amount of the token of a given account,41 /// @dev Function that burns an amount of the token of a given account,
42 /// deducting from the sender's allowance for said account.42 /// deducting from the sender's allowance for said account.
52 return false;52 return false;
53 }53 }
54
55 /// @dev Function that burns an amount of the token of a given account,
56 /// deducting from the sender's allowance for said account.
57 /// @param from The account whose tokens will be burnt.
58 /// @param amount The amount that will be burnt.
59 /// @dev EVM selector for this function is: 0xbb2f5a58,
60 /// or in textual repr: burnFromCross((address,uint256),uint256)
61 function burnFromCross(EthCrossAccount memory from, uint256 amount) public returns (bool) {
62 require(false, stub_error);
63 from;
64 amount;
65 dummy = 0;
66 return false;
67 }
68
69 /// @dev Approve the passed address to spend the specified amount of tokens on behalf of `msg.sender`.
70 /// Beware that changing an allowance with this method brings the risk that someone may use both the old
71 /// and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
72 /// race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
73 /// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
74 /// @param spender The crossaccount which will spend the funds.
75 /// @param amount The amount of tokens to be spent.
76 /// @dev EVM selector for this function is: 0x0ecd0ab0,
77 /// or in textual repr: approveCross((address,uint256),uint256)
78 function approveCross(EthCrossAccount memory spender, uint256 amount) public returns (bool) {
79 require(false, stub_error);
80 spender;
81 amount;
82 dummy = 0;
83 return false;
84 }
5485
55 /// @dev Function that changes total amount of the tokens.86 /// @dev Function that changes total amount of the tokens.
56 /// Throws if `msg.sender` doesn't owns all of the tokens.87 /// Throws if `msg.sender` doesn't owns all of the tokens.
64 return false;95 return false;
65 }96 }
97
98 /// @dev Transfer token for a specified address
99 /// @param to The crossaccount to transfer to.
100 /// @param amount The amount to be transferred.
101 /// @dev EVM selector for this function is: 0x2ada85ff,
102 /// or in textual repr: transferCross((address,uint256),uint256)
103 function transferCross(EthCrossAccount memory to, uint256 amount) public returns (bool) {
104 require(false, stub_error);
105 to;
106 amount;
107 dummy = 0;
108 return false;
109 }
110
111 /// @dev Transfer tokens from one address to another
112 /// @param from The address which you want to send tokens from
113 /// @param to The address which you want to transfer to
114 /// @param amount the amount of tokens to be transferred
115 /// @dev EVM selector for this function is: 0xd5cf430b,
116 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
117 function transferFromCross(
118 EthCrossAccount memory from,
119 EthCrossAccount memory to,
120 uint256 amount
121 ) public returns (bool) {
122 require(false, stub_error);
123 from;
124 to;
125 amount;
126 dummy = 0;
127 return false;
128 }
66}129}
130
131/// @dev Cross account struct
132struct EthCrossAccount {
133 address eth;
134 uint256 sub;
135}
67136
68/// @dev inlined interface137/// @dev inlined interface
69contract ERC20Events {138contract ERC20Events {
modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
1010pub type PropertyValue = BoundedBytes<ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;1010pub type PropertyValue = BoundedBytes<ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;
10111011
1012/// Property permission.1012/// Property permission.
1013#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]1013#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone, Default)]
1014#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1014#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
1015pub struct PropertyPermission {1015pub struct PropertyPermission {
1016 /// Permission to change the property and property permission.1016 /// Permission to change the property and property permission.
modifiedruntime/common/config/ethereum.rsdiffbeforeafterboth
7use sp_runtime::{RuntimeAppPublic, Perbill};7use sp_runtime::{RuntimeAppPublic, Perbill};
8use crate::{8use crate::{
9 runtime_common::{9 runtime_common::{
10 config::sponsoring::DefaultSponsoringRateLimit,
11 DealWithFees,
10 dispatch::CollectionDispatchT, ethereum::sponsoring::EvmSponsorshipHandler,12 dispatch::CollectionDispatchT,
11 config::sponsoring::DefaultSponsoringRateLimit, DealWithFees,13 ethereum::{precompiles::UniquePrecompiles, sponsoring::EvmSponsorshipHandler},
12 },14 },
13 Runtime, Aura, Balances, RuntimeEvent, ChainId,15 Runtime, Aura, Balances, RuntimeEvent, ChainId,
14};16};
34const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);36const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);
35parameter_types! {37parameter_types! {
36 pub BlockGasLimit: U256 = U256::from((NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightTimePerGas::get()).ref_time());38 pub BlockGasLimit: U256 = U256::from((NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightTimePerGas::get()).ref_time());
39 pub PrecompilesValue: UniquePrecompiles<Runtime> = UniquePrecompiles::<_>::new();
37}40}
3841
39pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);42pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);
62 type CallOrigin = EnsureAddressTruncated<Self>;65 type CallOrigin = EnsureAddressTruncated<Self>;
63 type WithdrawOrigin = EnsureAddressTruncated<Self>;66 type WithdrawOrigin = EnsureAddressTruncated<Self>;
64 type AddressMapping = HashedAddressMapping<Self::Hashing>;67 type AddressMapping = HashedAddressMapping<Self::Hashing>;
65 type PrecompilesType = ();68 type PrecompilesType = UniquePrecompiles<Self>;
66 type PrecompilesValue = ();69 type PrecompilesValue = PrecompilesValue;
67 type Currency = Balances;70 type Currency = Balances;
68 type RuntimeEvent = RuntimeEvent;71 type RuntimeEvent = RuntimeEvent;
69 type OnMethodCall = (72 type OnMethodCall = (
modifiedruntime/common/config/pallets/mod.rsdiffbeforeafterboth
106impl pallet_configuration::Config for Runtime {106impl pallet_configuration::Config for Runtime {
107 type DefaultWeightToFeeCoefficient = ConstU32<{ up_common::constants::WEIGHT_TO_FEE_COEFF }>;107 type DefaultWeightToFeeCoefficient = ConstU32<{ up_common::constants::WEIGHT_TO_FEE_COEFF }>;
108 type DefaultMinGasPrice = ConstU64<{ up_common::constants::MIN_GAS_PRICE }>;108 type DefaultMinGasPrice = ConstU64<{ up_common::constants::MIN_GAS_PRICE }>;
109 type MaxOverridedAllowedLocations = ConstU32<16>;109 type MaxXcmAllowedLocations = ConstU32<16>;
110 type AppPromotionDailyRate = AppPromotionDailyRate;110 type AppPromotionDailyRate = AppPromotionDailyRate;
111 type DayRelayBlocks = DayRelayBlocks;111 type DayRelayBlocks = DayRelayBlocks;
112}112}
modifiedruntime/common/construct_runtime/mod.rsdiffbeforeafterboth
82 #[runtimes(opal, quartz)]82 #[runtimes(opal, quartz)]
83 AppPromotion: pallet_app_promotion::{Pallet, Call, Storage, Event<T>} = 73,83 AppPromotion: pallet_app_promotion::{Pallet, Call, Storage, Event<T>} = 73,
8484
85 #[runtimes(opal)]85 #[runtimes(opal, quartz, unique)]
86 ForeignAssets: pallet_foreign_assets::{Pallet, Call, Storage, Event<T>} = 80,86 ForeignAssets: pallet_foreign_assets::{Pallet, Call, Storage, Event<T>} = 80,
8787
88 // Frontier88 // Frontier
modifiedruntime/common/ethereum/mod.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17pub mod precompiles;
17pub mod self_contained_call;18pub mod self_contained_call;
18pub mod sponsoring;19pub mod sponsoring;
19pub mod transaction_converter;20pub mod transaction_converter;
addedruntime/common/ethereum/precompiles/mod.rsdiffbeforeafterboth

no changes

addedruntime/common/ethereum/precompiles/sr25519.rsdiffbeforeafterboth

no changes

addedruntime/common/ethereum/precompiles/utils/data.rsdiffbeforeafterboth

no changes

addedruntime/common/ethereum/precompiles/utils/macro/Cargo.tomldiffbeforeafterboth

no changes

addedruntime/common/ethereum/precompiles/utils/macro/src/lib.rsdiffbeforeafterboth

no changes

addedruntime/common/ethereum/precompiles/utils/mod.rsdiffbeforeafterboth

no changes

modifiedruntime/opal/Cargo.tomldiffbeforeafterboth
471up-rpc = { path = "../../primitives/rpc", default-features = false }471up-rpc = { path = "../../primitives/rpc", default-features = false }
472app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false }472app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false }
473rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false }473rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false }
474fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
474fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }475fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
475pallet-inflation = { path = '../../pallets/inflation', default-features = false }476pallet-inflation = { path = '../../pallets/inflation', default-features = false }
476pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }477pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }
494pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }495pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
495fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }496fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
496fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }497fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
498pallet-evm-precompile-simple = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
497evm-coder = { default-features = false, path = '../../crates/evm-coder' }499evm-coder = { default-features = false, path = '../../crates/evm-coder' }
498up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.33' }500up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.33' }
499pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }501pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }
500pallet-maintenance = { default-features = false, path = "../../pallets/maintenance" }502pallet-maintenance = { default-features = false, path = "../../pallets/maintenance" }
503precompile-utils-macro = { path = "../common/ethereum/precompiles/utils/macro" }
504num_enum = { version = "0.5.3", default-features = false }
501505
502################################################################################506################################################################################
503# Test dependencies507# Test dependencies
modifiedruntime/opal/src/lib.rsdiffbeforeafterboth
25#[cfg(feature = "std")]25#[cfg(feature = "std")]
26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
27
28extern crate alloc;
2729
28use frame_support::parameter_types;30use frame_support::parameter_types;
2931
modifiedruntime/quartz/Cargo.tomldiffbeforeafterboth
169 "pallet-maintenance/std",169 "pallet-maintenance/std",
170]170]
171limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']171limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
172quartz-runtime = ['refungible', 'app-promotion']172quartz-runtime = ['refungible', 'app-promotion', 'foreign-assets']
173173
174refungible = []174refungible = []
175scheduler = []175scheduler = []
463pallet-unique = { path = '../../pallets/unique', default-features = false }463pallet-unique = { path = '../../pallets/unique', default-features = false }
464up-rpc = { path = "../../primitives/rpc", default-features = false }464up-rpc = { path = "../../primitives/rpc", default-features = false }
465app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false }465app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false }
466fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
466fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }467fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
467pallet-inflation = { path = '../../pallets/inflation', default-features = false }468pallet-inflation = { path = '../../pallets/inflation', default-features = false }
468pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }469pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }
486pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }487pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
487fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }488fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
488fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }489fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
490pallet-evm-precompile-simple = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
489evm-coder = { default-features = false, path = '../../crates/evm-coder' }491evm-coder = { default-features = false, path = '../../crates/evm-coder' }
490up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.33' }492up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.33' }
491pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }493pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }
492pallet-maintenance = { default-features = false, path = "../../pallets/maintenance" }494pallet-maintenance = { default-features = false, path = "../../pallets/maintenance" }
495precompile-utils-macro = { path = "../common/ethereum/precompiles/utils/macro" }
496num_enum = { version = "0.5.3", default-features = false }
493497
494################################################################################498################################################################################
495# Other Dependencies499# Other Dependencies
modifiedruntime/quartz/src/lib.rsdiffbeforeafterboth
25#[cfg(feature = "std")]25#[cfg(feature = "std")]
26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
27
28extern crate alloc;
2729
28use frame_support::parameter_types;30use frame_support::parameter_types;
2931
modifiedruntime/quartz/src/xcm_barrier.rsdiffbeforeafterboth
52 parents: 1,52 parents: 1,
53 interior: Here,53 interior: Here,
54 },54 },
55 // Statemint/Statemint location
56 MultiLocation {
57 parents: 1,
58 interior: X1(Parachain(1000)),
59 },
55 // Karura/Acala location60 // Karura/Acala location
56 MultiLocation {61 MultiLocation {
57 parents: 1,62 parents: 1,
modifiedruntime/unique/Cargo.tomldiffbeforeafterboth
170 "pallet-maintenance/std",170 "pallet-maintenance/std",
171]171]
172limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']172limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
173unique-runtime = []173unique-runtime = ['foreign-assets']
174stubgen = ["evm-coder/stubgen"]174stubgen = ["evm-coder/stubgen"]
175175
176refungible = []176refungible = []
479pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }479pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
480fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }480fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
481fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }481fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
482fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
482fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }483fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
484pallet-evm-precompile-simple = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.33" }
483evm-coder = { default-features = false, path = '../../crates/evm-coder' }485evm-coder = { default-features = false, path = '../../crates/evm-coder' }
484up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.33' }486up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.33' }
485pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }487pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }
486pallet-maintenance = { default-features = false, path = "../../pallets/maintenance" }488pallet-maintenance = { default-features = false, path = "../../pallets/maintenance" }
489precompile-utils-macro = { path = "../common/ethereum/precompiles/utils/macro" }
490num_enum = { version = "0.5.3", default-features = false }
487491
488################################################################################492################################################################################
489# Other Dependencies493# Other Dependencies
modifiedruntime/unique/src/lib.rsdiffbeforeafterboth
25#[cfg(feature = "std")]25#[cfg(feature = "std")]
26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
27
28extern crate alloc;
2729
28use frame_support::parameter_types;30use frame_support::parameter_types;
2931
modifiedruntime/unique/src/xcm_barrier.rsdiffbeforeafterboth
52 parents: 1,52 parents: 1,
53 interior: Here,53 interior: Here,
54 },54 },
55 // Statemint/Statemint location
56 MultiLocation {
57 parents: 1,
58 interior: X1(Parachain(1000)),
59 },
55 // Karura/Acala location60 // Karura/Acala location
56 MultiLocation {61 MultiLocation {
57 parents: 1,62 parents: 1,
modifiedtests/package.jsondiffbeforeafterboth
45 "testNesting": "mocha --timeout 9999999 -r ts-node/register ./**/nest.test.ts",45 "testNesting": "mocha --timeout 9999999 -r ts-node/register ./**/nest.test.ts",
46 "testUnnesting": "mocha --timeout 9999999 -r ts-node/register ./**/unnest.test.ts",46 "testUnnesting": "mocha --timeout 9999999 -r ts-node/register ./**/unnest.test.ts",
47 "testProperties": "mocha --timeout 9999999 -r ts-node/register ./**/collectionProperties.test.ts ./**/tokenProperties.test.ts ./**/getPropertiesRpc.test.ts",47 "testProperties": "mocha --timeout 9999999 -r ts-node/register ./**/collectionProperties.test.ts ./**/tokenProperties.test.ts ./**/getPropertiesRpc.test.ts",
48 "testCollectionProperties": "mocha --timeout 9999999 -r ts-node/register ./**/collectionProperties.test.ts",
48 "testMigration": "mocha --timeout 9999999 -r ts-node/register ./**/nesting/migration-check.test.ts",49 "testMigration": "mocha --timeout 9999999 -r ts-node/register ./**/nesting/migration-check.test.ts",
49 "testAddCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/addCollectionAdmin.test.ts",50 "testAddCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/addCollectionAdmin.test.ts",
50 "testSetCollectionLimits": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionLimits.test.ts",51 "testSetCollectionLimits": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionLimits.test.ts",
modifiedtests/src/eth/abi/nonFungible.jsondiffbeforeafterboth
697 },697 },
698 {698 {
699 "inputs": [699 "inputs": [
700 {
701 "components": [
700 { "internalType": "string", "name": "key", "type": "string" },702 { "internalType": "string", "name": "field_0", "type": "string" },
703 {
704 "components": [
701 { "internalType": "bool", "name": "isMutable", "type": "bool" },705 {
706 "internalType": "enum EthTokenPermissions",
707 "name": "field_0",
708 "type": "uint8"
709 },
702 { "internalType": "bool", "name": "collectionAdmin", "type": "bool" },710 { "internalType": "bool", "name": "field_1", "type": "bool" }
711 ],
712 "internalType": "struct Tuple46[]",
713 "name": "field_1",
714 "type": "tuple[]"
715 }
716 ],
703 { "internalType": "bool", "name": "tokenOwner", "type": "bool" }717 "internalType": "struct Tuple48[]",
718 "name": "permissions",
719 "type": "tuple[]"
720 }
704 ],721 ],
705 "name": "setTokenPropertyPermission",722 "name": "setTokenPropertyPermissions",
706 "outputs": [],723 "outputs": [],
707 "stateMutability": "nonpayable",724 "stateMutability": "nonpayable",
708 "type": "function"725 "type": "function"
742 "stateMutability": "view",759 "stateMutability": "view",
743 "type": "function"760 "type": "function"
744 },761 },
762 {
763 "inputs": [],
764 "name": "tokenPropertyPermissions",
765 "outputs": [
766 {
767 "components": [
768 { "internalType": "string", "name": "field_0", "type": "string" },
769 {
770 "components": [
771 {
772 "internalType": "enum EthTokenPermissions",
773 "name": "field_0",
774 "type": "uint8"
775 },
776 { "internalType": "bool", "name": "field_1", "type": "bool" }
777 ],
778 "internalType": "struct Tuple46[]",
779 "name": "field_1",
780 "type": "tuple[]"
781 }
782 ],
783 "internalType": "struct Tuple48[]",
784 "name": "",
785 "type": "tuple[]"
786 }
787 ],
788 "stateMutability": "view",
789 "type": "function"
790 },
745 {791 {
746 "inputs": [792 "inputs": [
747 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }793 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
modifiedtests/src/eth/abi/reFungible.jsondiffbeforeafterboth
679 },679 },
680 {680 {
681 "inputs": [681 "inputs": [
682 {
683 "components": [
682 { "internalType": "string", "name": "key", "type": "string" },684 { "internalType": "string", "name": "field_0", "type": "string" },
685 {
686 "components": [
683 { "internalType": "bool", "name": "isMutable", "type": "bool" },687 {
688 "internalType": "enum EthTokenPermissions",
689 "name": "field_0",
690 "type": "uint8"
691 },
684 { "internalType": "bool", "name": "collectionAdmin", "type": "bool" },692 { "internalType": "bool", "name": "field_1", "type": "bool" }
693 ],
694 "internalType": "struct Tuple51[]",
695 "name": "field_1",
696 "type": "tuple[]"
697 }
698 ],
685 { "internalType": "bool", "name": "tokenOwner", "type": "bool" }699 "internalType": "struct Tuple53[]",
700 "name": "permissions",
701 "type": "tuple[]"
702 }
686 ],703 ],
687 "name": "setTokenPropertyPermission",704 "name": "setTokenPropertyPermissions",
688 "outputs": [],705 "outputs": [],
689 "stateMutability": "nonpayable",706 "stateMutability": "nonpayable",
690 "type": "function"707 "type": "function"
733 "stateMutability": "view",750 "stateMutability": "view",
734 "type": "function"751 "type": "function"
735 },752 },
753 {
754 "inputs": [],
755 "name": "tokenPropertyPermissions",
756 "outputs": [
757 {
758 "components": [
759 { "internalType": "string", "name": "field_0", "type": "string" },
760 {
761 "components": [
762 {
763 "internalType": "enum EthTokenPermissions",
764 "name": "field_0",
765 "type": "uint8"
766 },
767 { "internalType": "bool", "name": "field_1", "type": "bool" }
768 ],
769 "internalType": "struct Tuple51[]",
770 "name": "field_1",
771 "type": "tuple[]"
772 }
773 ],
774 "internalType": "struct Tuple53[]",
775 "name": "",
776 "type": "tuple[]"
777 }
778 ],
779 "stateMutability": "view",
780 "type": "function"
781 },
736 {782 {
737 "inputs": [783 "inputs": [
738 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }784 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
modifiedtests/src/eth/abi/reFungibleToken.jsondiffbeforeafterboth
69 "stateMutability": "nonpayable",69 "stateMutability": "nonpayable",
70 "type": "function"70 "type": "function"
71 },71 },
72 {
73 "inputs": [
74 {
75 "components": [
76 { "internalType": "address", "name": "eth", "type": "address" },
77 { "internalType": "uint256", "name": "sub", "type": "uint256" }
78 ],
79 "internalType": "struct EthCrossAccount",
80 "name": "spender",
81 "type": "tuple"
82 },
83 { "internalType": "uint256", "name": "amount", "type": "uint256" }
84 ],
85 "name": "approveCross",
86 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
87 "stateMutability": "nonpayable",
88 "type": "function"
89 },
72 {90 {
73 "inputs": [91 "inputs": [
74 { "internalType": "address", "name": "owner", "type": "address" }92 { "internalType": "address", "name": "owner", "type": "address" }
88 "stateMutability": "nonpayable",106 "stateMutability": "nonpayable",
89 "type": "function"107 "type": "function"
90 },108 },
109 {
110 "inputs": [
111 {
112 "components": [
113 { "internalType": "address", "name": "eth", "type": "address" },
114 { "internalType": "uint256", "name": "sub", "type": "uint256" }
115 ],
116 "internalType": "struct EthCrossAccount",
117 "name": "from",
118 "type": "tuple"
119 },
120 { "internalType": "uint256", "name": "amount", "type": "uint256" }
121 ],
122 "name": "burnFromCross",
123 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
124 "stateMutability": "nonpayable",
125 "type": "function"
126 },
91 {127 {
92 "inputs": [],128 "inputs": [],
93 "name": "decimals",129 "name": "decimals",
158 "stateMutability": "nonpayable",194 "stateMutability": "nonpayable",
159 "type": "function"195 "type": "function"
160 },196 },
197 {
198 "inputs": [
199 {
200 "components": [
201 { "internalType": "address", "name": "eth", "type": "address" },
202 { "internalType": "uint256", "name": "sub", "type": "uint256" }
203 ],
204 "internalType": "struct EthCrossAccount",
205 "name": "to",
206 "type": "tuple"
207 },
208 { "internalType": "uint256", "name": "amount", "type": "uint256" }
209 ],
210 "name": "transferCross",
211 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
212 "stateMutability": "nonpayable",
213 "type": "function"
214 },
161 {215 {
162 "inputs": [216 "inputs": [
163 { "internalType": "address", "name": "from", "type": "address" },217 { "internalType": "address", "name": "from", "type": "address" },
168 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],222 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
169 "stateMutability": "nonpayable",223 "stateMutability": "nonpayable",
170 "type": "function"224 "type": "function"
171 }225 },
226 {
227 "inputs": [
228 {
229 "components": [
230 { "internalType": "address", "name": "eth", "type": "address" },
231 { "internalType": "uint256", "name": "sub", "type": "uint256" }
232 ],
233 "internalType": "struct EthCrossAccount",
234 "name": "from",
235 "type": "tuple"
236 },
237 {
238 "components": [
239 { "internalType": "address", "name": "eth", "type": "address" },
240 { "internalType": "uint256", "name": "sub", "type": "uint256" }
241 ],
242 "internalType": "struct EthCrossAccount",
243 "name": "to",
244 "type": "tuple"
245 },
246 { "internalType": "uint256", "name": "amount", "type": "uint256" }
247 ],
248 "name": "transferFromCross",
249 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
250 "stateMutability": "nonpayable",
251 "type": "function"
252 }
172]253]
173254
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
13}13}
1414
15/// @title A contract that allows to set and delete token properties and change token property permissions.15/// @title A contract that allows to set and delete token properties and change token property permissions.
16/// @dev the ERC-165 identifier for this interface is 0x91a97a6816/// @dev the ERC-165 identifier for this interface is 0xde0695c2
17interface TokenProperties is Dummy, ERC165 {17interface TokenProperties is Dummy, ERC165 {
18 // /// @notice Set permissions for token property.
19 // /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
20 // /// @param key Property key.
21 // /// @param isMutable Permission to mutate property.
22 // /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
23 // /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
24 // /// @dev EVM selector for this function is: 0x222d97fa,
25 // /// or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)
26 // function setTokenPropertyPermission(string memory key, bool isMutable, bool collectionAdmin, bool tokenOwner) external;
27
18 /// @notice Set permissions for token property.28 /// @notice Set permissions for token property.
19 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.29 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
20 /// @param key Property key.30 /// @param permissions Permissions for keys.
21 /// @param isMutable Permission to mutate property.
22 /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
23 /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
24 /// @dev EVM selector for this function is: 0x222d97fa,31 /// @dev EVM selector for this function is: 0xbd92983a,
25 /// or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)32 /// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
26 function setTokenPropertyPermission(33 function setTokenPropertyPermissions(Tuple43[] memory permissions) external;
27 string memory key,34
28 bool isMutable,35 /// @dev EVM selector for this function is: 0xf23d7790,
29 bool collectionAdmin,36 /// or in textual repr: tokenPropertyPermissions()
30 bool tokenOwner37 function tokenPropertyPermissions() external view returns (Tuple43[] memory);
31 ) external;
3238
33 // /// @notice Set token property value.39 // /// @notice Set token property value.
79 bytes value;85 bytes value;
80}86}
87
88enum EthTokenPermissions {
89 Mutable,
90 TokenOwner,
91 CollectionAdmin
92}
93
94/// @dev anonymous struct
95struct Tuple43 {
96 string field_0;
97 Tuple41[] field_1;
98}
99
100/// @dev anonymous struct
101struct Tuple41 {
102 EthTokenPermissions field_0;
103 bool field_1;
104}
81105
82/// @title A contract that allows you to work with collections.106/// @title A contract that allows you to work with collections.
83/// @dev the ERC-165 identifier for this interface is 0xb5e1747f107/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
modifiedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth
13}13}
1414
15/// @title A contract that allows to set and delete token properties and change token property permissions.15/// @title A contract that allows to set and delete token properties and change token property permissions.
16/// @dev the ERC-165 identifier for this interface is 0x91a97a6816/// @dev the ERC-165 identifier for this interface is 0xde0695c2
17interface TokenProperties is Dummy, ERC165 {17interface TokenProperties is Dummy, ERC165 {
18 // /// @notice Set permissions for token property.
19 // /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
20 // /// @param key Property key.
21 // /// @param isMutable Permission to mutate property.
22 // /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
23 // /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
24 // /// @dev EVM selector for this function is: 0x222d97fa,
25 // /// or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)
26 // function setTokenPropertyPermission(string memory key, bool isMutable, bool collectionAdmin, bool tokenOwner) external;
27
18 /// @notice Set permissions for token property.28 /// @notice Set permissions for token property.
19 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.29 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
20 /// @param key Property key.30 /// @param permissions Permissions for keys.
21 /// @param isMutable Permission to mutate property.
22 /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
23 /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
24 /// @dev EVM selector for this function is: 0x222d97fa,31 /// @dev EVM selector for this function is: 0xbd92983a,
25 /// or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)32 /// or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
26 function setTokenPropertyPermission(33 function setTokenPropertyPermissions(Tuple47[] memory permissions) external;
27 string memory key,34
28 bool isMutable,35 /// @notice Get permissions for token properties.
29 bool collectionAdmin,36 /// @dev EVM selector for this function is: 0xf23d7790,
30 bool tokenOwner37 /// or in textual repr: tokenPropertyPermissions()
31 ) external;38 function tokenPropertyPermissions() external view returns (Tuple47[] memory);
3239
33 // /// @notice Set token property value.40 // /// @notice Set token property value.
34 // /// @dev Throws error if `msg.sender` has no permission to edit the property.41 // /// @dev Throws error if `msg.sender` has no permission to edit the property.
79 bytes value;86 bytes value;
80}87}
88
89enum EthTokenPermissions {
90 Mutable,
91 TokenOwner,
92 CollectionAdmin
93}
94
95/// @dev anonymous struct
96struct Tuple47 {
97 string field_0;
98 Tuple45[] field_1;
99}
100
101/// @dev anonymous struct
102struct Tuple45 {
103 EthTokenPermissions field_0;
104 bool field_1;
105}
81106
82/// @title A contract that allows you to work with collections.107/// @title A contract that allows you to work with collections.
83/// @dev the ERC-165 identifier for this interface is 0xb5e1747f108/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
modifiedtests/src/eth/api/UniqueRefungibleToken.soldiffbeforeafterboth
23 function parentTokenId() external view returns (uint256);23 function parentTokenId() external view returns (uint256);
24}24}
2525
26/// @dev the ERC-165 identifier for this interface is 0xab8deb3726/// @dev the ERC-165 identifier for this interface is 0xe17a7d2b
27interface ERC20UniqueExtensions is Dummy, ERC165 {27interface ERC20UniqueExtensions is Dummy, ERC165 {
28 /// @dev Function that burns an amount of the token of a given account,28 /// @dev Function that burns an amount of the token of a given account,
29 /// deducting from the sender's allowance for said account.29 /// deducting from the sender's allowance for said account.
33 /// or in textual repr: burnFrom(address,uint256)33 /// or in textual repr: burnFrom(address,uint256)
34 function burnFrom(address from, uint256 amount) external returns (bool);34 function burnFrom(address from, uint256 amount) external returns (bool);
35
36 /// @dev Function that burns an amount of the token of a given account,
37 /// deducting from the sender's allowance for said account.
38 /// @param from The account whose tokens will be burnt.
39 /// @param amount The amount that will be burnt.
40 /// @dev EVM selector for this function is: 0xbb2f5a58,
41 /// or in textual repr: burnFromCross((address,uint256),uint256)
42 function burnFromCross(EthCrossAccount memory from, uint256 amount) external returns (bool);
43
44 /// @dev Approve the passed address to spend the specified amount of tokens on behalf of `msg.sender`.
45 /// Beware that changing an allowance with this method brings the risk that someone may use both the old
46 /// and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
47 /// race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
48 /// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
49 /// @param spender The crossaccount which will spend the funds.
50 /// @param amount The amount of tokens to be spent.
51 /// @dev EVM selector for this function is: 0x0ecd0ab0,
52 /// or in textual repr: approveCross((address,uint256),uint256)
53 function approveCross(EthCrossAccount memory spender, uint256 amount) external returns (bool);
3554
36 /// @dev Function that changes total amount of the tokens.55 /// @dev Function that changes total amount of the tokens.
37 /// Throws if `msg.sender` doesn't owns all of the tokens.56 /// Throws if `msg.sender` doesn't owns all of the tokens.
40 /// or in textual repr: repartition(uint256)59 /// or in textual repr: repartition(uint256)
41 function repartition(uint256 amount) external returns (bool);60 function repartition(uint256 amount) external returns (bool);
61
62 /// @dev Transfer token for a specified address
63 /// @param to The crossaccount to transfer to.
64 /// @param amount The amount to be transferred.
65 /// @dev EVM selector for this function is: 0x2ada85ff,
66 /// or in textual repr: transferCross((address,uint256),uint256)
67 function transferCross(EthCrossAccount memory to, uint256 amount) external returns (bool);
68
69 /// @dev Transfer tokens from one address to another
70 /// @param from The address which you want to send tokens from
71 /// @param to The address which you want to transfer to
72 /// @param amount the amount of tokens to be transferred
73 /// @dev EVM selector for this function is: 0xd5cf430b,
74 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
75 function transferFromCross(
76 EthCrossAccount memory from,
77 EthCrossAccount memory to,
78 uint256 amount
79 ) external returns (bool);
42}80}
81
82/// @dev Cross account struct
83struct EthCrossAccount {
84 address eth;
85 uint256 sub;
86}
4387
44/// @dev inlined interface88/// @dev inlined interface
45interface ERC20Events {89interface ERC20Events {
modifiedtests/src/eth/events.test.tsdiffbeforeafterboth
19import {EthUniqueHelper, itEth, usingEthPlaygrounds} from './util';19import {EthUniqueHelper, itEth, usingEthPlaygrounds} from './util';
20import {IEvent, TCollectionMode} from '../util/playgrounds/types';20import {IEvent, TCollectionMode} from '../util/playgrounds/types';
21import {Pallets, requirePalletsOrSkip} from '../util';21import {Pallets, requirePalletsOrSkip} from '../util';
22import {NormalizedEvent} from './util/playgrounds/types';22import {EthTokenPermissions, NormalizedEvent} from './util/playgrounds/types';
2323
24let donor: IKeyringPair;24let donor: IKeyringPair;
25 25
119 ethEvents.push(event);119 ethEvents.push(event);
120 });120 });
121 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['PropertyPermissionSet']}]);121 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['PropertyPermissionSet']}]);
122 await collection.methods.setTokenPropertyPermission('testKey', true, true, true).send({from: owner});122 await collection.methods.setTokenPropertyPermissions([
123 ['A', [
124 [EthTokenPermissions.Mutable, true],
125 [EthTokenPermissions.TokenOwner, true],
126 [EthTokenPermissions.CollectionAdmin, true]],
127 ],
128 ]).send({from: owner});
123 await helper.wait.newBlocks(1);129 await helper.wait.newBlocks(1);
124 expect(ethEvents).to.be.like([130 expect(ethEvents).to.be.like([
125 {131 {
374 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);380 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
375 const result = await collection.methods.mint(owner).send({from: owner});381 const result = await collection.methods.mint(owner).send({from: owner});
376 const tokenId = result.events.Transfer.returnValues.tokenId;382 const tokenId = result.events.Transfer.returnValues.tokenId;
377 await collection.methods.setTokenPropertyPermission('A', true, true, true).send({from: owner});383 await collection.methods.setTokenPropertyPermissions([
384 ['A', [
385 [EthTokenPermissions.Mutable, true],
386 [EthTokenPermissions.TokenOwner, true],
387 [EthTokenPermissions.CollectionAdmin, true]],
388 ],
389 ]).send({from: owner});
378390
379391
380 const ethEvents: any = [];392 const ethEvents: any = [];
addedtests/src/eth/precompile.test.tsdiffbeforeafterboth

no changes

modifiedtests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth
160 }160 }
161 });161 });
162162
163 itEth('Can perform approveCross()', async ({helper}) => {
164 const owner = await helper.eth.createAccountWithBalance(donor);
165 const spender = helper.eth.createAccount();
166 const spenderSub = (await helper.arrange.createAccounts([1n], donor))[0];
167 const spenderCrossEth = helper.ethCrossAccount.fromAddress(spender);
168 const spenderCrossSub = helper.ethCrossAccount.fromKeyringPair(spenderSub);
169
170
171 const collection = await helper.rft.mintCollection(alice);
172 const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});
173
174 const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
175 const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);
176
177 {
178 const result = await contract.methods.approveCross(spenderCrossEth, 100).send({from: owner});
179 const event = result.events.Approval;
180 expect(event.address).to.be.equal(tokenAddress);
181 expect(event.returnValues.owner).to.be.equal(owner);
182 expect(event.returnValues.spender).to.be.equal(spender);
183 expect(event.returnValues.value).to.be.equal('100');
184 }
185
186 {
187 const allowance = await contract.methods.allowance(owner, spender).call();
188 expect(+allowance).to.equal(100);
189 }
190
191
192 {
193 const result = await contract.methods.approveCross(spenderCrossSub, 100).send({from: owner});
194 const event = result.events.Approval;
195 expect(event.address).to.be.equal(tokenAddress);
196 expect(event.returnValues.owner).to.be.equal(owner);
197 expect(event.returnValues.spender).to.be.equal(helper.address.substrateToEth(spenderSub.address));
198 expect(event.returnValues.value).to.be.equal('100');
199 }
200
201 {
202 const allowance = await collection.getTokenApprovedPieces(tokenId, {Ethereum: owner}, {Substrate: spenderSub.address});
203 expect(allowance).to.equal(100n);
204 }
205
206 {
207 //TO-DO expect with future allowanceCross(owner, spenderCrossEth).call()
208 }
209 });
210
163 itEth('Can perform transferFrom()', async ({helper}) => {211 itEth('Can perform transferFrom()', async ({helper}) => {
164 const owner = await helper.eth.createAccountWithBalance(donor);212 const owner = await helper.eth.createAccountWithBalance(donor);
198 }246 }
199 });247 });
248
249 itEth('Can perform transferFromCross()', async ({helper}) => {
250 const owner = await helper.eth.createAccountWithBalance(donor);
251 const ownerCross = helper.ethCrossAccount.fromAddress(owner);
252 const spender = await helper.eth.createAccountWithBalance(donor);
253 const receiver = helper.eth.createAccount();
254 const receiverSub = (await helper.arrange.createAccounts([1n], donor))[0];
255 const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiver);
256 const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(receiverSub);
257
258 const collection = await helper.rft.mintCollection(alice);
259 const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});
260
261 const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
262 const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);
263
264 await contract.methods.approve(spender, 100).send({from: owner});
265
266 {
267 const result = await contract.methods.transferFromCross(ownerCross, receiverCrossEth, 49).send({from: spender});
268 let event = result.events.Transfer;
269 expect(event.address).to.be.equal(tokenAddress);
270 expect(event.returnValues.from).to.be.equal(owner);
271 expect(event.returnValues.to).to.be.equal(receiver);
272 expect(event.returnValues.value).to.be.equal('49');
273
274 event = result.events.Approval;
275 expect(event.address).to.be.equal(tokenAddress);
276 expect(event.returnValues.owner).to.be.equal(owner);
277 expect(event.returnValues.spender).to.be.equal(spender);
278 expect(event.returnValues.value).to.be.equal('51');
279 }
280
281 {
282 const balance = await contract.methods.balanceOf(receiver).call();
283 expect(+balance).to.equal(49);
284 }
285
286 {
287 const balance = await contract.methods.balanceOf(owner).call();
288 expect(+balance).to.equal(151);
289 }
290
291 {
292 const result = await contract.methods.transferFromCross(ownerCross, receiverCrossSub, 51).send({from: spender});
293 let event = result.events.Transfer;
294 expect(event.address).to.be.equal(tokenAddress);
295 expect(event.returnValues.from).to.be.equal(owner);
296 expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(receiverSub.address));
297 expect(event.returnValues.value).to.be.equal('51');
298
299 event = result.events.Approval;
300 expect(event.address).to.be.equal(tokenAddress);
301 expect(event.returnValues.owner).to.be.equal(owner);
302 expect(event.returnValues.spender).to.be.equal(spender);
303 expect(event.returnValues.value).to.be.equal('0');
304 }
305
306 {
307 const balance = await collection.getTokenBalance(tokenId, {Substrate: receiverSub.address});
308 expect(balance).to.equal(51n);
309 }
310
311 {
312 const balance = await contract.methods.balanceOf(owner).call();
313 expect(+balance).to.equal(100);
314 }
315 });
200316
201 itEth('Can perform transfer()', async ({helper}) => {317 itEth('Can perform transfer()', async ({helper}) => {
202 const owner = await helper.eth.createAccountWithBalance(donor);318 const owner = await helper.eth.createAccountWithBalance(donor);
267 expect(await rftReceiver.getTop10Owners()).to.deep.eq([{Ethereum: owner.toLowerCase()}]);383 expect(await rftReceiver.getTop10Owners()).to.deep.eq([{Ethereum: owner.toLowerCase()}]);
268 }));384 }));
269385
386 itEth('Can perform transferCross()', async ({helper}) => {
387 const owner = await helper.eth.createAccountWithBalance(donor);
388 const receiver = helper.eth.createAccount();
389 const receiverSub = (await helper.arrange.createAccounts([1n], donor))[0];
390 const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiver);
391 const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(receiverSub);
392 const collection = await helper.rft.mintCollection(alice);
393 const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});
394
395 const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
396 const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);
397
398 {
399 const result = await contract.methods.transferCross(receiverCrossEth, 50).send({from: owner});
400 const event = result.events.Transfer;
401 expect(event.address).to.be.equal(tokenAddress);
402 expect(event.returnValues.from).to.be.equal(owner);
403 expect(event.returnValues.to).to.be.equal(receiver);
404 expect(event.returnValues.value).to.be.equal('50');
405 }
406
407 {
408 const balance = await contract.methods.balanceOf(owner).call();
409 expect(+balance).to.equal(150);
410 }
411
412 {
413 const balance = await contract.methods.balanceOf(receiver).call();
414 expect(+balance).to.equal(50);
415 }
416
417 {
418 const result = await contract.methods.transferCross(receiverCrossSub, 50).send({from: owner});
419 const event = result.events.Transfer;
420 expect(event.address).to.be.equal(tokenAddress);
421 expect(event.returnValues.from).to.be.equal(owner);
422 expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(receiverSub.address));
423 expect(event.returnValues.value).to.be.equal('50');
424 }
425
426 {
427 const balance = await contract.methods.balanceOf(owner).call();
428 expect(+balance).to.equal(100);
429 }
430
431 {
432 const balance = await collection.getTokenBalance(tokenId, {Substrate: receiverSub.address});
433 expect(balance).to.equal(50n);
434 }
435 });
270 itEth('Can perform repartition()', async ({helper}) => {436 itEth('Can perform repartition()', async ({helper}) => {
271 const owner = await helper.eth.createAccountWithBalance(donor);437 const owner = await helper.eth.createAccountWithBalance(donor);
272 const receiver = await helper.eth.createAccountWithBalance(donor);438 const receiver = await helper.eth.createAccountWithBalance(donor);
354 expect(event.returnValues.tokenId).to.be.equal(tokenId);520 expect(event.returnValues.tokenId).to.be.equal(tokenId);
355 });521 });
522
523 itEth('Can perform burnFromCross()', async ({helper}) => {
524 const owner = await helper.eth.createAccountWithBalance(donor);
525 const ownerSub = (await helper.arrange.createAccounts([10n], donor))[0];
526 const ownerCross = helper.ethCrossAccount.fromAddress(owner);
527 const spender = await helper.eth.createAccountWithBalance(donor);
528
529 const spenderCrossEth = helper.ethCrossAccount.fromAddress(spender);
530 const ownerSubCross = helper.ethCrossAccount.fromKeyringPair(ownerSub);
531
532 const collection = await helper.rft.mintCollection(alice);
533 const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});
534
535
536 const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
537 const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);
538
539 {
540 await contract.methods.approveCross(spenderCrossEth, 100).send({from: owner});
541
542 await expect(contract.methods.burnFromCross(ownerCross, 50).send({from: spender})).to.be.fulfilled;
543 await expect(contract.methods.burnFromCross(ownerCross, 100).send({from: spender})).to.be.rejected;
544 expect(await contract.methods.balanceOf(owner).call({from: owner})).to.be.equal('150');
545 }
546 {
547 const {tokenId} = await collection.mintToken(alice, 200n, {Substrate: ownerSub.address});
548 await collection.approveToken(ownerSub, tokenId, {Ethereum: spender}, 100n);
549 const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);
550 const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);
551
552 await expect(contract.methods.burnFromCross(ownerSubCross, 50).send({from: spender})).to.be.fulfilled;
553 await expect(contract.methods.burnFromCross(ownerSubCross, 100).send({from: spender})).to.be.rejected;
554 expect(await collection.getTokenBalance(tokenId, {Substrate: ownerSub.address})).to.be.equal(150n);
555 }
556 });
356});557});
357558
358describe('Refungible: Fees', () => {559describe('Refungible: Fees', () => {
modifiedtests/src/eth/tokenProperties.test.tsdiffbeforeafterboth
20import {ITokenPropertyPermission} from '../util/playgrounds/types';20import {ITokenPropertyPermission} from '../util/playgrounds/types';
21import {Pallets} from '../util';21import {Pallets} from '../util';
22import {UniqueNFTCollection, UniqueNFToken, UniqueRFTCollection} from '../util/playgrounds/unique';22import {UniqueNFTCollection, UniqueNFToken, UniqueRFTCollection} from '../util/playgrounds/unique';
23import {EthTokenPermissions} from './util/playgrounds/types';
2324
24describe('EVM token properties', () => {25describe('EVM token properties', () => {
25 let donor: IKeyringPair;26 let donor: IKeyringPair;
32 });33 });
33 });34 });
3435
36 [
37 {mode: 'nft' as const, requiredPallets: []},
38 {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
39 ].map(testCase =>
35 itEth('Can be reconfigured', async({helper}) => {40 itEth.ifWithPallets(`[${testCase.mode}] Set and get token property permissions`, testCase.requiredPallets, async({helper}) => {
36 const caller = await helper.eth.createAccountWithBalance(donor);41 const owner = await helper.eth.createAccountWithBalance(donor);
42 const caller = await helper.ethCrossAccount.createAccountWithBalance(donor);
37 for(const [mutable,collectionAdmin, tokenOwner] of cartesian([], [false, true], [false, true], [false, true])) {43 for(const [mutable,collectionAdmin, tokenOwner] of cartesian([], [false, true], [false, true], [false, true])) {
38 const collection = await helper.nft.mintCollection(alice);44 const {collectionId, collectionAddress} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C');
39 await collection.addAdmin(alice, {Ethereum: caller});
40
41 const address = helper.ethAddress.fromCollectionId(collection.collectionId);45 const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner);
42 const contract = helper.ethNativeContract.collection(address, 'nft', caller);46 await collection.methods.addCollectionAdminCross(caller).send({from: owner});
43 47
44 await contract.methods.setTokenPropertyPermission('testKey', mutable, collectionAdmin, tokenOwner).send({from: caller});48 await collection.methods.setTokenPropertyPermissions([
45 49 ['testKey', [
50 [EthTokenPermissions.Mutable, mutable],
51 [EthTokenPermissions.TokenOwner, tokenOwner],
52 [EthTokenPermissions.CollectionAdmin, collectionAdmin]],
53 ],
54 ]).send({from: caller.eth});
55
46 expect(await collection.getPropertyPermissions()).to.be.deep.equal([{56 expect(await helper[testCase.mode].getPropertyPermissions(collectionId)).to.be.deep.equal([{
47 key: 'testKey',57 key: 'testKey',
48 permission: {mutable, collectionAdmin, tokenOwner},58 permission: {mutable, collectionAdmin, tokenOwner},
49 }]);59 }]);
60
61 expect(await collection.methods.tokenPropertyPermissions().call({from: caller.eth})).to.be.like([
62 ['testKey', [
63 [EthTokenPermissions.Mutable.toString(), mutable],
64 [EthTokenPermissions.TokenOwner.toString(), tokenOwner],
65 [EthTokenPermissions.CollectionAdmin.toString(), collectionAdmin]],
66 ],
67 ]);
50 }68 }
51 });69 }));
70
71 [
72 {mode: 'nft' as const, requiredPallets: []},
73 {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
74 ].map(testCase =>
75 itEth.ifWithPallets(`[${testCase.mode}] Set and get multiple token property permissions as owner`, testCase.requiredPallets, async({helper}) => {
76 const owner = await helper.eth.createAccountWithBalance(donor);
77
78 const {collectionId, collectionAddress} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C');
79 const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner);
80
81 await collection.methods.setTokenPropertyPermissions([
82 ['testKey_0', [
83 [EthTokenPermissions.Mutable, true],
84 [EthTokenPermissions.TokenOwner, true],
85 [EthTokenPermissions.CollectionAdmin, true]],
86 ],
87 ['testKey_1', [
88 [EthTokenPermissions.Mutable, true],
89 [EthTokenPermissions.TokenOwner, false],
90 [EthTokenPermissions.CollectionAdmin, true]],
91 ],
92 ['testKey_2', [
93 [EthTokenPermissions.Mutable, false],
94 [EthTokenPermissions.TokenOwner, true],
95 [EthTokenPermissions.CollectionAdmin, false]],
96 ],
97 ]).send({from: owner});
98
99 expect(await helper[testCase.mode].getPropertyPermissions(collectionId)).to.be.deep.equal([
100 {
101 key: 'testKey_0',
102 permission: {mutable: true, tokenOwner: true, collectionAdmin: true},
103 },
104 {
105 key: 'testKey_1',
106 permission: {mutable: true, tokenOwner: false, collectionAdmin: true},
107 },
108 {
109 key: 'testKey_2',
110 permission: {mutable: false, tokenOwner: true, collectionAdmin: false},
111 },
112 ]);
113
114 expect(await collection.methods.tokenPropertyPermissions().call({from: owner})).to.be.like([
115 ['testKey_0', [
116 [EthTokenPermissions.Mutable.toString(), true],
117 [EthTokenPermissions.TokenOwner.toString(), true],
118 [EthTokenPermissions.CollectionAdmin.toString(), true]],
119 ],
120 ['testKey_1', [
121 [EthTokenPermissions.Mutable.toString(), true],
122 [EthTokenPermissions.TokenOwner.toString(), false],
123 [EthTokenPermissions.CollectionAdmin.toString(), true]],
124 ],
125 ['testKey_2', [
126 [EthTokenPermissions.Mutable.toString(), false],
127 [EthTokenPermissions.TokenOwner.toString(), true],
128 [EthTokenPermissions.CollectionAdmin.toString(), false]],
129 ],
130 ]);
131
132 }));
133
134 [
135 {mode: 'nft' as const, requiredPallets: []},
136 {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
137 ].map(testCase =>
138 itEth.ifWithPallets(`[${testCase.mode}] Set and get multiple token property permissions as admin`, testCase.requiredPallets, async({helper}) => {
139 const owner = await helper.eth.createAccountWithBalance(donor);
140 const caller = await helper.ethCrossAccount.createAccountWithBalance(donor);
141
142 const {collectionId, collectionAddress} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C');
143 const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner);
144 await collection.methods.addCollectionAdminCross(caller).send({from: owner});
145
146 await collection.methods.setTokenPropertyPermissions([
147 ['testKey_0', [
148 [EthTokenPermissions.Mutable, true],
149 [EthTokenPermissions.TokenOwner, true],
150 [EthTokenPermissions.CollectionAdmin, true]],
151 ],
152 ['testKey_1', [
153 [EthTokenPermissions.Mutable, true],
154 [EthTokenPermissions.TokenOwner, false],
155 [EthTokenPermissions.CollectionAdmin, true]],
156 ],
157 ['testKey_2', [
158 [EthTokenPermissions.Mutable, false],
159 [EthTokenPermissions.TokenOwner, true],
160 [EthTokenPermissions.CollectionAdmin, false]],
161 ],
162 ]).send({from: caller.eth});
163
164 expect(await helper[testCase.mode].getPropertyPermissions(collectionId)).to.be.deep.equal([
165 {
166 key: 'testKey_0',
167 permission: {mutable: true, tokenOwner: true, collectionAdmin: true},
168 },
169 {
170 key: 'testKey_1',
171 permission: {mutable: true, tokenOwner: false, collectionAdmin: true},
172 },
173 {
174 key: 'testKey_2',
175 permission: {mutable: false, tokenOwner: true, collectionAdmin: false},
176 },
177 ]);
178
179 expect(await collection.methods.tokenPropertyPermissions().call({from: caller.eth})).to.be.like([
180 ['testKey_0', [
181 [EthTokenPermissions.Mutable.toString(), true],
182 [EthTokenPermissions.TokenOwner.toString(), true],
183 [EthTokenPermissions.CollectionAdmin.toString(), true]],
184 ],
185 ['testKey_1', [
186 [EthTokenPermissions.Mutable.toString(), true],
187 [EthTokenPermissions.TokenOwner.toString(), false],
188 [EthTokenPermissions.CollectionAdmin.toString(), true]],
189 ],
190 ['testKey_2', [
191 [EthTokenPermissions.Mutable.toString(), false],
192 [EthTokenPermissions.TokenOwner.toString(), true],
193 [EthTokenPermissions.CollectionAdmin.toString(), false]],
194 ],
195 ]);
196
197 }));
52198
53 [199 [
54 {200 {
302 expect(actualProps).to.deep.eq(expectedProps);448 expect(actualProps).to.deep.eq(expectedProps);
303 }));449 }));
450
451 [
452 {mode: 'nft' as const, requiredPallets: []},
453 {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
454 ].map(testCase =>
455 itEth.ifWithPallets(`[${testCase.mode}] Cant set token property permissions as non owner or admin`, testCase.requiredPallets, async({helper}) => {
456 const owner = await helper.eth.createAccountWithBalance(donor);
457 const caller = await helper.eth.createAccountWithBalance(donor);
458
459 const {collectionAddress} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C');
460 const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner);
461
462 await expect(collection.methods.setTokenPropertyPermissions([
463 ['testKey_0', [
464 [EthTokenPermissions.Mutable, true],
465 [EthTokenPermissions.TokenOwner, true],
466 [EthTokenPermissions.CollectionAdmin, true]],
467 ],
468 ]).call({from: caller})).to.be.rejectedWith('NoPermission');
469 }));
470
471 [
472 {mode: 'nft' as const, requiredPallets: []},
473 {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
474 ].map(testCase =>
475 itEth.ifWithPallets(`[${testCase.mode}] Cant set token property permissions with invalid character`, testCase.requiredPallets, async({helper}) => {
476 const owner = await helper.eth.createAccountWithBalance(donor);
477
478 const {collectionAddress} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C');
479 const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner);
480
481 await expect(collection.methods.setTokenPropertyPermissions([
482 // "Space" is invalid character
483 ['testKey 0', [
484 [EthTokenPermissions.Mutable, true],
485 [EthTokenPermissions.TokenOwner, true],
486 [EthTokenPermissions.CollectionAdmin, true]],
487 ],
488 ]).call({from: owner})).to.be.rejectedWith('InvalidCharacterInPropertyKey');
489 }));
490
304});491});
305492
modifiedtests/src/eth/util/playgrounds/types.tsdiffbeforeafterboth
2020
21export type EthProperty = string[];21export type EthProperty = string[];
2222
2323export enum EthTokenPermissions {
24 Mutable,
25 TokenOwner,
26 CollectionAdmin
27}
modifiedtests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth
60 }60 }
6161
62 async compile(name: string, src: string, imports?: ContractImports[]): Promise<CompiledContract> {62 async compile(name: string, src: string, imports?: ContractImports[]): Promise<CompiledContract> {
63 const out = JSON.parse(solc.compile(JSON.stringify({63 const compiled = JSON.parse(solc.compile(JSON.stringify({
64 language: 'Solidity',64 language: 'Solidity',
65 sources: {65 sources: {
66 [`${name}.sol`]: {66 [`${name}.sol`]: {
74 },74 },
75 },75 },
76 },76 },
77 }), {import: await this.findImports(imports)})).contracts[`${name}.sol`][name];77 }), {import: await this.findImports(imports)}));
78
79 const hasErrors = compiled['errors']
80 && compiled['errors'].length > 0
81 && compiled.errors.some(function(err: any) {
82 return err.severity == 'error';
83 });
84
85 if (hasErrors) {
86 throw compiled.errors;
87 }
88 const out = compiled.contracts[`${name}.sol`][name];
7889
79 return {90 return {
80 abi: out.abi,91 abi: out.abi,
modifiedtests/src/interfaces/augment-api-rpc.tsdiffbeforeafterboth
16import type { BlockHash } from '@polkadot/types/interfaces/chain';16import type { BlockHash } from '@polkadot/types/interfaces/chain';
17import type { PrefixedStorageKey } from '@polkadot/types/interfaces/childstate';17import type { PrefixedStorageKey } from '@polkadot/types/interfaces/childstate';
18import type { AuthorityId } from '@polkadot/types/interfaces/consensus';18import type { AuthorityId } from '@polkadot/types/interfaces/consensus';
19import type { CodeUploadRequest, CodeUploadResult, ContractCallRequest, ContractExecResult, ContractInstantiateResult, InstantiateRequestV1 } from '@polkadot/types/interfaces/contracts';19import type { CodeUploadRequest, CodeUploadResult, ContractCallRequest, ContractExecResult, ContractInstantiateResult, InstantiateRequest } from '@polkadot/types/interfaces/contracts';
20import type { BlockStats } from '@polkadot/types/interfaces/dev';20import type { BlockStats } from '@polkadot/types/interfaces/dev';
21import type { CreatedBlock } from '@polkadot/types/interfaces/engine';21import type { CreatedBlock } from '@polkadot/types/interfaces/engine';
22import type { EthAccount, EthCallRequest, EthFeeHistory, EthFilter, EthFilterChanges, EthLog, EthReceipt, EthRichBlock, EthSubKind, EthSubParams, EthSyncStatus, EthTransaction, EthTransactionRequest, EthWork } from '@polkadot/types/interfaces/eth';22import type { EthAccount, EthCallRequest, EthFeeHistory, EthFilter, EthFilterChanges, EthLog, EthReceipt, EthRichBlock, EthSubKind, EthSubParams, EthSyncStatus, EthTransaction, EthTransactionRequest, EthWork } from '@polkadot/types/interfaces/eth';
23import type { Extrinsic } from '@polkadot/types/interfaces/extrinsics';23import type { Extrinsic } from '@polkadot/types/interfaces/extrinsics';
24import type { EncodedFinalityProofs, JustificationNotification, ReportedRoundStates } from '@polkadot/types/interfaces/grandpa';24import type { EncodedFinalityProofs, JustificationNotification, ReportedRoundStates } from '@polkadot/types/interfaces/grandpa';
25import type { MmrLeafBatchProof, MmrLeafProof } from '@polkadot/types/interfaces/mmr';25import type { MmrLeafBatchProof, MmrLeafProof } from '@polkadot/types/interfaces/mmr';
26import type { StorageKind } from '@polkadot/types/interfaces/offchain';26import type { StorageKind } from '@polkadot/types/interfaces/offchain';
27import type { FeeDetails, RuntimeDispatchInfoV1 } from '@polkadot/types/interfaces/payment';27import type { FeeDetails, RuntimeDispatchInfo } from '@polkadot/types/interfaces/payment';
28import type { RpcMethods } from '@polkadot/types/interfaces/rpc';28import type { RpcMethods } from '@polkadot/types/interfaces/rpc';
29import type { AccountId, AccountId32, BlockNumber, H160, H256, H64, Hash, Header, Index, Justification, KeyValue, SignedBlock, StorageData } from '@polkadot/types/interfaces/runtime';29import type { AccountId, AccountId32, BlockNumber, H160, H256, H64, Hash, Header, Index, Justification, KeyValue, SignedBlock, StorageData } from '@polkadot/types/interfaces/runtime';
30import type { MigrationStatusResult, ReadProof, RuntimeVersion, TraceBlockResponse } from '@polkadot/types/interfaces/state';30import type { MigrationStatusResult, ReadProof, RuntimeVersion, TraceBlockResponse } from '@polkadot/types/interfaces/state';
174 * @deprecated Use the runtime interface `api.call.contractsApi.instantiate` instead174 * @deprecated Use the runtime interface `api.call.contractsApi.instantiate` instead
175 * Instantiate a new contract175 * Instantiate a new contract
176 **/176 **/
177 instantiate: AugmentedRpc<(request: InstantiateRequestV1 | { origin?: any; value?: any; gasLimit?: any; code?: any; data?: any; salt?: any } | string | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable<ContractInstantiateResult>>;177 instantiate: AugmentedRpc<(request: InstantiateRequest | { origin?: any; value?: any; gasLimit?: any; storageDepositLimit?: any; code?: any; data?: any; salt?: any } | string | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable<ContractInstantiateResult>>;
178 /**178 /**
179 * @deprecated Not available in newer versions of the contracts interfaces179 * @deprecated Not available in newer versions of the contracts interfaces
180 * Returns the projected time a given contract will be able to sustain paying its rent180 * Returns the projected time a given contract will be able to sustain paying its rent
425 localStorageSet: AugmentedRpc<(kind: StorageKind | 'PERSISTENT' | 'LOCAL' | number | Uint8Array, key: Bytes | string | Uint8Array, value: Bytes | string | Uint8Array) => Observable<Null>>;425 localStorageSet: AugmentedRpc<(kind: StorageKind | 'PERSISTENT' | 'LOCAL' | number | Uint8Array, key: Bytes | string | Uint8Array, value: Bytes | string | Uint8Array) => Observable<Null>>;
426 };426 };
427 payment: {427 payment: {
428 /**428 /**
429 * @deprecated Use `api.call.transactionPaymentApi.queryFeeDetails` instead429 * Query the detailed fee of a given encoded extrinsic
430 * Query the detailed fee of a given encoded extrinsic430 **/
431 **/
432 queryFeeDetails: AugmentedRpc<(extrinsic: Bytes | string | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable<FeeDetails>>;431 queryFeeDetails: AugmentedRpc<(extrinsic: Bytes | string | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable<FeeDetails>>;
433 /**432 /**
434 * @deprecated Use `api.call.transactionPaymentApi.queryInfo` instead433 * Retrieves the fee information for an encoded extrinsic
435 * Retrieves the fee information for an encoded extrinsic434 **/
436 **/
437 queryInfo: AugmentedRpc<(extrinsic: Bytes | string | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable<RuntimeDispatchInfoV1>>;435 queryInfo: AugmentedRpc<(extrinsic: Bytes | string | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable<RuntimeDispatchInfo>>;
438 };436 };
439 rmrk: {437 rmrk: {
440 /**438 /**
modifiedtests/src/interfaces/augment-api-runtime.tsdiffbeforeafterboth
6import '@polkadot/api-base/types/calls';6import '@polkadot/api-base/types/calls';
77
8import type { ApiTypes, AugmentedCall, DecoratedCallBase } from '@polkadot/api-base/types';8import type { ApiTypes, AugmentedCall, DecoratedCallBase } from '@polkadot/api-base/types';
9import type { Bytes, Null, Option, Result, U256, Vec, bool, u256, u32, u64 } from '@polkadot/types-codec';9import type { Bytes, Null, Option, Result, U256, Vec, bool, u256, u64 } from '@polkadot/types-codec';
10import type { AnyNumber, ITuple } from '@polkadot/types-codec/types';10import type { AnyNumber, ITuple } from '@polkadot/types-codec/types';
11import type { CheckInherentsResult, InherentData } from '@polkadot/types/interfaces/blockbuilder';11import type { CheckInherentsResult, InherentData } from '@polkadot/types/interfaces/blockbuilder';
12import type { BlockHash } from '@polkadot/types/interfaces/chain';12import type { BlockHash } from '@polkadot/types/interfaces/chain';
16import type { EvmAccount, EvmCallInfo, EvmCreateInfo } from '@polkadot/types/interfaces/evm';16import type { EvmAccount, EvmCallInfo, EvmCreateInfo } from '@polkadot/types/interfaces/evm';
17import type { Extrinsic } from '@polkadot/types/interfaces/extrinsics';17import type { Extrinsic } from '@polkadot/types/interfaces/extrinsics';
18import type { OpaqueMetadata } from '@polkadot/types/interfaces/metadata';18import type { OpaqueMetadata } from '@polkadot/types/interfaces/metadata';
19import type { FeeDetails, RuntimeDispatchInfo } from '@polkadot/types/interfaces/payment';
20import type { AccountId, Block, H160, H256, Header, Index, KeyTypeId, Permill, SlotDuration } from '@polkadot/types/interfaces/runtime';19import type { AccountId, Block, H160, H256, Header, Index, KeyTypeId, Permill, SlotDuration } from '@polkadot/types/interfaces/runtime';
21import type { RuntimeVersion } from '@polkadot/types/interfaces/state';20import type { RuntimeVersion } from '@polkadot/types/interfaces/state';
22import type { ApplyExtrinsicResult, DispatchError } from '@polkadot/types/interfaces/system';21import type { ApplyExtrinsicResult, DispatchError } from '@polkadot/types/interfaces/system';
229 **/228 **/
230 [key: string]: DecoratedCallBase<ApiType>;229 [key: string]: DecoratedCallBase<ApiType>;
231 };230 };
232 /** 0x37c8bb1350a9a2a8/2 */
233 transactionPaymentApi: {
234 /**
235 * The transaction fee details
236 **/
237 queryFeeDetails: AugmentedCall<ApiType, (uxt: Extrinsic | IExtrinsic | string | Uint8Array, len: u32 | AnyNumber | Uint8Array) => Observable<FeeDetails>>;
238 /**
239 * The transaction info
240 **/
241 queryInfo: AugmentedCall<ApiType, (uxt: Extrinsic | IExtrinsic | string | Uint8Array, len: u32 | AnyNumber | Uint8Array) => Observable<RuntimeDispatchInfo>>;
242 /**
243 * Generic call
244 **/
245 [key: string]: DecoratedCallBase<ApiType>;
246 };
247 } // AugmentedCalls231 } // AugmentedCalls
248} // declare module232} // declare module
249233
modifiedtests/src/interfaces/augment-types.tsdiffbeforeafterboth
24import type { StatementKind } from '@polkadot/types/interfaces/claims';24import type { StatementKind } from '@polkadot/types/interfaces/claims';
25import type { CollectiveOrigin, MemberCount, ProposalIndex, Votes, VotesTo230 } from '@polkadot/types/interfaces/collective';25import type { CollectiveOrigin, MemberCount, ProposalIndex, Votes, VotesTo230 } from '@polkadot/types/interfaces/collective';
26import type { AuthorityId, RawVRFOutput } from '@polkadot/types/interfaces/consensus';26import type { AuthorityId, RawVRFOutput } from '@polkadot/types/interfaces/consensus';
27import type { AliveContractInfo, CodeHash, CodeSource, CodeUploadRequest, CodeUploadResult, CodeUploadResultValue, ContractCallFlags, ContractCallRequest, ContractExecResult, ContractExecResultOk, ContractExecResultResult, ContractExecResultSuccessTo255, ContractExecResultSuccessTo260, ContractExecResultTo255, ContractExecResultTo260, ContractExecResultTo267, ContractExecResultU64, ContractInfo, ContractInstantiateResult, ContractInstantiateResultTo267, ContractInstantiateResultTo299, ContractInstantiateResultU64, ContractReturnFlags, ContractStorageKey, DeletedContract, ExecReturnValue, Gas, HostFnWeights, HostFnWeightsTo264, InstantiateRequest, InstantiateRequestV1, InstantiateRequestV2, InstantiateReturnValue, InstantiateReturnValueOk, InstantiateReturnValueTo267, InstructionWeights, Limits, LimitsTo264, PrefabWasmModule, RentProjection, Schedule, ScheduleTo212, ScheduleTo258, ScheduleTo264, SeedOf, StorageDeposit, TombstoneContractInfo, TrieId } from '@polkadot/types/interfaces/contracts';27import type { AliveContractInfo, CodeHash, CodeSource, CodeUploadRequest, CodeUploadResult, CodeUploadResultValue, ContractCallFlags, ContractCallRequest, ContractExecResult, ContractExecResultOk, ContractExecResultResult, ContractExecResultSuccessTo255, ContractExecResultSuccessTo260, ContractExecResultTo255, ContractExecResultTo260, ContractExecResultTo267, ContractInfo, ContractInstantiateResult, ContractInstantiateResultTo267, ContractInstantiateResultTo299, ContractReturnFlags, ContractStorageKey, DeletedContract, ExecReturnValue, Gas, HostFnWeights, HostFnWeightsTo264, InstantiateRequest, InstantiateRequestV1, InstantiateRequestV2, InstantiateReturnValue, InstantiateReturnValueOk, InstantiateReturnValueTo267, InstructionWeights, Limits, LimitsTo264, PrefabWasmModule, RentProjection, Schedule, ScheduleTo212, ScheduleTo258, ScheduleTo264, SeedOf, StorageDeposit, TombstoneContractInfo, TrieId } from '@polkadot/types/interfaces/contracts';
28import type { ContractConstructorSpecLatest, ContractConstructorSpecV0, ContractConstructorSpecV1, ContractConstructorSpecV2, ContractConstructorSpecV3, ContractContractSpecV0, ContractContractSpecV1, ContractContractSpecV2, ContractContractSpecV3, ContractContractSpecV4, ContractCryptoHasher, ContractDiscriminant, ContractDisplayName, ContractEventParamSpecLatest, ContractEventParamSpecV0, ContractEventParamSpecV2, ContractEventSpecLatest, ContractEventSpecV0, ContractEventSpecV1, ContractEventSpecV2, ContractLayoutArray, ContractLayoutCell, ContractLayoutEnum, ContractLayoutHash, ContractLayoutHashingStrategy, ContractLayoutKey, ContractLayoutStruct, ContractLayoutStructField, ContractMessageParamSpecLatest, ContractMessageParamSpecV0, ContractMessageParamSpecV2, ContractMessageSpecLatest, ContractMessageSpecV0, ContractMessageSpecV1, ContractMessageSpecV2, ContractMetadata, ContractMetadataLatest, ContractMetadataV0, ContractMetadataV1, ContractMetadataV2, ContractMetadataV3, ContractMetadataV4, ContractProject, ContractProjectContract, ContractProjectInfo, ContractProjectSource, ContractProjectV0, ContractSelector, ContractStorageLayout, ContractTypeSpec } from '@polkadot/types/interfaces/contractsAbi';28import type { ContractConstructorSpecLatest, ContractConstructorSpecV0, ContractConstructorSpecV1, ContractConstructorSpecV2, ContractConstructorSpecV3, ContractContractSpecV0, ContractContractSpecV1, ContractContractSpecV2, ContractContractSpecV3, ContractContractSpecV4, ContractCryptoHasher, ContractDiscriminant, ContractDisplayName, ContractEventParamSpecLatest, ContractEventParamSpecV0, ContractEventParamSpecV2, ContractEventSpecLatest, ContractEventSpecV0, ContractEventSpecV1, ContractEventSpecV2, ContractLayoutArray, ContractLayoutCell, ContractLayoutEnum, ContractLayoutHash, ContractLayoutHashingStrategy, ContractLayoutKey, ContractLayoutStruct, ContractLayoutStructField, ContractMessageParamSpecLatest, ContractMessageParamSpecV0, ContractMessageParamSpecV2, ContractMessageSpecLatest, ContractMessageSpecV0, ContractMessageSpecV1, ContractMessageSpecV2, ContractMetadata, ContractMetadataLatest, ContractMetadataV0, ContractMetadataV1, ContractMetadataV2, ContractMetadataV3, ContractMetadataV4, ContractProject, ContractProjectContract, ContractProjectInfo, ContractProjectSource, ContractProjectV0, ContractSelector, ContractStorageLayout, ContractTypeSpec } from '@polkadot/types/interfaces/contractsAbi';
29import type { FundIndex, FundInfo, LastContribution, TrieIndex } from '@polkadot/types/interfaces/crowdloan';29import type { FundIndex, FundInfo, LastContribution, TrieIndex } from '@polkadot/types/interfaces/crowdloan';
30import type { CollationInfo, CollationInfoV1, ConfigData, MessageId, OverweightIndex, PageCounter, PageIndexData } from '@polkadot/types/interfaces/cumulus';30import type { CollationInfo, CollationInfoV1, ConfigData, MessageId, OverweightIndex, PageCounter, PageIndexData } from '@polkadot/types/interfaces/cumulus';
47import type { StorageKind } from '@polkadot/types/interfaces/offchain';47import type { StorageKind } from '@polkadot/types/interfaces/offchain';
48import type { DeferredOffenceOf, Kind, OffenceDetails, Offender, OpaqueTimeSlot, ReportIdOf, Reporter } from '@polkadot/types/interfaces/offences';48import type { DeferredOffenceOf, Kind, OffenceDetails, Offender, OpaqueTimeSlot, ReportIdOf, Reporter } from '@polkadot/types/interfaces/offences';
49import type { AbridgedCandidateReceipt, AbridgedHostConfiguration, AbridgedHrmpChannel, AssignmentId, AssignmentKind, AttestedCandidate, AuctionIndex, AuthorityDiscoveryId, AvailabilityBitfield, AvailabilityBitfieldRecord, BackedCandidate, Bidder, BufferedSessionChange, CandidateCommitments, CandidateDescriptor, CandidateEvent, CandidateHash, CandidateInfo, CandidatePendingAvailability, CandidateReceipt, CollatorId, CollatorSignature, CommittedCandidateReceipt, CoreAssignment, CoreIndex, CoreOccupied, CoreState, DisputeLocation, DisputeResult, DisputeState, DisputeStatement, DisputeStatementSet, DoubleVoteReport, DownwardMessage, ExplicitDisputeStatement, GlobalValidationData, GlobalValidationSchedule, GroupIndex, GroupRotationInfo, HeadData, HostConfiguration, HrmpChannel, HrmpChannelId, HrmpOpenChannelRequest, InboundDownwardMessage, InboundHrmpMessage, InboundHrmpMessages, IncomingParachain, IncomingParachainDeploy, IncomingParachainFixed, InvalidDisputeStatementKind, LeasePeriod, LeasePeriodOf, LocalValidationData, MessageIngestionType, MessageQueueChain, MessagingStateSnapshot, MessagingStateSnapshotEgressEntry, MultiDisputeStatementSet, NewBidder, OccupiedCore, OccupiedCoreAssumption, OldV1SessionInfo, OutboundHrmpMessage, ParaGenesisArgs, ParaId, ParaInfo, ParaLifecycle, ParaPastCodeMeta, ParaScheduling, ParaValidatorIndex, ParachainDispatchOrigin, ParachainInherentData, ParachainProposal, ParachainsInherentData, ParathreadClaim, ParathreadClaimQueue, ParathreadEntry, PersistedValidationData, PvfCheckStatement, QueuedParathread, RegisteredParachainInfo, RelayBlockNumber, RelayChainBlockNumber, RelayChainHash, RelayHash, Remark, ReplacementTimes, Retriable, ScheduledCore, Scheduling, ScrapedOnChainVotes, ServiceQuality, SessionInfo, SessionInfoValidatorGroup, SignedAvailabilityBitfield, SignedAvailabilityBitfields, SigningContext, SlotRange, SlotRange10, Statement, SubId, SystemInherentData, TransientValidationData, UpgradeGoAhead, UpgradeRestriction, UpwardMessage, ValidDisputeStatementKind, ValidationCode, ValidationCodeHash, ValidationData, ValidationDataType, ValidationFunctionParams, ValidatorSignature, ValidityAttestation, VecInboundHrmpMessage, WinnersData, WinnersData10, WinnersDataTuple, WinnersDataTuple10, WinningData, WinningData10, WinningDataEntry } from '@polkadot/types/interfaces/parachains';49import type { AbridgedCandidateReceipt, AbridgedHostConfiguration, AbridgedHrmpChannel, AssignmentId, AssignmentKind, AttestedCandidate, AuctionIndex, AuthorityDiscoveryId, AvailabilityBitfield, AvailabilityBitfieldRecord, BackedCandidate, Bidder, BufferedSessionChange, CandidateCommitments, CandidateDescriptor, CandidateEvent, CandidateHash, CandidateInfo, CandidatePendingAvailability, CandidateReceipt, CollatorId, CollatorSignature, CommittedCandidateReceipt, CoreAssignment, CoreIndex, CoreOccupied, CoreState, DisputeLocation, DisputeResult, DisputeState, DisputeStatement, DisputeStatementSet, DoubleVoteReport, DownwardMessage, ExplicitDisputeStatement, GlobalValidationData, GlobalValidationSchedule, GroupIndex, GroupRotationInfo, HeadData, HostConfiguration, HrmpChannel, HrmpChannelId, HrmpOpenChannelRequest, InboundDownwardMessage, InboundHrmpMessage, InboundHrmpMessages, IncomingParachain, IncomingParachainDeploy, IncomingParachainFixed, InvalidDisputeStatementKind, LeasePeriod, LeasePeriodOf, LocalValidationData, MessageIngestionType, MessageQueueChain, MessagingStateSnapshot, MessagingStateSnapshotEgressEntry, MultiDisputeStatementSet, NewBidder, OccupiedCore, OccupiedCoreAssumption, OldV1SessionInfo, OutboundHrmpMessage, ParaGenesisArgs, ParaId, ParaInfo, ParaLifecycle, ParaPastCodeMeta, ParaScheduling, ParaValidatorIndex, ParachainDispatchOrigin, ParachainInherentData, ParachainProposal, ParachainsInherentData, ParathreadClaim, ParathreadClaimQueue, ParathreadEntry, PersistedValidationData, PvfCheckStatement, QueuedParathread, RegisteredParachainInfo, RelayBlockNumber, RelayChainBlockNumber, RelayChainHash, RelayHash, Remark, ReplacementTimes, Retriable, ScheduledCore, Scheduling, ScrapedOnChainVotes, ServiceQuality, SessionInfo, SessionInfoValidatorGroup, SignedAvailabilityBitfield, SignedAvailabilityBitfields, SigningContext, SlotRange, SlotRange10, Statement, SubId, SystemInherentData, TransientValidationData, UpgradeGoAhead, UpgradeRestriction, UpwardMessage, ValidDisputeStatementKind, ValidationCode, ValidationCodeHash, ValidationData, ValidationDataType, ValidationFunctionParams, ValidatorSignature, ValidityAttestation, VecInboundHrmpMessage, WinnersData, WinnersData10, WinnersDataTuple, WinnersDataTuple10, WinningData, WinningData10, WinningDataEntry } from '@polkadot/types/interfaces/parachains';
50import type { FeeDetails, InclusionFee, RuntimeDispatchInfo, RuntimeDispatchInfoV1, RuntimeDispatchInfoV2 } from '@polkadot/types/interfaces/payment';50import type { FeeDetails, InclusionFee, RuntimeDispatchInfo } from '@polkadot/types/interfaces/payment';
51import type { Approvals } from '@polkadot/types/interfaces/poll';51import type { Approvals } from '@polkadot/types/interfaces/poll';
52import type { ProxyAnnouncement, ProxyDefinition, ProxyType } from '@polkadot/types/interfaces/proxy';52import type { ProxyAnnouncement, ProxyDefinition, ProxyType } from '@polkadot/types/interfaces/proxy';
53import type { AccountStatus, AccountValidity } from '@polkadot/types/interfaces/purchase';53import type { AccountStatus, AccountValidity } from '@polkadot/types/interfaces/purchase';
273 ContractExecResultTo255: ContractExecResultTo255;273 ContractExecResultTo255: ContractExecResultTo255;
274 ContractExecResultTo260: ContractExecResultTo260;274 ContractExecResultTo260: ContractExecResultTo260;
275 ContractExecResultTo267: ContractExecResultTo267;275 ContractExecResultTo267: ContractExecResultTo267;
276 ContractExecResultU64: ContractExecResultU64;
277 ContractInfo: ContractInfo;276 ContractInfo: ContractInfo;
278 ContractInstantiateResult: ContractInstantiateResult;277 ContractInstantiateResult: ContractInstantiateResult;
279 ContractInstantiateResultTo267: ContractInstantiateResultTo267;278 ContractInstantiateResultTo267: ContractInstantiateResultTo267;
280 ContractInstantiateResultTo299: ContractInstantiateResultTo299;279 ContractInstantiateResultTo299: ContractInstantiateResultTo299;
281 ContractInstantiateResultU64: ContractInstantiateResultU64;
282 ContractLayoutArray: ContractLayoutArray;280 ContractLayoutArray: ContractLayoutArray;
283 ContractLayoutCell: ContractLayoutCell;281 ContractLayoutCell: ContractLayoutCell;
284 ContractLayoutEnum: ContractLayoutEnum;282 ContractLayoutEnum: ContractLayoutEnum;
1059 RpcMethods: RpcMethods;1057 RpcMethods: RpcMethods;
1060 RuntimeDbWeight: RuntimeDbWeight;1058 RuntimeDbWeight: RuntimeDbWeight;
1061 RuntimeDispatchInfo: RuntimeDispatchInfo;1059 RuntimeDispatchInfo: RuntimeDispatchInfo;
1062 RuntimeDispatchInfoV1: RuntimeDispatchInfoV1;
1063 RuntimeDispatchInfoV2: RuntimeDispatchInfoV2;
1064 RuntimeVersion: RuntimeVersion;1060 RuntimeVersion: RuntimeVersion;
1065 RuntimeVersionApi: RuntimeVersionApi;1061 RuntimeVersionApi: RuntimeVersionApi;
1066 RuntimeVersionPartial: RuntimeVersionPartial;1062 RuntimeVersionPartial: RuntimeVersionPartial;
modifiedtests/src/nesting/collectionProperties.test.tsdiffbeforeafterboth
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';
18import {itSub, Pallets, usingPlaygrounds, expect} from '../util';18import {itSub, Pallets, usingPlaygrounds, expect, requirePalletsOrSkip} from '../util';
19import {UniqueBaseCollection} from '../util/playgrounds/unique';
2019
21describe('Integration Test: Collection Properties', () => {20describe('Integration Test: Collection Properties', () => {
22 let alice: IKeyringPair;21 let alice: IKeyringPair;
34 expect(await collection.getProperties()).to.be.empty;33 expect(await collection.getProperties()).to.be.empty;
35 });34 });
36 35
37 async function testSetsPropertiesForCollection(collection: UniqueBaseCollection) {36 [
38 // As owner37 {mode: 'nft' as const, requiredPallets: []},
39 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}])).to.be.fulfilled;38 {mode: 'ft' as const, requiredPallets: []},
40 39 {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
41 await collection.addAdmin(alice, {Substrate: bob.address});40 ].map(testSuite => describe(`${testSuite.mode.toUpperCase()}`, () => {
42 41 before(async function() {
43 // As administrator42 // eslint-disable-next-line require-await
44 await expect(collection.setProperties(bob, [{key: 'black_hole'}])).to.be.fulfilled;43 await usingPlaygrounds(async helper => {
45 44 requirePalletsOrSkip(this, helper, testSuite.requiredPallets);
46 const properties = await collection.getProperties();45 });
47 expect(properties).to.include.deep.members([
48 {key: 'electron', value: 'come bond'},
49 {key: 'black_hole', value: ''},
50 ]);
51 }
52
53 itSub('Sets properties for a NFT collection', async ({helper}) => {
54 await testSetsPropertiesForCollection(await helper.nft.mintCollection(alice));
55 });46 });
56 47
48 itSub('Sets properties for a collection', async ({helper}) => {
49 const collection = await helper[testSuite.mode].mintCollection(alice);
50
51 // As owner
52 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}])).to.be.fulfilled;
53
57 itSub.ifWithPallets('Sets properties for a ReFungible collection', [Pallets.ReFungible], async ({helper}) => {54 await collection.addAdmin(alice, {Substrate: bob.address});
58 await testSetsPropertiesForCollection(await helper.rft.mintCollection(alice));55
56 // As administrator
57 await expect(collection.setProperties(bob, [{key: 'black_hole'}])).to.be.fulfilled;
58
59 const properties = await collection.getProperties();
60 expect(properties).to.include.deep.members([
61 {key: 'electron', value: 'come bond'},
62 {key: 'black_hole', value: ''},
63 ]);
59 });64 });
60 65
61 async function testCheckValidNames(collection: UniqueBaseCollection) {66 itSub('Check valid names for collection properties keys', async ({helper}) => {
67 const collection = await helper[testSuite.mode].mintCollection(alice);
68
62 // alpha symbols69 // alpha symbols
63 await expect(collection.setProperties(alice, [{key: 'answer'}])).to.be.fulfilled;70 await expect(collection.setProperties(alice, [{key: 'answer'}])).to.be.fulfilled;
82 {key: '-', value: ''},89 {key: '-', value: ''},
83 {key: 'once.in.a.long.long.while...', value: 'you get a little lost'},90 {key: 'once.in.a.long.long.while...', value: 'you get a little lost'},
84 ]);91 ]);
85 }92 });
86 93
87 itSub('Check valid names for NFT collection properties keys', async ({helper}) => {
88 await testCheckValidNames(await helper.nft.mintCollection(alice));
89 });
90
91 itSub.ifWithPallets('Check valid names for ReFungible collection properties keys', [Pallets.ReFungible], async ({helper}) => {
92 await testCheckValidNames(await helper.rft.mintCollection(alice));
93 });
94
95 async function testChangesProperties(collection: UniqueBaseCollection) {94 itSub('Changes properties of a collection', async ({helper}) => {
95 const collection = await helper[testSuite.mode].mintCollection(alice);
96
96 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: ''}])).to.be.fulfilled;97 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: ''}])).to.be.fulfilled;
97 98
103 {key: 'electron', value: 'come bond'},104 {key: 'electron', value: 'come bond'},
104 {key: 'black_hole', value: 'LIGO'},105 {key: 'black_hole', value: 'LIGO'},
105 ]);106 ]);
106 }107 });
107 108
108 itSub('Changes properties of a NFT collection', async ({helper}) => {
109 await testChangesProperties(await helper.nft.mintCollection(alice));
110 });
111
112 itSub.ifWithPallets('Changes properties of a ReFungible collection', [Pallets.ReFungible], async ({helper}) => {
113 await testChangesProperties(await helper.rft.mintCollection(alice));
114 });
115
116 async function testDeleteProperties(collection: UniqueBaseCollection) {109 itSub('Deletes properties of a collection', async ({helper}) => {
110 const collection = await helper[testSuite.mode].mintCollection(alice);
111
117 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}])).to.be.fulfilled;112 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}])).to.be.fulfilled;
118 113
122 expect(properties).to.be.deep.equal([117 expect(properties).to.be.deep.equal([
123 {key: 'black_hole', value: 'LIGO'},118 {key: 'black_hole', value: 'LIGO'},
124 ]);119 ]);
125 }120 });
126 121
127 itSub('Deletes properties of a NFT collection', async ({helper}) => {
128 await testDeleteProperties(await helper.nft.mintCollection(alice));
129 });
130
131 itSub.ifWithPallets('Deletes properties of a ReFungible collection', [Pallets.ReFungible], async ({helper}) => {
132 await testDeleteProperties(await helper.rft.mintCollection(alice));
133 });
134
135 [
136 // TODO enable properties for FT collection in Substrate (release 040)
137 // {mode: 'ft' as const, requiredPallets: []},
138 {mode: 'nft' as const, requiredPallets: []},
139 {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
140 ].map(testCase =>
141 itSub.ifWithPallets(`Allows modifying a collection property multiple times with the same size (${testCase.mode})`, testCase.requiredPallets, async({helper}) => {122 itSub('Allows modifying a collection property multiple times with the same size', async({helper}) => {
142 const propKey = 'tok-prop';123 const propKey = 'tok-prop';
143124
144 const collection = await helper[testCase.mode].mintCollection(alice);125 const collection = await helper[testSuite.mode].mintCollection(alice);
145126
146 const maxCollectionPropertiesSize = 40960;127 const maxCollectionPropertiesSize = 40960;
147128
166 const consumedSpace = await collection.getPropertiesConsumedSpace();147 const consumedSpace = await collection.getPropertiesConsumedSpace();
167 expect(consumedSpace).to.be.equal(originalSpace);148 expect(consumedSpace).to.be.equal(originalSpace);
168 }149 }
169 }));150 });
170151
171 [
172 // TODO enable properties for FT collection in Substrate (release 040)
173 // {mode: 'ft' as const, requiredPallets: []},
174 {mode: 'nft' as const, requiredPallets: []},
175 {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
176 ].map(testCase =>
177 itSub.ifWithPallets(`Adding then removing a collection property doesn't change the consumed space (${testCase.mode})`, testCase.requiredPallets, async({helper}) => {152 itSub('Adding then removing a collection property doesn\'t change the consumed space', async({helper}) => {
178 const propKey = 'tok-prop';153 const propKey = 'tok-prop';
179154
180 const collection = await helper[testCase.mode].mintCollection(alice);155 const collection = await helper[testSuite.mode].mintCollection(alice);
181 const originalSpace = await collection.getPropertiesConsumedSpace();156 const originalSpace = await collection.getPropertiesConsumedSpace();
182157
183 const propDataSize = 4096;158 const propDataSize = 4096;
190 await collection.deleteProperties(alice, [propKey]);165 await collection.deleteProperties(alice, [propKey]);
191 consumedSpace = await collection.getPropertiesConsumedSpace();166 consumedSpace = await collection.getPropertiesConsumedSpace();
192 expect(consumedSpace).to.be.equal(originalSpace);167 expect(consumedSpace).to.be.equal(originalSpace);
193 }));168 });
194169
195 [
196 // TODO enable properties for FT collection in Substrate (release 040)
197 // {mode: 'ft' as const, requiredPallets: []},
198 {mode: 'nft' as const, requiredPallets: []},
199 {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
200 ].map(testCase =>
201 itSub.ifWithPallets(`Modifying a collection property with different sizes correctly changes the consumed space (${testCase.mode})`, testCase.requiredPallets, async({helper}) => {170 itSub('Modifying a collection property with different sizes correctly changes the consumed space', async({helper}) => {
202 const propKey = 'tok-prop';171 const propKey = 'tok-prop';
203172
204 const collection = await helper[testCase.mode].mintCollection(alice);173 const collection = await helper[testSuite.mode].mintCollection(alice);
205 const originalSpace = await collection.getPropertiesConsumedSpace();174 const originalSpace = await collection.getPropertiesConsumedSpace();
206175
207 const initPropDataSize = 4096;176 const initPropDataSize = 4096;
229 consumedSpace = await collection.getPropertiesConsumedSpace();198 consumedSpace = await collection.getPropertiesConsumedSpace();
230 expectedConsumedSpaceDiff = biggerPropDataSize - smallerPropDataSize;199 expectedConsumedSpaceDiff = biggerPropDataSize - smallerPropDataSize;
231 expect(consumedSpace).to.be.equal(biggerPropDataSize - expectedConsumedSpaceDiff);200 expect(consumedSpace).to.be.equal(biggerPropDataSize - expectedConsumedSpaceDiff);
232 }));201 });
202 }));
233});203});
234 204
235describe('Negative Integration Test: Collection Properties', () => {205describe('Negative Integration Test: Collection Properties', () => {
243 });213 });
244 });214 });
245 215
246 async function testFailsSetPropertiesIfNotOwnerOrAdmin(collection: UniqueBaseCollection) { 216 [
247 await expect(collection.setProperties(bob, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]))217 {mode: 'nft' as const, requiredPallets: []},
248 .to.be.rejectedWith(/common\.NoPermission/);218 {mode: 'ft' as const, requiredPallets: []},
249 219 {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
250 expect(await collection.getProperties()).to.be.empty;220 ].map(testSuite => describe(`${testSuite.mode.toUpperCase()}`, () => {
251 }221 before(async function() {
252 222 // eslint-disable-next-line require-await
253 itSub('Fails to set properties in a NFT collection if not its onwer/administrator', async ({helper}) => {223 await usingPlaygrounds(async helper => {
254 await testFailsSetPropertiesIfNotOwnerOrAdmin(await helper.nft.mintCollection(alice));224 requirePalletsOrSkip(this, helper, testSuite.requiredPallets);
225 });
255 });226 });
256 227
228 itSub('Fails to set properties in a collection if not its onwer/administrator', async ({helper}) => {
257 itSub.ifWithPallets('Fails to set properties in a ReFungible collection if not its onwer/administrator', [Pallets.ReFungible], async ({helper}) => {229 const collection = await helper[testSuite.mode].mintCollection(alice);
258 await testFailsSetPropertiesIfNotOwnerOrAdmin(await helper.rft.mintCollection(alice));230
231 await expect(collection.setProperties(bob, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]))
232 .to.be.rejectedWith(/common\.NoPermission/);
233
259 });234 expect(await collection.getProperties()).to.be.empty;
260 235 });
236
261 async function testFailsSetPropertiesThatExeedLimits(collection: UniqueBaseCollection) {237 itSub('Fails to set properties that exceed the limits', async ({helper}) => {
238 const collection = await helper[testSuite.mode].mintCollection(alice);
239
262 const spaceLimit = (await (collection.helper!.api! as any).query.common.collectionProperties(collection.collectionId)).spaceLimit.toNumber();240 const spaceLimit = (await (collection.helper!.api! as any).query.common.collectionProperties(collection.collectionId)).spaceLimit.toNumber();
263 241
277 ])).to.be.rejectedWith(/common\.NoSpaceForProperty/);255 ])).to.be.rejectedWith(/common\.NoSpaceForProperty/);
278 256
279 expect(await collection.getProperties(['electron', 'black_hole'])).to.be.empty;257 expect(await collection.getProperties(['electron', 'black_hole'])).to.be.empty;
280 }258 });
281 259
282 itSub('Fails to set properties that exceed the limits (NFT)', async ({helper}) => {
283 await testFailsSetPropertiesThatExeedLimits(await helper.nft.mintCollection(alice));
284 });
285
286 itSub.ifWithPallets('Fails to set properties that exceed the limits (ReFungible)', [Pallets.ReFungible], async ({helper}) => {
287 await testFailsSetPropertiesThatExeedLimits(await helper.rft.mintCollection(alice));
288 });
289
290 async function testFailsSetMorePropertiesThanAllowed(collection: UniqueBaseCollection) {260 itSub('Fails to set more properties than it is allowed', async ({helper}) => {
261 const collection = await helper[testSuite.mode].mintCollection(alice);
262
291 const propertiesToBeSet = [];263 const propertiesToBeSet = [];
292 for (let i = 0; i < 65; i++) {264 for (let i = 0; i < 65; i++) {
300 to.be.rejectedWith(/common\.PropertyLimitReached/);272 to.be.rejectedWith(/common\.PropertyLimitReached/);
301 273
302 expect(await collection.getProperties()).to.be.empty;274 expect(await collection.getProperties()).to.be.empty;
303 }275 });
304 276
305 itSub('Fails to set more properties than it is allowed (NFT)', async ({helper}) => {
306 await testFailsSetMorePropertiesThanAllowed(await helper.nft.mintCollection(alice));
307 });
308
309 itSub.ifWithPallets('Fails to set more properties than it is allowed (ReFungible)', [Pallets.ReFungible], async ({helper}) => {
310 await testFailsSetMorePropertiesThanAllowed(await helper.rft.mintCollection(alice));
311 });
312
313 async function testFailsSetPropertiesWithInvalidNames(collection: UniqueBaseCollection) {277 itSub('Fails to set properties with invalid names', async ({helper}) => {
278 const collection = await helper[testSuite.mode].mintCollection(alice);
279
314 const invalidProperties = [280 const invalidProperties = [
315 [{key: 'electron', value: 'negative'}, {key: 'string theory', value: 'understandable'}],281 [{key: 'electron', value: 'negative'}, {key: 'string theory', value: 'understandable'}],
347 `on trying to delete the non-existent badly-named property #${i}`,313 `on trying to delete the non-existent badly-named property #${i}`,
348 ).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);314 ).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);
349 }315 }
350 }316 });
351
352 itSub('Fails to set properties with invalid names (NFT)', async ({helper}) => {
353 await testFailsSetPropertiesWithInvalidNames(await helper.nft.mintCollection(alice));
354 });317 }));
355
356 itSub.ifWithPallets('Fails to set properties with invalid names (ReFungible)', [Pallets.ReFungible], async ({helper}) => {
357 await testFailsSetPropertiesWithInvalidNames(await helper.rft.mintCollection(alice));
358 });
359});318});
360 319
modifiedtests/src/pallet-presence.test.tsdiffbeforeafterboth
80 requiredPallets.push(80 requiredPallets.push(
81 refungible,81 refungible,
82 appPromotion,82 appPromotion,
83 foreignAssets,
83 );84 );
84 } else if (chain.eq('UNIQUE')) {85 } else if (chain.eq('UNIQUE')) {
85 // Insert Unique additional pallets here86 // Insert Unique additional pallets here