difftreelog
Merge branch 'develop' into CI-41-forckless-update-parachain-relay-nodata
in: master
155 files changed
.docker/Dockerfile-parachaindiffbeforeafterboth9ENV PATH="/cargo-home/bin:$PATH"9ENV PATH="/cargo-home/bin:$PATH"101011111213RUN apt-get update && \12RUN apt-get update && \14 apt-get install -y curl cmake pkg-config libssl-dev git clang && \13 apt-get install -y curl cmake pkg-config libssl-dev git clang && \15 apt-get clean && \14 apt-get clean && \24 rustup show23 rustup show25RUN rustup target add wasm32-unknown-unknown --toolchain $RUST_TOOLCHAIN24RUN rustup target add wasm32-unknown-unknown --toolchain $RUST_TOOLCHAIN26252728RUN mkdir /unique_parachain26RUN mkdir /unique_parachain29WORKDIR /unique_parachain27WORKDIR /unique_parachain30282931# ===== BUILD ======30# ===== BUILD ======32FROM rust-builder as builder-unique31FROM rust-builder as builder-unique3332414042RUN git clone $REPO_URL -b $BRANCH && \41RUN git clone $REPO_URL -b $BRANCH && \43 cargo build --features=$FEATURE --$PROFILE42 cargo build --features=$FEATURE --$PROFILE43444445# ===== BUILD POLKADOT =====45# ===== BUILD POLKADOT =====46FROM rust-builder as builder-polkadot46FROM rust-builder as builder-polkadot60FROM ubuntu:20.0460FROM ubuntu:20.04616162RUN apt-get -y update && \62RUN apt-get -y update && \63 apt-get -y upgrade && \64 apt-get -y install curl git && \63 apt-get -y install curl git && \65 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash && \64 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash && \66 export NVM_DIR="$HOME/.nvm" && \65 export NVM_DIR="$HOME/.nvm" && \.docker/docker-compose-master.yamldiffbeforeafterbothno changes
.docker/docker-compose.tmp-master.j2diffbeforeafterbothno changes
.gitattributesdiffbeforeafterboth1* text=auto1* text=auto2*.sh text eol=lf2*.sh text eol=lf33*.ts linguist-detectable=false.github/workflows/build-test-master.ymldiffbeforeafterbothno changes
.github/workflows/node_build_test.ymldiffbeforeafterboth32 matrix:32 matrix:33 include:33 include:34 - network: "Opal"34 - network: "Opal"35 features: "--features=opal-runtime"35 features: " "36 - network: "Quartz"36 - network: "Quartz"37 features: "--features=quartz-runtime"37 features: "--features=quartz-runtime"38 - network: "Unique"38 - network: "Unique"57 if: github.event.pull_request.draft == true57 if: github.event.pull_request.draft == true58 run: exit 158 run: exit 1595960 # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it60 - name: Clean Workspace61 uses: AutoModality/action-clean@v1.1.06263 # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it61 - uses: actions/checkout@v364 - uses: actions/checkout@v362 with:65 with:63 ref: ${{ github.head_ref }} #Checking out head commit66 ref: ${{ github.head_ref }} #Checking out head commit70 with:73 with:71 template: .docker/docker-compose.tmp.j274 template: .docker/docker-compose.tmp.j272 output_file: .docker/docker-compose.${{ matrix.network }}.yml75 output_file: .docker/docker-compose.${{ matrix.network }}.yml73 variables: |76 variables: |74 REPO_URL=${{ github.server_url }}/${{ github.repository }}.git77 REPO_URL=${{ github.server_url }}/${{ github.repository }}.git75 RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}78 RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}76 POLKADOT_BUILD_BRANCH=${{ env.POLKADOT_BUILD_BRANCH }}79 POLKADOT_BUILD_BRANCH=${{ env.POLKADOT_BUILD_BRANCH }}77 FEATURE='${{ matrix.features }}'80 FEATURE=${{ matrix.features }}78 BRANCH=${{ github.head_ref }}81 BRANCH=${{ github.head_ref }}798280 - name: Show build configuration83 - name: Show build configuration81 run: cat .docker/docker-compose.${{ matrix.network }}.yml84 run: cat .docker/docker-compose.${{ matrix.network }}.yml100103101 - name: Test Report104 - name: Test Report102 uses: phoenix-actions/test-reporting@v8105 uses: phoenix-actions/test-reporting@v8106 id: test-report103 if: success() || failure() # run this step even if previous step failed107 if: success() || failure() # run this step even if previous step failed104 with:108 with:105 name: Tests ${{ matrix.network }} # Name of the check run which will be created109 name: Tests ${{ matrix.network }} # Name of the check run which will be createdCargo.lockdiffbeforeafterboth5291 "cumulus-primitives-timestamp",5291 "cumulus-primitives-timestamp",5292 "cumulus-primitives-utility",5292 "cumulus-primitives-utility",5293 "derivative",5293 "derivative",5294 "evm-coder",5294 "fp-evm-mapping",5295 "fp-evm-mapping",5295 "fp-rpc",5296 "fp-rpc",5296 "fp-self-contained",5297 "fp-self-contained",5352 "sp-transaction-pool",5353 "sp-transaction-pool",5353 "sp-version",5354 "sp-version",5354 "substrate-wasm-builder",5355 "substrate-wasm-builder",5355 "unique-runtime-common",5356 "up-common",5356 "up-data-structs",5357 "up-data-structs",5357 "up-rpc",5358 "up-rpc",5359 "up-sponsorship",5358 "xcm",5360 "xcm",5359 "xcm-builder",5361 "xcm-builder",5360 "xcm-executor",5362 "xcm-executor",8605 "cumulus-primitives-timestamp",8607 "cumulus-primitives-timestamp",8606 "cumulus-primitives-utility",8608 "cumulus-primitives-utility",8607 "derivative",8609 "derivative",8610 "evm-coder",8608 "fp-evm-mapping",8611 "fp-evm-mapping",8609 "fp-rpc",8612 "fp-rpc",8610 "fp-self-contained",8613 "fp-self-contained",8666 "sp-transaction-pool",8669 "sp-transaction-pool",8667 "sp-version",8670 "sp-version",8668 "substrate-wasm-builder",8671 "substrate-wasm-builder",8669 "unique-runtime-common",8672 "up-common",8670 "up-data-structs",8673 "up-data-structs",8671 "up-rpc",8674 "up-rpc",8675 "up-sponsorship",8672 "xcm",8676 "xcm",8673 "xcm-builder",8677 "xcm-builder",8674 "xcm-executor",8678 "xcm-executor",11881name = "tests"11885name = "tests"11882version = "0.1.0"11886version = "0.1.0"11883dependencies = [11887dependencies = [11888 "evm-coder",11884 "fp-evm-mapping",11889 "fp-evm-mapping",11885 "frame-support",11890 "frame-support",11886 "frame-system",11891 "frame-system",11902 "sp-io",11907 "sp-io",11903 "sp-runtime",11908 "sp-runtime",11904 "sp-std",11909 "sp-std",11905 "unique-runtime-common",11906 "up-data-structs",11910 "up-data-structs",11911 "up-sponsorship",11907]11912]119081191311909[[package]]11914[[package]]12387 "sp-core",12392 "sp-core",12388 "sp-rpc",12393 "sp-rpc",12389 "sp-runtime",12394 "sp-runtime",12390 "unique-runtime-common",12391 "up-data-structs",12395 "up-data-structs",12392 "up-rpc",12396 "up-rpc",12393]12397]12541 "try-runtime-cli",12545 "try-runtime-cli",12542 "unique-rpc",12546 "unique-rpc",12543 "unique-runtime",12547 "unique-runtime",12544 "unique-runtime-common",12548 "up-common",12545 "up-data-structs",12549 "up-data-structs",12546 "up-rpc",12550 "up-rpc",12547]12551]12590 "substrate-frame-rpc-system",12594 "substrate-frame-rpc-system",12591 "tokio 0.2.25",12595 "tokio 0.2.25",12592 "uc-rpc",12596 "uc-rpc",12593 "unique-runtime-common",12597 "up-common",12594 "up-data-structs",12598 "up-data-structs",12595 "up-rpc",12599 "up-rpc",12596]12600]12608 "cumulus-primitives-timestamp",12612 "cumulus-primitives-timestamp",12609 "cumulus-primitives-utility",12613 "cumulus-primitives-utility",12610 "derivative",12614 "derivative",12615 "evm-coder",12611 "fp-evm-mapping",12616 "fp-evm-mapping",12612 "fp-rpc",12617 "fp-rpc",12613 "fp-self-contained",12618 "fp-self-contained",12669 "sp-transaction-pool",12674 "sp-transaction-pool",12670 "sp-version",12675 "sp-version",12671 "substrate-wasm-builder",12676 "substrate-wasm-builder",12672 "unique-runtime-common",12677 "up-common",12673 "up-data-structs",12678 "up-data-structs",12674 "up-rpc",12679 "up-rpc",12680 "up-sponsorship",12675 "xcm",12681 "xcm",12676 "xcm-builder",12682 "xcm-builder",12677 "xcm-executor",12683 "xcm-executor",12678]12684]1267912680[[package]]12681name = "unique-runtime-common"12682version = "0.9.24"12683dependencies = [12684 "evm-coder",12685 "fp-rpc",12686 "frame-support",12687 "frame-system",12688 "pallet-common",12689 "pallet-evm",12690 "pallet-fungible",12691 "pallet-nonfungible",12692 "pallet-refungible",12693 "pallet-unique",12694 "pallet-unique-scheduler",12695 "parity-scale-codec 3.1.5",12696 "rmrk-rpc",12697 "scale-info",12698 "sp-consensus-aura",12699 "sp-core",12700 "sp-runtime",12701 "sp-std",12702 "up-data-structs",12703 "up-sponsorship",12704]127051268512706[[package]]12686[[package]]12707name = "universal-hash"12687name = "universal-hash"12731source = "registry+https://github.com/rust-lang/crates.io-index"12711source = "registry+https://github.com/rust-lang/crates.io-index"12732checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"12712checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"1271312714[[package]]12715name = "up-common"12716version = "0.9.24"12717dependencies = [12718 "fp-rpc",12719 "frame-support",12720 "pallet-evm",12721 "sp-consensus-aura",12722 "sp-core",12723 "sp-runtime",12724 "sp-std",12725]127331272612734[[package]]12727[[package]]12735name = "up-data-structs"12728name = "up-data-structs"README.mddiffbeforeafterboth232324Wider Unique Ecosystem (most of it was developed during Hackusama):24Wider Unique Ecosystem (most of it was developed during Hackusama):252526- [SubstraPunks Game hosted on IPFS](https://github.com/usetech-llc/substrapunks)26- [SubstraPunks Game hosted on IPFS](https://github.com/UniqueNetwork/substrapunks)27- [Unique Wallet and UI](https://uniqueapps.usetech.com/#/nft)27- [Unique Wallet and UI](https://wallet.unique.network)28- [NFT Asset for Unity Framework](https://github.com/usetech-llc/nft_unity)28- [NFT Asset for Unity Framework](https://github.com/usetech-llc/nft_unity)292930Please see our [walk-through instructions](doc/hackusama_walk_through.md) to try everything out!30Please see our [walk-through instructions](doc/hackusama_walk_through.md) to try everything out!client/rpc/Cargo.tomldiffbeforeafterboth5edition = "2021"5edition = "2021"667[dependencies]7[dependencies]8unique-runtime-common = { default-features = false, path = "../../runtime/common" }9pallet-common = { default-features = false, path = '../../pallets/common' }8pallet-common = { default-features = false, path = '../../pallets/common' }10up-data-structs = { default-features = false, path = '../../primitives/data-structs' }9up-data-structs = { default-features = false, path = '../../primitives/data-structs' }11up-rpc = { path = "../../primitives/rpc" }10up-rpc = { path = "../../primitives/rpc" }node/cli/Cargo.tomldiffbeforeafterboth253################################################################################253################################################################################254# Local dependencies254# Local dependencies255255256[dependencies.unique-runtime-common]256[dependencies.up-common]257default-features = false258path = "../../runtime/common"257path = "../../primitives/common"259258260[dependencies.unique-runtime]259[dependencies.unique-runtime]261path = '../../runtime/unique'260path = '../../runtime/unique'node/cli/src/chain_spec.rsdiffbeforeafterboth23use serde::{Deserialize, Serialize};23use serde::{Deserialize, Serialize};24use serde_json::map::Map;24use serde_json::map::Map;252526use unique_runtime_common::types::*;26use up_common::types::opaque::*;272728#[cfg(feature = "unique-runtime")]28#[cfg(feature = "unique-runtime")]29pub use unique_runtime as default_runtime;29pub use unique_runtime as default_runtime;node/cli/src/command.rsdiffbeforeafterboth64use sp_runtime::traits::{AccountIdConversion, Block as BlockT};64use sp_runtime::traits::{AccountIdConversion, Block as BlockT};65use std::{io::Write, net::SocketAddr, time::Duration};65use std::{io::Write, net::SocketAddr, time::Duration};666667use unique_runtime_common::types::Block;67use up_common::types::opaque::Block;686869macro_rules! no_runtime_err {69macro_rules! no_runtime_err {70 ($chain_name:expr) => {70 ($chain_name:expr) => {node/cli/src/service.rsdiffbeforeafterboth63use fc_rpc_core::types::FilterPool;63use fc_rpc_core::types::FilterPool;64use fc_mapping_sync::{MappingSyncWorker, SyncStrategy};64use fc_mapping_sync::{MappingSyncWorker, SyncStrategy};656566use unique_runtime_common::types::{AuraId, RuntimeInstance, AccountId, Balance, Index, Hash, Block};66use up_common::types::opaque::{AuraId, RuntimeInstance, AccountId, Balance, Index, Hash, Block};676768// RMRK68// RMRK69use up_data_structs::{69use up_data_structs::{node/rpc/Cargo.tomldiffbeforeafterboth49fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }49fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }505051pallet-common = { default-features = false, path = "../../pallets/common" }51pallet-common = { default-features = false, path = "../../pallets/common" }52unique-runtime-common = { default-features = false, path = "../../runtime/common" }52up-common = { path = "../../primitives/common" }53pallet-unique = { path = "../../pallets/unique" }53pallet-unique = { path = "../../pallets/unique" }54uc-rpc = { path = "../../client/rpc" }54uc-rpc = { path = "../../client/rpc" }55up-rpc = { path = "../../primitives/rpc" }55up-rpc = { path = "../../primitives/rpc" }node/rpc/src/lib.rsdiffbeforeafterboth40use sc_service::TransactionPool;40use sc_service::TransactionPool;41use std::{collections::BTreeMap, sync::Arc};41use std::{collections::BTreeMap, sync::Arc};424243use unique_runtime_common::types::{43use up_common::types::opaque::{Hash, AccountId, RuntimeInstance, Index, Block, BlockNumber, Balance};44 Hash, AccountId, RuntimeInstance, Index, Block, BlockNumber, Balance,4445};46// RMRK45// RMRK47use up_data_structs::{46use up_data_structs::{pallets/common/src/erc.rsdiffbeforeafterboth25use pallet_evm_coder_substrate::dispatch_to_evm;25use pallet_evm_coder_substrate::dispatch_to_evm;26use sp_std::vec::Vec;26use sp_std::vec::Vec;27use up_data_structs::{27use up_data_structs::{28 Property, SponsoringRateLimit, OwnerRestrictedSet, AccessMode, CollectionPermissions,28 AccessMode, CollectionMode, CollectionPermissions, OwnerRestrictedSet, Property,29 SponsoringRateLimit,29};30};30use alloc::format;31use alloc::format;3132409 save(self)410 save(self)410 }411 }412413 /// Check that account is the owner or admin of the collection414 ///415 /// @param user account to verify416 /// @return "true" if account is the owner or admin417 fn verify_owner_or_admin(&self, user: address) -> Result<bool> {418 Ok(check_is_owner_or_admin(user, self)419 .map(|_| true)420 .unwrap_or(false))421 }422423 /// Returns collection type424 ///425 /// @return `Fungible` or `NFT` or `ReFungible`426 fn unique_collection_type(&mut self) -> Result<string> {427 let mode = match self.collection.mode {428 CollectionMode::Fungible(_) => "Fungible",429 CollectionMode::NFT => "NFT",430 CollectionMode::ReFungible => "ReFungible",431 };432 Ok(mode.into())433 }411}434}412435413fn check_is_owner_or_admin<T: Config>(436fn check_is_owner_or_admin<T: Config>(463 property_key_from_bytes(b"suffix").expect(EXPECT_CONVERT_ERROR)486 property_key_from_bytes(b"suffix").expect(EXPECT_CONVERT_ERROR)464 }487 }488489 /// Key "parentNft".490 pub fn parent_nft() -> up_data_structs::PropertyKey {491 property_key_from_bytes(b"parentNft").expect(EXPECT_CONVERT_ERROR)492 }465 }493 }466494467 /// Values.495 /// Values.pallets/common/src/lib.rsdiffbeforeafterboth535535536 /// Can't transfer tokens to ethereum zero address536 /// Can't transfer tokens to ethereum zero address537 AddressIsZero,537 AddressIsZero,538 /// Target collection doesn't support this operation538539 /// The oprtation is not supported539 UnsupportedOperation,540 UnsupportedOperation,540541541 /// Insufficient funds to perform an action542 /// Insufficient funds to perform an action1111 collection: &CollectionHandle<T>,1112 collection: &CollectionHandle<T>,1112 sender: &T::CrossAccountId,1113 sender: &T::CrossAccountId,1113 property_permission: PropertyKeyPermission,1114 property_permission: PropertyKeyPermission,1114 ) -> DispatchResult {1115 ) -> DispatchResult {1116 Self::set_scoped_property_permission(1117 collection,1118 sender,1119 PropertyScope::None,1120 property_permission,1121 )1122 }11231124 /// Set collection property permission with scope.1125 ///1126 /// * `collection` - Collection handler.1127 /// * `sender` - The owner or administrator of the collection.1128 /// * `scope` - Property scope.1129 /// * `property_permission` - Property permission.1130 pub fn set_scoped_property_permission(1131 collection: &CollectionHandle<T>,1132 sender: &T::CrossAccountId,1133 scope: PropertyScope,1134 property_permission: PropertyKeyPermission,1135 ) -> DispatchResult {1115 collection.check_is_owner_or_admin(sender)?;1136 collection.check_is_owner_or_admin(sender)?;111611371117 let all_permissions = CollectionPropertyPermissions::<T>::get(collection.id);1138 let all_permissions = CollectionPropertyPermissions::<T>::get(collection.id);112511461126 CollectionPropertyPermissions::<T>::try_mutate(collection.id, |permissions| {1147 CollectionPropertyPermissions::<T>::try_mutate(collection.id, |permissions| {1127 let property_permission = property_permission.clone();1148 let property_permission = property_permission.clone();1128 permissions.try_set(property_permission.key, property_permission.permission)1149 permissions.try_scoped_set(1150 scope,1151 property_permission.key,1152 property_permission.permission,1153 )1129 })1154 })1130 .map_err(<Error<T>>::from)?;1155 .map_err(<Error<T>>::from)?;1147 collection: &CollectionHandle<T>,1172 collection: &CollectionHandle<T>,1148 sender: &T::CrossAccountId,1173 sender: &T::CrossAccountId,1149 property_permissions: Vec<PropertyKeyPermission>,1174 property_permissions: Vec<PropertyKeyPermission>,1150 ) -> DispatchResult {1175 ) -> DispatchResult {1176 Self::set_scoped_token_property_permissions(1177 collection,1178 sender,1179 PropertyScope::None,1180 property_permissions,1181 )1182 }11831184 /// Set token property permission with scope.1185 ///1186 /// * `collection` - Collection handler.1187 /// * `sender` - The owner or administrator of the collection.1188 /// * `scope` - Property scope.1189 /// * `property_permissions` - Property permissions.1190 #[transactional]1191 pub fn set_scoped_token_property_permissions(1192 collection: &CollectionHandle<T>,1193 sender: &T::CrossAccountId,1194 scope: PropertyScope,1195 property_permissions: Vec<PropertyKeyPermission>,1196 ) -> DispatchResult {1151 for prop_pemission in property_permissions {1197 for prop_pemission in property_permissions {1152 Self::set_property_permission(collection, sender, prop_pemission)?;1198 Self::set_scoped_property_permission(collection, sender, scope, prop_pemission)?;1153 }1199 }115412001155 Ok(())1201 Ok(())1353/// Indicates unsupported methods by returning [Error::UnsupportedOperation].1399/// Indicates unsupported methods by returning [Error::UnsupportedOperation].1354#[macro_export]1400#[macro_export]1355macro_rules! unsupported {1401macro_rules! unsupported {1356 () => {1402 ($runtime:path) => {1357 Err(<Error<T>>::UnsupportedOperation.into())1403 Err($crate::Error::<$runtime>::UnsupportedOperation.into())1358 };1404 };1359}1405}136014061430 .saturating_add(Self::burn_recursively_breadth_raw(max_breadth))1476 .saturating_add(Self::burn_recursively_breadth_raw(max_breadth))1431 }1477 }14781479 /// The price of retrieving token owner1480 fn token_owner() -> Weight;1432}1481}143314821434/// Weight info extension trait for refungible pallet.1483/// Weight info extension trait for refungible pallet.1567 ///1616 ///1568 /// * `sender` - Must be either the owner of the token or its admin.1617 /// * `sender` - Must be either the owner of the token or its admin.1569 /// * `token_id` - The token for which the properties are being set.1618 /// * `token_id` - The token for which the properties are being set.1570 /// * `properties` - Properties to be set.1619 /// * `property_permissions` - Property permissions to be set.1571 /// * `budget` - Budget for setting properties.1620 /// * `budget` - Budget for setting properties.1572 fn set_token_property_permissions(1621 fn set_token_property_permissions(1573 &self,1622 &self,pallets/fungible/src/common.rsdiffbeforeafterboth104 0104 0105 }105 }106107 fn token_owner() -> Weight {108 0109 }106}110}107111108/// Implementation of `CommonCollectionOperations` for `FungibleHandle`. It wraps FungibleHandle Pallete112/// Implementation of `CommonCollectionOperations` for `FungibleHandle`. It wraps FungibleHandle Palletepallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth31 );31 );32}32}3334// Selector: 6cf113cd35contract Collection is Dummy, ERC165 {36 // Set collection property.37 //38 // @param key Property key.39 // @param value Propery value.40 //41 // Selector: setCollectionProperty(string,bytes) 2f073f6642 function setCollectionProperty(string memory key, bytes memory value)43 public44 {45 require(false, stub_error);46 key;47 value;48 dummy = 0;49 }5051 // Delete collection property.52 //53 // @param key Property key.54 //55 // Selector: deleteCollectionProperty(string) 7b7debce56 function deleteCollectionProperty(string memory key) public {57 require(false, stub_error);58 key;59 dummy = 0;60 }6162 // Get collection property.63 //64 // @dev Throws error if key not found.65 //66 // @param key Property key.67 // @return bytes The property corresponding to the key.68 //69 // Selector: collectionProperty(string) cf24fd6d70 function collectionProperty(string memory key)71 public72 view73 returns (bytes memory)74 {75 require(false, stub_error);76 key;77 dummy;78 return hex"";79 }8081 // Set the sponsor of the collection.82 //83 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.84 //85 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.86 //87 // Selector: setCollectionSponsor(address) 7623402e88 function setCollectionSponsor(address sponsor) public {89 require(false, stub_error);90 sponsor;91 dummy = 0;92 }9394 // Collection sponsorship confirmation.95 //96 // @dev After setting the sponsor for the collection, it must be confirmed with this function.97 //98 // Selector: confirmCollectionSponsorship() 3c50e97a99 function confirmCollectionSponsorship() public {100 require(false, stub_error);101 dummy = 0;102 }103104 // Set limits for the collection.105 // @dev Throws error if limit not found.106 // @param limit Name of the limit. Valid names:107 // "accountTokenOwnershipLimit",108 // "sponsoredDataSize",109 // "sponsoredDataRateLimit",110 // "tokenLimit",111 // "sponsorTransferTimeout",112 // "sponsorApproveTimeout"113 // @param value Value of the limit.114 //115 // Selector: setCollectionLimit(string,uint32) 6a3841db116 function setCollectionLimit(string memory limit, uint32 value) public {117 require(false, stub_error);118 limit;119 value;120 dummy = 0;121 }122123 // Set limits for the collection.124 // @dev Throws error if limit not found.125 // @param limit Name of the limit. Valid names:126 // "ownerCanTransfer",127 // "ownerCanDestroy",128 // "transfersEnabled"129 // @param value Value of the limit.130 //131 // Selector: setCollectionLimit(string,bool) 993b7fba132 function setCollectionLimit(string memory limit, bool value) public {133 require(false, stub_error);134 limit;135 value;136 dummy = 0;137 }138139 // Get contract address.140 //141 // Selector: contractAddress() f6b4dfb4142 function contractAddress() public view returns (address) {143 require(false, stub_error);144 dummy;145 return 0x0000000000000000000000000000000000000000;146 }147148 // Add collection admin by substrate address.149 // @param new_admin Substrate administrator address.150 //151 // Selector: addCollectionAdminSubstrate(uint256) 5730062b152 function addCollectionAdminSubstrate(uint256 newAdmin) public {153 require(false, stub_error);154 newAdmin;155 dummy = 0;156 }157158 // Remove collection admin by substrate address.159 // @param admin Substrate administrator address.160 //161 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9162 function removeCollectionAdminSubstrate(uint256 admin) public {163 require(false, stub_error);164 admin;165 dummy = 0;166 }167168 // Add collection admin.169 // @param new_admin Address of the added administrator.170 //171 // Selector: addCollectionAdmin(address) 92e462c7172 function addCollectionAdmin(address newAdmin) public {173 require(false, stub_error);174 newAdmin;175 dummy = 0;176 }177178 // Remove collection admin.179 //180 // @param new_admin Address of the removed administrator.181 //182 // Selector: removeCollectionAdmin(address) fafd7b42183 function removeCollectionAdmin(address admin) public {184 require(false, stub_error);185 admin;186 dummy = 0;187 }188189 // Toggle accessibility of collection nesting.190 //191 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'192 //193 // Selector: setCollectionNesting(bool) 112d4586194 function setCollectionNesting(bool enable) public {195 require(false, stub_error);196 enable;197 dummy = 0;198 }199200 // Toggle accessibility of collection nesting.201 //202 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'203 // @param collections Addresses of collections that will be available for nesting.204 //205 // Selector: setCollectionNesting(bool,address[]) 64872396206 function setCollectionNesting(bool enable, address[] memory collections)207 public208 {209 require(false, stub_error);210 enable;211 collections;212 dummy = 0;213 }214215 // Set the collection access method.216 // @param mode Access mode217 // 0 for Normal218 // 1 for AllowList219 //220 // Selector: setCollectionAccess(uint8) 41835d4c221 function setCollectionAccess(uint8 mode) public {222 require(false, stub_error);223 mode;224 dummy = 0;225 }226227 // Add the user to the allowed list.228 //229 // @param user Address of a trusted user.230 //231 // Selector: addToCollectionAllowList(address) 67844fe6232 function addToCollectionAllowList(address user) public {233 require(false, stub_error);234 user;235 dummy = 0;236 }237238 // Remove the user from the allowed list.239 //240 // @param user Address of a removed user.241 //242 // Selector: removeFromCollectionAllowList(address) 85c51acb243 function removeFromCollectionAllowList(address user) public {244 require(false, stub_error);245 user;246 dummy = 0;247 }248249 // Switch permission for minting.250 //251 // @param mode Enable if "true".252 //253 // Selector: setCollectionMintMode(bool) 00018e84254 function setCollectionMintMode(bool mode) public {255 require(false, stub_error);256 mode;257 dummy = 0;258 }259260 // Check that account is the owner or admin of the collection261 //262 // @param user account to verify263 // @return "true" if account is the owner or admin264 //265 // Selector: verifyOwnerOrAdmin(address) c2282493266 function verifyOwnerOrAdmin(address user) public view returns (bool) {267 require(false, stub_error);268 user;269 dummy;270 return false;271 }272273 // Returns collection type274 //275 // @return `Fungible` or `NFT` or `ReFungible`276 //277 // Selector: uniqueCollectionType() d34b55b8278 function uniqueCollectionType() public returns (string memory) {279 require(false, stub_error);280 dummy = 0;281 return "";282 }283}3328434// Selector: 79cc6790285// Selector: 79cc679035contract ERC20UniqueExtensions is Dummy, ERC165 {286contract ERC20UniqueExtensions is Dummy, ERC165 {43 }294 }44}295}4546// Selector: 7d9262e647contract Collection is Dummy, ERC165 {48 // Set collection property.49 //50 // @param key Property key.51 // @param value Propery value.52 //53 // Selector: setCollectionProperty(string,bytes) 2f073f6654 function setCollectionProperty(string memory key, bytes memory value)55 public56 {57 require(false, stub_error);58 key;59 value;60 dummy = 0;61 }6263 // Delete collection property.64 //65 // @param key Property key.66 //67 // Selector: deleteCollectionProperty(string) 7b7debce68 function deleteCollectionProperty(string memory key) public {69 require(false, stub_error);70 key;71 dummy = 0;72 }7374 // Get collection property.75 //76 // @dev Throws error if key not found.77 //78 // @param key Property key.79 // @return bytes The property corresponding to the key.80 //81 // Selector: collectionProperty(string) cf24fd6d82 function collectionProperty(string memory key)83 public84 view85 returns (bytes memory)86 {87 require(false, stub_error);88 key;89 dummy;90 return hex"";91 }9293 // Set the sponsor of the collection.94 //95 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.96 //97 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.98 //99 // Selector: setCollectionSponsor(address) 7623402e100 function setCollectionSponsor(address sponsor) public {101 require(false, stub_error);102 sponsor;103 dummy = 0;104 }105106 // Collection sponsorship confirmation.107 //108 // @dev After setting the sponsor for the collection, it must be confirmed with this function.109 //110 // Selector: confirmCollectionSponsorship() 3c50e97a111 function confirmCollectionSponsorship() public {112 require(false, stub_error);113 dummy = 0;114 }115116 // Set limits for the collection.117 // @dev Throws error if limit not found.118 // @param limit Name of the limit. Valid names:119 // "accountTokenOwnershipLimit",120 // "sponsoredDataSize",121 // "sponsoredDataRateLimit",122 // "tokenLimit",123 // "sponsorTransferTimeout",124 // "sponsorApproveTimeout"125 // @param value Value of the limit.126 //127 // Selector: setCollectionLimit(string,uint32) 6a3841db128 function setCollectionLimit(string memory limit, uint32 value) public {129 require(false, stub_error);130 limit;131 value;132 dummy = 0;133 }134135 // Set limits for the collection.136 // @dev Throws error if limit not found.137 // @param limit Name of the limit. Valid names:138 // "ownerCanTransfer",139 // "ownerCanDestroy",140 // "transfersEnabled"141 // @param value Value of the limit.142 //143 // Selector: setCollectionLimit(string,bool) 993b7fba144 function setCollectionLimit(string memory limit, bool value) public {145 require(false, stub_error);146 limit;147 value;148 dummy = 0;149 }150151 // Get contract address.152 //153 // Selector: contractAddress() f6b4dfb4154 function contractAddress() public view returns (address) {155 require(false, stub_error);156 dummy;157 return 0x0000000000000000000000000000000000000000;158 }159160 // Add collection admin by substrate address.161 // @param new_admin Substrate administrator address.162 //163 // Selector: addCollectionAdminSubstrate(uint256) 5730062b164 function addCollectionAdminSubstrate(uint256 newAdmin) public {165 require(false, stub_error);166 newAdmin;167 dummy = 0;168 }169170 // Remove collection admin by substrate address.171 // @param admin Substrate administrator address.172 //173 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9174 function removeCollectionAdminSubstrate(uint256 admin) public {175 require(false, stub_error);176 admin;177 dummy = 0;178 }179180 // Add collection admin.181 // @param new_admin Address of the added administrator.182 //183 // Selector: addCollectionAdmin(address) 92e462c7184 function addCollectionAdmin(address newAdmin) public {185 require(false, stub_error);186 newAdmin;187 dummy = 0;188 }189190 // Remove collection admin.191 //192 // @param new_admin Address of the removed administrator.193 //194 // Selector: removeCollectionAdmin(address) fafd7b42195 function removeCollectionAdmin(address admin) public {196 require(false, stub_error);197 admin;198 dummy = 0;199 }200201 // Toggle accessibility of collection nesting.202 //203 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'204 //205 // Selector: setCollectionNesting(bool) 112d4586206 function setCollectionNesting(bool enable) public {207 require(false, stub_error);208 enable;209 dummy = 0;210 }211212 // Toggle accessibility of collection nesting.213 //214 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'215 // @param collections Addresses of collections that will be available for nesting.216 //217 // Selector: setCollectionNesting(bool,address[]) 64872396218 function setCollectionNesting(bool enable, address[] memory collections)219 public220 {221 require(false, stub_error);222 enable;223 collections;224 dummy = 0;225 }226227 // Set the collection access method.228 // @param mode Access mode229 // 0 for Normal230 // 1 for AllowList231 //232 // Selector: setCollectionAccess(uint8) 41835d4c233 function setCollectionAccess(uint8 mode) public {234 require(false, stub_error);235 mode;236 dummy = 0;237 }238239 // Add the user to the allowed list.240 //241 // @param user Address of a trusted user.242 //243 // Selector: addToCollectionAllowList(address) 67844fe6244 function addToCollectionAllowList(address user) public {245 require(false, stub_error);246 user;247 dummy = 0;248 }249250 // Remove the user from the allowed list.251 //252 // @param user Address of a removed user.253 //254 // Selector: removeFromCollectionAllowList(address) 85c51acb255 function removeFromCollectionAllowList(address user) public {256 require(false, stub_error);257 user;258 dummy = 0;259 }260261 // Switch permission for minting.262 //263 // @param mode Enable if "true".264 //265 // Selector: setCollectionMintMode(bool) 00018e84266 function setCollectionMintMode(bool mode) public {267 require(false, stub_error);268 mode;269 dummy = 0;270 }271}272296273// Selector: 942e8b22297// Selector: 942e8b22274contract ERC20 is Dummy, ERC165, ERC20Events {298contract ERC20 is Dummy, ERC165, ERC20Events {pallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth17use super::*;17use super::*;18use crate::{Pallet, Config, NonfungibleHandle};18use crate::{Pallet, Config, NonfungibleHandle};191920use sp_std::prelude::*;20use frame_benchmarking::{benchmarks, account};21use pallet_common::benchmarking::{create_collection_raw, property_key, property_value};21use pallet_common::{22 bench_init,23 benchmarking::{create_collection_raw, property_key, property_value},24 CommonCollectionOperations,25};22use frame_benchmarking::{benchmarks, account};26use sp_std::prelude::*;23use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH, MAX_PROPERTIES_PER_ITEM, budget::Unlimited};27use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH, MAX_PROPERTIES_PER_ITEM, budget::Unlimited};24use pallet_common::bench_init;252826const SEED: u32 = 1;29const SEED: u32 = 1;2730209 let to_delete = (0..b).map(|k| property_key(k as usize)).collect::<Vec<_>>();212 let to_delete = (0..b).map(|k| property_key(k as usize)).collect::<Vec<_>>();210 }: {<Pallet<T>>::delete_token_properties(&collection, &owner, item, to_delete.into_iter(), &Unlimited)?}213 }: {<Pallet<T>>::delete_token_properties(&collection, &owner, item, to_delete.into_iter(), &Unlimited)?}214215 token_owner {216 bench_init!{217 owner: sub; collection: collection(owner);218 owner: cross_from_sub;219 };220 let item = create_max_item(&collection, &owner, owner.clone())?;221222 }: {collection.token_owner(item)}211}223}212224pallets/nonfungible/src/common.rsdiffbeforeafterboth119 .saturating_sub(Self::burn_recursively_self_raw().saturating_mul(amount as u64 + 1))119 .saturating_sub(Self::burn_recursively_self_raw().saturating_mul(amount as u64 + 1))120 }120 }121122 fn token_owner() -> Weight {123 <SelfWeightOf<T>>::token_owner()124 }121}125}122126123fn map_create_data<T: Config>(127fn map_create_data<T: Config>(pallets/nonfungible/src/lib.rsdiffbeforeafterboth784 <PalletCommon<T>>::set_token_property_permissions(collection, sender, property_permissions)784 <PalletCommon<T>>::set_token_property_permissions(collection, sender, property_permissions)785 }785 }786787 /// Set property permissions for the token with scope.788 ///789 /// Sender should be the owner or admin of token's collection.790 pub fn set_scoped_token_property_permissions(791 collection: &CollectionHandle<T>,792 sender: &T::CrossAccountId,793 scope: PropertyScope,794 property_permissions: Vec<PropertyKeyPermission>,795 ) -> DispatchResult {796 <PalletCommon<T>>::set_scoped_token_property_permissions(797 collection,798 sender,799 scope,800 property_permissions,801 )802 }786803787 /// Set property permissions for the collection.804 /// Set property permissions for the collection.788 ///805 ///pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth373 }373 }374}374}375376// Selector: 6cf113cd377contract Collection is Dummy, ERC165 {378 // Set collection property.379 //380 // @param key Property key.381 // @param value Propery value.382 //383 // Selector: setCollectionProperty(string,bytes) 2f073f66384 function setCollectionProperty(string memory key, bytes memory value)385 public386 {387 require(false, stub_error);388 key;389 value;390 dummy = 0;391 }392393 // Delete collection property.394 //395 // @param key Property key.396 //397 // Selector: deleteCollectionProperty(string) 7b7debce398 function deleteCollectionProperty(string memory key) public {399 require(false, stub_error);400 key;401 dummy = 0;402 }403404 // Get collection property.405 //406 // @dev Throws error if key not found.407 //408 // @param key Property key.409 // @return bytes The property corresponding to the key.410 //411 // Selector: collectionProperty(string) cf24fd6d412 function collectionProperty(string memory key)413 public414 view415 returns (bytes memory)416 {417 require(false, stub_error);418 key;419 dummy;420 return hex"";421 }422423 // Set the sponsor of the collection.424 //425 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.426 //427 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.428 //429 // Selector: setCollectionSponsor(address) 7623402e430 function setCollectionSponsor(address sponsor) public {431 require(false, stub_error);432 sponsor;433 dummy = 0;434 }435436 // Collection sponsorship confirmation.437 //438 // @dev After setting the sponsor for the collection, it must be confirmed with this function.439 //440 // Selector: confirmCollectionSponsorship() 3c50e97a441 function confirmCollectionSponsorship() public {442 require(false, stub_error);443 dummy = 0;444 }445446 // Set limits for the collection.447 // @dev Throws error if limit not found.448 // @param limit Name of the limit. Valid names:449 // "accountTokenOwnershipLimit",450 // "sponsoredDataSize",451 // "sponsoredDataRateLimit",452 // "tokenLimit",453 // "sponsorTransferTimeout",454 // "sponsorApproveTimeout"455 // @param value Value of the limit.456 //457 // Selector: setCollectionLimit(string,uint32) 6a3841db458 function setCollectionLimit(string memory limit, uint32 value) public {459 require(false, stub_error);460 limit;461 value;462 dummy = 0;463 }464465 // Set limits for the collection.466 // @dev Throws error if limit not found.467 // @param limit Name of the limit. Valid names:468 // "ownerCanTransfer",469 // "ownerCanDestroy",470 // "transfersEnabled"471 // @param value Value of the limit.472 //473 // Selector: setCollectionLimit(string,bool) 993b7fba474 function setCollectionLimit(string memory limit, bool value) public {475 require(false, stub_error);476 limit;477 value;478 dummy = 0;479 }480481 // Get contract address.482 //483 // Selector: contractAddress() f6b4dfb4484 function contractAddress() public view returns (address) {485 require(false, stub_error);486 dummy;487 return 0x0000000000000000000000000000000000000000;488 }489490 // Add collection admin by substrate address.491 // @param new_admin Substrate administrator address.492 //493 // Selector: addCollectionAdminSubstrate(uint256) 5730062b494 function addCollectionAdminSubstrate(uint256 newAdmin) public {495 require(false, stub_error);496 newAdmin;497 dummy = 0;498 }499500 // Remove collection admin by substrate address.501 // @param admin Substrate administrator address.502 //503 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9504 function removeCollectionAdminSubstrate(uint256 admin) public {505 require(false, stub_error);506 admin;507 dummy = 0;508 }509510 // Add collection admin.511 // @param new_admin Address of the added administrator.512 //513 // Selector: addCollectionAdmin(address) 92e462c7514 function addCollectionAdmin(address newAdmin) public {515 require(false, stub_error);516 newAdmin;517 dummy = 0;518 }519520 // Remove collection admin.521 //522 // @param new_admin Address of the removed administrator.523 //524 // Selector: removeCollectionAdmin(address) fafd7b42525 function removeCollectionAdmin(address admin) public {526 require(false, stub_error);527 admin;528 dummy = 0;529 }530531 // Toggle accessibility of collection nesting.532 //533 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'534 //535 // Selector: setCollectionNesting(bool) 112d4586536 function setCollectionNesting(bool enable) public {537 require(false, stub_error);538 enable;539 dummy = 0;540 }541542 // Toggle accessibility of collection nesting.543 //544 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'545 // @param collections Addresses of collections that will be available for nesting.546 //547 // Selector: setCollectionNesting(bool,address[]) 64872396548 function setCollectionNesting(bool enable, address[] memory collections)549 public550 {551 require(false, stub_error);552 enable;553 collections;554 dummy = 0;555 }556557 // Set the collection access method.558 // @param mode Access mode559 // 0 for Normal560 // 1 for AllowList561 //562 // Selector: setCollectionAccess(uint8) 41835d4c563 function setCollectionAccess(uint8 mode) public {564 require(false, stub_error);565 mode;566 dummy = 0;567 }568569 // Add the user to the allowed list.570 //571 // @param user Address of a trusted user.572 //573 // Selector: addToCollectionAllowList(address) 67844fe6574 function addToCollectionAllowList(address user) public {575 require(false, stub_error);576 user;577 dummy = 0;578 }579580 // Remove the user from the allowed list.581 //582 // @param user Address of a removed user.583 //584 // Selector: removeFromCollectionAllowList(address) 85c51acb585 function removeFromCollectionAllowList(address user) public {586 require(false, stub_error);587 user;588 dummy = 0;589 }590591 // Switch permission for minting.592 //593 // @param mode Enable if "true".594 //595 // Selector: setCollectionMintMode(bool) 00018e84596 function setCollectionMintMode(bool mode) public {597 require(false, stub_error);598 mode;599 dummy = 0;600 }601602 // Check that account is the owner or admin of the collection603 //604 // @param user account to verify605 // @return "true" if account is the owner or admin606 //607 // Selector: verifyOwnerOrAdmin(address) c2282493608 function verifyOwnerOrAdmin(address user) public view returns (bool) {609 require(false, stub_error);610 user;611 dummy;612 return false;613 }614615 // Returns collection type616 //617 // @return `Fungible` or `NFT` or `ReFungible`618 //619 // Selector: uniqueCollectionType() d34b55b8620 function uniqueCollectionType() public returns (string memory) {621 require(false, stub_error);622 dummy = 0;623 return "";624 }625}375626376// Selector: 780e9d63627// Selector: 780e9d63377contract ERC721Enumerable is Dummy, ERC165 {628contract ERC721Enumerable is Dummy, ERC165 {415 }666 }416}667}417418// Selector: 7d9262e6419contract Collection is Dummy, ERC165 {420 // Set collection property.421 //422 // @param key Property key.423 // @param value Propery value.424 //425 // Selector: setCollectionProperty(string,bytes) 2f073f66426 function setCollectionProperty(string memory key, bytes memory value)427 public428 {429 require(false, stub_error);430 key;431 value;432 dummy = 0;433 }434435 // Delete collection property.436 //437 // @param key Property key.438 //439 // Selector: deleteCollectionProperty(string) 7b7debce440 function deleteCollectionProperty(string memory key) public {441 require(false, stub_error);442 key;443 dummy = 0;444 }445446 // Get collection property.447 //448 // @dev Throws error if key not found.449 //450 // @param key Property key.451 // @return bytes The property corresponding to the key.452 //453 // Selector: collectionProperty(string) cf24fd6d454 function collectionProperty(string memory key)455 public456 view457 returns (bytes memory)458 {459 require(false, stub_error);460 key;461 dummy;462 return hex"";463 }464465 // Set the sponsor of the collection.466 //467 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.468 //469 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.470 //471 // Selector: setCollectionSponsor(address) 7623402e472 function setCollectionSponsor(address sponsor) public {473 require(false, stub_error);474 sponsor;475 dummy = 0;476 }477478 // Collection sponsorship confirmation.479 //480 // @dev After setting the sponsor for the collection, it must be confirmed with this function.481 //482 // Selector: confirmCollectionSponsorship() 3c50e97a483 function confirmCollectionSponsorship() public {484 require(false, stub_error);485 dummy = 0;486 }487488 // Set limits for the collection.489 // @dev Throws error if limit not found.490 // @param limit Name of the limit. Valid names:491 // "accountTokenOwnershipLimit",492 // "sponsoredDataSize",493 // "sponsoredDataRateLimit",494 // "tokenLimit",495 // "sponsorTransferTimeout",496 // "sponsorApproveTimeout"497 // @param value Value of the limit.498 //499 // Selector: setCollectionLimit(string,uint32) 6a3841db500 function setCollectionLimit(string memory limit, uint32 value) public {501 require(false, stub_error);502 limit;503 value;504 dummy = 0;505 }506507 // Set limits for the collection.508 // @dev Throws error if limit not found.509 // @param limit Name of the limit. Valid names:510 // "ownerCanTransfer",511 // "ownerCanDestroy",512 // "transfersEnabled"513 // @param value Value of the limit.514 //515 // Selector: setCollectionLimit(string,bool) 993b7fba516 function setCollectionLimit(string memory limit, bool value) public {517 require(false, stub_error);518 limit;519 value;520 dummy = 0;521 }522523 // Get contract address.524 //525 // Selector: contractAddress() f6b4dfb4526 function contractAddress() public view returns (address) {527 require(false, stub_error);528 dummy;529 return 0x0000000000000000000000000000000000000000;530 }531532 // Add collection admin by substrate address.533 // @param new_admin Substrate administrator address.534 //535 // Selector: addCollectionAdminSubstrate(uint256) 5730062b536 function addCollectionAdminSubstrate(uint256 newAdmin) public {537 require(false, stub_error);538 newAdmin;539 dummy = 0;540 }541542 // Remove collection admin by substrate address.543 // @param admin Substrate administrator address.544 //545 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9546 function removeCollectionAdminSubstrate(uint256 admin) public {547 require(false, stub_error);548 admin;549 dummy = 0;550 }551552 // Add collection admin.553 // @param new_admin Address of the added administrator.554 //555 // Selector: addCollectionAdmin(address) 92e462c7556 function addCollectionAdmin(address newAdmin) public {557 require(false, stub_error);558 newAdmin;559 dummy = 0;560 }561562 // Remove collection admin.563 //564 // @param new_admin Address of the removed administrator.565 //566 // Selector: removeCollectionAdmin(address) fafd7b42567 function removeCollectionAdmin(address admin) public {568 require(false, stub_error);569 admin;570 dummy = 0;571 }572573 // Toggle accessibility of collection nesting.574 //575 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'576 //577 // Selector: setCollectionNesting(bool) 112d4586578 function setCollectionNesting(bool enable) public {579 require(false, stub_error);580 enable;581 dummy = 0;582 }583584 // Toggle accessibility of collection nesting.585 //586 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'587 // @param collections Addresses of collections that will be available for nesting.588 //589 // Selector: setCollectionNesting(bool,address[]) 64872396590 function setCollectionNesting(bool enable, address[] memory collections)591 public592 {593 require(false, stub_error);594 enable;595 collections;596 dummy = 0;597 }598599 // Set the collection access method.600 // @param mode Access mode601 // 0 for Normal602 // 1 for AllowList603 //604 // Selector: setCollectionAccess(uint8) 41835d4c605 function setCollectionAccess(uint8 mode) public {606 require(false, stub_error);607 mode;608 dummy = 0;609 }610611 // Add the user to the allowed list.612 //613 // @param user Address of a trusted user.614 //615 // Selector: addToCollectionAllowList(address) 67844fe6616 function addToCollectionAllowList(address user) public {617 require(false, stub_error);618 user;619 dummy = 0;620 }621622 // Remove the user from the allowed list.623 //624 // @param user Address of a removed user.625 //626 // Selector: removeFromCollectionAllowList(address) 85c51acb627 function removeFromCollectionAllowList(address user) public {628 require(false, stub_error);629 user;630 dummy = 0;631 }632633 // Switch permission for minting.634 //635 // @param mode Enable if "true".636 //637 // Selector: setCollectionMintMode(bool) 00018e84638 function setCollectionMintMode(bool mode) public {639 require(false, stub_error);640 mode;641 dummy = 0;642 }643}644668645// Selector: d74d154f669// Selector: d74d154f646contract ERC721UniqueExtensions is Dummy, ERC165 {670contract ERC721UniqueExtensions is Dummy, ERC165 {pallets/nonfungible/src/weights.rsdiffbeforeafterboth3//! Autogenerated weights for pallet_nonfungible3//! Autogenerated weights for pallet_nonfungible4//!4//!5//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev5//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev6//! DATE: 2022-07-20, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`6//! DATE: 2022-08-01, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`7//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 10247//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024889// Executed Command:9// Executed Command:46 fn set_token_property_permissions(b: u32, ) -> Weight;46 fn set_token_property_permissions(b: u32, ) -> Weight;47 fn set_token_properties(b: u32, ) -> Weight;47 fn set_token_properties(b: u32, ) -> Weight;48 fn delete_token_properties(b: u32, ) -> Weight;48 fn delete_token_properties(b: u32, ) -> Weight;49 fn token_owner() -> Weight;49}50}505151/// Weights for pallet_nonfungible using the Substrate node and recommended hardware.52/// Weights for pallet_nonfungible using the Substrate node and recommended hardware.56 // Storage: Nonfungible TokenData (r:0 w:1)57 // Storage: Nonfungible TokenData (r:0 w:1)57 // Storage: Nonfungible Owned (r:0 w:1)58 // Storage: Nonfungible Owned (r:0 w:1)58 fn create_item() -> Weight {59 fn create_item() -> Weight {59 (20_328_000 as Weight)60 (20_909_000 as Weight)60 .saturating_add(T::DbWeight::get().reads(2 as Weight))61 .saturating_add(T::DbWeight::get().reads(2 as Weight))61 .saturating_add(T::DbWeight::get().writes(4 as Weight))62 .saturating_add(T::DbWeight::get().writes(4 as Weight))62 }63 }65 // Storage: Nonfungible TokenData (r:0 w:4)66 // Storage: Nonfungible TokenData (r:0 w:4)66 // Storage: Nonfungible Owned (r:0 w:4)67 // Storage: Nonfungible Owned (r:0 w:4)67 fn create_multiple_items(b: u32, ) -> Weight {68 fn create_multiple_items(b: u32, ) -> Weight {68 (10_134_000 as Weight)69 (12_601_000 as Weight)69 // Standard Error: 3_00070 // Standard Error: 1_00070 .saturating_add((4_927_000 as Weight).saturating_mul(b as Weight))71 .saturating_add((4_920_000 as Weight).saturating_mul(b as Weight))71 .saturating_add(T::DbWeight::get().reads(2 as Weight))72 .saturating_add(T::DbWeight::get().reads(2 as Weight))72 .saturating_add(T::DbWeight::get().writes(2 as Weight))73 .saturating_add(T::DbWeight::get().writes(2 as Weight))73 .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(b as Weight)))74 .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(b as Weight)))77 // Storage: Nonfungible TokenData (r:0 w:4)78 // Storage: Nonfungible TokenData (r:0 w:4)78 // Storage: Nonfungible Owned (r:0 w:4)79 // Storage: Nonfungible Owned (r:0 w:4)79 fn create_multiple_items_ex(b: u32, ) -> Weight {80 fn create_multiple_items_ex(b: u32, ) -> Weight {80 (5_710_000 as Weight)81 (0 as Weight)81 // Standard Error: 4_00082 // Standard Error: 3_00082 .saturating_add((7_578_000 as Weight).saturating_mul(b as Weight))83 .saturating_add((7_734_000 as Weight).saturating_mul(b as Weight))83 .saturating_add(T::DbWeight::get().reads(1 as Weight))84 .saturating_add(T::DbWeight::get().reads(1 as Weight))84 .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))85 .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))85 .saturating_add(T::DbWeight::get().writes(1 as Weight))86 .saturating_add(T::DbWeight::get().writes(1 as Weight))93 // Storage: Nonfungible Owned (r:0 w:1)94 // Storage: Nonfungible Owned (r:0 w:1)94 // Storage: Nonfungible TokenProperties (r:0 w:1)95 // Storage: Nonfungible TokenProperties (r:0 w:1)95 fn burn_item() -> Weight {96 fn burn_item() -> Weight {96 (28_433_000 as Weight)97 (29_746_000 as Weight)97 .saturating_add(T::DbWeight::get().reads(5 as Weight))98 .saturating_add(T::DbWeight::get().reads(5 as Weight))98 .saturating_add(T::DbWeight::get().writes(5 as Weight))99 .saturating_add(T::DbWeight::get().writes(5 as Weight))99 }100 }105 // Storage: Nonfungible Owned (r:0 w:1)106 // Storage: Nonfungible Owned (r:0 w:1)106 // Storage: Nonfungible TokenProperties (r:0 w:1)107 // Storage: Nonfungible TokenProperties (r:0 w:1)107 fn burn_recursively_self_raw() -> Weight {108 fn burn_recursively_self_raw() -> Weight {108 (34_435_000 as Weight)109 (36_077_000 as Weight)109 .saturating_add(T::DbWeight::get().reads(5 as Weight))110 .saturating_add(T::DbWeight::get().reads(5 as Weight))110 .saturating_add(T::DbWeight::get().writes(5 as Weight))111 .saturating_add(T::DbWeight::get().writes(5 as Weight))111 }112 }119 // Storage: Common CollectionById (r:1 w:0)120 // Storage: Common CollectionById (r:1 w:0)120 fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight {121 fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight {121 (0 as Weight)122 (0 as Weight)122 // Standard Error: 1_539_000123 // Standard Error: 1_605_000123 .saturating_add((304_456_000 as Weight).saturating_mul(b as Weight))124 .saturating_add((312_391_000 as Weight).saturating_mul(b as Weight))124 .saturating_add(T::DbWeight::get().reads(7 as Weight))125 .saturating_add(T::DbWeight::get().reads(7 as Weight))125 .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(b as Weight)))126 .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(b as Weight)))126 .saturating_add(T::DbWeight::get().writes(6 as Weight))127 .saturating_add(T::DbWeight::get().writes(6 as Weight))131 // Storage: Nonfungible Allowance (r:1 w:0)132 // Storage: Nonfungible Allowance (r:1 w:0)132 // Storage: Nonfungible Owned (r:0 w:2)133 // Storage: Nonfungible Owned (r:0 w:2)133 fn transfer() -> Weight {134 fn transfer() -> Weight {134 (24_376_000 as Weight)135 (25_248_000 as Weight)135 .saturating_add(T::DbWeight::get().reads(4 as Weight))136 .saturating_add(T::DbWeight::get().reads(4 as Weight))136 .saturating_add(T::DbWeight::get().writes(5 as Weight))137 .saturating_add(T::DbWeight::get().writes(5 as Weight))137 }138 }138 // Storage: Nonfungible TokenData (r:1 w:0)139 // Storage: Nonfungible TokenData (r:1 w:0)139 // Storage: Nonfungible Allowance (r:1 w:1)140 // Storage: Nonfungible Allowance (r:1 w:1)140 fn approve() -> Weight {141 fn approve() -> Weight {141 (15_890_000 as Weight)142 (16_321_000 as Weight)142 .saturating_add(T::DbWeight::get().reads(2 as Weight))143 .saturating_add(T::DbWeight::get().reads(2 as Weight))143 .saturating_add(T::DbWeight::get().writes(1 as Weight))144 .saturating_add(T::DbWeight::get().writes(1 as Weight))144 }145 }147 // Storage: Nonfungible AccountBalance (r:2 w:2)148 // Storage: Nonfungible AccountBalance (r:2 w:2)148 // Storage: Nonfungible Owned (r:0 w:2)149 // Storage: Nonfungible Owned (r:0 w:2)149 fn transfer_from() -> Weight {150 fn transfer_from() -> Weight {150 (28_634_000 as Weight)151 (29_325_000 as Weight)151 .saturating_add(T::DbWeight::get().reads(4 as Weight))152 .saturating_add(T::DbWeight::get().reads(4 as Weight))152 .saturating_add(T::DbWeight::get().writes(6 as Weight))153 .saturating_add(T::DbWeight::get().writes(6 as Weight))153 }154 }159 // Storage: Nonfungible Owned (r:0 w:1)160 // Storage: Nonfungible Owned (r:0 w:1)160 // Storage: Nonfungible TokenProperties (r:0 w:1)161 // Storage: Nonfungible TokenProperties (r:0 w:1)161 fn burn_from() -> Weight {162 fn burn_from() -> Weight {162 (32_201_000 as Weight)163 (33_323_000 as Weight)163 .saturating_add(T::DbWeight::get().reads(5 as Weight))164 .saturating_add(T::DbWeight::get().reads(5 as Weight))164 .saturating_add(T::DbWeight::get().writes(6 as Weight))165 .saturating_add(T::DbWeight::get().writes(6 as Weight))165 }166 }166 // Storage: Common CollectionPropertyPermissions (r:1 w:1)167 // Storage: Common CollectionPropertyPermissions (r:1 w:1)167 fn set_token_property_permissions(b: u32, ) -> Weight {168 fn set_token_property_permissions(b: u32, ) -> Weight {168 (0 as Weight)169 (0 as Weight)169 // Standard Error: 57_000170 // Standard Error: 62_000170 .saturating_add((15_232_000 as Weight).saturating_mul(b as Weight))171 .saturating_add((16_222_000 as Weight).saturating_mul(b as Weight))171 .saturating_add(T::DbWeight::get().reads(1 as Weight))172 .saturating_add(T::DbWeight::get().reads(1 as Weight))172 .saturating_add(T::DbWeight::get().writes(1 as Weight))173 .saturating_add(T::DbWeight::get().writes(1 as Weight))173 }174 }174 // Storage: Common CollectionPropertyPermissions (r:1 w:0)175 // Storage: Common CollectionPropertyPermissions (r:1 w:0)175 // Storage: Nonfungible TokenProperties (r:1 w:1)176 // Storage: Nonfungible TokenProperties (r:1 w:1)176 fn set_token_properties(b: u32, ) -> Weight {177 fn set_token_properties(b: u32, ) -> Weight {177 (0 as Weight)178 (0 as Weight)178 // Standard Error: 1_648_000179 // Standard Error: 1_750_000179 .saturating_add((288_654_000 as Weight).saturating_mul(b as Weight))180 .saturating_add((304_476_000 as Weight).saturating_mul(b as Weight))180 .saturating_add(T::DbWeight::get().reads(2 as Weight))181 .saturating_add(T::DbWeight::get().reads(2 as Weight))181 .saturating_add(T::DbWeight::get().writes(1 as Weight))182 .saturating_add(T::DbWeight::get().writes(1 as Weight))182 }183 }183 // Storage: Common CollectionPropertyPermissions (r:1 w:0)184 // Storage: Common CollectionPropertyPermissions (r:1 w:0)184 // Storage: Nonfungible TokenProperties (r:1 w:1)185 // Storage: Nonfungible TokenProperties (r:1 w:1)185 fn delete_token_properties(b: u32, ) -> Weight {186 fn delete_token_properties(b: u32, ) -> Weight {186 (0 as Weight)187 (0 as Weight)187 // Standard Error: 1_632_000188 // Standard Error: 1_638_000188 .saturating_add((289_190_000 as Weight).saturating_mul(b as Weight))189 .saturating_add((294_096_000 as Weight).saturating_mul(b as Weight))189 .saturating_add(T::DbWeight::get().reads(2 as Weight))190 .saturating_add(T::DbWeight::get().reads(2 as Weight))190 .saturating_add(T::DbWeight::get().writes(1 as Weight))191 .saturating_add(T::DbWeight::get().writes(1 as Weight))191 }192 }193 // Storage: Nonfungible TokenData (r:1 w:0)194 fn token_owner() -> Weight {195 (2_986_000 as Weight)196 .saturating_add(T::DbWeight::get().reads(1 as Weight))197 }192}198}193199194// For backwards compatibility and tests200// For backwards compatibility and tests198 // Storage: Nonfungible TokenData (r:0 w:1)204 // Storage: Nonfungible TokenData (r:0 w:1)199 // Storage: Nonfungible Owned (r:0 w:1)205 // Storage: Nonfungible Owned (r:0 w:1)200 fn create_item() -> Weight {206 fn create_item() -> Weight {201 (20_328_000 as Weight)207 (20_909_000 as Weight)202 .saturating_add(RocksDbWeight::get().reads(2 as Weight))208 .saturating_add(RocksDbWeight::get().reads(2 as Weight))203 .saturating_add(RocksDbWeight::get().writes(4 as Weight))209 .saturating_add(RocksDbWeight::get().writes(4 as Weight))204 }210 }207 // Storage: Nonfungible TokenData (r:0 w:4)213 // Storage: Nonfungible TokenData (r:0 w:4)208 // Storage: Nonfungible Owned (r:0 w:4)214 // Storage: Nonfungible Owned (r:0 w:4)209 fn create_multiple_items(b: u32, ) -> Weight {215 fn create_multiple_items(b: u32, ) -> Weight {210 (10_134_000 as Weight)216 (12_601_000 as Weight)211 // Standard Error: 3_000217 // Standard Error: 1_000212 .saturating_add((4_927_000 as Weight).saturating_mul(b as Weight))218 .saturating_add((4_920_000 as Weight).saturating_mul(b as Weight))213 .saturating_add(RocksDbWeight::get().reads(2 as Weight))219 .saturating_add(RocksDbWeight::get().reads(2 as Weight))214 .saturating_add(RocksDbWeight::get().writes(2 as Weight))220 .saturating_add(RocksDbWeight::get().writes(2 as Weight))215 .saturating_add(RocksDbWeight::get().writes((2 as Weight).saturating_mul(b as Weight)))221 .saturating_add(RocksDbWeight::get().writes((2 as Weight).saturating_mul(b as Weight)))219 // Storage: Nonfungible TokenData (r:0 w:4)225 // Storage: Nonfungible TokenData (r:0 w:4)220 // Storage: Nonfungible Owned (r:0 w:4)226 // Storage: Nonfungible Owned (r:0 w:4)221 fn create_multiple_items_ex(b: u32, ) -> Weight {227 fn create_multiple_items_ex(b: u32, ) -> Weight {222 (5_710_000 as Weight)228 (0 as Weight)223 // Standard Error: 4_000229 // Standard Error: 3_000224 .saturating_add((7_578_000 as Weight).saturating_mul(b as Weight))230 .saturating_add((7_734_000 as Weight).saturating_mul(b as Weight))225 .saturating_add(RocksDbWeight::get().reads(1 as Weight))231 .saturating_add(RocksDbWeight::get().reads(1 as Weight))226 .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))232 .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))227 .saturating_add(RocksDbWeight::get().writes(1 as Weight))233 .saturating_add(RocksDbWeight::get().writes(1 as Weight))235 // Storage: Nonfungible Owned (r:0 w:1)241 // Storage: Nonfungible Owned (r:0 w:1)236 // Storage: Nonfungible TokenProperties (r:0 w:1)242 // Storage: Nonfungible TokenProperties (r:0 w:1)237 fn burn_item() -> Weight {243 fn burn_item() -> Weight {238 (28_433_000 as Weight)244 (29_746_000 as Weight)239 .saturating_add(RocksDbWeight::get().reads(5 as Weight))245 .saturating_add(RocksDbWeight::get().reads(5 as Weight))240 .saturating_add(RocksDbWeight::get().writes(5 as Weight))246 .saturating_add(RocksDbWeight::get().writes(5 as Weight))241 }247 }247 // Storage: Nonfungible Owned (r:0 w:1)253 // Storage: Nonfungible Owned (r:0 w:1)248 // Storage: Nonfungible TokenProperties (r:0 w:1)254 // Storage: Nonfungible TokenProperties (r:0 w:1)249 fn burn_recursively_self_raw() -> Weight {255 fn burn_recursively_self_raw() -> Weight {250 (34_435_000 as Weight)256 (36_077_000 as Weight)251 .saturating_add(RocksDbWeight::get().reads(5 as Weight))257 .saturating_add(RocksDbWeight::get().reads(5 as Weight))252 .saturating_add(RocksDbWeight::get().writes(5 as Weight))258 .saturating_add(RocksDbWeight::get().writes(5 as Weight))253 }259 }261 // Storage: Common CollectionById (r:1 w:0)267 // Storage: Common CollectionById (r:1 w:0)262 fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight {268 fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight {263 (0 as Weight)269 (0 as Weight)264 // Standard Error: 1_539_000270 // Standard Error: 1_605_000265 .saturating_add((304_456_000 as Weight).saturating_mul(b as Weight))271 .saturating_add((312_391_000 as Weight).saturating_mul(b as Weight))266 .saturating_add(RocksDbWeight::get().reads(7 as Weight))272 .saturating_add(RocksDbWeight::get().reads(7 as Weight))267 .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(b as Weight)))273 .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(b as Weight)))268 .saturating_add(RocksDbWeight::get().writes(6 as Weight))274 .saturating_add(RocksDbWeight::get().writes(6 as Weight))273 // Storage: Nonfungible Allowance (r:1 w:0)279 // Storage: Nonfungible Allowance (r:1 w:0)274 // Storage: Nonfungible Owned (r:0 w:2)280 // Storage: Nonfungible Owned (r:0 w:2)275 fn transfer() -> Weight {281 fn transfer() -> Weight {276 (24_376_000 as Weight)282 (25_248_000 as Weight)277 .saturating_add(RocksDbWeight::get().reads(4 as Weight))283 .saturating_add(RocksDbWeight::get().reads(4 as Weight))278 .saturating_add(RocksDbWeight::get().writes(5 as Weight))284 .saturating_add(RocksDbWeight::get().writes(5 as Weight))279 }285 }280 // Storage: Nonfungible TokenData (r:1 w:0)286 // Storage: Nonfungible TokenData (r:1 w:0)281 // Storage: Nonfungible Allowance (r:1 w:1)287 // Storage: Nonfungible Allowance (r:1 w:1)282 fn approve() -> Weight {288 fn approve() -> Weight {283 (15_890_000 as Weight)289 (16_321_000 as Weight)284 .saturating_add(RocksDbWeight::get().reads(2 as Weight))290 .saturating_add(RocksDbWeight::get().reads(2 as Weight))285 .saturating_add(RocksDbWeight::get().writes(1 as Weight))291 .saturating_add(RocksDbWeight::get().writes(1 as Weight))286 }292 }289 // Storage: Nonfungible AccountBalance (r:2 w:2)295 // Storage: Nonfungible AccountBalance (r:2 w:2)290 // Storage: Nonfungible Owned (r:0 w:2)296 // Storage: Nonfungible Owned (r:0 w:2)291 fn transfer_from() -> Weight {297 fn transfer_from() -> Weight {292 (28_634_000 as Weight)298 (29_325_000 as Weight)293 .saturating_add(RocksDbWeight::get().reads(4 as Weight))299 .saturating_add(RocksDbWeight::get().reads(4 as Weight))294 .saturating_add(RocksDbWeight::get().writes(6 as Weight))300 .saturating_add(RocksDbWeight::get().writes(6 as Weight))295 }301 }301 // Storage: Nonfungible Owned (r:0 w:1)307 // Storage: Nonfungible Owned (r:0 w:1)302 // Storage: Nonfungible TokenProperties (r:0 w:1)308 // Storage: Nonfungible TokenProperties (r:0 w:1)303 fn burn_from() -> Weight {309 fn burn_from() -> Weight {304 (32_201_000 as Weight)310 (33_323_000 as Weight)305 .saturating_add(RocksDbWeight::get().reads(5 as Weight))311 .saturating_add(RocksDbWeight::get().reads(5 as Weight))306 .saturating_add(RocksDbWeight::get().writes(6 as Weight))312 .saturating_add(RocksDbWeight::get().writes(6 as Weight))307 }313 }308 // Storage: Common CollectionPropertyPermissions (r:1 w:1)314 // Storage: Common CollectionPropertyPermissions (r:1 w:1)309 fn set_token_property_permissions(b: u32, ) -> Weight {315 fn set_token_property_permissions(b: u32, ) -> Weight {310 (0 as Weight)316 (0 as Weight)311 // Standard Error: 57_000317 // Standard Error: 62_000312 .saturating_add((15_232_000 as Weight).saturating_mul(b as Weight))318 .saturating_add((16_222_000 as Weight).saturating_mul(b as Weight))313 .saturating_add(RocksDbWeight::get().reads(1 as Weight))319 .saturating_add(RocksDbWeight::get().reads(1 as Weight))314 .saturating_add(RocksDbWeight::get().writes(1 as Weight))320 .saturating_add(RocksDbWeight::get().writes(1 as Weight))315 }321 }316 // Storage: Common CollectionPropertyPermissions (r:1 w:0)322 // Storage: Common CollectionPropertyPermissions (r:1 w:0)317 // Storage: Nonfungible TokenProperties (r:1 w:1)323 // Storage: Nonfungible TokenProperties (r:1 w:1)318 fn set_token_properties(b: u32, ) -> Weight {324 fn set_token_properties(b: u32, ) -> Weight {319 (0 as Weight)325 (0 as Weight)320 // Standard Error: 1_648_000326 // Standard Error: 1_750_000321 .saturating_add((288_654_000 as Weight).saturating_mul(b as Weight))327 .saturating_add((304_476_000 as Weight).saturating_mul(b as Weight))322 .saturating_add(RocksDbWeight::get().reads(2 as Weight))328 .saturating_add(RocksDbWeight::get().reads(2 as Weight))323 .saturating_add(RocksDbWeight::get().writes(1 as Weight))329 .saturating_add(RocksDbWeight::get().writes(1 as Weight))324 }330 }325 // Storage: Common CollectionPropertyPermissions (r:1 w:0)331 // Storage: Common CollectionPropertyPermissions (r:1 w:0)326 // Storage: Nonfungible TokenProperties (r:1 w:1)332 // Storage: Nonfungible TokenProperties (r:1 w:1)327 fn delete_token_properties(b: u32, ) -> Weight {333 fn delete_token_properties(b: u32, ) -> Weight {328 (0 as Weight)334 (0 as Weight)329 // Standard Error: 1_632_000335 // Standard Error: 1_638_000330 .saturating_add((289_190_000 as Weight).saturating_mul(b as Weight))336 .saturating_add((294_096_000 as Weight).saturating_mul(b as Weight))331 .saturating_add(RocksDbWeight::get().reads(2 as Weight))337 .saturating_add(RocksDbWeight::get().reads(2 as Weight))332 .saturating_add(RocksDbWeight::get().writes(1 as Weight))338 .saturating_add(RocksDbWeight::get().writes(1 as Weight))333 }339 }340 // Storage: Nonfungible TokenData (r:1 w:0)341 fn token_owner() -> Weight {342 (2_986_000 as Weight)343 .saturating_add(RocksDbWeight::get().reads(1 as Weight))344 }334}345}335346pallets/refungible/src/benchmarking.rsdiffbeforeafterboth17use super::*;17use super::*;18use crate::{Pallet, Config, RefungibleHandle};18use crate::{Pallet, Config, RefungibleHandle};191920use sp_std::prelude::*;20use core::convert::TryInto;21use pallet_common::benchmarking::{create_collection_raw, property_key, property_value, create_data};21use core::iter::IntoIterator;22use frame_benchmarking::{benchmarks, account};22use frame_benchmarking::{benchmarks, account};23use up_data_structs::{23use pallet_common::{24 CollectionMode, MAX_ITEMS_PER_BATCH, MAX_PROPERTIES_PER_ITEM, CUSTOM_DATA_LIMIT,24 bench_init,25 budget::Unlimited,25 benchmarking::{create_collection_raw, property_key, property_value, create_data},26};26};27use pallet_common::bench_init;27use sp_core::H160;28use core::convert::TryInto;28use sp_std::prelude::*;29use core::iter::IntoIterator;29use up_data_structs::{30 CollectionMode, MAX_ITEMS_PER_BATCH, MAX_PROPERTIES_PER_ITEM, CUSTOM_DATA_LIMIT,31 budget::Unlimited,32};303331const SEED: u32 = 1;34const SEED: u32 = 1;323533fn create_max_item_data<CrossAccountId: Ord>(36fn create_max_item_data<CrossAccountId: Ord>(34 users: impl IntoIterator<Item = (CrossAccountId, u128)>,37 users: impl IntoIterator<Item = (CrossAccountId, u128)>,35) -> CreateRefungibleExData<CrossAccountId> {38) -> CreateRefungibleExData<CrossAccountId> {36 let const_data = create_data::<CUSTOM_DATA_LIMIT>();37 CreateRefungibleExData {39 CreateRefungibleExData {38 const_data,39 users: users40 users: users40 .into_iter()41 .into_iter()41 .collect::<BTreeMap<_, _>>()42 .collect::<BTreeMap<_, _>>()59) -> Result<RefungibleHandle<T>, DispatchError> {61) -> Result<RefungibleHandle<T>, DispatchError> {60 create_collection_raw(62 create_collection_raw(61 owner,63 owner,62 CollectionMode::NFT,64 CollectionMode::ReFungible,63 <Pallet<T>>::init_collection,65 <Pallet<T>>::init_collection,64 RefungibleHandle::cast,66 RefungibleHandle::cast,65 )67 )278 let item = create_max_item(&collection, &sender, [(owner.clone(), 100)])?;281 let item = create_max_item(&collection, &sender, [(owner.clone(), 100)])?;279 }: {<Pallet<T>>::repartition(&collection, &owner, item, 200)?}282 }: {<Pallet<T>>::repartition(&collection, &owner, item, 200)?}283284 set_parent_nft_unchecked {285 bench_init!{286 owner: sub; collection: collection(owner);287 sender: cross_from_sub(owner); owner: cross_sub;288 };289 let item = create_max_item(&collection, &sender, [(owner.clone(), 100)])?;290291 }: {<Pallet<T>>::set_parent_nft_unchecked(&collection, item, owner, T::CrossAccountId::from_eth(H160::default()))?}292293 token_owner {294 bench_init!{295 owner: sub; collection: collection(owner);296 sender: cross_from_sub(owner); owner: cross_sub;297 };298 let item = create_max_item(&collection, &sender, [(owner.clone(), 100)])?;299 }: {<Pallet<T>>::token_owner(collection.id, item)}280}300}281301pallets/refungible/src/common.rsdiffbeforeafterboth149 0149 0150 }150 }151152 fn token_owner() -> Weight {153 <SelfWeightOf<T>>::token_owner()154 }151}155}152156153fn map_create_data<T: Config>(157fn map_create_data<T: Config>(pallets/refungible/src/erc.rsdiffbeforeafterboth41use sp_core::H160;41use sp_core::H160;42use sp_std::{collections::btree_map::BTreeMap, vec::Vec, vec};42use sp_std::{collections::btree_map::BTreeMap, vec::Vec, vec};43use up_data_structs::{43use up_data_structs::{44 CollectionId, CollectionPropertiesVec, Property, PropertyKey, PropertyKeyPermission,44 CollectionId, CollectionPropertiesVec, mapping::TokenAddressMapping, Property, PropertyKey,45 PropertyPermission, TokenId,45 PropertyKeyPermission, PropertyPermission, TokenId,46};46};4747413}413}414414415/// Returns amount of pieces of `token` that `owner` have415/// Returns amount of pieces of `token` that `owner` have416fn balance<T: Config>(416pub fn balance<T: Config>(417 collection: &RefungibleHandle<T>,417 collection: &RefungibleHandle<T>,418 token: TokenId,418 token: TokenId,419 owner: &T::CrossAccountId,419 owner: &T::CrossAccountId,424}424}425425426/// Throws if `owner_balance` is lower than total amount of `token` pieces426/// Throws if `owner_balance` is lower than total amount of `token` pieces427fn ensure_single_owner<T: Config>(427pub fn ensure_single_owner<T: Config>(428 collection: &RefungibleHandle<T>,428 collection: &RefungibleHandle<T>,429 token: TokenId,429 token: TokenId,430 owner_balance: u128,430 owner_balance: u128,789 Ok(true)789 Ok(true)790 }790 }791792 /// Returns EVM address for refungible token793 ///794 /// @param token ID of the token795 fn token_contract_address(&self, token: uint256) -> Result<address> {796 Ok(T::EvmTokenAddressMapping::token_to_address(797 self.id,798 token.try_into().map_err(|_| "token id overflow")?,799 ))800 }791}801}792802793#[solidity_interface(803#[solidity_interface(pallets/refungible/src/erc_token.rsdiffbeforeafterboth212122extern crate alloc;22extern crate alloc;2324#[cfg(not(feature = "std"))]25use alloc::format;2623use core::{27use core::{24 char::{REPLACEMENT_CHARACTER, decode_utf16},28 char::{REPLACEMENT_CHARACTER, decode_utf16},25 convert::TryInto,29 convert::TryInto,26 ops::Deref,30 ops::Deref,27};31};28use evm_coder::{ToLog, execution::*, generate_stubgen, solidity_interface, types::*, weight};32use evm_coder::{ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*, weight};29use pallet_common::{33use pallet_common::{30 CommonWeightInfo,34 CommonWeightInfo,31 erc::{CommonEvmHandler, PrecompileResult},35 erc::{CommonEvmHandler, PrecompileResult, static_property::key},36 eth::map_eth_to_id,32};37};33use pallet_evm::{account::CrossAccountId, PrecompileHandle};38use pallet_evm::{account::CrossAccountId, PrecompileHandle};34use pallet_evm_coder_substrate::{call, dispatch_to_evm, WithRecorder};39use pallet_evm_coder_substrate::{call, dispatch_to_evm, WithRecorder};35use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};40use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};41use sp_core::H160;36use sp_std::vec::Vec;42use sp_std::vec::Vec;37use up_data_structs::TokenId;43use up_data_structs::{mapping::TokenAddressMapping, PropertyScope, TokenId};384439use crate::{45use crate::{40 Allowance, Balance, common::CommonWeights, Config, Pallet, RefungibleHandle, SelfWeightOf,46 Allowance, Balance, common::CommonWeights, Config, Pallet, RefungibleHandle, SelfWeightOf,41 weights::WeightInfo, TotalSupply,47 TokenProperties, TotalSupply, weights::WeightInfo,42};48};434944pub struct RefungibleTokenHandle<T: Config>(pub RefungibleHandle<T>, pub TokenId);50pub struct RefungibleTokenHandle<T: Config>(pub RefungibleHandle<T>, pub TokenId);5152#[solidity_interface(name = "ERC1633")]53impl<T: Config> RefungibleTokenHandle<T> {54 fn parent_token(&self) -> Result<address> {55 self.consume_store_reads(2)?;56 let props = <TokenProperties<T>>::get((self.id, self.1));57 let key = key::parent_nft();5859 let key_scoped = PropertyScope::Eth60 .apply(key)61 .expect("property key shouldn't exceed length limit");62 if let Some(value) = props.get(&key_scoped) {63 Ok(H160::from_slice(value.as_slice()))64 } else {65 Ok(*T::CrossTokenAddressMapping::token_to_address(self.id, self.1).as_eth())66 }67 }6869 fn parent_token_id(&self) -> Result<uint256> {70 self.consume_store_reads(2)?;71 let props = <TokenProperties<T>>::get((self.id, self.1));72 let key = key::parent_nft();7374 let key_scoped = PropertyScope::Eth75 .apply(key)76 .expect("property key shouldn't exceed length limit");77 if let Some(value) = props.get(&key_scoped) {78 let nft_token_address = H160::from_slice(value.as_slice());79 let nft_token_account = T::CrossAccountId::from_eth(nft_token_address);80 let (_, token_id) = T::CrossTokenAddressMapping::address_to_token(&nft_token_account)81 .ok_or("parent NFT should contain NFT token address")?;8283 Ok(token_id.into())84 } else {85 Ok(self.1.into())86 }87 }88}8990#[solidity_interface(name = "ERC1633UniqueExtensions")]91impl<T: Config> RefungibleTokenHandle<T> {92 #[solidity(rename_selector = "setParentNFT")]93 #[weight(<CommonWeights<T>>::token_owner() + <SelfWeightOf<T>>::set_parent_nft_unchecked())]94 fn set_parent_nft(95 &mut self,96 caller: caller,97 collection: address,98 nft_id: uint256,99 ) -> Result<bool> {100 self.consume_store_reads(1)?;101 let caller = T::CrossAccountId::from_eth(caller);102 let nft_collection = map_eth_to_id(&collection).ok_or("collection not found")?;103 let nft_token = nft_id.try_into()?;104105 <Pallet<T>>::set_parent_nft(&self.0, self.1, caller, nft_collection, nft_token)106 .map_err(dispatch_to_evm::<T>)?;107108 Ok(true)109 }110}4511146#[derive(ToLog)]112#[derive(ToLog)]47pub enum ERC20Events {113pub enum ERC20Events {120 .weight_calls_budget(<StructureWeight<T>>::find_parent());186 .weight_calls_budget(<StructureWeight<T>>::find_parent());121187122 <Pallet<T>>::transfer(self, &caller, &to, self.1, amount, &budget)188 <Pallet<T>>::transfer(self, &caller, &to, self.1, amount, &budget)123 .map_err(|_| "transfer error")?;189 .map_err(dispatch_to_evm::<T>)?;124 Ok(true)190 Ok(true)125 }191 }126192241307242#[solidity_interface(name = "UniqueRefungibleToken", is(ERC20, ERC20UniqueExtensions,))]308#[solidity_interface(309 name = "UniqueRefungibleToken",310 is(ERC20, ERC20UniqueExtensions, ERC1633, ERC1633UniqueExtensions)311)]243impl<T: Config> RefungibleTokenHandle<T> where T::AccountId: From<[u8; 32]> {}312impl<T: Config> RefungibleTokenHandle<T> where T::AccountId: From<[u8; 32]> {}244313pallets/refungible/src/lib.rsdiffbeforeafterboth99use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};99use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};100use pallet_evm_coder_substrate::WithRecorder;100use pallet_evm_coder_substrate::WithRecorder;101use pallet_common::{101use pallet_common::{102 CommonCollectionOperations, Error as CommonError, Event as CommonEvent,102 CollectionHandle, CommonCollectionOperations,103 dispatch::CollectionDispatch,104 erc::static_property::{key, property_value_from_bytes},105 Error as CommonError,103 eth::collection_id_to_address, Pallet as PalletCommon,106 eth::collection_id_to_address,107 Event as CommonEvent, Pallet as PalletCommon,104};108};105use pallet_structure::Pallet as PalletStructure;109use pallet_structure::Pallet as PalletStructure;106use scale_info::TypeInfo;110use scale_info::TypeInfo;107use sp_core::H160;111use sp_core::H160;108use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};112use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};109use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};113use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};110use up_data_structs::{114use up_data_structs::{111 AccessMode, budget::Budget, CollectionId, CreateCollectionData, CustomDataLimit,115 AccessMode, budget::Budget, CollectionId, CollectionMode, CollectionPropertiesVec,112 mapping::TokenAddressMapping, MAX_REFUNGIBLE_PIECES, MAX_ITEMS_PER_BATCH, TokenId, Property,116 CreateCollectionData, CustomDataLimit, mapping::TokenAddressMapping, MAX_ITEMS_PER_BATCH,113 PropertyKey, PropertyKeyPermission, PropertyPermission, PropertyScope, PropertyValue,117 MAX_REFUNGIBLE_PIECES, Property, PropertyKey, PropertyKeyPermission, PropertyPermission,114 TrySetProperty, CollectionPropertiesVec,118 PropertyScope, PropertyValue, TokenId, TrySetProperty,115};119};116use frame_support::BoundedBTreeMap;120use frame_support::BoundedBTreeMap;117use derivative::Derivative;121use derivative::Derivative;1341 <PalletCommon<T>>::set_token_property_permissions(collection, sender, property_permissions)1345 <PalletCommon<T>>::set_token_property_permissions(collection, sender, property_permissions)1342 }1346 }13471348 pub fn set_scoped_token_property_permissions(1349 collection: &RefungibleHandle<T>,1350 sender: &T::CrossAccountId,1351 scope: PropertyScope,1352 property_permissions: Vec<PropertyKeyPermission>,1353 ) -> DispatchResult {1354 <PalletCommon<T>>::set_scoped_token_property_permissions(1355 collection,1356 sender,1357 scope,1358 property_permissions,1359 )1360 }134313611344 /// Returns 10 token in no particular order.1362 /// Returns 10 token in no particular order.1345 ///1363 ///1363 }1381 }1364 }1382 }13831384 /// Sets the NFT token as a parent for the RFT token1385 ///1386 /// Throws if `sender` is not the owner of the NFT token.1387 /// Throws if `sender` is not the owner of all of the RFT token pieces.1388 pub fn set_parent_nft(1389 collection: &RefungibleHandle<T>,1390 rft_token_id: TokenId,1391 sender: T::CrossAccountId,1392 nft_collection: CollectionId,1393 nft_token: TokenId,1394 ) -> DispatchResult {1395 let handle = <CollectionHandle<T>>::try_get(nft_collection)?;1396 if handle.mode != CollectionMode::NFT {1397 return Err("Only NFT token could be parent to RFT".into());1398 }1399 let dispatch = T::CollectionDispatch::dispatch(handle);1400 let dispatch = dispatch.as_dyn();14011402 let owner = dispatch.token_owner(nft_token).ok_or("owner not found")?;1403 if owner != sender {1404 return Err("Only owned token could be set as parent".into());1405 }14061407 let nft_token_address =1408 T::CrossTokenAddressMapping::token_to_address(nft_collection, nft_token);14091410 Self::set_parent_nft_unchecked(collection, rft_token_id, sender, nft_token_address)1411 }14121413 /// Sets the NFT token as a parent for the RFT token1414 ///1415 /// `sender` should be the owner of the NFT token.1416 /// Throws if `sender` is not the owner of all of the RFT token pieces.1417 pub fn set_parent_nft_unchecked(1418 collection: &RefungibleHandle<T>,1419 rft_token_id: TokenId,1420 sender: T::CrossAccountId,1421 nft_token_address: T::CrossAccountId,1422 ) -> DispatchResult {1423 let owner_balance = <Balance<T>>::get((collection.id, rft_token_id, &sender));1424 let total_supply = <TotalSupply<T>>::get((collection.id, rft_token_id));1425 if total_supply != owner_balance {1426 return Err("token has multiple owners".into());1427 }14281429 let parent_nft_property_key = key::parent_nft();14301431 let parent_nft_property_value =1432 property_value_from_bytes(&nft_token_address.as_eth().to_fixed_bytes())1433 .expect("address should fit in value length limit");14341435 <Pallet<T>>::set_scoped_token_property(1436 collection.id,1437 rft_token_id,1438 PropertyScope::Eth,1439 Property {1440 key: parent_nft_property_key,1441 value: parent_nft_property_value,1442 },1443 )?;14441445 Ok(())1446 }1365}1447}13661448pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth371 }371 }372}372}373374// Selector: 6cf113cd375contract Collection is Dummy, ERC165 {376 // Set collection property.377 //378 // @param key Property key.379 // @param value Propery value.380 //381 // Selector: setCollectionProperty(string,bytes) 2f073f66382 function setCollectionProperty(string memory key, bytes memory value)383 public384 {385 require(false, stub_error);386 key;387 value;388 dummy = 0;389 }390391 // Delete collection property.392 //393 // @param key Property key.394 //395 // Selector: deleteCollectionProperty(string) 7b7debce396 function deleteCollectionProperty(string memory key) public {397 require(false, stub_error);398 key;399 dummy = 0;400 }401402 // Get collection property.403 //404 // @dev Throws error if key not found.405 //406 // @param key Property key.407 // @return bytes The property corresponding to the key.408 //409 // Selector: collectionProperty(string) cf24fd6d410 function collectionProperty(string memory key)411 public412 view413 returns (bytes memory)414 {415 require(false, stub_error);416 key;417 dummy;418 return hex"";419 }420421 // Set the sponsor of the collection.422 //423 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.424 //425 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.426 //427 // Selector: setCollectionSponsor(address) 7623402e428 function setCollectionSponsor(address sponsor) public {429 require(false, stub_error);430 sponsor;431 dummy = 0;432 }433434 // Collection sponsorship confirmation.435 //436 // @dev After setting the sponsor for the collection, it must be confirmed with this function.437 //438 // Selector: confirmCollectionSponsorship() 3c50e97a439 function confirmCollectionSponsorship() public {440 require(false, stub_error);441 dummy = 0;442 }443444 // Set limits for the collection.445 // @dev Throws error if limit not found.446 // @param limit Name of the limit. Valid names:447 // "accountTokenOwnershipLimit",448 // "sponsoredDataSize",449 // "sponsoredDataRateLimit",450 // "tokenLimit",451 // "sponsorTransferTimeout",452 // "sponsorApproveTimeout"453 // @param value Value of the limit.454 //455 // Selector: setCollectionLimit(string,uint32) 6a3841db456 function setCollectionLimit(string memory limit, uint32 value) public {457 require(false, stub_error);458 limit;459 value;460 dummy = 0;461 }462463 // Set limits for the collection.464 // @dev Throws error if limit not found.465 // @param limit Name of the limit. Valid names:466 // "ownerCanTransfer",467 // "ownerCanDestroy",468 // "transfersEnabled"469 // @param value Value of the limit.470 //471 // Selector: setCollectionLimit(string,bool) 993b7fba472 function setCollectionLimit(string memory limit, bool value) public {473 require(false, stub_error);474 limit;475 value;476 dummy = 0;477 }478479 // Get contract address.480 //481 // Selector: contractAddress() f6b4dfb4482 function contractAddress() public view returns (address) {483 require(false, stub_error);484 dummy;485 return 0x0000000000000000000000000000000000000000;486 }487488 // Add collection admin by substrate address.489 // @param new_admin Substrate administrator address.490 //491 // Selector: addCollectionAdminSubstrate(uint256) 5730062b492 function addCollectionAdminSubstrate(uint256 newAdmin) public {493 require(false, stub_error);494 newAdmin;495 dummy = 0;496 }497498 // Remove collection admin by substrate address.499 // @param admin Substrate administrator address.500 //501 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9502 function removeCollectionAdminSubstrate(uint256 admin) public {503 require(false, stub_error);504 admin;505 dummy = 0;506 }507508 // Add collection admin.509 // @param new_admin Address of the added administrator.510 //511 // Selector: addCollectionAdmin(address) 92e462c7512 function addCollectionAdmin(address newAdmin) public {513 require(false, stub_error);514 newAdmin;515 dummy = 0;516 }517518 // Remove collection admin.519 //520 // @param new_admin Address of the removed administrator.521 //522 // Selector: removeCollectionAdmin(address) fafd7b42523 function removeCollectionAdmin(address admin) public {524 require(false, stub_error);525 admin;526 dummy = 0;527 }528529 // Toggle accessibility of collection nesting.530 //531 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'532 //533 // Selector: setCollectionNesting(bool) 112d4586534 function setCollectionNesting(bool enable) public {535 require(false, stub_error);536 enable;537 dummy = 0;538 }539540 // Toggle accessibility of collection nesting.541 //542 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'543 // @param collections Addresses of collections that will be available for nesting.544 //545 // Selector: setCollectionNesting(bool,address[]) 64872396546 function setCollectionNesting(bool enable, address[] memory collections)547 public548 {549 require(false, stub_error);550 enable;551 collections;552 dummy = 0;553 }554555 // Set the collection access method.556 // @param mode Access mode557 // 0 for Normal558 // 1 for AllowList559 //560 // Selector: setCollectionAccess(uint8) 41835d4c561 function setCollectionAccess(uint8 mode) public {562 require(false, stub_error);563 mode;564 dummy = 0;565 }566567 // Add the user to the allowed list.568 //569 // @param user Address of a trusted user.570 //571 // Selector: addToCollectionAllowList(address) 67844fe6572 function addToCollectionAllowList(address user) public {573 require(false, stub_error);574 user;575 dummy = 0;576 }577578 // Remove the user from the allowed list.579 //580 // @param user Address of a removed user.581 //582 // Selector: removeFromCollectionAllowList(address) 85c51acb583 function removeFromCollectionAllowList(address user) public {584 require(false, stub_error);585 user;586 dummy = 0;587 }588589 // Switch permission for minting.590 //591 // @param mode Enable if "true".592 //593 // Selector: setCollectionMintMode(bool) 00018e84594 function setCollectionMintMode(bool mode) public {595 require(false, stub_error);596 mode;597 dummy = 0;598 }599600 // Check that account is the owner or admin of the collection601 //602 // @param user account to verify603 // @return "true" if account is the owner or admin604 //605 // Selector: verifyOwnerOrAdmin(address) c2282493606 function verifyOwnerOrAdmin(address user) public view returns (bool) {607 require(false, stub_error);608 user;609 dummy;610 return false;611 }612613 // Returns collection type614 //615 // @return `Fungible` or `NFT` or `ReFungible`616 //617 // Selector: uniqueCollectionType() d34b55b8618 function uniqueCollectionType() public returns (string memory) {619 require(false, stub_error);620 dummy = 0;621 return "";622 }623}373624374// Selector: 780e9d63625// Selector: 780e9d63375contract ERC721Enumerable is Dummy, ERC165 {626contract ERC721Enumerable is Dummy, ERC165 {413 }664 }414}665}415666416// Selector: 7d9262e6667// Selector: 7c3bef89417contract Collection is Dummy, ERC165 {418 // Set collection property.419 //420 // @param key Property key.421 // @param value Propery value.422 //423 // Selector: setCollectionProperty(string,bytes) 2f073f66424 function setCollectionProperty(string memory key, bytes memory value)425 public426 {427 require(false, stub_error);428 key;429 value;430 dummy = 0;431 }432433 // Delete collection property.434 //435 // @param key Property key.436 //437 // Selector: deleteCollectionProperty(string) 7b7debce438 function deleteCollectionProperty(string memory key) public {439 require(false, stub_error);440 key;441 dummy = 0;442 }443444 // Get collection property.445 //446 // @dev Throws error if key not found.447 //448 // @param key Property key.449 // @return bytes The property corresponding to the key.450 //451 // Selector: collectionProperty(string) cf24fd6d452 function collectionProperty(string memory key)453 public454 view455 returns (bytes memory)456 {457 require(false, stub_error);458 key;459 dummy;460 return hex"";461 }462463 // Set the sponsor of the collection.464 //465 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.466 //467 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.468 //469 // Selector: setCollectionSponsor(address) 7623402e470 function setCollectionSponsor(address sponsor) public {471 require(false, stub_error);472 sponsor;473 dummy = 0;474 }475476 // Collection sponsorship confirmation.477 //478 // @dev After setting the sponsor for the collection, it must be confirmed with this function.479 //480 // Selector: confirmCollectionSponsorship() 3c50e97a481 function confirmCollectionSponsorship() public {482 require(false, stub_error);483 dummy = 0;484 }485486 // Set limits for the collection.487 // @dev Throws error if limit not found.488 // @param limit Name of the limit. Valid names:489 // "accountTokenOwnershipLimit",490 // "sponsoredDataSize",491 // "sponsoredDataRateLimit",492 // "tokenLimit",493 // "sponsorTransferTimeout",494 // "sponsorApproveTimeout"495 // @param value Value of the limit.496 //497 // Selector: setCollectionLimit(string,uint32) 6a3841db498 function setCollectionLimit(string memory limit, uint32 value) public {499 require(false, stub_error);500 limit;501 value;502 dummy = 0;503 }504505 // Set limits for the collection.506 // @dev Throws error if limit not found.507 // @param limit Name of the limit. Valid names:508 // "ownerCanTransfer",509 // "ownerCanDestroy",510 // "transfersEnabled"511 // @param value Value of the limit.512 //513 // Selector: setCollectionLimit(string,bool) 993b7fba514 function setCollectionLimit(string memory limit, bool value) public {515 require(false, stub_error);516 limit;517 value;518 dummy = 0;519 }520521 // Get contract address.522 //523 // Selector: contractAddress() f6b4dfb4524 function contractAddress() public view returns (address) {525 require(false, stub_error);526 dummy;527 return 0x0000000000000000000000000000000000000000;528 }529530 // Add collection admin by substrate address.531 // @param new_admin Substrate administrator address.532 //533 // Selector: addCollectionAdminSubstrate(uint256) 5730062b534 function addCollectionAdminSubstrate(uint256 newAdmin) public {535 require(false, stub_error);536 newAdmin;537 dummy = 0;538 }539540 // Remove collection admin by substrate address.541 // @param admin Substrate administrator address.542 //543 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9544 function removeCollectionAdminSubstrate(uint256 admin) public {545 require(false, stub_error);546 admin;547 dummy = 0;548 }549550 // Add collection admin.551 // @param new_admin Address of the added administrator.552 //553 // Selector: addCollectionAdmin(address) 92e462c7554 function addCollectionAdmin(address newAdmin) public {555 require(false, stub_error);556 newAdmin;557 dummy = 0;558 }559560 // Remove collection admin.561 //562 // @param new_admin Address of the removed administrator.563 //564 // Selector: removeCollectionAdmin(address) fafd7b42565 function removeCollectionAdmin(address admin) public {566 require(false, stub_error);567 admin;568 dummy = 0;569 }570571 // Toggle accessibility of collection nesting.572 //573 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'574 //575 // Selector: setCollectionNesting(bool) 112d4586576 function setCollectionNesting(bool enable) public {577 require(false, stub_error);578 enable;579 dummy = 0;580 }581582 // Toggle accessibility of collection nesting.583 //584 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'585 // @param collections Addresses of collections that will be available for nesting.586 //587 // Selector: setCollectionNesting(bool,address[]) 64872396588 function setCollectionNesting(bool enable, address[] memory collections)589 public590 {591 require(false, stub_error);592 enable;593 collections;594 dummy = 0;595 }596597 // Set the collection access method.598 // @param mode Access mode599 // 0 for Normal600 // 1 for AllowList601 //602 // Selector: setCollectionAccess(uint8) 41835d4c603 function setCollectionAccess(uint8 mode) public {604 require(false, stub_error);605 mode;606 dummy = 0;607 }608609 // Add the user to the allowed list.610 //611 // @param user Address of a trusted user.612 //613 // Selector: addToCollectionAllowList(address) 67844fe6614 function addToCollectionAllowList(address user) public {615 require(false, stub_error);616 user;617 dummy = 0;618 }619620 // Remove the user from the allowed list.621 //622 // @param user Address of a removed user.623 //624 // Selector: removeFromCollectionAllowList(address) 85c51acb625 function removeFromCollectionAllowList(address user) public {626 require(false, stub_error);627 user;628 dummy = 0;629 }630631 // Switch permission for minting.632 //633 // @param mode Enable if "true".634 //635 // Selector: setCollectionMintMode(bool) 00018e84636 function setCollectionMintMode(bool mode) public {637 require(false, stub_error);638 mode;639 dummy = 0;640 }641}642643// Selector: d74d154f644contract ERC721UniqueExtensions is Dummy, ERC165 {668contract ERC721UniqueExtensions is Dummy, ERC165 {645 // @notice Transfer ownership of an RFT669 // @notice Transfer ownership of an RFT646 // @dev Throws unless `msg.sender` is the current owner. Throws if `to`670 // @dev Throws unless `msg.sender` is the current owner. Throws if `to`720 return false;744 return false;721 }745 }746747 // Returns EVM address for refungible token748 //749 // @param token ID of the token750 //751 // Selector: tokenContractAddress(uint256) ab76fac6752 function tokenContractAddress(uint256 token) public view returns (address) {753 require(false, stub_error);754 token;755 dummy;756 return 0x0000000000000000000000000000000000000000;757 }722}758}723759724contract UniqueRefungible is760contract UniqueRefungible ispallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungibleToken.soldiffbeforeafterboth31 );31 );32}32}3334// Selector: 042f110635contract ERC1633UniqueExtensions is Dummy, ERC165 {36 // Selector: setParentNFT(address,uint256) 042f110637 function setParentNFT(address collection, uint256 nftId)38 public39 returns (bool)40 {41 require(false, stub_error);42 collection;43 nftId;44 dummy = 0;45 return false;46 }47}4849// Selector: 5755c3f250contract ERC1633 is Dummy, ERC165 {51 // Selector: parentToken() 80a5400152 function parentToken() public view returns (address) {53 require(false, stub_error);54 dummy;55 return 0x0000000000000000000000000000000000000000;56 }5758 // Selector: parentTokenId() d7f083f359 function parentTokenId() public view returns (uint256) {60 require(false, stub_error);61 dummy;62 return 0;63 }64}336534// Selector: 942e8b2266// Selector: 942e8b2235contract ERC20 is Dummy, ERC165, ERC20Events {67contract ERC20 is Dummy, ERC165, ERC20Events {214 Dummy,215 ERC165,216 ERC20,217 ERC20UniqueExtensions,218 ERC1633,219 ERC1633UniqueExtensions220{}182221pallets/refungible/src/weights.rsdiffbeforeafterboth3//! Autogenerated weights for pallet_refungible3//! Autogenerated weights for pallet_refungible4//!4//!5//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev5//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev6//! DATE: 2022-07-20, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`6//! DATE: 2022-08-01, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`7//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 10247//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024889// Executed Command:9// Executed Command:53 fn set_token_properties(b: u32, ) -> Weight;53 fn set_token_properties(b: u32, ) -> Weight;54 fn delete_token_properties(b: u32, ) -> Weight;54 fn delete_token_properties(b: u32, ) -> Weight;55 fn repartition_item() -> Weight;55 fn repartition_item() -> Weight;56 fn set_parent_nft_unchecked() -> Weight;57 fn token_owner() -> Weight;56}58}575958/// Weights for pallet_refungible using the Substrate node and recommended hardware.60/// Weights for pallet_refungible using the Substrate node and recommended hardware.65 // Storage: Refungible TokenData (r:0 w:1)67 // Storage: Refungible TokenData (r:0 w:1)66 // Storage: Refungible Owned (r:0 w:1)68 // Storage: Refungible Owned (r:0 w:1)67 fn create_item() -> Weight {69 fn create_item() -> Weight {68 (21_310_000 as Weight)70 (25_197_000 as Weight)69 .saturating_add(T::DbWeight::get().reads(2 as Weight))71 .saturating_add(T::DbWeight::get().reads(2 as Weight))70 .saturating_add(T::DbWeight::get().writes(6 as Weight))72 .saturating_add(T::DbWeight::get().writes(6 as Weight))71 }73 }76 // Storage: Refungible TokenData (r:0 w:4)78 // Storage: Refungible TokenData (r:0 w:4)77 // Storage: Refungible Owned (r:0 w:4)79 // Storage: Refungible Owned (r:0 w:4)78 fn create_multiple_items(b: u32, ) -> Weight {80 fn create_multiple_items(b: u32, ) -> Weight {79 (9_552_000 as Weight)81 (10_852_000 as Weight)80 // Standard Error: 2_00082 // Standard Error: 2_00081 .saturating_add((7_056_000 as Weight).saturating_mul(b as Weight))83 .saturating_add((8_087_000 as Weight).saturating_mul(b as Weight))82 .saturating_add(T::DbWeight::get().reads(2 as Weight))84 .saturating_add(T::DbWeight::get().reads(2 as Weight))83 .saturating_add(T::DbWeight::get().writes(2 as Weight))85 .saturating_add(T::DbWeight::get().writes(2 as Weight))84 .saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(b as Weight)))86 .saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(b as Weight)))90 // Storage: Refungible TokenData (r:0 w:4)92 // Storage: Refungible TokenData (r:0 w:4)91 // Storage: Refungible Owned (r:0 w:4)93 // Storage: Refungible Owned (r:0 w:4)92 fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {94 fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {93 (4_857_000 as Weight)95 (9_978_000 as Weight)94 // Standard Error: 2_00096 // Standard Error: 2_00095 .saturating_add((9_838_000 as Weight).saturating_mul(b as Weight))97 .saturating_add((10_848_000 as Weight).saturating_mul(b as Weight))96 .saturating_add(T::DbWeight::get().reads(1 as Weight))98 .saturating_add(T::DbWeight::get().reads(1 as Weight))97 .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))99 .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))98 .saturating_add(T::DbWeight::get().writes(1 as Weight))100 .saturating_add(T::DbWeight::get().writes(1 as Weight))105 // Storage: Refungible Balance (r:0 w:4)107 // Storage: Refungible Balance (r:0 w:4)106 // Storage: Refungible Owned (r:0 w:4)108 // Storage: Refungible Owned (r:0 w:4)107 fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {109 fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {108 (11_335_000 as Weight)110 (15_419_000 as Weight)109 // Standard Error: 2_000111 // Standard Error: 2_000110 .saturating_add((6_784_000 as Weight).saturating_mul(b as Weight))112 .saturating_add((7_813_000 as Weight).saturating_mul(b as Weight))111 .saturating_add(T::DbWeight::get().reads(1 as Weight))113 .saturating_add(T::DbWeight::get().reads(1 as Weight))112 .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))114 .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))113 .saturating_add(T::DbWeight::get().writes(3 as Weight))115 .saturating_add(T::DbWeight::get().writes(3 as Weight))118 // Storage: Refungible AccountBalance (r:1 w:1)120 // Storage: Refungible AccountBalance (r:1 w:1)119 // Storage: Refungible Owned (r:0 w:1)121 // Storage: Refungible Owned (r:0 w:1)120 fn burn_item_partial() -> Weight {122 fn burn_item_partial() -> Weight {121 (21_239_000 as Weight)123 (25_578_000 as Weight)122 .saturating_add(T::DbWeight::get().reads(3 as Weight))124 .saturating_add(T::DbWeight::get().reads(3 as Weight))123 .saturating_add(T::DbWeight::get().writes(4 as Weight))125 .saturating_add(T::DbWeight::get().writes(4 as Weight))124 }126 }130 // Storage: Refungible Owned (r:0 w:1)132 // Storage: Refungible Owned (r:0 w:1)131 // Storage: Refungible TokenProperties (r:0 w:1)133 // Storage: Refungible TokenProperties (r:0 w:1)132 fn burn_item_fully() -> Weight {134 fn burn_item_fully() -> Weight {133 (29_426_000 as Weight)135 (33_593_000 as Weight)134 .saturating_add(T::DbWeight::get().reads(4 as Weight))136 .saturating_add(T::DbWeight::get().reads(4 as Weight))135 .saturating_add(T::DbWeight::get().writes(7 as Weight))137 .saturating_add(T::DbWeight::get().writes(7 as Weight))136 }138 }137 // Storage: Refungible Balance (r:2 w:2)139 // Storage: Refungible Balance (r:2 w:2)138 fn transfer_normal() -> Weight {140 fn transfer_normal() -> Weight {139 (17_743_000 as Weight)141 (21_049_000 as Weight)140 .saturating_add(T::DbWeight::get().reads(2 as Weight))142 .saturating_add(T::DbWeight::get().reads(2 as Weight))141 .saturating_add(T::DbWeight::get().writes(2 as Weight))143 .saturating_add(T::DbWeight::get().writes(2 as Weight))142 }144 }143 // Storage: Refungible Balance (r:2 w:2)145 // Storage: Refungible Balance (r:2 w:2)144 // Storage: Refungible AccountBalance (r:1 w:1)146 // Storage: Refungible AccountBalance (r:1 w:1)145 // Storage: Refungible Owned (r:0 w:1)147 // Storage: Refungible Owned (r:0 w:1)146 fn transfer_creating() -> Weight {148 fn transfer_creating() -> Weight {147 (20_699_000 as Weight)149 (24_646_000 as Weight)148 .saturating_add(T::DbWeight::get().reads(3 as Weight))150 .saturating_add(T::DbWeight::get().reads(3 as Weight))149 .saturating_add(T::DbWeight::get().writes(4 as Weight))151 .saturating_add(T::DbWeight::get().writes(4 as Weight))150 }152 }151 // Storage: Refungible Balance (r:2 w:2)153 // Storage: Refungible Balance (r:2 w:2)152 // Storage: Refungible AccountBalance (r:1 w:1)154 // Storage: Refungible AccountBalance (r:1 w:1)153 // Storage: Refungible Owned (r:0 w:1)155 // Storage: Refungible Owned (r:0 w:1)154 fn transfer_removing() -> Weight {156 fn transfer_removing() -> Weight {155 (22_833_000 as Weight)157 (26_570_000 as Weight)156 .saturating_add(T::DbWeight::get().reads(3 as Weight))158 .saturating_add(T::DbWeight::get().reads(3 as Weight))157 .saturating_add(T::DbWeight::get().writes(4 as Weight))159 .saturating_add(T::DbWeight::get().writes(4 as Weight))158 }160 }159 // Storage: Refungible Balance (r:2 w:2)161 // Storage: Refungible Balance (r:2 w:2)160 // Storage: Refungible AccountBalance (r:2 w:2)162 // Storage: Refungible AccountBalance (r:2 w:2)161 // Storage: Refungible Owned (r:0 w:2)163 // Storage: Refungible Owned (r:0 w:2)162 fn transfer_creating_removing() -> Weight {164 fn transfer_creating_removing() -> Weight {163 (24_936_000 as Weight)165 (28_906_000 as Weight)164 .saturating_add(T::DbWeight::get().reads(4 as Weight))166 .saturating_add(T::DbWeight::get().reads(4 as Weight))165 .saturating_add(T::DbWeight::get().writes(6 as Weight))167 .saturating_add(T::DbWeight::get().writes(6 as Weight))166 }168 }167 // Storage: Refungible Balance (r:1 w:0)169 // Storage: Refungible Balance (r:1 w:0)168 // Storage: Refungible Allowance (r:0 w:1)170 // Storage: Refungible Allowance (r:0 w:1)169 fn approve() -> Weight {171 fn approve() -> Weight {170 (13_446_000 as Weight)172 (16_451_000 as Weight)171 .saturating_add(T::DbWeight::get().reads(1 as Weight))173 .saturating_add(T::DbWeight::get().reads(1 as Weight))172 .saturating_add(T::DbWeight::get().writes(1 as Weight))174 .saturating_add(T::DbWeight::get().writes(1 as Weight))173 }175 }174 // Storage: Refungible Allowance (r:1 w:1)176 // Storage: Refungible Allowance (r:1 w:1)175 // Storage: Refungible Balance (r:2 w:2)177 // Storage: Refungible Balance (r:2 w:2)176 fn transfer_from_normal() -> Weight {178 fn transfer_from_normal() -> Weight {177 (24_777_000 as Weight)179 (29_545_000 as Weight)178 .saturating_add(T::DbWeight::get().reads(3 as Weight))180 .saturating_add(T::DbWeight::get().reads(3 as Weight))179 .saturating_add(T::DbWeight::get().writes(3 as Weight))181 .saturating_add(T::DbWeight::get().writes(3 as Weight))180 }182 }183 // Storage: Refungible AccountBalance (r:1 w:1)185 // Storage: Refungible AccountBalance (r:1 w:1)184 // Storage: Refungible Owned (r:0 w:1)186 // Storage: Refungible Owned (r:0 w:1)185 fn transfer_from_creating() -> Weight {187 fn transfer_from_creating() -> Weight {186 (28_483_000 as Weight)188 (33_392_000 as Weight)187 .saturating_add(T::DbWeight::get().reads(4 as Weight))189 .saturating_add(T::DbWeight::get().reads(4 as Weight))188 .saturating_add(T::DbWeight::get().writes(5 as Weight))190 .saturating_add(T::DbWeight::get().writes(5 as Weight))189 }191 }192 // Storage: Refungible AccountBalance (r:1 w:1)194 // Storage: Refungible AccountBalance (r:1 w:1)193 // Storage: Refungible Owned (r:0 w:1)195 // Storage: Refungible Owned (r:0 w:1)194 fn transfer_from_removing() -> Weight {196 fn transfer_from_removing() -> Weight {195 (29_896_000 as Weight)197 (35_446_000 as Weight)196 .saturating_add(T::DbWeight::get().reads(4 as Weight))198 .saturating_add(T::DbWeight::get().reads(4 as Weight))197 .saturating_add(T::DbWeight::get().writes(5 as Weight))199 .saturating_add(T::DbWeight::get().writes(5 as Weight))198 }200 }201 // Storage: Refungible AccountBalance (r:2 w:2)203 // Storage: Refungible AccountBalance (r:2 w:2)202 // Storage: Refungible Owned (r:0 w:2)204 // Storage: Refungible Owned (r:0 w:2)203 fn transfer_from_creating_removing() -> Weight {205 fn transfer_from_creating_removing() -> Weight {204 (32_070_000 as Weight)206 (37_762_000 as Weight)205 .saturating_add(T::DbWeight::get().reads(5 as Weight))207 .saturating_add(T::DbWeight::get().reads(5 as Weight))206 .saturating_add(T::DbWeight::get().writes(7 as Weight))208 .saturating_add(T::DbWeight::get().writes(7 as Weight))207 }209 }214 // Storage: Refungible Owned (r:0 w:1)216 // Storage: Refungible Owned (r:0 w:1)215 // Storage: Refungible TokenProperties (r:0 w:1)217 // Storage: Refungible TokenProperties (r:0 w:1)216 fn burn_from() -> Weight {218 fn burn_from() -> Weight {217 (36_789_000 as Weight)219 (42_620_000 as Weight)218 .saturating_add(T::DbWeight::get().reads(5 as Weight))220 .saturating_add(T::DbWeight::get().reads(5 as Weight))219 .saturating_add(T::DbWeight::get().writes(8 as Weight))221 .saturating_add(T::DbWeight::get().writes(8 as Weight))220 }222 }221 // Storage: Common CollectionPropertyPermissions (r:1 w:1)223 // Storage: Common CollectionPropertyPermissions (r:1 w:1)222 fn set_token_property_permissions(b: u32, ) -> Weight {224 fn set_token_property_permissions(b: u32, ) -> Weight {223 (0 as Weight)225 (0 as Weight)224 // Standard Error: 62_000226 // Standard Error: 65_000225 .saturating_add((15_803_000 as Weight).saturating_mul(b as Weight))227 .saturating_add((16_513_000 as Weight).saturating_mul(b as Weight))226 .saturating_add(T::DbWeight::get().reads(1 as Weight))228 .saturating_add(T::DbWeight::get().reads(1 as Weight))227 .saturating_add(T::DbWeight::get().writes(1 as Weight))229 .saturating_add(T::DbWeight::get().writes(1 as Weight))228 }230 }229 // Storage: Common CollectionPropertyPermissions (r:1 w:0)231 // Storage: Common CollectionPropertyPermissions (r:1 w:0)230 // Storage: Refungible TokenProperties (r:1 w:1)232 // Storage: Refungible TokenProperties (r:1 w:1)231 fn set_token_properties(b: u32, ) -> Weight {233 fn set_token_properties(b: u32, ) -> Weight {232 (0 as Weight)234 (0 as Weight)233 // Standard Error: 1_668_000235 // Standard Error: 1_583_000234 .saturating_add((302_308_000 as Weight).saturating_mul(b as Weight))236 .saturating_add((291_392_000 as Weight).saturating_mul(b as Weight))235 .saturating_add(T::DbWeight::get().reads(2 as Weight))237 .saturating_add(T::DbWeight::get().reads(2 as Weight))236 .saturating_add(T::DbWeight::get().writes(1 as Weight))238 .saturating_add(T::DbWeight::get().writes(1 as Weight))237 }239 }238 // Storage: Common CollectionPropertyPermissions (r:1 w:0)240 // Storage: Common CollectionPropertyPermissions (r:1 w:0)239 // Storage: Refungible TokenProperties (r:1 w:1)241 // Storage: Refungible TokenProperties (r:1 w:1)240 fn delete_token_properties(b: u32, ) -> Weight {242 fn delete_token_properties(b: u32, ) -> Weight {241 (0 as Weight)243 (0 as Weight)242 // Standard Error: 1_619_000244 // Standard Error: 1_699_000243 .saturating_add((294_574_000 as Weight).saturating_mul(b as Weight))245 .saturating_add((293_270_000 as Weight).saturating_mul(b as Weight))244 .saturating_add(T::DbWeight::get().reads(2 as Weight))246 .saturating_add(T::DbWeight::get().reads(2 as Weight))245 .saturating_add(T::DbWeight::get().writes(1 as Weight))247 .saturating_add(T::DbWeight::get().writes(1 as Weight))246 }248 }247 // Storage: Refungible TotalSupply (r:1 w:1)249 // Storage: Refungible TotalSupply (r:1 w:1)248 // Storage: Refungible Balance (r:1 w:1)250 // Storage: Refungible Balance (r:1 w:1)249 fn repartition_item() -> Weight {251 fn repartition_item() -> Weight {250 (8_325_000 as Weight)252 (19_206_000 as Weight)251 .saturating_add(T::DbWeight::get().reads(2 as Weight))253 .saturating_add(T::DbWeight::get().reads(2 as Weight))252 .saturating_add(T::DbWeight::get().writes(2 as Weight))254 .saturating_add(T::DbWeight::get().writes(2 as Weight))253 }255 }256 // Storage: Refungible Balance (r:1 w:0)257 // Storage: Refungible TotalSupply (r:1 w:0)258 // Storage: Refungible TokenProperties (r:1 w:1)259 fn set_parent_nft_unchecked() -> Weight {260 (10_189_000 as Weight)261 .saturating_add(T::DbWeight::get().reads(3 as Weight))262 .saturating_add(T::DbWeight::get().writes(1 as Weight))263 }264 // Storage: Refungible Balance (r:2 w:0)265 fn token_owner() -> Weight {266 (8_205_000 as Weight)267 .saturating_add(T::DbWeight::get().reads(2 as Weight))268 }254}269}255270256// For backwards compatibility and tests271// For backwards compatibility and tests262 // Storage: Refungible TokenData (r:0 w:1)277 // Storage: Refungible TokenData (r:0 w:1)263 // Storage: Refungible Owned (r:0 w:1)278 // Storage: Refungible Owned (r:0 w:1)264 fn create_item() -> Weight {279 fn create_item() -> Weight {265 (21_310_000 as Weight)280 (25_197_000 as Weight)266 .saturating_add(RocksDbWeight::get().reads(2 as Weight))281 .saturating_add(RocksDbWeight::get().reads(2 as Weight))267 .saturating_add(RocksDbWeight::get().writes(6 as Weight))282 .saturating_add(RocksDbWeight::get().writes(6 as Weight))268 }283 }273 // Storage: Refungible TokenData (r:0 w:4)288 // Storage: Refungible TokenData (r:0 w:4)274 // Storage: Refungible Owned (r:0 w:4)289 // Storage: Refungible Owned (r:0 w:4)275 fn create_multiple_items(b: u32, ) -> Weight {290 fn create_multiple_items(b: u32, ) -> Weight {276 (9_552_000 as Weight)291 (10_852_000 as Weight)277 // Standard Error: 2_000292 // Standard Error: 2_000278 .saturating_add((7_056_000 as Weight).saturating_mul(b as Weight))293 .saturating_add((8_087_000 as Weight).saturating_mul(b as Weight))279 .saturating_add(RocksDbWeight::get().reads(2 as Weight))294 .saturating_add(RocksDbWeight::get().reads(2 as Weight))280 .saturating_add(RocksDbWeight::get().writes(2 as Weight))295 .saturating_add(RocksDbWeight::get().writes(2 as Weight))281 .saturating_add(RocksDbWeight::get().writes((4 as Weight).saturating_mul(b as Weight)))296 .saturating_add(RocksDbWeight::get().writes((4 as Weight).saturating_mul(b as Weight)))287 // Storage: Refungible TokenData (r:0 w:4)302 // Storage: Refungible TokenData (r:0 w:4)288 // Storage: Refungible Owned (r:0 w:4)303 // Storage: Refungible Owned (r:0 w:4)289 fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {304 fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {290 (4_857_000 as Weight)305 (9_978_000 as Weight)291 // Standard Error: 2_000306 // Standard Error: 2_000292 .saturating_add((9_838_000 as Weight).saturating_mul(b as Weight))307 .saturating_add((10_848_000 as Weight).saturating_mul(b as Weight))293 .saturating_add(RocksDbWeight::get().reads(1 as Weight))308 .saturating_add(RocksDbWeight::get().reads(1 as Weight))294 .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))309 .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))295 .saturating_add(RocksDbWeight::get().writes(1 as Weight))310 .saturating_add(RocksDbWeight::get().writes(1 as Weight))302 // Storage: Refungible Balance (r:0 w:4)317 // Storage: Refungible Balance (r:0 w:4)303 // Storage: Refungible Owned (r:0 w:4)318 // Storage: Refungible Owned (r:0 w:4)304 fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {319 fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {305 (11_335_000 as Weight)320 (15_419_000 as Weight)306 // Standard Error: 2_000321 // Standard Error: 2_000307 .saturating_add((6_784_000 as Weight).saturating_mul(b as Weight))322 .saturating_add((7_813_000 as Weight).saturating_mul(b as Weight))308 .saturating_add(RocksDbWeight::get().reads(1 as Weight))323 .saturating_add(RocksDbWeight::get().reads(1 as Weight))309 .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))324 .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))310 .saturating_add(RocksDbWeight::get().writes(3 as Weight))325 .saturating_add(RocksDbWeight::get().writes(3 as Weight))315 // Storage: Refungible AccountBalance (r:1 w:1)330 // Storage: Refungible AccountBalance (r:1 w:1)316 // Storage: Refungible Owned (r:0 w:1)331 // Storage: Refungible Owned (r:0 w:1)317 fn burn_item_partial() -> Weight {332 fn burn_item_partial() -> Weight {318 (21_239_000 as Weight)333 (25_578_000 as Weight)319 .saturating_add(RocksDbWeight::get().reads(3 as Weight))334 .saturating_add(RocksDbWeight::get().reads(3 as Weight))320 .saturating_add(RocksDbWeight::get().writes(4 as Weight))335 .saturating_add(RocksDbWeight::get().writes(4 as Weight))321 }336 }327 // Storage: Refungible Owned (r:0 w:1)342 // Storage: Refungible Owned (r:0 w:1)328 // Storage: Refungible TokenProperties (r:0 w:1)343 // Storage: Refungible TokenProperties (r:0 w:1)329 fn burn_item_fully() -> Weight {344 fn burn_item_fully() -> Weight {330 (29_426_000 as Weight)345 (33_593_000 as Weight)331 .saturating_add(RocksDbWeight::get().reads(4 as Weight))346 .saturating_add(RocksDbWeight::get().reads(4 as Weight))332 .saturating_add(RocksDbWeight::get().writes(7 as Weight))347 .saturating_add(RocksDbWeight::get().writes(7 as Weight))333 }348 }334 // Storage: Refungible Balance (r:2 w:2)349 // Storage: Refungible Balance (r:2 w:2)335 fn transfer_normal() -> Weight {350 fn transfer_normal() -> Weight {336 (17_743_000 as Weight)351 (21_049_000 as Weight)337 .saturating_add(RocksDbWeight::get().reads(2 as Weight))352 .saturating_add(RocksDbWeight::get().reads(2 as Weight))338 .saturating_add(RocksDbWeight::get().writes(2 as Weight))353 .saturating_add(RocksDbWeight::get().writes(2 as Weight))339 }354 }340 // Storage: Refungible Balance (r:2 w:2)355 // Storage: Refungible Balance (r:2 w:2)341 // Storage: Refungible AccountBalance (r:1 w:1)356 // Storage: Refungible AccountBalance (r:1 w:1)342 // Storage: Refungible Owned (r:0 w:1)357 // Storage: Refungible Owned (r:0 w:1)343 fn transfer_creating() -> Weight {358 fn transfer_creating() -> Weight {344 (20_699_000 as Weight)359 (24_646_000 as Weight)345 .saturating_add(RocksDbWeight::get().reads(3 as Weight))360 .saturating_add(RocksDbWeight::get().reads(3 as Weight))346 .saturating_add(RocksDbWeight::get().writes(4 as Weight))361 .saturating_add(RocksDbWeight::get().writes(4 as Weight))347 }362 }348 // Storage: Refungible Balance (r:2 w:2)363 // Storage: Refungible Balance (r:2 w:2)349 // Storage: Refungible AccountBalance (r:1 w:1)364 // Storage: Refungible AccountBalance (r:1 w:1)350 // Storage: Refungible Owned (r:0 w:1)365 // Storage: Refungible Owned (r:0 w:1)351 fn transfer_removing() -> Weight {366 fn transfer_removing() -> Weight {352 (22_833_000 as Weight)367 (26_570_000 as Weight)353 .saturating_add(RocksDbWeight::get().reads(3 as Weight))368 .saturating_add(RocksDbWeight::get().reads(3 as Weight))354 .saturating_add(RocksDbWeight::get().writes(4 as Weight))369 .saturating_add(RocksDbWeight::get().writes(4 as Weight))355 }370 }356 // Storage: Refungible Balance (r:2 w:2)371 // Storage: Refungible Balance (r:2 w:2)357 // Storage: Refungible AccountBalance (r:2 w:2)372 // Storage: Refungible AccountBalance (r:2 w:2)358 // Storage: Refungible Owned (r:0 w:2)373 // Storage: Refungible Owned (r:0 w:2)359 fn transfer_creating_removing() -> Weight {374 fn transfer_creating_removing() -> Weight {360 (24_936_000 as Weight)375 (28_906_000 as Weight)361 .saturating_add(RocksDbWeight::get().reads(4 as Weight))376 .saturating_add(RocksDbWeight::get().reads(4 as Weight))362 .saturating_add(RocksDbWeight::get().writes(6 as Weight))377 .saturating_add(RocksDbWeight::get().writes(6 as Weight))363 }378 }364 // Storage: Refungible Balance (r:1 w:0)379 // Storage: Refungible Balance (r:1 w:0)365 // Storage: Refungible Allowance (r:0 w:1)380 // Storage: Refungible Allowance (r:0 w:1)366 fn approve() -> Weight {381 fn approve() -> Weight {367 (13_446_000 as Weight)382 (16_451_000 as Weight)368 .saturating_add(RocksDbWeight::get().reads(1 as Weight))383 .saturating_add(RocksDbWeight::get().reads(1 as Weight))369 .saturating_add(RocksDbWeight::get().writes(1 as Weight))384 .saturating_add(RocksDbWeight::get().writes(1 as Weight))370 }385 }371 // Storage: Refungible Allowance (r:1 w:1)386 // Storage: Refungible Allowance (r:1 w:1)372 // Storage: Refungible Balance (r:2 w:2)387 // Storage: Refungible Balance (r:2 w:2)373 fn transfer_from_normal() -> Weight {388 fn transfer_from_normal() -> Weight {374 (24_777_000 as Weight)389 (29_545_000 as Weight)375 .saturating_add(RocksDbWeight::get().reads(3 as Weight))390 .saturating_add(RocksDbWeight::get().reads(3 as Weight))376 .saturating_add(RocksDbWeight::get().writes(3 as Weight))391 .saturating_add(RocksDbWeight::get().writes(3 as Weight))377 }392 }380 // Storage: Refungible AccountBalance (r:1 w:1)395 // Storage: Refungible AccountBalance (r:1 w:1)381 // Storage: Refungible Owned (r:0 w:1)396 // Storage: Refungible Owned (r:0 w:1)382 fn transfer_from_creating() -> Weight {397 fn transfer_from_creating() -> Weight {383 (28_483_000 as Weight)398 (33_392_000 as Weight)384 .saturating_add(RocksDbWeight::get().reads(4 as Weight))399 .saturating_add(RocksDbWeight::get().reads(4 as Weight))385 .saturating_add(RocksDbWeight::get().writes(5 as Weight))400 .saturating_add(RocksDbWeight::get().writes(5 as Weight))386 }401 }389 // Storage: Refungible AccountBalance (r:1 w:1)404 // Storage: Refungible AccountBalance (r:1 w:1)390 // Storage: Refungible Owned (r:0 w:1)405 // Storage: Refungible Owned (r:0 w:1)391 fn transfer_from_removing() -> Weight {406 fn transfer_from_removing() -> Weight {392 (29_896_000 as Weight)407 (35_446_000 as Weight)393 .saturating_add(RocksDbWeight::get().reads(4 as Weight))408 .saturating_add(RocksDbWeight::get().reads(4 as Weight))394 .saturating_add(RocksDbWeight::get().writes(5 as Weight))409 .saturating_add(RocksDbWeight::get().writes(5 as Weight))395 }410 }398 // Storage: Refungible AccountBalance (r:2 w:2)413 // Storage: Refungible AccountBalance (r:2 w:2)399 // Storage: Refungible Owned (r:0 w:2)414 // Storage: Refungible Owned (r:0 w:2)400 fn transfer_from_creating_removing() -> Weight {415 fn transfer_from_creating_removing() -> Weight {401 (32_070_000 as Weight)416 (37_762_000 as Weight)402 .saturating_add(RocksDbWeight::get().reads(5 as Weight))417 .saturating_add(RocksDbWeight::get().reads(5 as Weight))403 .saturating_add(RocksDbWeight::get().writes(7 as Weight))418 .saturating_add(RocksDbWeight::get().writes(7 as Weight))404 }419 }411 // Storage: Refungible Owned (r:0 w:1)426 // Storage: Refungible Owned (r:0 w:1)412 // Storage: Refungible TokenProperties (r:0 w:1)427 // Storage: Refungible TokenProperties (r:0 w:1)413 fn burn_from() -> Weight {428 fn burn_from() -> Weight {414 (36_789_000 as Weight)429 (42_620_000 as Weight)415 .saturating_add(RocksDbWeight::get().reads(5 as Weight))430 .saturating_add(RocksDbWeight::get().reads(5 as Weight))416 .saturating_add(RocksDbWeight::get().writes(8 as Weight))431 .saturating_add(RocksDbWeight::get().writes(8 as Weight))417 }432 }418 // Storage: Common CollectionPropertyPermissions (r:1 w:1)433 // Storage: Common CollectionPropertyPermissions (r:1 w:1)419 fn set_token_property_permissions(b: u32, ) -> Weight {434 fn set_token_property_permissions(b: u32, ) -> Weight {420 (0 as Weight)435 (0 as Weight)421 // Standard Error: 62_000436 // Standard Error: 65_000422 .saturating_add((15_803_000 as Weight).saturating_mul(b as Weight))437 .saturating_add((16_513_000 as Weight).saturating_mul(b as Weight))423 .saturating_add(RocksDbWeight::get().reads(1 as Weight))438 .saturating_add(RocksDbWeight::get().reads(1 as Weight))424 .saturating_add(RocksDbWeight::get().writes(1 as Weight))439 .saturating_add(RocksDbWeight::get().writes(1 as Weight))425 }440 }426 // Storage: Common CollectionPropertyPermissions (r:1 w:0)441 // Storage: Common CollectionPropertyPermissions (r:1 w:0)427 // Storage: Refungible TokenProperties (r:1 w:1)442 // Storage: Refungible TokenProperties (r:1 w:1)428 fn set_token_properties(b: u32, ) -> Weight {443 fn set_token_properties(b: u32, ) -> Weight {429 (0 as Weight)444 (0 as Weight)430 // Standard Error: 1_668_000445 // Standard Error: 1_583_000431 .saturating_add((302_308_000 as Weight).saturating_mul(b as Weight))446 .saturating_add((291_392_000 as Weight).saturating_mul(b as Weight))432 .saturating_add(RocksDbWeight::get().reads(2 as Weight))447 .saturating_add(RocksDbWeight::get().reads(2 as Weight))433 .saturating_add(RocksDbWeight::get().writes(1 as Weight))448 .saturating_add(RocksDbWeight::get().writes(1 as Weight))434 }449 }435 // Storage: Common CollectionPropertyPermissions (r:1 w:0)450 // Storage: Common CollectionPropertyPermissions (r:1 w:0)436 // Storage: Refungible TokenProperties (r:1 w:1)451 // Storage: Refungible TokenProperties (r:1 w:1)437 fn delete_token_properties(b: u32, ) -> Weight {452 fn delete_token_properties(b: u32, ) -> Weight {438 (0 as Weight)453 (0 as Weight)439 // Standard Error: 1_619_000454 // Standard Error: 1_699_000440 .saturating_add((294_574_000 as Weight).saturating_mul(b as Weight))455 .saturating_add((293_270_000 as Weight).saturating_mul(b as Weight))441 .saturating_add(RocksDbWeight::get().reads(2 as Weight))456 .saturating_add(RocksDbWeight::get().reads(2 as Weight))442 .saturating_add(RocksDbWeight::get().writes(1 as Weight))457 .saturating_add(RocksDbWeight::get().writes(1 as Weight))443 }458 }444 // Storage: Refungible TotalSupply (r:1 w:1)459 // Storage: Refungible TotalSupply (r:1 w:1)445 // Storage: Refungible Balance (r:1 w:1)460 // Storage: Refungible Balance (r:1 w:1)446 fn repartition_item() -> Weight {461 fn repartition_item() -> Weight {447 (8_325_000 as Weight)462 (19_206_000 as Weight)448 .saturating_add(RocksDbWeight::get().reads(2 as Weight))463 .saturating_add(RocksDbWeight::get().reads(2 as Weight))449 .saturating_add(RocksDbWeight::get().writes(2 as Weight))464 .saturating_add(RocksDbWeight::get().writes(2 as Weight))450 }465 }466 // Storage: Refungible Balance (r:1 w:0)467 // Storage: Refungible TotalSupply (r:1 w:0)468 // Storage: Refungible TokenProperties (r:1 w:1)469 fn set_parent_nft_unchecked() -> Weight {470 (10_189_000 as Weight)471 .saturating_add(RocksDbWeight::get().reads(3 as Weight))472 .saturating_add(RocksDbWeight::get().writes(1 as Weight))473 }474 // Storage: Refungible Balance (r:2 w:0)475 fn token_owner() -> Weight {476 (8_205_000 as Weight)477 .saturating_add(RocksDbWeight::get().reads(2 as Weight))478 }451}479}452480pallets/unique/src/eth/mod.rsdiffbeforeafterboth17//! Implementation of CollectionHelpers contract.17//! Implementation of CollectionHelpers contract.181819use core::marker::PhantomData;19use core::marker::PhantomData;20use ethereum as _;20use evm_coder::{execution::*, generate_stubgen, solidity_interface, solidity, weight, types::*};21use evm_coder::{execution::*, generate_stubgen, solidity_interface, solidity, weight, types::*};22use frame_support::traits::Get;21use ethereum as _;23use pallet_common::{24 CollectionById, CollectionHandle,25 dispatch::CollectionDispatch,26 erc::{27 CollectionHelpersEvents,28 static_property::{key, value as property_value},29 },30 Pallet as PalletCommon,31};22use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};32use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};23use pallet_evm::{OnMethodCall, PrecompileResult, account::CrossAccountId, PrecompileHandle};33use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};34use pallet_evm_coder_substrate::dispatch_to_evm;24use up_data_structs::{35use up_data_structs::{25 CollectionName, CollectionDescription, CollectionTokenPrefix, CreateCollectionData,36 CollectionName, CollectionDescription, CollectionTokenPrefix, CreateCollectionData,26 CollectionMode, PropertyValue,37 CollectionMode, PropertyKeyPermission, PropertyPermission, PropertyScope, PropertyValue,27};38};28use frame_support::traits::Get;3929use pallet_common::{30 CollectionById,31 erc::{32 static_property::{key, value as property_value},33 CollectionHelpersEvents,34 },35 dispatch::CollectionDispatch,36};37use crate::{SelfWeightOf, Config, weights::WeightInfo};40use crate::{Config, SelfWeightOf, weights::WeightInfo};384139use sp_std::vec::Vec;42use sp_std::{vec, vec::Vec};40use alloc::format;43use alloc::format;414442/// See [`CollectionHelpersCall`]45/// See [`CollectionHelpersCall`]151 Ok(data)154 Ok(data)152}155}156157fn parent_nft_property_permissions() -> PropertyKeyPermission {158 PropertyKeyPermission {159 key: key::parent_nft(),160 permission: PropertyPermission {161 mutable: false,162 collection_admin: false,163 token_owner: true,164 },165 }166}167168fn create_refungible_collection_internal<169 T: Config + pallet_nonfungible::Config + pallet_refungible::Config,170>(171 caller: caller,172 name: string,173 description: string,174 token_prefix: string,175 base_uri: string,176 add_properties: bool,177) -> Result<address> {178 let (caller, name, description, token_prefix, base_uri_value) =179 convert_data::<T>(caller, name, description, token_prefix, base_uri)?;180 let data = make_data::<T>(181 name,182 CollectionMode::ReFungible,183 description,184 token_prefix,185 base_uri_value,186 add_properties,187 )?;188189 let collection_id = T::CollectionDispatch::create(caller.clone(), data)190 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;191192 let handle = <CollectionHandle<T>>::try_get(collection_id).map_err(dispatch_to_evm::<T>)?;193 <PalletCommon<T>>::set_scoped_token_property_permissions(194 &handle,195 &caller,196 PropertyScope::Eth,197 vec![parent_nft_property_permissions()],198 )199 .map_err(dispatch_to_evm::<T>)?;200201 let address = pallet_common::eth::collection_id_to_address(collection_id);202 Ok(address)203}153204154/// @title Contract, which allows users to operate with collections205/// @title Contract, which allows users to operate with collections155#[solidity_interface(name = "CollectionHelpers", events(CollectionHelpersEvents))]206#[solidity_interface(name = "CollectionHelpers", events(CollectionHelpersEvents))]216267217 #[weight(<SelfWeightOf<T>>::create_collection())]268 #[weight(<SelfWeightOf<T>>::create_collection())]218 fn create_refungible_collection(269 fn create_refungible_collection(219 &self,270 &mut self,220 caller: caller,271 caller: caller,221 name: string,272 name: string,222 description: string,273 description: string,223 token_prefix: string,274 token_prefix: string,224 ) -> Result<address> {275 ) -> Result<address> {225 let (caller, name, description, token_prefix, _base_uri) =226 convert_data::<T>(caller, name, description, token_prefix, "".into())?;227 let data = make_data::<T>(276 create_refungible_collection_internal::<T>(277 caller,228 name,278 name,229 CollectionMode::ReFungible,230 description,279 description,231 token_prefix,280 token_prefix,232 Default::default(),281 Default::default(),233 false,282 false,234 )?;283 )235 let collection_id = T::CollectionDispatch::create(caller, data)236 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;237238 let address = pallet_common::eth::collection_id_to_address(collection_id);239 Ok(address)240 }284 }241285242 #[weight(<SelfWeightOf<T>>::create_collection())]286 #[weight(<SelfWeightOf<T>>::create_collection())]249 token_prefix: string,293 token_prefix: string,250 base_uri: string,294 base_uri: string,251 ) -> Result<address> {295 ) -> Result<address> {252 let (caller, name, description, token_prefix, base_uri_value) =253 convert_data::<T>(caller, name, description, token_prefix, base_uri)?;296 create_refungible_collection_internal::<T>(254 let data = make_data::<T>(297 caller,255 name,298 name,256 CollectionMode::NFT,299 description,257 description,300 token_prefix,258 token_prefix,301 base_uri,259 base_uri_value,302 true,260 true,303 )261 )?;262 let collection_id = T::CollectionDispatch::create(caller, data)263 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;264265 let address = pallet_common::eth::collection_id_to_address(collection_id);266 Ok(address)267 }304 }268305269 /// Check if a collection exists306 /// Check if a collection existspallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/unique/src/eth/stubs/CollectionHelpers.soldiffbeforeafterboth72 string memory name,72 string memory name,73 string memory description,73 string memory description,74 string memory tokenPrefix74 string memory tokenPrefix75 ) public view returns (address) {75 ) public returns (address) {76 require(false, stub_error);76 require(false, stub_error);77 name;77 name;78 description;78 description;79 tokenPrefix;79 tokenPrefix;80 dummy;80 dummy = 0;81 return 0x0000000000000000000000000000000000000000;81 return 0x0000000000000000000000000000000000000000;82 }82 }8383primitives/common/Cargo.tomldiffbeforeafterbothno changes
primitives/common/src/constants.rsdiffbeforeafterbothno changes
primitives/common/src/lib.rsdiffbeforeafterbothno changes
primitives/common/src/types.rsdiffbeforeafterbothno changes
primitives/data-structs/src/lib.rsdiffbeforeafterboth1050pub enum PropertyScope {1050pub enum PropertyScope {1051 None,1051 None,1052 Rmrk,1052 Rmrk,1053 Eth,1053}1054}105410551055impl PropertyScope {1056impl PropertyScope {1058 let scope_str: &[u8] = match self {1059 let scope_str: &[u8] = match self {1059 Self::None => return Ok(key),1060 Self::None => return Ok(key),1060 Self::Rmrk => b"rmrk",1061 Self::Rmrk => b"rmrk",1062 Self::Eth => b"eth",1061 };1063 };106210641063 [scope_str, b":", key.as_slice()]1065 [scope_str, b":", key.as_slice()]runtime/common/Cargo.tomldiffbeforeafterbothno changes
runtime/common/config/ethereum.rsdiffbeforeafterbothno changes
runtime/common/config/mod.rsdiffbeforeafterbothno changes
runtime/common/config/orml.rsdiffbeforeafterbothno changes
runtime/common/config/pallets/mod.rsdiffbeforeafterbothno changes
runtime/common/config/pallets/rmrk.rsdiffbeforeafterbothno changes
runtime/common/config/pallets/scheduler.rsdiffbeforeafterbothno changes
runtime/common/config/parachain.rsdiffbeforeafterbothno changes
runtime/common/config/sponsoring.rsdiffbeforeafterbothno changes
runtime/common/config/substrate.rsdiffbeforeafterbothno changes
runtime/common/config/xcm.rsdiffbeforeafterbothno changes
runtime/common/constants.rsdiffbeforeafterbothno changes
runtime/common/construct_runtime/mod.rsdiffbeforeafterbothno changes
runtime/common/construct_runtime/util.rsdiffbeforeafterbothno changes
runtime/common/dispatch.rsdiffbeforeafterbothno changes
runtime/common/ethereum/mod.rsdiffbeforeafterbothno changes
runtime/common/ethereum/self_contained_call.rsdiffbeforeafterbothno changes
runtime/common/ethereum/sponsoring.rsdiffbeforeafterbothno changes
runtime/common/ethereum/transaction_converter.rsdiffbeforeafterbothno changes
runtime/common/instance.rsdiffbeforeafterbothno changes
runtime/common/mod.rsdiffbeforeafterbothno changes
runtime/common/runtime_apis.rsdiffbeforeafterbothno changes
runtime/common/scheduler.rsdiffbeforeafterbothno changes
runtime/common/sponsoring.rsdiffbeforeafterbothno changes
runtime/common/src/constants.rsdiffbeforeafterbothno changes
runtime/common/src/dispatch.rsdiffbeforeafterbothno changes
runtime/common/src/eth_sponsoring.rsdiffbeforeafterbothno changes
runtime/common/src/lib.rsdiffbeforeafterbothno changes
runtime/common/src/runtime_apis.rsdiffbeforeafterbothno changes
runtime/common/src/sponsoring.rsdiffbeforeafterbothno changes
runtime/common/src/types.rsdiffbeforeafterbothno changes
runtime/common/src/weights.rsdiffbeforeafterbothno changes
runtime/common/weights.rsdiffbeforeafterbothno changes
runtime/opal/Cargo.tomldiffbeforeafterboth16targets = ['x86_64-unknown-linux-gnu']16targets = ['x86_64-unknown-linux-gnu']171718[features]18[features]19default = ['std']19default = ['std', 'opal-runtime']20runtime-benchmarks = [20runtime-benchmarks = [21 'hex-literal',21 'hex-literal',22 'frame-benchmarking',22 'frame-benchmarking',113 'xcm/std',113 'xcm/std',114 'xcm-builder/std',114 'xcm-builder/std',115 'xcm-executor/std',115 'xcm-executor/std',116 'unique-runtime-common/std',116 'up-common/std',117 'rmrk-rpc/std',117 'rmrk-rpc/std',118 'evm-coder/std',119 'up-sponsorship/std',118120119 "orml-vesting/std",121 "orml-vesting/std",120]122]121limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']123limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']124opal-runtime = ['refungible', 'scheduler', 'rmrk']125126refungible = []127scheduler = []128rmrk = []122129123################################################################################130################################################################################124# Substrate Dependencies131# Substrate Dependencies396403397[dependencies]404[dependencies]398log = { version = "0.4.16", default-features = false }405log = { version = "0.4.16", default-features = false }399unique-runtime-common = { path = "../common", default-features = false }406up-common = { path = "../../primitives/common", default-features = false }400scale-info = { version = "2.0.1", default-features = false, features = [407scale-info = { version = "2.0.1", default-features = false, features = [401 "derive",408 "derive",402] }409] }426pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }433pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }427fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }434fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }428fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }435fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }436evm-coder = { default-features = false, path = '../../crates/evm-coder' }437up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.24' }429438430################################################################################439################################################################################431# Build Dependencies440# Build Dependenciesruntime/opal/src/lib.rsdiffbeforeafterboth25#[cfg(feature = "std")]25#[cfg(feature = "std")]26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));272728use sp_api::impl_runtime_apis;28use frame_support::parameter_types;2929use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};30use sp_version::RuntimeVersion;30use sp_runtime::DispatchError;31use fp_self_contained::*;32// #[cfg(any(feature = "std", test))]33// pub use sp_runtime::BuildStorage;3435use sp_runtime::{31use sp_runtime::create_runtime_str;36 Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,37 traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, Member},38 transaction_validity::{TransactionSource, TransactionValidity},39 ApplyExtrinsicResult, RuntimeAppPublic,40};413242use sp_std::prelude::*;33use up_common::types::*;433444#[cfg(feature = "std")]35#[path = "../../common/mod.rs"]45use sp_version::NativeVersion;36mod runtime_common;46use sp_version::RuntimeVersion;3747pub use pallet_transaction_payment::{38pub use runtime_common::*;48 Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,49};50// A few exports that help ease life for downstream crates.51pub use pallet_balances::Call as BalancesCall;52pub use pallet_evm::{53 EnsureAddressTruncated, HashedAddressMapping, Runner, account::CrossAccountId as _,54 OnMethodCall, Account as EVMAccount, FeeCalculator, GasWeightMapping,55};56pub use frame_support::{57 construct_runtime, match_types,58 dispatch::DispatchResult,59 PalletId, parameter_types, StorageValue, ConsensusEngineId,60 traits::{61 tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,62 Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,63 OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, PrivilegeCmp,64 },65 weights::{66 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},67 DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,68 WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier,69 WeightToFee,70 },71};72use pallet_unique_scheduler::DispatchCall;73use up_data_structs::{74 CollectionId, TokenId, TokenData, Property, PropertyKeyPermission, CollectionLimits,75 CollectionStats, RpcCollection,76 mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},77 TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo,78 RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkCollectionId, RmrkNftId,79 RmrkNftChild, RmrkPropertyKey, RmrkResourceId, RmrkBaseId,80};8182// use pallet_contracts::weights::WeightInfo;83// #[cfg(any(feature = "std", test))]84use frame_system::{85 self as frame_system, EnsureRoot, EnsureSigned,86 limits::{BlockWeights, BlockLength},87};88use sp_arithmetic::{89 traits::{BaseArithmetic, Unsigned},90};91use smallvec::smallvec;92// use scale_info::TypeInfo;93use codec::{Encode, Decode};94use fp_rpc::TransactionStatus;95use sp_runtime::{96 traits::{97 Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,98 Saturating, CheckedConversion,99 },100 generic::Era,101 transaction_validity::TransactionValidityError,102 DispatchErrorWithPostInfo, SaturatedConversion,103};104105// pub use pallet_timestamp::Call as TimestampCall;106pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;107108// Polkadot imports109use pallet_xcm::XcmPassthrough;110use polkadot_parachain::primitives::Sibling;111use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};112use xcm_builder::{113 AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,114 EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,115 RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,116 SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,117 ParentIsPreset,118};119use xcm_executor::{Config, XcmExecutor, Assets};120use sp_std::{cmp::Ordering, marker::PhantomData};121122use xcm::latest::{123 // Xcm,124 AssetId::{Concrete},125 Fungibility::Fungible as XcmFungible,126 MultiAsset,127 Error as XcmError,128};129use xcm_executor::traits::{MatchesFungible, WeightTrader};130//use xcm_executor::traits::MatchesFungible;131132use unique_runtime_common::{133 impl_common_runtime_apis,134 types::*,135 constants::*,136 dispatch::{CollectionDispatchT, CollectionDispatch},137 sponsoring::UniqueSponsorshipHandler,138 eth_sponsoring::UniqueEthSponsorshipHandler,139 weights::CommonWeights,140};14139142pub const RUNTIME_NAME: &str = "opal";40pub const RUNTIME_NAME: &str = "opal";143pub const TOKEN_SYMBOL: &str = "OPL";41pub const TOKEN_SYMBOL: &str = "OPL";144145type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;146147impl RuntimeInstance for Runtime {148 type CrossAccountId = self::CrossAccountId;149 type TransactionConverter = self::TransactionConverter;150151 fn get_transaction_converter() -> TransactionConverter {152 TransactionConverter153 }154}155156/// The type for looking up accounts. We don't expect more than 4 billion of them, but you157/// never know...158pub type AccountIndex = u32;159160/// Balance of an account.161pub type Balance = u128;162163/// Index of a transaction in the chain.164pub type Index = u32;165166/// A hash of some data used by the chain.167pub type Hash = sp_core::H256;168169/// Digest item type.170pub type DigestItem = generic::DigestItem;171172/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know173/// the specifics of the runtime. They can then be made to be agnostic over specific formats174/// of data like extrinsics, allowing for them to continue syncing the network through upgrades175/// to even the core data structures.176pub mod opaque {177 use sp_std::prelude::*;178 use sp_runtime::impl_opaque_keys;179 use super::Aura;180181 pub use unique_runtime_common::types::*;182183 impl_opaque_keys! {184 pub struct SessionKeys {185 pub aura: Aura,186 }187 }188}18942190/// This runtime version.43/// This runtime version.191pub const VERSION: RuntimeVersion = RuntimeVersion {44pub const VERSION: RuntimeVersion = RuntimeVersion {199 state_version: 0,52 state_version: 0,200};53};201202#[derive(codec::Encode, codec::Decode)]203pub enum XCMPMessage<XAccountId, XBalance> {204 /// Transfer tokens to the given account from the Parachain account.205 TransferToken(XAccountId, XBalance),206}207208/// The version information used to identify this runtime when compiled natively.209#[cfg(feature = "std")]210pub fn native_version() -> NativeVersion {211 NativeVersion {212 runtime_version: VERSION,213 can_author_with: Default::default(),214 }215}216217type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;218219pub struct DealWithFees;220impl OnUnbalanced<NegativeImbalance> for DealWithFees {221 fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {222 if let Some(fees) = fees_then_tips.next() {223 // for fees, 100% to treasury224 let mut split = fees.ration(100, 0);225 if let Some(tips) = fees_then_tips.next() {226 // for tips, if any, 100% to treasury227 tips.ration_merge_into(100, 0, &mut split);228 }229 Treasury::on_unbalanced(split.0);230 // Author::on_unbalanced(split.1);231 }232 }233}23454235parameter_types! {55parameter_types! {236 pub const BlockHashCount: BlockNumber = 2400;237 pub RuntimeBlockLength: BlockLength =238 BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);239 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);240 pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;241 pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()242 .base_block(BlockExecutionWeight::get())243 .for_class(DispatchClass::all(), |weights| {244 weights.base_extrinsic = ExtrinsicBaseWeight::get();245 })246 .for_class(DispatchClass::Normal, |weights| {247 weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);248 })249 .for_class(DispatchClass::Operational, |weights| {250 weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);251 // Operational transactions have some extra reserved space, so that they252 // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.253 weights.reserved = Some(254 MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT255 );256 })257 .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)258 .build_or_panic();259 pub const Version: RuntimeVersion = VERSION;56 pub const Version: RuntimeVersion = VERSION;260 pub const SS58Prefix: u8 = 42;57 pub const SS58Prefix: u8 = 42;261}262263parameter_types! {264 pub const ChainId: u64 = 8882;58 pub const ChainId: u64 = 8882;265}59}266267pub struct FixedFee;268impl FeeCalculator for FixedFee {269 fn min_gas_price() -> (U256, u64) {270 (MIN_GAS_PRICE.into(), 0)271 }272}273274// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case275// (contract, which only writes a lot of data),276// approximating on top of our real store write weight277parameter_types! {278 pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;279 pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;280 pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();281}282283/// Limiting EVM execution to 50% of block for substrate users and management tasks284/// EVM transaction consumes more weight than substrate's, so we can't rely on them being285/// scheduled fairly286const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);287parameter_types! {288 pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());289}290291pub enum FixedGasWeightMapping {}292impl GasWeightMapping for FixedGasWeightMapping {293 fn gas_to_weight(gas: u64) -> Weight {294 gas.saturating_mul(WeightPerGas::get())295 }296 fn weight_to_gas(weight: Weight) -> u64 {297 weight / WeightPerGas::get()298 }299}300301impl pallet_evm::account::Config for Runtime {302 type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;303 type EvmAddressMapping = pallet_evm::HashedAddressMapping<Self::Hashing>;304 type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;305}306307impl pallet_evm::Config for Runtime {308 type BlockGasLimit = BlockGasLimit;309 type FeeCalculator = FixedFee;310 type GasWeightMapping = FixedGasWeightMapping;311 type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;312 type CallOrigin = EnsureAddressTruncated<Self>;313 type WithdrawOrigin = EnsureAddressTruncated<Self>;314 type AddressMapping = HashedAddressMapping<Self::Hashing>;315 type PrecompilesType = ();316 type PrecompilesValue = ();317 type Currency = Balances;318 type Event = Event;319 type OnMethodCall = (320 pallet_evm_migration::OnMethodCall<Self>,321 pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,322 CollectionDispatchT<Self>,323 pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,324 );325 type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;326 type ChainId = ChainId;327 type Runner = pallet_evm::runner::stack::Runner<Self>;328 type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;329 type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;330 type FindAuthor = EthereumFindAuthor<Aura>;331}332333impl pallet_evm_migration::Config for Runtime {334 type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;335}336337pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);338impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {339 fn find_author<'a, I>(digests: I) -> Option<H160>340 where341 I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,342 {343 if let Some(author_index) = F::find_author(digests) {344 let authority_id = Aura::authorities()[author_index as usize].clone();345 return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));346 }347 None348 }349}350351impl pallet_ethereum::Config for Runtime {352 type Event = Event;353 type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;354}355356impl pallet_randomness_collective_flip::Config for Runtime {}357358impl frame_system::Config for Runtime {359 /// The data to be stored in an account.360 type AccountData = pallet_balances::AccountData<Balance>;361 /// The identifier used to distinguish between accounts.362 type AccountId = AccountId;363 /// The basic call filter to use in dispatchable.364 type BaseCallFilter = Everything;365 /// Maximum number of block number to block hash mappings to keep (oldest pruned first).366 type BlockHashCount = BlockHashCount;367 /// The maximum length of a block (in bytes).368 type BlockLength = RuntimeBlockLength;369 /// The index type for blocks.370 type BlockNumber = BlockNumber;371 /// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.372 type BlockWeights = RuntimeBlockWeights;373 /// The aggregated dispatch type that is available for extrinsics.374 type Call = Call;375 /// The weight of database operations that the runtime can invoke.376 type DbWeight = RocksDbWeight;377 /// The ubiquitous event type.378 type Event = Event;379 /// The type for hashing blocks and tries.380 type Hash = Hash;381 /// The hashing algorithm used.382 type Hashing = BlakeTwo256;383 /// The header type.384 type Header = generic::Header<BlockNumber, BlakeTwo256>;385 /// The index type for storing how many extrinsics an account has signed.386 type Index = Index;387 /// The lookup mechanism to get account ID from whatever is passed in dispatchers.388 type Lookup = AccountIdLookup<AccountId, ()>;389 /// What to do if an account is fully reaped from the system.390 type OnKilledAccount = ();391 /// What to do if a new account is created.392 type OnNewAccount = ();393 type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;394 /// The ubiquitous origin type.395 type Origin = Origin;396 /// This type is being generated by `construct_runtime!`.397 type PalletInfo = PalletInfo;398 /// This is used as an identifier of the chain. 42 is the generic substrate prefix.399 type SS58Prefix = SS58Prefix;400 /// Weight information for the extrinsics of this pallet.401 type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;402 /// Version of the runtime.403 type Version = Version;404 type MaxConsumers = ConstU32<16>;405}406407parameter_types! {408 pub const MinimumPeriod: u64 = SLOT_DURATION / 2;409}410411impl pallet_timestamp::Config for Runtime {412 /// A timestamp: milliseconds since the unix epoch.413 type Moment = u64;414 type OnTimestampSet = ();415 type MinimumPeriod = MinimumPeriod;416 type WeightInfo = ();417}418419parameter_types! {420 // pub const ExistentialDeposit: u128 = 500;421 pub const ExistentialDeposit: u128 = 0;422 pub const MaxLocks: u32 = 50;423 pub const MaxReserves: u32 = 50;424}425426impl pallet_balances::Config for Runtime {427 type MaxLocks = MaxLocks;428 type MaxReserves = MaxReserves;429 type ReserveIdentifier = [u8; 16];430 /// The type for recording an account's balance.431 type Balance = Balance;432 /// The ubiquitous event type.433 type Event = Event;434 type DustRemoval = Treasury;435 type ExistentialDeposit = ExistentialDeposit;436 type AccountStore = System;437 type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;438}439440pub const fn deposit(items: u32, bytes: u32) -> Balance {441 items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE442}443444/*445parameter_types! {446 pub TombstoneDeposit: Balance = deposit(447 1,448 sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,449 );450 pub DepositPerContract: Balance = TombstoneDeposit::get();451 pub const DepositPerStorageByte: Balance = deposit(0, 1);452 pub const DepositPerStorageItem: Balance = deposit(1, 0);453 pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);454 pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;455 pub const SignedClaimHandicap: u32 = 2;456 pub const MaxDepth: u32 = 32;457 pub const MaxValueSize: u32 = 16 * 1024;458 pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb459 // The lazy deletion runs inside on_initialize.460 pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *461 RuntimeBlockWeights::get().max_block;462 // The weight needed for decoding the queue should be less or equal than a fifth463 // of the overall weight dedicated to the lazy deletion.464 pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (465 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -466 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)467 )) / 5) as u32;468 pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();469}470471impl pallet_contracts::Config for Runtime {472 type Time = Timestamp;473 type Randomness = RandomnessCollectiveFlip;474 type Currency = Balances;475 type Event = Event;476 type RentPayment = ();477 type SignedClaimHandicap = SignedClaimHandicap;478 type TombstoneDeposit = TombstoneDeposit;479 type DepositPerContract = DepositPerContract;480 type DepositPerStorageByte = DepositPerStorageByte;481 type DepositPerStorageItem = DepositPerStorageItem;482 type RentFraction = RentFraction;483 type SurchargeReward = SurchargeReward;484 type WeightPrice = pallet_transaction_payment::Pallet<Self>;485 type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;486 type ChainExtension = NFTExtension;487 type DeletionQueueDepth = DeletionQueueDepth;488 type DeletionWeightLimit = DeletionWeightLimit;489 type Schedule = Schedule;490 type CallStack = [pallet_contracts::Frame<Self>; 31];491}492*/493494parameter_types! {495 /// This value increases the priority of `Operational` transactions by adding496 /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.497 pub const OperationalFeeMultiplier: u8 = 5;498}499500/// Linear implementor of `WeightToFeePolynomial`501pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);502503impl<T> WeightToFeePolynomial for LinearFee<T>504where505 T: BaseArithmetic + From<u32> + Copy + Unsigned,506{507 type Balance = T;508509 fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {510 smallvec!(WeightToFeeCoefficient {511 coeff_integer: WEIGHT_TO_FEE_COEFF.into(),512 coeff_frac: Perbill::zero(),513 negative: false,514 degree: 1,515 })516 }517}518519impl pallet_transaction_payment::Config for Runtime {520 type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;521 type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;522 type OperationalFeeMultiplier = OperationalFeeMultiplier;523 type WeightToFee = LinearFee<Balance>;524 type FeeMultiplierUpdate = ();525}526527parameter_types! {528 pub const ProposalBond: Permill = Permill::from_percent(5);529 pub const ProposalBondMinimum: Balance = 1 * UNIQUE;530 pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;531 pub const SpendPeriod: BlockNumber = 5 * MINUTES;532 pub const Burn: Permill = Permill::from_percent(0);533 pub const TipCountdown: BlockNumber = 1 * DAYS;534 pub const TipFindersFee: Percent = Percent::from_percent(20);535 pub const TipReportDepositBase: Balance = 1 * UNIQUE;536 pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;537 pub const BountyDepositBase: Balance = 1 * UNIQUE;538 pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;539 pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");540 pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;541 pub const MaximumReasonLength: u32 = 16384;542 pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);543 pub const BountyValueMinimum: Balance = 5 * UNIQUE;544 pub const MaxApprovals: u32 = 100;545}546547impl pallet_treasury::Config for Runtime {548 type PalletId = TreasuryModuleId;549 type Currency = Balances;550 type ApproveOrigin = EnsureRoot<AccountId>;551 type RejectOrigin = EnsureRoot<AccountId>;552 type Event = Event;553 type OnSlash = ();554 type ProposalBond = ProposalBond;555 type ProposalBondMinimum = ProposalBondMinimum;556 type ProposalBondMaximum = ProposalBondMaximum;557 type SpendPeriod = SpendPeriod;558 type Burn = Burn;559 type BurnDestination = ();560 type SpendFunds = ();561 type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;562 type MaxApprovals = MaxApprovals;563}564565impl pallet_sudo::Config for Runtime {566 type Event = Event;567 type Call = Call;568}569570pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);571572impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider573 for RelayChainBlockNumberProvider<T>574{575 type BlockNumber = BlockNumber;576577 fn current_block_number() -> Self::BlockNumber {578 cumulus_pallet_parachain_system::Pallet::<T>::validation_data()579 .map(|d| d.relay_parent_number)580 .unwrap_or_default()581 }582}583584parameter_types! {585 pub const MinVestedTransfer: Balance = 10 * UNIQUE;586 pub const MaxVestingSchedules: u32 = 28;587}588589impl orml_vesting::Config for Runtime {590 type Event = Event;591 type Currency = pallet_balances::Pallet<Runtime>;592 type MinVestedTransfer = MinVestedTransfer;593 type VestedTransferOrigin = EnsureSigned<AccountId>;594 type WeightInfo = ();595 type MaxVestingSchedules = MaxVestingSchedules;596 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;597}598599parameter_types! {600 pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;601 pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;602}603604impl cumulus_pallet_parachain_system::Config for Runtime {605 type Event = Event;606 type SelfParaId = parachain_info::Pallet<Self>;607 type OnSystemEvent = ();608 // type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<609 // MaxDownwardMessageWeight,610 // XcmExecutor<XcmConfig>,611 // Call,612 // >;613 type OutboundXcmpMessageSource = XcmpQueue;614 type DmpMessageHandler = DmpQueue;615 type ReservedDmpWeight = ReservedDmpWeight;616 type ReservedXcmpWeight = ReservedXcmpWeight;617 type XcmpMessageHandler = XcmpQueue;618}619620impl parachain_info::Config for Runtime {}621622impl cumulus_pallet_aura_ext::Config for Runtime {}623624parameter_types! {625 pub const RelayLocation: MultiLocation = MultiLocation::parent();626 pub const RelayNetwork: NetworkId = NetworkId::Polkadot;627 pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();628 pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();629}630631/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used632/// when determining ownership of accounts for asset transacting and when attempting to use XCM633/// `Transact` in order to determine the dispatch Origin.634pub type LocationToAccountId = (635 // The parent (Relay-chain) origin converts to the default `AccountId`.636 ParentIsPreset<AccountId>,637 // Sibling parachain origins convert to AccountId via the `ParaId::into`.638 SiblingParachainConvertsVia<Sibling, AccountId>,639 // Straight up local `AccountId32` origins just alias directly to `AccountId`.640 AccountId32Aliases<RelayNetwork, AccountId>,641);642643pub struct OnlySelfCurrency;644impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {645 fn matches_fungible(a: &MultiAsset) -> Option<B> {646 match (&a.id, &a.fun) {647 (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),648 _ => None,649 }650 }651}652653/// Means for transacting assets on this chain.654pub type LocalAssetTransactor = CurrencyAdapter<655 // Use this currency:656 Balances,657 // Use this currency when it is a fungible asset matching the given location or name:658 OnlySelfCurrency,659 // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:660 LocationToAccountId,661 // Our chain's account ID type (we can't get away without mentioning it explicitly):662 AccountId,663 // We don't track any teleports.664 (),665>;666667/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,668/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can669/// biases the kind of local `Origin` it will become.670pub type XcmOriginToTransactDispatchOrigin = (671 // Sovereign account converter; this attempts to derive an `AccountId` from the origin location672 // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for673 // foreign chains who want to have a local sovereign account on this chain which they control.674 SovereignSignedViaLocation<LocationToAccountId, Origin>,675 // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when676 // recognised.677 RelayChainAsNative<RelayOrigin, Origin>,678 // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when679 // recognised.680 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,681 // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a682 // transaction from the Root origin.683 ParentAsSuperuser<Origin>,684 // Native signed account converter; this just converts an `AccountId32` origin into a normal685 // `Origin::Signed` origin of the same 32-byte value.686 SignedAccountId32AsNative<RelayNetwork, Origin>,687 // Xcm origins can be represented natively under the Xcm pallet's Xcm origin.688 XcmPassthrough<Origin>,689);690691parameter_types! {692 // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.693 pub UnitWeightCost: Weight = 1_000_000;694 // 1200 UNIQUEs buy 1 second of weight.695 pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);696 pub const MaxInstructions: u32 = 100;697 pub const MaxAuthorities: u32 = 100_000;698}699700match_types! {701 pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {702 MultiLocation { parents: 1, interior: Here } |703 MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }704 };705}706707pub type Barrier = (708 TakeWeightCredit,709 AllowTopLevelPaidExecutionFrom<Everything>,710 // ^^^ Parent & its unit plurality gets free execution711);712713pub struct UsingOnlySelfCurrencyComponents<714 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,715 AssetId: Get<MultiLocation>,716 AccountId,717 Currency: CurrencyT<AccountId>,718 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,719>(720 Weight,721 Currency::Balance,722 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,723);724impl<725 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,726 AssetId: Get<MultiLocation>,727 AccountId,728 Currency: CurrencyT<AccountId>,729 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,730 > WeightTrader731 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>732{733 fn new() -> Self {734 Self(0, Zero::zero(), PhantomData)735 }736737 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {738 let amount = WeightToFee::weight_to_fee(&weight);739 let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;740741 // location to this parachain through relay chain742 let option1: xcm::v1::AssetId = Concrete(MultiLocation {743 parents: 1,744 interior: X1(Parachain(ParachainInfo::parachain_id().into())),745 });746 // direct location747 let option2: xcm::v1::AssetId = Concrete(MultiLocation {748 parents: 0,749 interior: Here,750 });751752 let required = if payment.fungible.contains_key(&option1) {753 (option1, u128_amount).into()754 } else if payment.fungible.contains_key(&option2) {755 (option2, u128_amount).into()756 } else {757 (Concrete(MultiLocation::default()), u128_amount).into()758 };759760 let unused = payment761 .checked_sub(required)762 .map_err(|_| XcmError::TooExpensive)?;763 self.0 = self.0.saturating_add(weight);764 self.1 = self.1.saturating_add(amount);765 Ok(unused)766 }767768 fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {769 let weight = weight.min(self.0);770 let amount = WeightToFee::weight_to_fee(&weight);771 self.0 -= weight;772 self.1 = self.1.saturating_sub(amount);773 let amount: u128 = amount.saturated_into();774 if amount > 0 {775 Some((AssetId::get(), amount).into())776 } else {777 None778 }779 }780}781impl<782 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,783 AssetId: Get<MultiLocation>,784 AccountId,785 Currency: CurrencyT<AccountId>,786 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,787 > Drop788 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>789{790 fn drop(&mut self) {791 OnUnbalanced::on_unbalanced(Currency::issue(self.1));792 }793}794795pub struct XcmConfig;796impl Config for XcmConfig {797 type Call = Call;798 type XcmSender = XcmRouter;799 // How to withdraw and deposit an asset.800 type AssetTransactor = LocalAssetTransactor;801 type OriginConverter = XcmOriginToTransactDispatchOrigin;802 type IsReserve = NativeAsset;803 type IsTeleporter = (); // Teleportation is disabled804 type LocationInverter = LocationInverter<Ancestry>;805 type Barrier = Barrier;806 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;807 type Trader =808 UsingOnlySelfCurrencyComponents<LinearFee<Balance>, RelayLocation, AccountId, Balances, ()>;809 type ResponseHandler = (); // Don't handle responses for now.810 type SubscriptionService = PolkadotXcm;811812 type AssetTrap = PolkadotXcm;813 type AssetClaims = PolkadotXcm;814}815816// parameter_types! {817// pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;818// }819820/// No local origins on this chain are allowed to dispatch XCM sends/executions.821pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);822823/// The means for routing XCM messages which are not for local execution into the right message824/// queues.825pub type XcmRouter = (826 // Two routers - use UMP to communicate with the relay chain:827 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,828 // ..and XCMP to communicate with the sibling chains.829 XcmpQueue,830);831832impl pallet_evm_coder_substrate::Config for Runtime {}833834impl pallet_xcm::Config for Runtime {835 type Event = Event;836 type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;837 type XcmRouter = XcmRouter;838 type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;839 type XcmExecuteFilter = Everything;840 type XcmExecutor = XcmExecutor<XcmConfig>;841 type XcmTeleportFilter = Everything;842 type XcmReserveTransferFilter = Everything;843 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;844 type LocationInverter = LocationInverter<Ancestry>;845 type Origin = Origin;846 type Call = Call;847 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;848 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;849}850851impl cumulus_pallet_xcm::Config for Runtime {852 type Event = Event;853 type XcmExecutor = XcmExecutor<XcmConfig>;854}855856impl cumulus_pallet_xcmp_queue::Config for Runtime {857 type WeightInfo = ();858 type Event = Event;859 type XcmExecutor = XcmExecutor<XcmConfig>;860 type ChannelInfo = ParachainSystem;861 type VersionWrapper = ();862 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;863 type ControllerOrigin = EnsureRoot<AccountId>;864 type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;865}866867impl cumulus_pallet_dmp_queue::Config for Runtime {868 type Event = Event;869 type XcmExecutor = XcmExecutor<XcmConfig>;870 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;871}872873impl pallet_aura::Config for Runtime {874 type AuthorityId = AuraId;875 type DisabledValidators = ();876 type MaxAuthorities = MaxAuthorities;877}878879parameter_types! {880 pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();881 pub const CollectionCreationPrice: Balance = 2 * UNIQUE;882}883884impl pallet_common::Config for Runtime {885 type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;886 type Event = Event;887 type Currency = Balances;888 type CollectionCreationPrice = CollectionCreationPrice;889 type TreasuryAccountId = TreasuryAccountId;890 type CollectionDispatch = CollectionDispatchT<Self>;891892 type EvmTokenAddressMapping = EvmTokenAddressMapping;893 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;894 type ContractAddress = EvmCollectionHelpersAddress;895}896897impl pallet_structure::Config for Runtime {898 type Event = Event;899 type Call = Call;900 type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;901}902903impl pallet_fungible::Config for Runtime {904 type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;905}906impl pallet_refungible::Config for Runtime {907 type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;908}909impl pallet_nonfungible::Config for Runtime {910 type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;911}912913impl pallet_proxy_rmrk_core::Config for Runtime {914 type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;915 type Event = Event;916}917918impl pallet_proxy_rmrk_equip::Config for Runtime {919 type WeightInfo = pallet_proxy_rmrk_equip::weights::SubstrateWeight<Self>;920 type Event = Event;921}922923impl pallet_unique::Config for Runtime {924 type Event = Event;925 type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;926 type CommonWeightInfo = CommonWeights<Self>;927 type RefungibleExtensionsWeightInfo = CommonWeights<Self>;928}929930parameter_types! {931 pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied932}933934/// Used for the pallet inflation935impl pallet_inflation::Config for Runtime {936 type Currency = Balances;937 type TreasuryAccountId = TreasuryAccountId;938 type InflationBlockInterval = InflationBlockInterval;939 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;940}941942parameter_types! {943 pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *944 RuntimeBlockWeights::get().max_block;945 pub const MaxScheduledPerBlock: u32 = 50;946}947948type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;949use frame_support::traits::NamedReservableCurrency;950951fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {952 (953 frame_system::CheckSpecVersion::<Runtime>::new(),954 frame_system::CheckGenesis::<Runtime>::new(),955 frame_system::CheckEra::<Runtime>::from(Era::Immortal),956 frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(957 from,958 )),959 frame_system::CheckWeight::<Runtime>::new(),960 // sponsoring transaction logic961 // pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),962 )963}964965pub struct SchedulerPaymentExecutor;966impl<T: frame_system::Config + pallet_unique_scheduler::Config, SelfContainedSignedInfo>967 DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor968where969 <T as frame_system::Config>::Call: Member970 + Dispatchable<Origin = Origin, Info = DispatchInfo>971 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>972 + GetDispatchInfo973 + From<frame_system::Call<Runtime>>,974 SelfContainedSignedInfo: Send + Sync + 'static,975 Call: From<<T as frame_system::Config>::Call>976 + From<<T as pallet_unique_scheduler::Config>::Call>977 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,978 sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,979{980 fn dispatch_call(981 signer: <T as frame_system::Config>::AccountId,982 call: <T as pallet_unique_scheduler::Config>::Call,983 ) -> Result<984 Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,985 TransactionValidityError,986 > {987 let dispatch_info = call.get_dispatch_info();988 let extrinsic = fp_self_contained::CheckedExtrinsic::<989 AccountId,990 Call,991 SignedExtraScheduler,992 SelfContainedSignedInfo,993 > {994 signed:995 CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(996 signer.clone().into(),997 get_signed_extras(signer.into()),998 ),999 function: call.into(),1000 };10011002 extrinsic.apply::<Runtime>(&dispatch_info, 0)1003 }10041005 fn reserve_balance(1006 id: [u8; 16],1007 sponsor: <T as frame_system::Config>::AccountId,1008 call: <T as pallet_unique_scheduler::Config>::Call,1009 count: u32,1010 ) -> Result<(), DispatchError> {1011 let dispatch_info = call.get_dispatch_info();1012 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)1013 .saturating_mul(count.into());10141015 <Balances as NamedReservableCurrency<AccountId>>::reserve_named(1016 &id,1017 &(sponsor.into()),1018 weight,1019 )1020 }10211022 fn pay_for_call(1023 id: [u8; 16],1024 sponsor: <T as frame_system::Config>::AccountId,1025 call: <T as pallet_unique_scheduler::Config>::Call,1026 ) -> Result<u128, DispatchError> {1027 let dispatch_info = call.get_dispatch_info();1028 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);1029 Ok(1030 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1031 &id,1032 &(sponsor.into()),1033 weight,1034 ),1035 )1036 }10371038 fn cancel_reserve(1039 id: [u8; 16],1040 sponsor: <T as frame_system::Config>::AccountId,1041 ) -> Result<u128, DispatchError> {1042 Ok(1043 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1044 &id,1045 &(sponsor.into()),1046 u128::MAX,1047 ),1048 )1049 }1050}10511052parameter_types! {1053 pub const NoPreimagePostponement: Option<u32> = Some(10);1054 pub const Preimage: Option<u32> = Some(10);1055}10561057/// Used the compare the privilege of an origin inside the scheduler.1058pub struct OriginPrivilegeCmp;10591060impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {1061 fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {1062 Some(Ordering::Equal)1063 }1064}10651066impl pallet_unique_scheduler::Config for Runtime {1067 type Event = Event;1068 type Origin = Origin;1069 type Currency = Balances;1070 type PalletsOrigin = OriginCaller;1071 type Call = Call;1072 type MaximumWeight = MaximumSchedulerWeight;1073 type ScheduleOrigin = EnsureSigned<AccountId>;1074 type MaxScheduledPerBlock = MaxScheduledPerBlock;1075 type WeightInfo = ();1076 type CallExecutor = SchedulerPaymentExecutor;1077 type OriginPrivilegeCmp = OriginPrivilegeCmp;1078 type PreimageProvider = ();1079 type NoPreimagePostponement = NoPreimagePostponement;1080}10811082type EvmSponsorshipHandler = (1083 UniqueEthSponsorshipHandler<Runtime>,1084 pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,1085);10861087type SponsorshipHandler = (1088 UniqueSponsorshipHandler<Runtime>,1089 //pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,1090 pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,1091);10921093impl pallet_evm_transaction_payment::Config for Runtime {1094 type EvmSponsorshipHandler = EvmSponsorshipHandler;1095 type Currency = Balances;1096}10971098impl pallet_charge_transaction::Config for Runtime {1099 type SponsorshipHandler = SponsorshipHandler;1100}11011102// impl pallet_contract_helpers::Config for Runtime {1103// type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1104// }11051106parameter_types! {1107 // 0x842899ECF380553E8a4de75bF534cdf6fBF640491108 pub const HelpersContractAddress: H160 = H160([1109 0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,1110 ]);11111112 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f1113 pub const EvmCollectionHelpersAddress: H160 = H160([1114 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,1115 ]);1116}11171118impl pallet_evm_contract_helpers::Config for Runtime {1119 type ContractAddress = HelpersContractAddress;1120 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1121}1122601123construct_runtime!(61construct_runtime!(opal);1124 pub enum Runtime where1125 Block = Block,1126 NodeBlock = opaque::Block,1127 UncheckedExtrinsic = UncheckedExtrinsic1128 {1129 ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,1130 ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,11311132 Aura: pallet_aura::{Pallet, Config<T>} = 22,1133 AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,11341135 Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,1136 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,1137 Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,1138 TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,1139 Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,1140 Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,1141 System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,1142 Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,1143 // Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,1144 // Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,11451146 // XCM helpers.1147 XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,1148 PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,1149 CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,1150 DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,11511152 // Unique Pallets1153 Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,1154 Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,1155 Scheduler: pallet_unique_scheduler::{Pallet, Call, Storage, Event<T>} = 62,1156 // free = 631157 Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,1158 // ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,1159 Common: pallet_common::{Pallet, Storage, Event<T>} = 66,1160 Fungible: pallet_fungible::{Pallet, Storage} = 67,1161 Refungible: pallet_refungible::{Pallet, Storage} = 68,1162 Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,1163 Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,1164 RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,1165 RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,11661167 // Frontier1168 EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,1169 Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,11701171 EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,1172 EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,1173 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,1174 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,1175 }1176);11771178pub struct TransactionConverter;11791180impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {1181 fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {1182 UncheckedExtrinsic::new_unsigned(1183 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1184 )1185 }1186}11871188impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {1189 fn convert_transaction(1190 &self,1191 transaction: pallet_ethereum::Transaction,1192 ) -> opaque::UncheckedExtrinsic {1193 let extrinsic = UncheckedExtrinsic::new_unsigned(1194 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1195 );1196 let encoded = extrinsic.encode();1197 opaque::UncheckedExtrinsic::decode(&mut &encoded[..])1198 .expect("Encoded extrinsic is always valid")1199 }1200}12011202/// The address format for describing accounts.1203pub type Address = sp_runtime::MultiAddress<AccountId, ()>;1204/// Block header type as expected by this runtime.1205pub type Header = generic::Header<BlockNumber, BlakeTwo256>;1206/// Block type as expected by this runtime.1207pub type Block = generic::Block<Header, UncheckedExtrinsic>;1208/// A Block signed with a Justification1209pub type SignedBlock = generic::SignedBlock<Block>;1210/// BlockId type as expected by this runtime.1211pub type BlockId = generic::BlockId<Block>;1212/// The SignedExtension to the basic transaction logic.1213pub type SignedExtra = (1214 frame_system::CheckSpecVersion<Runtime>,1215 // system::CheckTxVersion<Runtime>,1216 frame_system::CheckGenesis<Runtime>,1217 frame_system::CheckEra<Runtime>,1218 frame_system::CheckNonce<Runtime>,1219 frame_system::CheckWeight<Runtime>,1220 ChargeTransactionPayment,1221 //pallet_contract_helpers::ContractHelpersExtension<Runtime>,1222 pallet_ethereum::FakeTransactionFinalizer<Runtime>,1223);1224pub type SignedExtraScheduler = (1225 frame_system::CheckSpecVersion<Runtime>,1226 frame_system::CheckGenesis<Runtime>,1227 frame_system::CheckEra<Runtime>,1228 frame_system::CheckNonce<Runtime>,1229 frame_system::CheckWeight<Runtime>,1230);1231/// Unchecked extrinsic type as expected by this runtime.1232pub type UncheckedExtrinsic =1233 fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;1234/// Extrinsic type that has already been checked.1235pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;1236/// Executive: handles dispatch to the various modules.1237pub type Executive = frame_executive::Executive<1238 Runtime,1239 Block,1240 frame_system::ChainContext<Runtime>,1241 Runtime,1242 AllPalletsReversedWithSystemFirst,1243>;12441245impl_opaque_keys! {1246 pub struct SessionKeys {1247 pub aura: Aura,1248 }1249}12501251impl fp_self_contained::SelfContainedCall for Call {1252 type SignedInfo = H160;12531254 fn is_self_contained(&self) -> bool {1255 match self {1256 Call::Ethereum(call) => call.is_self_contained(),1257 _ => false,1258 }1259 }12601261 fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {1262 match self {1263 Call::Ethereum(call) => call.check_self_contained(),1264 _ => None,1265 }1266 }12671268 fn validate_self_contained(1269 &self,1270 info: &Self::SignedInfo,1271 dispatch_info: &DispatchInfoOf<Call>,1272 len: usize,1273 ) -> Option<TransactionValidity> {1274 match self {1275 Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),1276 _ => None,1277 }1278 }12791280 fn pre_dispatch_self_contained(1281 &self,1282 info: &Self::SignedInfo,1283 ) -> Option<Result<(), TransactionValidityError>> {1284 match self {1285 Call::Ethereum(call) => call.pre_dispatch_self_contained(info),1286 _ => None,1287 }1288 }12891290 fn apply_self_contained(1291 self,1292 info: Self::SignedInfo,1293 ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {1294 match self {1295 call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(1296 Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),1297 )),1298 _ => None,1299 }1300 }1301}13021303macro_rules! dispatch_unique_runtime {1304 ($collection:ident.$method:ident($($name:ident),*)) => {{1305 let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);1306 let dispatch = collection.as_dyn();13071308 Ok::<_, DispatchError>(dispatch.$method($($name),*))1309 }};1310}1311621312impl_common_runtime_apis! {63impl_common_runtime_apis!();1313 #![custom_apis]13141315 impl rmrk_rpc::RmrkApi<1316 Block,1317 AccountId,1318 RmrkCollectionInfo<AccountId>,1319 RmrkInstanceInfo<AccountId>,1320 RmrkResourceInfo,1321 RmrkPropertyInfo,1322 RmrkBaseInfo<AccountId>,1323 RmrkPartType,1324 RmrkTheme1325 > for Runtime {1326 fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {1327 pallet_proxy_rmrk_core::rpc::last_collection_idx::<Runtime>()1328 }13291330 fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {1331 pallet_proxy_rmrk_core::rpc::collection_by_id::<Runtime>(collection_id)1332 }13331334 fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {1335 pallet_proxy_rmrk_core::rpc::nft_by_id::<Runtime>(collection_id, nft_by_id)1336 }13371338 fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {1339 pallet_proxy_rmrk_core::rpc::account_tokens::<Runtime>(account_id, collection_id)1340 }13411342 fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {1343 pallet_proxy_rmrk_core::rpc::nft_children::<Runtime>(collection_id, nft_id)1344 }13451346 fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {1347 pallet_proxy_rmrk_core::rpc::collection_properties::<Runtime>(collection_id, filter_keys)1348 }13491350 fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {1351 pallet_proxy_rmrk_core::rpc::nft_properties::<Runtime>(collection_id, nft_id, filter_keys)1352 }13531354 fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {1355 pallet_proxy_rmrk_core::rpc::nft_resources::<Runtime>(collection_id, nft_id)1356 }13571358 fn nft_resource_priority(collection_id: RmrkCollectionId, nft_id: RmrkNftId, resource_id: RmrkResourceId) -> Result<Option<u32>, DispatchError> {1359 pallet_proxy_rmrk_core::rpc::nft_resource_priority::<Runtime>(collection_id, nft_id, resource_id)1360 }13611362 fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {1363 pallet_proxy_rmrk_equip::rpc::base::<Runtime>(base_id)1364 }13651366 fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {1367 pallet_proxy_rmrk_equip::rpc::base_parts::<Runtime>(base_id)1368 }13691370 fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {1371 pallet_proxy_rmrk_equip::rpc::theme_names::<Runtime>(base_id)1372 }13731374 fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {1375 pallet_proxy_rmrk_equip::rpc::theme::<Runtime>(base_id, theme_name, filter_keys)1376 }1377 }1378}13791380struct CheckInherents;13811382impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {1383 fn check_inherents(1384 block: &Block,1385 relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,1386 ) -> sp_inherents::CheckInherentsResult {1387 let relay_chain_slot = relay_state_proof1388 .read_slot()1389 .expect("Could not read the relay chain slot from the proof");13901391 let inherent_data =1392 cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(1393 relay_chain_slot,1394 sp_std::time::Duration::from_secs(6),1395 )1396 .create_inherent_data()1397 .expect("Could not create the timestamp inherent data");13981399 inherent_data.check_extrinsics(block)1400 }1401}1402641403cumulus_pallet_parachain_system::register_validate_block!(65cumulus_pallet_parachain_system::register_validate_block!(1404 Runtime = Runtime,66 Runtime = Runtime,runtime/quartz/Cargo.tomldiffbeforeafterboth16targets = ['x86_64-unknown-linux-gnu']16targets = ['x86_64-unknown-linux-gnu']171718[features]18[features]19default = ['std']19default = ['std', 'quartz-runtime']20runtime-benchmarks = [20runtime-benchmarks = [21 'hex-literal',21 'hex-literal',22 'frame-benchmarking',22 'frame-benchmarking',113 'xcm/std',113 'xcm/std',114 'xcm-builder/std',114 'xcm-builder/std',115 'xcm-executor/std',115 'xcm-executor/std',116 'unique-runtime-common/std',116 'up-common/std',117117118 "orml-vesting/std",118 "orml-vesting/std",119]119]120limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']120limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']121quartz-runtime = []122123refungible = []124scheduler = []125rmrk = []121126122################################################################################127################################################################################123# Substrate Dependencies128# Substrate Dependencies403408404[dependencies]409[dependencies]405log = { version = "0.4.16", default-features = false }410log = { version = "0.4.16", default-features = false }406unique-runtime-common = { path = "../common", default-features = false }411up-common = { path = "../../primitives/common", default-features = false }407scale-info = { version = "2.0.1", default-features = false, features = [412scale-info = { version = "2.0.1", default-features = false, features = [408 "derive",413 "derive",409] }414] }432pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }437pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }433fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }438fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }434fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }439fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }440evm-coder = { default-features = false, path = '../../crates/evm-coder' }441up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.24' }435442436################################################################################443################################################################################437# Build Dependencies444# Build Dependenciesruntime/quartz/src/lib.rsdiffbeforeafterboth25#[cfg(feature = "std")]25#[cfg(feature = "std")]26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));272728use sp_api::impl_runtime_apis;28use frame_support::parameter_types;2929use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};30use sp_version::RuntimeVersion;30use sp_runtime::DispatchError;31use fp_self_contained::*;32// #[cfg(any(feature = "std", test))]33// pub use sp_runtime::BuildStorage;3435use sp_runtime::{31use sp_runtime::create_runtime_str;36 Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,37 traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, Member},38 transaction_validity::{TransactionSource, TransactionValidity},39 ApplyExtrinsicResult, RuntimeAppPublic,40};413242use sp_std::prelude::*;33use up_common::types::*;433444#[cfg(feature = "std")]35#[path = "../../common/mod.rs"]45use sp_version::NativeVersion;36mod runtime_common;46use sp_version::RuntimeVersion;3747pub use pallet_transaction_payment::{38pub use runtime_common::*;48 Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,49};50// A few exports that help ease life for downstream crates.51pub use pallet_balances::Call as BalancesCall;52pub use pallet_evm::{53 EnsureAddressTruncated, HashedAddressMapping, Runner, account::CrossAccountId as _,54 OnMethodCall, Account as EVMAccount, FeeCalculator, GasWeightMapping,55};56pub use frame_support::{57 construct_runtime, match_types,58 dispatch::DispatchResult,59 PalletId, parameter_types, StorageValue, ConsensusEngineId,60 traits::{61 tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,62 Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,63 OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, PrivilegeCmp,64 },65 weights::{66 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},67 DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,68 WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier,69 WeightToFee,70 },71};72use pallet_unique_scheduler::DispatchCall;73use up_data_structs::{74 CollectionId, TokenId, TokenData, Property, PropertyKeyPermission, CollectionLimits,75 CollectionStats, RpcCollection,76 mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},77 TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo,78 RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkCollectionId, RmrkNftId,79 RmrkNftChild, RmrkPropertyKey, RmrkResourceId, RmrkBaseId,80};8182// use pallet_contracts::weights::WeightInfo;83// #[cfg(any(feature = "std", test))]84use frame_system::{85 self as frame_system, EnsureRoot, EnsureSigned,86 limits::{BlockWeights, BlockLength},87};88use sp_arithmetic::{89 traits::{BaseArithmetic, Unsigned},90};91use smallvec::smallvec;92use codec::{Encode, Decode};93use fp_rpc::TransactionStatus;94use sp_runtime::{95 traits::{96 Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,97 Saturating, CheckedConversion,98 },99 generic::Era,100 transaction_validity::TransactionValidityError,101 DispatchErrorWithPostInfo, SaturatedConversion,102};103104// pub use pallet_timestamp::Call as TimestampCall;105pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;106107// Polkadot imports108use pallet_xcm::XcmPassthrough;109use polkadot_parachain::primitives::Sibling;110use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};111use xcm_builder::{112 AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,113 EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,114 RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,115 SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,116 ParentIsPreset,117};118use xcm_executor::{Config, XcmExecutor, Assets};119use sp_std::{cmp::Ordering, marker::PhantomData};120121use xcm::latest::{122 // Xcm,123 AssetId::{Concrete},124 Fungibility::Fungible as XcmFungible,125 MultiAsset,126 Error as XcmError,127};128use xcm_executor::traits::{MatchesFungible, WeightTrader};129130use unique_runtime_common::{131 impl_common_runtime_apis,132 types::*,133 constants::*,134 dispatch::{CollectionDispatchT, CollectionDispatch},135 sponsoring::UniqueSponsorshipHandler,136 eth_sponsoring::UniqueEthSponsorshipHandler,137 weights::CommonWeights,138};13939140pub const RUNTIME_NAME: &str = "quartz";40pub const RUNTIME_NAME: &str = "quartz";141pub const TOKEN_SYMBOL: &str = "QTZ";41pub const TOKEN_SYMBOL: &str = "QTZ";142143type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;144145impl RuntimeInstance for Runtime {146 type CrossAccountId = self::CrossAccountId;147148 type TransactionConverter = self::TransactionConverter;149150 fn get_transaction_converter() -> TransactionConverter {151 TransactionConverter152 }153}154155/// The type for looking up accounts. We don't expect more than 4 billion of them, but you156/// never know...157pub type AccountIndex = u32;158159/// Balance of an account.160pub type Balance = u128;161162/// Index of a transaction in the chain.163pub type Index = u32;164165/// A hash of some data used by the chain.166pub type Hash = sp_core::H256;167168/// Digest item type.169pub type DigestItem = generic::DigestItem;170171/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know172/// the specifics of the runtime. They can then be made to be agnostic over specific formats173/// of data like extrinsics, allowing for them to continue syncing the network through upgrades174/// to even the core data structures.175pub mod opaque {176 use sp_std::prelude::*;177 use sp_runtime::impl_opaque_keys;178 use super::Aura;179180 pub use unique_runtime_common::types::*;181182 impl_opaque_keys! {183 pub struct SessionKeys {184 pub aura: Aura,185 }186 }187}18842189/// This runtime version.43/// This runtime version.190pub const VERSION: RuntimeVersion = RuntimeVersion {44pub const VERSION: RuntimeVersion = RuntimeVersion {198 state_version: 0,52 state_version: 0,199};53};200201#[derive(codec::Encode, codec::Decode)]202pub enum XCMPMessage<XAccountId, XBalance> {203 /// Transfer tokens to the given account from the Parachain account.204 TransferToken(XAccountId, XBalance),205}206207/// The version information used to identify this runtime when compiled natively.208#[cfg(feature = "std")]209pub fn native_version() -> NativeVersion {210 NativeVersion {211 runtime_version: VERSION,212 can_author_with: Default::default(),213 }214}215216type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;217218pub struct DealWithFees;219impl OnUnbalanced<NegativeImbalance> for DealWithFees {220 fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {221 if let Some(fees) = fees_then_tips.next() {222 // for fees, 100% to treasury223 let mut split = fees.ration(100, 0);224 if let Some(tips) = fees_then_tips.next() {225 // for tips, if any, 100% to treasury226 tips.ration_merge_into(100, 0, &mut split);227 }228 Treasury::on_unbalanced(split.0);229 // Author::on_unbalanced(split.1);230 }231 }232}23354234parameter_types! {55parameter_types! {235 pub const BlockHashCount: BlockNumber = 2400;236 pub RuntimeBlockLength: BlockLength =237 BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);238 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);239 pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;240 pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()241 .base_block(BlockExecutionWeight::get())242 .for_class(DispatchClass::all(), |weights| {243 weights.base_extrinsic = ExtrinsicBaseWeight::get();244 })245 .for_class(DispatchClass::Normal, |weights| {246 weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);247 })248 .for_class(DispatchClass::Operational, |weights| {249 weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);250 // Operational transactions have some extra reserved space, so that they251 // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.252 weights.reserved = Some(253 MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT254 );255 })256 .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)257 .build_or_panic();258 pub const Version: RuntimeVersion = VERSION;56 pub const Version: RuntimeVersion = VERSION;259 pub const SS58Prefix: u8 = 255;57 pub const SS58Prefix: u8 = 255;260}261262parameter_types! {263 pub const ChainId: u64 = 8881;58 pub const ChainId: u64 = 8881;264}59}265266pub struct FixedFee;267impl FeeCalculator for FixedFee {268 fn min_gas_price() -> (U256, u64) {269 (MIN_GAS_PRICE.into(), 0)270 }271}272273// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case274// (contract, which only writes a lot of data),275// approximating on top of our real store write weight276parameter_types! {277 pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;278 pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;279 pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();280}281282/// Limiting EVM execution to 50% of block for substrate users and management tasks283/// EVM transaction consumes more weight than substrate's, so we can't rely on them being284/// scheduled fairly285const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);286parameter_types! {287 pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());288}289290pub enum FixedGasWeightMapping {}291impl GasWeightMapping for FixedGasWeightMapping {292 fn gas_to_weight(gas: u64) -> Weight {293 gas.saturating_mul(WeightPerGas::get())294 }295 fn weight_to_gas(weight: Weight) -> u64 {296 weight / WeightPerGas::get()297 }298}299300impl pallet_evm::account::Config for Runtime {301 type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;302 type EvmAddressMapping = HashedAddressMapping<Self::Hashing>;303 type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;304}305306impl pallet_evm::Config for Runtime {307 type BlockGasLimit = BlockGasLimit;308 type FeeCalculator = FixedFee;309 type GasWeightMapping = FixedGasWeightMapping;310 type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;311 type CallOrigin = EnsureAddressTruncated<Self>;312 type WithdrawOrigin = EnsureAddressTruncated<Self>;313 type AddressMapping = HashedAddressMapping<Self::Hashing>;314 type PrecompilesType = ();315 type PrecompilesValue = ();316 type Currency = Balances;317 type Event = Event;318 type OnMethodCall = (319 pallet_evm_migration::OnMethodCall<Self>,320 pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,321 CollectionDispatchT<Self>,322 pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,323 );324 type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;325 type ChainId = ChainId;326 type Runner = pallet_evm::runner::stack::Runner<Self>;327 type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;328 type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;329 type FindAuthor = EthereumFindAuthor<Aura>;330}331332impl pallet_evm_migration::Config for Runtime {333 type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;334}335336pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);337impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {338 fn find_author<'a, I>(digests: I) -> Option<H160>339 where340 I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,341 {342 if let Some(author_index) = F::find_author(digests) {343 let authority_id = Aura::authorities()[author_index as usize].clone();344 return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));345 }346 None347 }348}349350impl pallet_ethereum::Config for Runtime {351 type Event = Event;352 type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;353}354355impl pallet_randomness_collective_flip::Config for Runtime {}356357impl frame_system::Config for Runtime {358 /// The data to be stored in an account.359 type AccountData = pallet_balances::AccountData<Balance>;360 /// The identifier used to distinguish between accounts.361 type AccountId = AccountId;362 /// The basic call filter to use in dispatchable.363 type BaseCallFilter = Everything;364 /// Maximum number of block number to block hash mappings to keep (oldest pruned first).365 type BlockHashCount = BlockHashCount;366 /// The maximum length of a block (in bytes).367 type BlockLength = RuntimeBlockLength;368 /// The index type for blocks.369 type BlockNumber = BlockNumber;370 /// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.371 type BlockWeights = RuntimeBlockWeights;372 /// The aggregated dispatch type that is available for extrinsics.373 type Call = Call;374 /// The weight of database operations that the runtime can invoke.375 type DbWeight = RocksDbWeight;376 /// The ubiquitous event type.377 type Event = Event;378 /// The type for hashing blocks and tries.379 type Hash = Hash;380 /// The hashing algorithm used.381 type Hashing = BlakeTwo256;382 /// The header type.383 type Header = generic::Header<BlockNumber, BlakeTwo256>;384 /// The index type for storing how many extrinsics an account has signed.385 type Index = Index;386 /// The lookup mechanism to get account ID from whatever is passed in dispatchers.387 type Lookup = AccountIdLookup<AccountId, ()>;388 /// What to do if an account is fully reaped from the system.389 type OnKilledAccount = ();390 /// What to do if a new account is created.391 type OnNewAccount = ();392 type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;393 /// The ubiquitous origin type.394 type Origin = Origin;395 /// This type is being generated by `construct_runtime!`.396 type PalletInfo = PalletInfo;397 /// This is used as an identifier of the chain. 42 is the generic substrate prefix.398 type SS58Prefix = SS58Prefix;399 /// Weight information for the extrinsics of this pallet.400 type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;401 /// Version of the runtime.402 type Version = Version;403 type MaxConsumers = ConstU32<16>;404}405406parameter_types! {407 pub const MinimumPeriod: u64 = SLOT_DURATION / 2;408}409410impl pallet_timestamp::Config for Runtime {411 /// A timestamp: milliseconds since the unix epoch.412 type Moment = u64;413 type OnTimestampSet = ();414 type MinimumPeriod = MinimumPeriod;415 type WeightInfo = ();416}417418parameter_types! {419 // pub const ExistentialDeposit: u128 = 500;420 pub const ExistentialDeposit: u128 = 0;421 pub const MaxLocks: u32 = 50;422 pub const MaxReserves: u32 = 50;423}424425impl pallet_balances::Config for Runtime {426 type MaxLocks = MaxLocks;427 type MaxReserves = MaxReserves;428 type ReserveIdentifier = [u8; 16];429 /// The type for recording an account's balance.430 type Balance = Balance;431 /// The ubiquitous event type.432 type Event = Event;433 type DustRemoval = Treasury;434 type ExistentialDeposit = ExistentialDeposit;435 type AccountStore = System;436 type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;437}438439pub const fn deposit(items: u32, bytes: u32) -> Balance {440 items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE441}442443/*444parameter_types! {445 pub TombstoneDeposit: Balance = deposit(446 1,447 sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,448 );449 pub DepositPerContract: Balance = TombstoneDeposit::get();450 pub const DepositPerStorageByte: Balance = deposit(0, 1);451 pub const DepositPerStorageItem: Balance = deposit(1, 0);452 pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);453 pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;454 pub const SignedClaimHandicap: u32 = 2;455 pub const MaxDepth: u32 = 32;456 pub const MaxValueSize: u32 = 16 * 1024;457 pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb458 // The lazy deletion runs inside on_initialize.459 pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *460 RuntimeBlockWeights::get().max_block;461 // The weight needed for decoding the queue should be less or equal than a fifth462 // of the overall weight dedicated to the lazy deletion.463 pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (464 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -465 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)466 )) / 5) as u32;467 pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();468}469470impl pallet_contracts::Config for Runtime {471 type Time = Timestamp;472 type Randomness = RandomnessCollectiveFlip;473 type Currency = Balances;474 type Event = Event;475 type RentPayment = ();476 type SignedClaimHandicap = SignedClaimHandicap;477 type TombstoneDeposit = TombstoneDeposit;478 type DepositPerContract = DepositPerContract;479 type DepositPerStorageByte = DepositPerStorageByte;480 type DepositPerStorageItem = DepositPerStorageItem;481 type RentFraction = RentFraction;482 type SurchargeReward = SurchargeReward;483 type WeightPrice = pallet_transaction_payment::Pallet<Self>;484 type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;485 type ChainExtension = NFTExtension;486 type DeletionQueueDepth = DeletionQueueDepth;487 type DeletionWeightLimit = DeletionWeightLimit;488 type Schedule = Schedule;489 type CallStack = [pallet_contracts::Frame<Self>; 31];490}491*/492493parameter_types! {494 /// This value increases the priority of `Operational` transactions by adding495 /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.496 pub const OperationalFeeMultiplier: u8 = 5;497}498499/// Linear implementor of `WeightToFeePolynomial`500pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);501502impl<T> WeightToFeePolynomial for LinearFee<T>503where504 T: BaseArithmetic + From<u32> + Copy + Unsigned,505{506 type Balance = T;507508 fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {509 smallvec!(WeightToFeeCoefficient {510 coeff_integer: WEIGHT_TO_FEE_COEFF.into(),511 coeff_frac: Perbill::zero(),512 negative: false,513 degree: 1,514 })515 }516}517518impl pallet_transaction_payment::Config for Runtime {519 type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;520 type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;521 type OperationalFeeMultiplier = OperationalFeeMultiplier;522 type WeightToFee = LinearFee<Balance>;523 type FeeMultiplierUpdate = ();524}525526parameter_types! {527 pub const ProposalBond: Permill = Permill::from_percent(5);528 pub const ProposalBondMinimum: Balance = 1 * UNIQUE;529 pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;530 pub const SpendPeriod: BlockNumber = 5 * MINUTES;531 pub const Burn: Permill = Permill::from_percent(0);532 pub const TipCountdown: BlockNumber = 1 * DAYS;533 pub const TipFindersFee: Percent = Percent::from_percent(20);534 pub const TipReportDepositBase: Balance = 1 * UNIQUE;535 pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;536 pub const BountyDepositBase: Balance = 1 * UNIQUE;537 pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;538 pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");539 pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;540 pub const MaximumReasonLength: u32 = 16384;541 pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);542 pub const BountyValueMinimum: Balance = 5 * UNIQUE;543 pub const MaxApprovals: u32 = 100;544}545546impl pallet_treasury::Config for Runtime {547 type PalletId = TreasuryModuleId;548 type Currency = Balances;549 type ApproveOrigin = EnsureRoot<AccountId>;550 type RejectOrigin = EnsureRoot<AccountId>;551 type Event = Event;552 type OnSlash = ();553 type ProposalBond = ProposalBond;554 type ProposalBondMinimum = ProposalBondMinimum;555 type ProposalBondMaximum = ProposalBondMaximum;556 type SpendPeriod = SpendPeriod;557 type Burn = Burn;558 type BurnDestination = ();559 type SpendFunds = ();560 type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;561 type MaxApprovals = MaxApprovals;562}563564impl pallet_sudo::Config for Runtime {565 type Event = Event;566 type Call = Call;567}568569pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);570571impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider572 for RelayChainBlockNumberProvider<T>573{574 type BlockNumber = BlockNumber;575576 fn current_block_number() -> Self::BlockNumber {577 cumulus_pallet_parachain_system::Pallet::<T>::validation_data()578 .map(|d| d.relay_parent_number)579 .unwrap_or_default()580 }581}582583parameter_types! {584 pub const MinVestedTransfer: Balance = 10 * UNIQUE;585 pub const MaxVestingSchedules: u32 = 28;586}587588impl orml_vesting::Config for Runtime {589 type Event = Event;590 type Currency = pallet_balances::Pallet<Runtime>;591 type MinVestedTransfer = MinVestedTransfer;592 type VestedTransferOrigin = EnsureSigned<AccountId>;593 type WeightInfo = ();594 type MaxVestingSchedules = MaxVestingSchedules;595 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;596}597598parameter_types! {599 pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;600 pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;601}602603impl cumulus_pallet_parachain_system::Config for Runtime {604 type Event = Event;605 type SelfParaId = parachain_info::Pallet<Self>;606 type OnSystemEvent = ();607 // type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<608 // MaxDownwardMessageWeight,609 // XcmExecutor<XcmConfig>,610 // Call,611 // >;612 type OutboundXcmpMessageSource = XcmpQueue;613 type DmpMessageHandler = DmpQueue;614 type ReservedDmpWeight = ReservedDmpWeight;615 type ReservedXcmpWeight = ReservedXcmpWeight;616 type XcmpMessageHandler = XcmpQueue;617}618619impl parachain_info::Config for Runtime {}620621impl cumulus_pallet_aura_ext::Config for Runtime {}622623parameter_types! {624 pub const RelayLocation: MultiLocation = MultiLocation::parent();625 pub const RelayNetwork: NetworkId = NetworkId::Polkadot;626 pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();627 pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();628}629630/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used631/// when determining ownership of accounts for asset transacting and when attempting to use XCM632/// `Transact` in order to determine the dispatch Origin.633pub type LocationToAccountId = (634 // The parent (Relay-chain) origin converts to the default `AccountId`.635 ParentIsPreset<AccountId>,636 // Sibling parachain origins convert to AccountId via the `ParaId::into`.637 SiblingParachainConvertsVia<Sibling, AccountId>,638 // Straight up local `AccountId32` origins just alias directly to `AccountId`.639 AccountId32Aliases<RelayNetwork, AccountId>,640);641642pub struct OnlySelfCurrency;643impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {644 fn matches_fungible(a: &MultiAsset) -> Option<B> {645 match (&a.id, &a.fun) {646 (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),647 _ => None,648 }649 }650}651652/// Means for transacting assets on this chain.653pub type LocalAssetTransactor = CurrencyAdapter<654 // Use this currency:655 Balances,656 // Use this currency when it is a fungible asset matching the given location or name:657 OnlySelfCurrency,658 // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:659 LocationToAccountId,660 // Our chain's account ID type (we can't get away without mentioning it explicitly):661 AccountId,662 // We don't track any teleports.663 (),664>;665666/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,667/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can668/// biases the kind of local `Origin` it will become.669pub type XcmOriginToTransactDispatchOrigin = (670 // Sovereign account converter; this attempts to derive an `AccountId` from the origin location671 // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for672 // foreign chains who want to have a local sovereign account on this chain which they control.673 SovereignSignedViaLocation<LocationToAccountId, Origin>,674 // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when675 // recognised.676 RelayChainAsNative<RelayOrigin, Origin>,677 // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when678 // recognised.679 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,680 // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a681 // transaction from the Root origin.682 ParentAsSuperuser<Origin>,683 // Native signed account converter; this just converts an `AccountId32` origin into a normal684 // `Origin::Signed` origin of the same 32-byte value.685 SignedAccountId32AsNative<RelayNetwork, Origin>,686 // Xcm origins can be represented natively under the Xcm pallet's Xcm origin.687 XcmPassthrough<Origin>,688);689690parameter_types! {691 // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.692 pub UnitWeightCost: Weight = 1_000_000;693 // 1200 UNIQUEs buy 1 second of weight.694 pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);695 pub const MaxInstructions: u32 = 100;696 pub const MaxAuthorities: u32 = 100_000;697}698699match_types! {700 pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {701 MultiLocation { parents: 1, interior: Here } |702 MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }703 };704}705706pub type Barrier = (707 TakeWeightCredit,708 AllowTopLevelPaidExecutionFrom<Everything>,709 // ^^^ Parent & its unit plurality gets free execution710);711712pub struct UsingOnlySelfCurrencyComponents<713 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,714 AssetId: Get<MultiLocation>,715 AccountId,716 Currency: CurrencyT<AccountId>,717 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,718>(719 Weight,720 Currency::Balance,721 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,722);723impl<724 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,725 AssetId: Get<MultiLocation>,726 AccountId,727 Currency: CurrencyT<AccountId>,728 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,729 > WeightTrader730 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>731{732 fn new() -> Self {733 Self(0, Zero::zero(), PhantomData)734 }735736 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {737 let amount = WeightToFee::weight_to_fee(&weight);738 let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;739740 // location to this parachain through relay chain741 let option1: xcm::v1::AssetId = Concrete(MultiLocation {742 parents: 1,743 interior: X1(Parachain(ParachainInfo::parachain_id().into())),744 });745 // direct location746 let option2: xcm::v1::AssetId = Concrete(MultiLocation {747 parents: 0,748 interior: Here,749 });750751 let required = if payment.fungible.contains_key(&option1) {752 (option1, u128_amount).into()753 } else if payment.fungible.contains_key(&option2) {754 (option2, u128_amount).into()755 } else {756 (Concrete(MultiLocation::default()), u128_amount).into()757 };758759 let unused = payment760 .checked_sub(required)761 .map_err(|_| XcmError::TooExpensive)?;762 self.0 = self.0.saturating_add(weight);763 self.1 = self.1.saturating_add(amount);764 Ok(unused)765 }766767 fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {768 let weight = weight.min(self.0);769 let amount = WeightToFee::weight_to_fee(&weight);770 self.0 -= weight;771 self.1 = self.1.saturating_sub(amount);772 let amount: u128 = amount.saturated_into();773 if amount > 0 {774 Some((AssetId::get(), amount).into())775 } else {776 None777 }778 }779}780impl<781 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,782 AssetId: Get<MultiLocation>,783 AccountId,784 Currency: CurrencyT<AccountId>,785 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,786 > Drop787 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>788{789 fn drop(&mut self) {790 OnUnbalanced::on_unbalanced(Currency::issue(self.1));791 }792}793794pub struct XcmConfig;795impl Config for XcmConfig {796 type Call = Call;797 type XcmSender = XcmRouter;798 // How to withdraw and deposit an asset.799 type AssetTransactor = LocalAssetTransactor;800 type OriginConverter = XcmOriginToTransactDispatchOrigin;801 type IsReserve = NativeAsset;802 type IsTeleporter = (); // Teleportation is disabled803 type LocationInverter = LocationInverter<Ancestry>;804 type Barrier = Barrier;805 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;806 type Trader =807 UsingOnlySelfCurrencyComponents<LinearFee<Balance>, RelayLocation, AccountId, Balances, ()>;808 type ResponseHandler = (); // Don't handle responses for now.809 type SubscriptionService = PolkadotXcm;810811 type AssetTrap = PolkadotXcm;812 type AssetClaims = PolkadotXcm;813}814815// parameter_types! {816// pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;817// }818819/// No local origins on this chain are allowed to dispatch XCM sends/executions.820pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);821822/// The means for routing XCM messages which are not for local execution into the right message823/// queues.824pub type XcmRouter = (825 // Two routers - use UMP to communicate with the relay chain:826 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,827 // ..and XCMP to communicate with the sibling chains.828 XcmpQueue,829);830831impl pallet_evm_coder_substrate::Config for Runtime {}832833impl pallet_xcm::Config for Runtime {834 type Event = Event;835 type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;836 type XcmRouter = XcmRouter;837 type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;838 type XcmExecuteFilter = Everything;839 type XcmExecutor = XcmExecutor<XcmConfig>;840 type XcmTeleportFilter = Everything;841 type XcmReserveTransferFilter = Everything;842 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;843 type LocationInverter = LocationInverter<Ancestry>;844 type Origin = Origin;845 type Call = Call;846 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;847 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;848}849850impl cumulus_pallet_xcm::Config for Runtime {851 type Event = Event;852 type XcmExecutor = XcmExecutor<XcmConfig>;853}854855impl cumulus_pallet_xcmp_queue::Config for Runtime {856 type WeightInfo = ();857 type Event = Event;858 type XcmExecutor = XcmExecutor<XcmConfig>;859 type ChannelInfo = ParachainSystem;860 type VersionWrapper = ();861 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;862 type ControllerOrigin = EnsureRoot<AccountId>;863 type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;864}865866impl cumulus_pallet_dmp_queue::Config for Runtime {867 type Event = Event;868 type XcmExecutor = XcmExecutor<XcmConfig>;869 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;870}871872impl pallet_aura::Config for Runtime {873 type AuthorityId = AuraId;874 type DisabledValidators = ();875 type MaxAuthorities = MaxAuthorities;876}877878parameter_types! {879 pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();880 pub const CollectionCreationPrice: Balance = 2 * UNIQUE;881}882883impl pallet_common::Config for Runtime {884 type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;885 type Event = Event;886 type Currency = Balances;887 type CollectionCreationPrice = CollectionCreationPrice;888 type TreasuryAccountId = TreasuryAccountId;889 type CollectionDispatch = CollectionDispatchT<Self>;890891 type EvmTokenAddressMapping = EvmTokenAddressMapping;892 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;893 type ContractAddress = EvmCollectionHelpersAddress;894}895896impl pallet_structure::Config for Runtime {897 type Event = Event;898 type Call = Call;899 type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;900}901902impl pallet_fungible::Config for Runtime {903 type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;904}905impl pallet_refungible::Config for Runtime {906 type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;907}908impl pallet_nonfungible::Config for Runtime {909 type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;910}911912impl pallet_proxy_rmrk_core::Config for Runtime {913 type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;914 type Event = Event;915}916917impl pallet_proxy_rmrk_equip::Config for Runtime {918 type WeightInfo = pallet_proxy_rmrk_equip::weights::SubstrateWeight<Self>;919 type Event = Event;920}921922impl pallet_unique::Config for Runtime {923 type Event = Event;924 type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;925 type CommonWeightInfo = CommonWeights<Self>;926 type RefungibleExtensionsWeightInfo = CommonWeights<Self>;927}928929parameter_types! {930 pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied931}932933/// Used for the pallet inflation934impl pallet_inflation::Config for Runtime {935 type Currency = Balances;936 type TreasuryAccountId = TreasuryAccountId;937 type InflationBlockInterval = InflationBlockInterval;938 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;939}940941parameter_types! {942 pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *943 RuntimeBlockWeights::get().max_block;944 pub const MaxScheduledPerBlock: u32 = 50;945}946947type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;948use frame_support::traits::NamedReservableCurrency;949950fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {951 (952 frame_system::CheckSpecVersion::<Runtime>::new(),953 frame_system::CheckGenesis::<Runtime>::new(),954 frame_system::CheckEra::<Runtime>::from(Era::Immortal),955 frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(956 from,957 )),958 frame_system::CheckWeight::<Runtime>::new(),959 // sponsoring transaction logic960 // pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),961 )962}963964pub struct SchedulerPaymentExecutor;965impl<T: frame_system::Config + pallet_unique_scheduler::Config, SelfContainedSignedInfo>966 DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor967where968 <T as frame_system::Config>::Call: Member969 + Dispatchable<Origin = Origin, Info = DispatchInfo>970 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>971 + GetDispatchInfo972 + From<frame_system::Call<Runtime>>,973 SelfContainedSignedInfo: Send + Sync + 'static,974 Call: From<<T as frame_system::Config>::Call>975 + From<<T as pallet_unique_scheduler::Config>::Call>976 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,977 sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,978{979 fn dispatch_call(980 signer: <T as frame_system::Config>::AccountId,981 call: <T as pallet_unique_scheduler::Config>::Call,982 ) -> Result<983 Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,984 TransactionValidityError,985 > {986 let dispatch_info = call.get_dispatch_info();987 let extrinsic = fp_self_contained::CheckedExtrinsic::<988 AccountId,989 Call,990 SignedExtraScheduler,991 SelfContainedSignedInfo,992 > {993 signed:994 CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(995 signer.clone().into(),996 get_signed_extras(signer.into()),997 ),998 function: call.into(),999 };10001001 extrinsic.apply::<Runtime>(&dispatch_info, 0)1002 }10031004 fn reserve_balance(1005 id: [u8; 16],1006 sponsor: <T as frame_system::Config>::AccountId,1007 call: <T as pallet_unique_scheduler::Config>::Call,1008 count: u32,1009 ) -> Result<(), DispatchError> {1010 let dispatch_info = call.get_dispatch_info();1011 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)1012 .saturating_mul(count.into());10131014 <Balances as NamedReservableCurrency<AccountId>>::reserve_named(1015 &id,1016 &(sponsor.into()),1017 weight.into(),1018 )1019 }10201021 fn pay_for_call(1022 id: [u8; 16],1023 sponsor: <T as frame_system::Config>::AccountId,1024 call: <T as pallet_unique_scheduler::Config>::Call,1025 ) -> Result<u128, DispatchError> {1026 let dispatch_info = call.get_dispatch_info();1027 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);1028 Ok(1029 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1030 &id,1031 &(sponsor.into()),1032 weight.into(),1033 ),1034 )1035 }10361037 fn cancel_reserve(1038 id: [u8; 16],1039 sponsor: <T as frame_system::Config>::AccountId,1040 ) -> Result<u128, DispatchError> {1041 Ok(1042 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1043 &id,1044 &(sponsor.into()),1045 u128::MAX,1046 ),1047 )1048 }1049}10501051parameter_types! {1052 pub const NoPreimagePostponement: Option<u32> = Some(10);1053 pub const Preimage: Option<u32> = Some(10);1054}10551056/// Used the compare the privilege of an origin inside the scheduler.1057pub struct OriginPrivilegeCmp;10581059impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {1060 fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {1061 Some(Ordering::Equal)1062 }1063}10641065impl pallet_unique_scheduler::Config for Runtime {1066 type Event = Event;1067 type Origin = Origin;1068 type Currency = Balances;1069 type PalletsOrigin = OriginCaller;1070 type Call = Call;1071 type MaximumWeight = MaximumSchedulerWeight;1072 type ScheduleOrigin = EnsureSigned<AccountId>;1073 type MaxScheduledPerBlock = MaxScheduledPerBlock;1074 type WeightInfo = ();1075 type CallExecutor = SchedulerPaymentExecutor;1076 type OriginPrivilegeCmp = OriginPrivilegeCmp;1077 type PreimageProvider = ();1078 type NoPreimagePostponement = NoPreimagePostponement;1079}10801081type EvmSponsorshipHandler = (1082 UniqueEthSponsorshipHandler<Runtime>,1083 pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,1084);1085type SponsorshipHandler = (1086 UniqueSponsorshipHandler<Runtime>,1087 //pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,1088 pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,1089);10901091impl pallet_evm_transaction_payment::Config for Runtime {1092 type EvmSponsorshipHandler = EvmSponsorshipHandler;1093 type Currency = Balances;1094}10951096impl pallet_charge_transaction::Config for Runtime {1097 type SponsorshipHandler = SponsorshipHandler;1098}10991100// impl pallet_contract_helpers::Config for Runtime {1101// type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1102// }11031104parameter_types! {1105 // 0x842899ECF380553E8a4de75bF534cdf6fBF640491106 pub const HelpersContractAddress: H160 = H160([1107 0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,1108 ]);11091110 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f1111 pub const EvmCollectionHelpersAddress: H160 = H160([1112 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,1113 ]);1114}11151116impl pallet_evm_contract_helpers::Config for Runtime {1117 type ContractAddress = HelpersContractAddress;1118 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1119}1120601121construct_runtime!(61construct_runtime!(quartz);1122 pub enum Runtime where1123 Block = Block,1124 NodeBlock = opaque::Block,1125 UncheckedExtrinsic = UncheckedExtrinsic1126 {1127 ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,1128 ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,11291130 Aura: pallet_aura::{Pallet, Config<T>} = 22,1131 AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,11321133 Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,1134 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,1135 Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,1136 TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,1137 Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,1138 Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,1139 System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,1140 Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,1141 // Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,1142 // Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,11431144 // XCM helpers.1145 XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,1146 PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,1147 CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,1148 DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,11491150 // Unique Pallets1151 Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,1152 Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,1153 Scheduler: pallet_unique_scheduler::{Pallet, Call, Storage, Event<T>} = 62,1154 // free = 631155 Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,1156 // ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,1157 Common: pallet_common::{Pallet, Storage, Event<T>} = 66,1158 Fungible: pallet_fungible::{Pallet, Storage} = 67,1159 Refungible: pallet_refungible::{Pallet, Storage} = 68,1160 Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,1161 Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,1162 RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,1163 RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,11641165 // Frontier1166 EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,1167 Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,11681169 EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,1170 EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,1171 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,1172 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,1173 }1174);11751176pub struct TransactionConverter;11771178impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {1179 fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {1180 UncheckedExtrinsic::new_unsigned(1181 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1182 )1183 }1184}11851186impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {1187 fn convert_transaction(1188 &self,1189 transaction: pallet_ethereum::Transaction,1190 ) -> opaque::UncheckedExtrinsic {1191 let extrinsic = UncheckedExtrinsic::new_unsigned(1192 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1193 );1194 let encoded = extrinsic.encode();1195 opaque::UncheckedExtrinsic::decode(&mut &encoded[..])1196 .expect("Encoded extrinsic is always valid")1197 }1198}11991200/// The address format for describing accounts.1201pub type Address = sp_runtime::MultiAddress<AccountId, ()>;1202/// Block header type as expected by this runtime.1203pub type Header = generic::Header<BlockNumber, BlakeTwo256>;1204/// Block type as expected by this runtime.1205pub type Block = generic::Block<Header, UncheckedExtrinsic>;1206/// A Block signed with a Justification1207pub type SignedBlock = generic::SignedBlock<Block>;1208/// BlockId type as expected by this runtime.1209pub type BlockId = generic::BlockId<Block>;1210/// The SignedExtension to the basic transaction logic.1211pub type SignedExtra = (1212 frame_system::CheckSpecVersion<Runtime>,1213 // system::CheckTxVersion<Runtime>,1214 frame_system::CheckGenesis<Runtime>,1215 frame_system::CheckEra<Runtime>,1216 frame_system::CheckNonce<Runtime>,1217 frame_system::CheckWeight<Runtime>,1218 ChargeTransactionPayment,1219 //pallet_contract_helpers::ContractHelpersExtension<Runtime>,1220 pallet_ethereum::FakeTransactionFinalizer<Runtime>,1221);12221223pub type SignedExtraScheduler = (1224 frame_system::CheckSpecVersion<Runtime>,1225 frame_system::CheckGenesis<Runtime>,1226 frame_system::CheckEra<Runtime>,1227 frame_system::CheckNonce<Runtime>,1228 frame_system::CheckWeight<Runtime>,1229 // pallet_charge_transaction::ChargeTransactionPayment<Runtime>,1230);1231/// Unchecked extrinsic type as expected by this runtime.1232pub type UncheckedExtrinsic =1233 fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;1234/// Extrinsic type that has already been checked.1235pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;1236/// Executive: handles dispatch to the various modules.1237pub type Executive = frame_executive::Executive<1238 Runtime,1239 Block,1240 frame_system::ChainContext<Runtime>,1241 Runtime,1242 AllPalletsReversedWithSystemFirst,1243>;12441245impl_opaque_keys! {1246 pub struct SessionKeys {1247 pub aura: Aura,1248 }1249}12501251impl fp_self_contained::SelfContainedCall for Call {1252 type SignedInfo = H160;12531254 fn is_self_contained(&self) -> bool {1255 match self {1256 Call::Ethereum(call) => call.is_self_contained(),1257 _ => false,1258 }1259 }12601261 fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {1262 match self {1263 Call::Ethereum(call) => call.check_self_contained(),1264 _ => None,1265 }1266 }12671268 fn validate_self_contained(1269 &self,1270 info: &Self::SignedInfo,1271 dispatch_info: &DispatchInfoOf<Call>,1272 len: usize,1273 ) -> Option<TransactionValidity> {1274 match self {1275 Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),1276 _ => None,1277 }1278 }12791280 fn pre_dispatch_self_contained(1281 &self,1282 info: &Self::SignedInfo,1283 ) -> Option<Result<(), TransactionValidityError>> {1284 match self {1285 Call::Ethereum(call) => call.pre_dispatch_self_contained(info),1286 _ => None,1287 }1288 }12891290 fn apply_self_contained(1291 self,1292 info: Self::SignedInfo,1293 ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {1294 match self {1295 call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(1296 Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),1297 )),1298 _ => None,1299 }1300 }1301}13021303macro_rules! dispatch_unique_runtime {1304 ($collection:ident.$method:ident($($name:ident),*)) => {{1305 let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);1306 let dispatch = collection.as_dyn();13071308 Ok::<_, DispatchError>(dispatch.$method($($name),*))1309 }};1310}1311621312impl_common_runtime_apis! {63impl_common_runtime_apis!();1313 #![custom_apis]13141315 impl rmrk_rpc::RmrkApi<1316 Block,1317 AccountId,1318 RmrkCollectionInfo<AccountId>,1319 RmrkInstanceInfo<AccountId>,1320 RmrkResourceInfo,1321 RmrkPropertyInfo,1322 RmrkBaseInfo<AccountId>,1323 RmrkPartType,1324 RmrkTheme1325 > for Runtime {1326 fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {1327 pallet_proxy_rmrk_core::rpc::last_collection_idx::<Runtime>()1328 }13291330 fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {1331 pallet_proxy_rmrk_core::rpc::collection_by_id::<Runtime>(collection_id)1332 }13331334 fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {1335 pallet_proxy_rmrk_core::rpc::nft_by_id::<Runtime>(collection_id, nft_by_id)1336 }13371338 fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {1339 pallet_proxy_rmrk_core::rpc::account_tokens::<Runtime>(account_id, collection_id)1340 }13411342 fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {1343 pallet_proxy_rmrk_core::rpc::nft_children::<Runtime>(collection_id, nft_id)1344 }13451346 fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {1347 pallet_proxy_rmrk_core::rpc::collection_properties::<Runtime>(collection_id, filter_keys)1348 }13491350 fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {1351 pallet_proxy_rmrk_core::rpc::nft_properties::<Runtime>(collection_id, nft_id, filter_keys)1352 }13531354 fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {1355 pallet_proxy_rmrk_core::rpc::nft_resources::<Runtime>(collection_id, nft_id)1356 }13571358 fn nft_resource_priority(collection_id: RmrkCollectionId, nft_id: RmrkNftId, resource_id: RmrkResourceId) -> Result<Option<u32>, DispatchError> {1359 pallet_proxy_rmrk_core::rpc::nft_resource_priority::<Runtime>(collection_id, nft_id, resource_id)1360 }13611362 fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {1363 pallet_proxy_rmrk_equip::rpc::base::<Runtime>(base_id)1364 }13651366 fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {1367 pallet_proxy_rmrk_equip::rpc::base_parts::<Runtime>(base_id)1368 }13691370 fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {1371 pallet_proxy_rmrk_equip::rpc::theme_names::<Runtime>(base_id)1372 }13731374 fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {1375 pallet_proxy_rmrk_equip::rpc::theme::<Runtime>(base_id, theme_name, filter_keys)1376 }1377 }1378}13791380struct CheckInherents;13811382impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {1383 fn check_inherents(1384 block: &Block,1385 relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,1386 ) -> sp_inherents::CheckInherentsResult {1387 let relay_chain_slot = relay_state_proof1388 .read_slot()1389 .expect("Could not read the relay chain slot from the proof");13901391 let inherent_data =1392 cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(1393 relay_chain_slot,1394 sp_std::time::Duration::from_secs(6),1395 )1396 .create_inherent_data()1397 .expect("Could not create the timestamp inherent data");13981399 inherent_data.check_extrinsics(block)1400 }1401}1402641403cumulus_pallet_parachain_system::register_validate_block!(65cumulus_pallet_parachain_system::register_validate_block!(1404 Runtime = Runtime,66 Runtime = Runtime,runtime/tests/Cargo.tomldiffbeforeafterboth3version = "0.1.0"3version = "0.1.0"4edition = "2021"4edition = "2021"56[features]7default = ['refungible']89refungible = []5106[dependencies]11[dependencies]7unique-runtime-common = { path = '../common' }8up-data-structs = { default-features = false, path = '../../primitives/data-structs' }12up-data-structs = { default-features = false, path = '../../primitives/data-structs' }91310sp-core = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.24' }14sp-core = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.24' }38] }42] }39scale-info = "*"43scale-info = "*"4445evm-coder = { default-features = false, path = '../../crates/evm-coder' }46up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.24' }4047runtime/tests/src/lib.rsdiffbeforeafterboth35use parity_scale_codec::{Encode, Decode, MaxEncodedLen};35use parity_scale_codec::{Encode, Decode, MaxEncodedLen};36use scale_info::TypeInfo;36use scale_info::TypeInfo;373738use unique_runtime_common::{dispatch::CollectionDispatchT, weights::CommonWeights};39use up_data_structs::mapping::{CrossTokenAddressMapping, EvmTokenAddressMapping};38use up_data_structs::mapping::{CrossTokenAddressMapping, EvmTokenAddressMapping};3940#[path = "../../common/dispatch.rs"]41mod dispatch;4243use dispatch::CollectionDispatchT;4445#[path = "../../common/weights.rs"]46mod weights;4748use weights::CommonWeights;404941type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;50type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;42type Block = frame_system::mocking::MockBlock<Test>;51type Block = frame_system::mocking::MockBlock<Test>;runtime/unique/Cargo.tomldiffbeforeafterboth114 'xcm/std',114 'xcm/std',115 'xcm-builder/std',115 'xcm-builder/std',116 'xcm-executor/std',116 'xcm-executor/std',117 'unique-runtime-common/std',117 'up-common/std',118118119 "orml-vesting/std",119 "orml-vesting/std",120]120]121limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']121limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']122unique-runtime = []122unique-runtime = []123124refungible = []125scheduler = []126rmrk = []123127124################################################################################128################################################################################125# Substrate Dependencies129# Substrate Dependencies397401398[dependencies]402[dependencies]399log = { version = "0.4.16", default-features = false }403log = { version = "0.4.16", default-features = false }400unique-runtime-common = { path = "../common", default-features = false }404up-common = { path = "../../primitives/common", default-features = false }401scale-info = { version = "2.0.1", default-features = false, features = [405scale-info = { version = "2.0.1", default-features = false, features = [402 "derive",406 "derive",403] }407] }427fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }431fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }428fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }432fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }429fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }433fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }434evm-coder = { default-features = false, path = '../../crates/evm-coder' }435up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.24' }430436431################################################################################437################################################################################432# Build Dependencies438# Build Dependenciesruntime/unique/src/lib.rsdiffbeforeafterboth25#[cfg(feature = "std")]25#[cfg(feature = "std")]26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));272728use sp_api::impl_runtime_apis;28use frame_support::parameter_types;2929use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};30use sp_version::RuntimeVersion;30use sp_runtime::DispatchError;31use fp_self_contained::*;32// #[cfg(any(feature = "std", test))]33// pub use sp_runtime::BuildStorage;3435use sp_runtime::{31use sp_runtime::create_runtime_str;36 Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,37 traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, Member},38 transaction_validity::{TransactionSource, TransactionValidity},39 ApplyExtrinsicResult, RuntimeAppPublic,40};413242use sp_std::prelude::*;33use up_common::types::*;433444#[cfg(feature = "std")]35#[path = "../../common/mod.rs"]45use sp_version::NativeVersion;36mod runtime_common;46use sp_version::RuntimeVersion;3747pub use pallet_transaction_payment::{38pub use runtime_common::*;48 Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,49};50// A few exports that help ease life for downstream crates.51pub use pallet_balances::Call as BalancesCall;52pub use pallet_evm::{53 EnsureAddressTruncated, HashedAddressMapping, Runner, account::CrossAccountId as _,54 OnMethodCall, Account as EVMAccount, FeeCalculator, GasWeightMapping,55};56pub use frame_support::{57 construct_runtime, match_types,58 dispatch::DispatchResult,59 PalletId, parameter_types, StorageValue, ConsensusEngineId,60 traits::{61 tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,62 Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,63 OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, PrivilegeCmp,64 },65 weights::{66 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},67 DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,68 WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier,69 WeightToFee,70 },71};72use pallet_unique_scheduler::DispatchCall;73use up_data_structs::{74 CollectionId, TokenId, TokenData, Property, PropertyKeyPermission, CollectionLimits,75 CollectionStats, RpcCollection,76 mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},77 TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo,78 RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkCollectionId, RmrkNftId,79 RmrkNftChild, RmrkPropertyKey, RmrkResourceId, RmrkBaseId,80};8182// use pallet_contracts::weights::WeightInfo;83// #[cfg(any(feature = "std", test))]84use frame_system::{85 self as frame_system, EnsureRoot, EnsureSigned,86 limits::{BlockWeights, BlockLength},87};88use sp_arithmetic::{89 traits::{BaseArithmetic, Unsigned},90};91use smallvec::smallvec;92use codec::{Encode, Decode};93use fp_rpc::TransactionStatus;94use sp_runtime::{95 traits::{96 Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,97 Saturating, CheckedConversion,98 },99 generic::Era,100 transaction_validity::TransactionValidityError,101 DispatchErrorWithPostInfo, SaturatedConversion,102};103104// pub use pallet_timestamp::Call as TimestampCall;105pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;106107// Polkadot imports108use pallet_xcm::XcmPassthrough;109use polkadot_parachain::primitives::Sibling;110use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};111use xcm_builder::{112 AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,113 EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,114 RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,115 SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,116 ParentIsPreset,117};118use xcm_executor::{Config, XcmExecutor, Assets};119use sp_std::{cmp::Ordering, marker::PhantomData};120121use xcm::latest::{122 // Xcm,123 AssetId::{Concrete},124 Fungibility::Fungible as XcmFungible,125 MultiAsset,126 Error as XcmError,127};128use xcm_executor::traits::{MatchesFungible, WeightTrader};129130use unique_runtime_common::{131 impl_common_runtime_apis,132 types::*,133 constants::*,134 dispatch::{CollectionDispatchT, CollectionDispatch},135 sponsoring::UniqueSponsorshipHandler,136 eth_sponsoring::UniqueEthSponsorshipHandler,137 weights::CommonWeights,138};13939140pub const RUNTIME_NAME: &str = "unique";40pub const RUNTIME_NAME: &str = "unique";141pub const TOKEN_SYMBOL: &str = "UNQ";41pub const TOKEN_SYMBOL: &str = "UNQ";142143type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;144145impl RuntimeInstance for Runtime {146 type CrossAccountId = self::CrossAccountId;147 type TransactionConverter = self::TransactionConverter;148149 fn get_transaction_converter() -> TransactionConverter {150 TransactionConverter151 }152}153154/// The type for looking up accounts. We don't expect more than 4 billion of them, but you155/// never know...156pub type AccountIndex = u32;157158/// Balance of an account.159pub type Balance = u128;160161/// Index of a transaction in the chain.162pub type Index = u32;163164/// A hash of some data used by the chain.165pub type Hash = sp_core::H256;166167/// Digest item type.168pub type DigestItem = generic::DigestItem;169170/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know171/// the specifics of the runtime. They can then be made to be agnostic over specific formats172/// of data like extrinsics, allowing for them to continue syncing the network through upgrades173/// to even the core data structures.174pub mod opaque {175 use sp_std::prelude::*;176 use sp_runtime::impl_opaque_keys;177 use super::Aura;178179 pub use unique_runtime_common::types::*;180181 impl_opaque_keys! {182 pub struct SessionKeys {183 pub aura: Aura,184 }185 }186}18742188/// This runtime version.43/// This runtime version.189pub const VERSION: RuntimeVersion = RuntimeVersion {44pub const VERSION: RuntimeVersion = RuntimeVersion {197 state_version: 0,52 state_version: 0,198};53};199200#[derive(codec::Encode, codec::Decode)]201pub enum XCMPMessage<XAccountId, XBalance> {202 /// Transfer tokens to the given account from the Parachain account.203 TransferToken(XAccountId, XBalance),204}205206/// The version information used to identify this runtime when compiled natively.207#[cfg(feature = "std")]208pub fn native_version() -> NativeVersion {209 NativeVersion {210 runtime_version: VERSION,211 can_author_with: Default::default(),212 }213}214215type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;216217pub struct DealWithFees;218impl OnUnbalanced<NegativeImbalance> for DealWithFees {219 fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {220 if let Some(fees) = fees_then_tips.next() {221 // for fees, 100% to treasury222 let mut split = fees.ration(100, 0);223 if let Some(tips) = fees_then_tips.next() {224 // for tips, if any, 100% to treasury225 tips.ration_merge_into(100, 0, &mut split);226 }227 Treasury::on_unbalanced(split.0);228 // Author::on_unbalanced(split.1);229 }230 }231}23254233parameter_types! {55parameter_types! {234 pub const BlockHashCount: BlockNumber = 2400;235 pub RuntimeBlockLength: BlockLength =236 BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);237 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);238 pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;239 pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()240 .base_block(BlockExecutionWeight::get())241 .for_class(DispatchClass::all(), |weights| {242 weights.base_extrinsic = ExtrinsicBaseWeight::get();243 })244 .for_class(DispatchClass::Normal, |weights| {245 weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);246 })247 .for_class(DispatchClass::Operational, |weights| {248 weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);249 // Operational transactions have some extra reserved space, so that they250 // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.251 weights.reserved = Some(252 MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT253 );254 })255 .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)256 .build_or_panic();257 pub const Version: RuntimeVersion = VERSION;56 pub const Version: RuntimeVersion = VERSION;258 pub const SS58Prefix: u16 = 7391;57 pub const SS58Prefix: u16 = 7391;259}260261parameter_types! {262 pub const ChainId: u64 = 8880;58 pub const ChainId: u64 = 8880;263}59}264265pub struct FixedFee;266impl FeeCalculator for FixedFee {267 fn min_gas_price() -> (U256, u64) {268 (MIN_GAS_PRICE.into(), 0)269 }270}271272// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case273// (contract, which only writes a lot of data),274// approximating on top of our real store write weight275parameter_types! {276 pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;277 pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;278 pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();279}280281/// Limiting EVM execution to 50% of block for substrate users and management tasks282/// EVM transaction consumes more weight than substrate's, so we can't rely on them being283/// scheduled fairly284const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);285parameter_types! {286 pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());287}288289pub enum FixedGasWeightMapping {}290impl GasWeightMapping for FixedGasWeightMapping {291 fn gas_to_weight(gas: u64) -> Weight {292 gas.saturating_mul(WeightPerGas::get())293 }294 fn weight_to_gas(weight: Weight) -> u64 {295 weight / WeightPerGas::get()296 }297}298299impl pallet_evm::account::Config for Runtime {300 type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;301 type EvmAddressMapping = pallet_evm::HashedAddressMapping<Self::Hashing>;302 type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;303}304305impl pallet_evm::Config for Runtime {306 type BlockGasLimit = BlockGasLimit;307 type FeeCalculator = FixedFee;308 type GasWeightMapping = FixedGasWeightMapping;309 type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;310 type CallOrigin = EnsureAddressTruncated<Self>;311 type WithdrawOrigin = EnsureAddressTruncated<Self>;312 type AddressMapping = HashedAddressMapping<Self::Hashing>;313 type PrecompilesType = ();314 type PrecompilesValue = ();315 type Currency = Balances;316 type Event = Event;317 type OnMethodCall = (318 pallet_evm_migration::OnMethodCall<Self>,319 pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,320 CollectionDispatchT<Self>,321 pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,322 );323 type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;324 type ChainId = ChainId;325 type Runner = pallet_evm::runner::stack::Runner<Self>;326 type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;327 type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;328 type FindAuthor = EthereumFindAuthor<Aura>;329}330331impl pallet_evm_migration::Config for Runtime {332 type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;333}334335pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);336impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {337 fn find_author<'a, I>(digests: I) -> Option<H160>338 where339 I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,340 {341 if let Some(author_index) = F::find_author(digests) {342 let authority_id = Aura::authorities()[author_index as usize].clone();343 return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));344 }345 None346 }347}348349impl pallet_ethereum::Config for Runtime {350 type Event = Event;351 type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;352}353354impl pallet_randomness_collective_flip::Config for Runtime {}355356impl frame_system::Config for Runtime {357 /// The data to be stored in an account.358 type AccountData = pallet_balances::AccountData<Balance>;359 /// The identifier used to distinguish between accounts.360 type AccountId = AccountId;361 /// The basic call filter to use in dispatchable.362 type BaseCallFilter = Everything;363 /// Maximum number of block number to block hash mappings to keep (oldest pruned first).364 type BlockHashCount = BlockHashCount;365 /// The maximum length of a block (in bytes).366 type BlockLength = RuntimeBlockLength;367 /// The index type for blocks.368 type BlockNumber = BlockNumber;369 /// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.370 type BlockWeights = RuntimeBlockWeights;371 /// The aggregated dispatch type that is available for extrinsics.372 type Call = Call;373 /// The weight of database operations that the runtime can invoke.374 type DbWeight = RocksDbWeight;375 /// The ubiquitous event type.376 type Event = Event;377 /// The type for hashing blocks and tries.378 type Hash = Hash;379 /// The hashing algorithm used.380 type Hashing = BlakeTwo256;381 /// The header type.382 type Header = generic::Header<BlockNumber, BlakeTwo256>;383 /// The index type for storing how many extrinsics an account has signed.384 type Index = Index;385 /// The lookup mechanism to get account ID from whatever is passed in dispatchers.386 type Lookup = AccountIdLookup<AccountId, ()>;387 /// What to do if an account is fully reaped from the system.388 type OnKilledAccount = ();389 /// What to do if a new account is created.390 type OnNewAccount = ();391 type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;392 /// The ubiquitous origin type.393 type Origin = Origin;394 /// This type is being generated by `construct_runtime!`.395 type PalletInfo = PalletInfo;396 /// This is used as an identifier of the chain. 42 is the generic substrate prefix.397 type SS58Prefix = SS58Prefix;398 /// Weight information for the extrinsics of this pallet.399 type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;400 /// Version of the runtime.401 type Version = Version;402 type MaxConsumers = ConstU32<16>;403}404405parameter_types! {406 pub const MinimumPeriod: u64 = SLOT_DURATION / 2;407}408409impl pallet_timestamp::Config for Runtime {410 /// A timestamp: milliseconds since the unix epoch.411 type Moment = u64;412 type OnTimestampSet = ();413 type MinimumPeriod = MinimumPeriod;414 type WeightInfo = ();415}416417parameter_types! {418 // pub const ExistentialDeposit: u128 = 500;419 pub const ExistentialDeposit: u128 = 0;420 pub const MaxLocks: u32 = 50;421 pub const MaxReserves: u32 = 50;422}423424impl pallet_balances::Config for Runtime {425 type MaxLocks = MaxLocks;426 type MaxReserves = MaxReserves;427 type ReserveIdentifier = [u8; 16];428 /// The type for recording an account's balance.429 type Balance = Balance;430 /// The ubiquitous event type.431 type Event = Event;432 type DustRemoval = Treasury;433 type ExistentialDeposit = ExistentialDeposit;434 type AccountStore = System;435 type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;436}437438pub const fn deposit(items: u32, bytes: u32) -> Balance {439 items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE440}441442/*443parameter_types! {444 pub TombstoneDeposit: Balance = deposit(445 1,446 sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,447 );448 pub DepositPerContract: Balance = TombstoneDeposit::get();449 pub const DepositPerStorageByte: Balance = deposit(0, 1);450 pub const DepositPerStorageItem: Balance = deposit(1, 0);451 pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);452 pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;453 pub const SignedClaimHandicap: u32 = 2;454 pub const MaxDepth: u32 = 32;455 pub const MaxValueSize: u32 = 16 * 1024;456 pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb457 // The lazy deletion runs inside on_initialize.458 pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *459 RuntimeBlockWeights::get().max_block;460 // The weight needed for decoding the queue should be less or equal than a fifth461 // of the overall weight dedicated to the lazy deletion.462 pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (463 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -464 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)465 )) / 5) as u32;466 pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();467}468469impl pallet_contracts::Config for Runtime {470 type Time = Timestamp;471 type Randomness = RandomnessCollectiveFlip;472 type Currency = Balances;473 type Event = Event;474 type RentPayment = ();475 type SignedClaimHandicap = SignedClaimHandicap;476 type TombstoneDeposit = TombstoneDeposit;477 type DepositPerContract = DepositPerContract;478 type DepositPerStorageByte = DepositPerStorageByte;479 type DepositPerStorageItem = DepositPerStorageItem;480 type RentFraction = RentFraction;481 type SurchargeReward = SurchargeReward;482 type WeightPrice = pallet_transaction_payment::Pallet<Self>;483 type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;484 type ChainExtension = NFTExtension;485 type DeletionQueueDepth = DeletionQueueDepth;486 type DeletionWeightLimit = DeletionWeightLimit;487 type Schedule = Schedule;488 type CallStack = [pallet_contracts::Frame<Self>; 31];489}490*/491492parameter_types! {493 /// This value increases the priority of `Operational` transactions by adding494 /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.495 pub const OperationalFeeMultiplier: u8 = 5;496}497498/// Linear implementor of `WeightToFeePolynomial`499pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);500501impl<T> WeightToFeePolynomial for LinearFee<T>502where503 T: BaseArithmetic + From<u32> + Copy + Unsigned,504{505 type Balance = T;506507 fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {508 smallvec!(WeightToFeeCoefficient {509 coeff_integer: WEIGHT_TO_FEE_COEFF.into(),510 coeff_frac: Perbill::zero(),511 negative: false,512 degree: 1,513 })514 }515}516517impl pallet_transaction_payment::Config for Runtime {518 type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;519 type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;520 type OperationalFeeMultiplier = OperationalFeeMultiplier;521 type WeightToFee = LinearFee<Balance>;522 type FeeMultiplierUpdate = ();523}524525parameter_types! {526 pub const ProposalBond: Permill = Permill::from_percent(5);527 pub const ProposalBondMinimum: Balance = 1 * UNIQUE;528 pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;529 pub const SpendPeriod: BlockNumber = 5 * MINUTES;530 pub const Burn: Permill = Permill::from_percent(0);531 pub const TipCountdown: BlockNumber = 1 * DAYS;532 pub const TipFindersFee: Percent = Percent::from_percent(20);533 pub const TipReportDepositBase: Balance = 1 * UNIQUE;534 pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;535 pub const BountyDepositBase: Balance = 1 * UNIQUE;536 pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;537 pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");538 pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;539 pub const MaximumReasonLength: u32 = 16384;540 pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);541 pub const BountyValueMinimum: Balance = 5 * UNIQUE;542 pub const MaxApprovals: u32 = 100;543}544545impl pallet_treasury::Config for Runtime {546 type PalletId = TreasuryModuleId;547 type Currency = Balances;548 type ApproveOrigin = EnsureRoot<AccountId>;549 type RejectOrigin = EnsureRoot<AccountId>;550 type Event = Event;551 type OnSlash = ();552 type ProposalBond = ProposalBond;553 type ProposalBondMinimum = ProposalBondMinimum;554 type ProposalBondMaximum = ProposalBondMaximum;555 type SpendPeriod = SpendPeriod;556 type Burn = Burn;557 type BurnDestination = ();558 type SpendFunds = ();559 type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;560 type MaxApprovals = MaxApprovals;561}562563impl pallet_sudo::Config for Runtime {564 type Event = Event;565 type Call = Call;566}567568pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);569570impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider571 for RelayChainBlockNumberProvider<T>572{573 type BlockNumber = BlockNumber;574575 fn current_block_number() -> Self::BlockNumber {576 cumulus_pallet_parachain_system::Pallet::<T>::validation_data()577 .map(|d| d.relay_parent_number)578 .unwrap_or_default()579 }580}581582parameter_types! {583 pub const MinVestedTransfer: Balance = 10 * UNIQUE;584 pub const MaxVestingSchedules: u32 = 28;585}586587impl orml_vesting::Config for Runtime {588 type Event = Event;589 type Currency = pallet_balances::Pallet<Runtime>;590 type MinVestedTransfer = MinVestedTransfer;591 type VestedTransferOrigin = EnsureSigned<AccountId>;592 type WeightInfo = ();593 type MaxVestingSchedules = MaxVestingSchedules;594 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;595}596597parameter_types! {598 pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;599 pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;600}601602impl cumulus_pallet_parachain_system::Config for Runtime {603 type Event = Event;604 type SelfParaId = parachain_info::Pallet<Self>;605 type OnSystemEvent = ();606 // type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<607 // MaxDownwardMessageWeight,608 // XcmExecutor<XcmConfig>,609 // Call,610 // >;611 type OutboundXcmpMessageSource = XcmpQueue;612 type DmpMessageHandler = DmpQueue;613 type ReservedDmpWeight = ReservedDmpWeight;614 type ReservedXcmpWeight = ReservedXcmpWeight;615 type XcmpMessageHandler = XcmpQueue;616}617618impl parachain_info::Config for Runtime {}619620impl cumulus_pallet_aura_ext::Config for Runtime {}621622parameter_types! {623 pub const RelayLocation: MultiLocation = MultiLocation::parent();624 pub const RelayNetwork: NetworkId = NetworkId::Polkadot;625 pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();626 pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();627}628629/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used630/// when determining ownership of accounts for asset transacting and when attempting to use XCM631/// `Transact` in order to determine the dispatch Origin.632pub type LocationToAccountId = (633 // The parent (Relay-chain) origin converts to the default `AccountId`.634 ParentIsPreset<AccountId>,635 // Sibling parachain origins convert to AccountId via the `ParaId::into`.636 SiblingParachainConvertsVia<Sibling, AccountId>,637 // Straight up local `AccountId32` origins just alias directly to `AccountId`.638 AccountId32Aliases<RelayNetwork, AccountId>,639);640641pub struct OnlySelfCurrency;642impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {643 fn matches_fungible(a: &MultiAsset) -> Option<B> {644 match (&a.id, &a.fun) {645 (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),646 _ => None,647 }648 }649}650651/// Means for transacting assets on this chain.652pub type LocalAssetTransactor = CurrencyAdapter<653 // Use this currency:654 Balances,655 // Use this currency when it is a fungible asset matching the given location or name:656 OnlySelfCurrency,657 // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:658 LocationToAccountId,659 // Our chain's account ID type (we can't get away without mentioning it explicitly):660 AccountId,661 // We don't track any teleports.662 (),663>;664665/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,666/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can667/// biases the kind of local `Origin` it will become.668pub type XcmOriginToTransactDispatchOrigin = (669 // Sovereign account converter; this attempts to derive an `AccountId` from the origin location670 // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for671 // foreign chains who want to have a local sovereign account on this chain which they control.672 SovereignSignedViaLocation<LocationToAccountId, Origin>,673 // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when674 // recognised.675 RelayChainAsNative<RelayOrigin, Origin>,676 // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when677 // recognised.678 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,679 // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a680 // transaction from the Root origin.681 ParentAsSuperuser<Origin>,682 // Native signed account converter; this just converts an `AccountId32` origin into a normal683 // `Origin::Signed` origin of the same 32-byte value.684 SignedAccountId32AsNative<RelayNetwork, Origin>,685 // Xcm origins can be represented natively under the Xcm pallet's Xcm origin.686 XcmPassthrough<Origin>,687);688689parameter_types! {690 // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.691 pub UnitWeightCost: Weight = 1_000_000;692 // 1200 UNIQUEs buy 1 second of weight.693 pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);694 pub const MaxInstructions: u32 = 100;695 pub const MaxAuthorities: u32 = 100_000;696}697698match_types! {699 pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {700 MultiLocation { parents: 1, interior: Here } |701 MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }702 };703}704705pub type Barrier = (706 TakeWeightCredit,707 AllowTopLevelPaidExecutionFrom<Everything>,708 // ^^^ Parent & its unit plurality gets free execution709);710711pub struct UsingOnlySelfCurrencyComponents<712 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,713 AssetId: Get<MultiLocation>,714 AccountId,715 Currency: CurrencyT<AccountId>,716 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,717>(718 Weight,719 Currency::Balance,720 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,721);722impl<723 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,724 AssetId: Get<MultiLocation>,725 AccountId,726 Currency: CurrencyT<AccountId>,727 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,728 > WeightTrader729 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>730{731 fn new() -> Self {732 Self(0, Zero::zero(), PhantomData)733 }734735 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {736 let amount = WeightToFee::weight_to_fee(&weight);737 let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;738739 // location to this parachain through relay chain740 let option1: xcm::v1::AssetId = Concrete(MultiLocation {741 parents: 1,742 interior: X1(Parachain(ParachainInfo::parachain_id().into())),743 });744 // direct location745 let option2: xcm::v1::AssetId = Concrete(MultiLocation {746 parents: 0,747 interior: Here,748 });749750 let required = if payment.fungible.contains_key(&option1) {751 (option1, u128_amount).into()752 } else if payment.fungible.contains_key(&option2) {753 (option2, u128_amount).into()754 } else {755 (Concrete(MultiLocation::default()), u128_amount).into()756 };757758 let unused = payment759 .checked_sub(required)760 .map_err(|_| XcmError::TooExpensive)?;761 self.0 = self.0.saturating_add(weight);762 self.1 = self.1.saturating_add(amount);763 Ok(unused)764 }765766 fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {767 let weight = weight.min(self.0);768 let amount = WeightToFee::weight_to_fee(&weight);769 self.0 -= weight;770 self.1 = self.1.saturating_sub(amount);771 let amount: u128 = amount.saturated_into();772 if amount > 0 {773 Some((AssetId::get(), amount).into())774 } else {775 None776 }777 }778}779impl<780 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,781 AssetId: Get<MultiLocation>,782 AccountId,783 Currency: CurrencyT<AccountId>,784 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,785 > Drop786 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>787{788 fn drop(&mut self) {789 OnUnbalanced::on_unbalanced(Currency::issue(self.1));790 }791}792793pub struct XcmConfig;794impl Config for XcmConfig {795 type Call = Call;796 type XcmSender = XcmRouter;797 // How to withdraw and deposit an asset.798 type AssetTransactor = LocalAssetTransactor;799 type OriginConverter = XcmOriginToTransactDispatchOrigin;800 type IsReserve = NativeAsset;801 type IsTeleporter = (); // Teleportation is disabled802 type LocationInverter = LocationInverter<Ancestry>;803 type Barrier = Barrier;804 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;805 type Trader =806 UsingOnlySelfCurrencyComponents<LinearFee<Balance>, RelayLocation, AccountId, Balances, ()>;807 type ResponseHandler = (); // Don't handle responses for now.808 type SubscriptionService = PolkadotXcm;809810 type AssetTrap = PolkadotXcm;811 type AssetClaims = PolkadotXcm;812}813814// parameter_types! {815// pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;816// }817818/// No local origins on this chain are allowed to dispatch XCM sends/executions.819pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);820821/// The means for routing XCM messages which are not for local execution into the right message822/// queues.823pub type XcmRouter = (824 // Two routers - use UMP to communicate with the relay chain:825 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,826 // ..and XCMP to communicate with the sibling chains.827 XcmpQueue,828);829830impl pallet_evm_coder_substrate::Config for Runtime {}831832impl pallet_xcm::Config for Runtime {833 type Event = Event;834 type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;835 type XcmRouter = XcmRouter;836 type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;837 type XcmExecuteFilter = Everything;838 type XcmExecutor = XcmExecutor<XcmConfig>;839 type XcmTeleportFilter = Everything;840 type XcmReserveTransferFilter = Everything;841 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;842 type LocationInverter = LocationInverter<Ancestry>;843 type Origin = Origin;844 type Call = Call;845 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;846 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;847}848849impl cumulus_pallet_xcm::Config for Runtime {850 type Event = Event;851 type XcmExecutor = XcmExecutor<XcmConfig>;852}853854impl cumulus_pallet_xcmp_queue::Config for Runtime {855 type WeightInfo = ();856 type Event = Event;857 type XcmExecutor = XcmExecutor<XcmConfig>;858 type ChannelInfo = ParachainSystem;859 type VersionWrapper = ();860 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;861 type ControllerOrigin = EnsureRoot<AccountId>;862 type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;863}864865impl cumulus_pallet_dmp_queue::Config for Runtime {866 type Event = Event;867 type XcmExecutor = XcmExecutor<XcmConfig>;868 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;869}870871impl pallet_aura::Config for Runtime {872 type AuthorityId = AuraId;873 type DisabledValidators = ();874 type MaxAuthorities = MaxAuthorities;875}876877parameter_types! {878 pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();879 pub const CollectionCreationPrice: Balance = 2 * UNIQUE;880}881882impl pallet_common::Config for Runtime {883 type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;884 type Event = Event;885 type Currency = Balances;886 type CollectionCreationPrice = CollectionCreationPrice;887 type TreasuryAccountId = TreasuryAccountId;888 type CollectionDispatch = CollectionDispatchT<Self>;889890 type EvmTokenAddressMapping = EvmTokenAddressMapping;891 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;892 type ContractAddress = EvmCollectionHelpersAddress;893}894895impl pallet_structure::Config for Runtime {896 type Event = Event;897 type Call = Call;898 type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;899}900901impl pallet_fungible::Config for Runtime {902 type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;903}904impl pallet_refungible::Config for Runtime {905 type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;906}907impl pallet_nonfungible::Config for Runtime {908 type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;909}910911impl pallet_unique::Config for Runtime {912 type Event = Event;913 type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;914 type CommonWeightInfo = CommonWeights<Self>;915 type RefungibleExtensionsWeightInfo = CommonWeights<Self>;916}917918parameter_types! {919 pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied920}921922/// Used for the pallet inflation923impl pallet_inflation::Config for Runtime {924 type Currency = Balances;925 type TreasuryAccountId = TreasuryAccountId;926 type InflationBlockInterval = InflationBlockInterval;927 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;928}929930parameter_types! {931 pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *932 RuntimeBlockWeights::get().max_block;933 pub const MaxScheduledPerBlock: u32 = 50;934}935936type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;937use frame_support::traits::NamedReservableCurrency;938939fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {940 (941 frame_system::CheckSpecVersion::<Runtime>::new(),942 frame_system::CheckGenesis::<Runtime>::new(),943 frame_system::CheckEra::<Runtime>::from(Era::Immortal),944 frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(945 from,946 )),947 frame_system::CheckWeight::<Runtime>::new(),948 // sponsoring transaction logic949 // pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),950 )951}952953pub struct SchedulerPaymentExecutor;954impl<T: frame_system::Config + pallet_unique_scheduler::Config, SelfContainedSignedInfo>955 DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor956where957 <T as frame_system::Config>::Call: Member958 + Dispatchable<Origin = Origin, Info = DispatchInfo>959 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>960 + GetDispatchInfo961 + From<frame_system::Call<Runtime>>,962 SelfContainedSignedInfo: Send + Sync + 'static,963 Call: From<<T as frame_system::Config>::Call>964 + From<<T as pallet_unique_scheduler::Config>::Call>965 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,966 sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,967{968 fn dispatch_call(969 signer: <T as frame_system::Config>::AccountId,970 call: <T as pallet_unique_scheduler::Config>::Call,971 ) -> Result<972 Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,973 TransactionValidityError,974 > {975 let dispatch_info = call.get_dispatch_info();976 let extrinsic = fp_self_contained::CheckedExtrinsic::<977 AccountId,978 Call,979 SignedExtraScheduler,980 SelfContainedSignedInfo,981 > {982 signed:983 CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(984 signer.clone().into(),985 get_signed_extras(signer.into()),986 ),987 function: call.into(),988 };989990 extrinsic.apply::<Runtime>(&dispatch_info, 0)991 }992993 fn reserve_balance(994 id: [u8; 16],995 sponsor: <T as frame_system::Config>::AccountId,996 call: <T as pallet_unique_scheduler::Config>::Call,997 count: u32,998 ) -> Result<(), DispatchError> {999 let dispatch_info = call.get_dispatch_info();1000 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)1001 .saturating_mul(count.into());10021003 <Balances as NamedReservableCurrency<AccountId>>::reserve_named(1004 &id,1005 &(sponsor.into()),1006 weight,1007 )1008 }10091010 fn pay_for_call(1011 id: [u8; 16],1012 sponsor: <T as frame_system::Config>::AccountId,1013 call: <T as pallet_unique_scheduler::Config>::Call,1014 ) -> Result<u128, DispatchError> {1015 let dispatch_info = call.get_dispatch_info();1016 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);1017 Ok(1018 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1019 &id,1020 &(sponsor.into()),1021 weight,1022 ),1023 )1024 }10251026 fn cancel_reserve(1027 id: [u8; 16],1028 sponsor: <T as frame_system::Config>::AccountId,1029 ) -> Result<u128, DispatchError> {1030 Ok(1031 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1032 &id,1033 &(sponsor.into()),1034 u128::MAX,1035 ),1036 )1037 }1038}10391040parameter_types! {1041 pub const NoPreimagePostponement: Option<u32> = Some(10);1042 pub const Preimage: Option<u32> = Some(10);1043}10441045/// Used the compare the privilege of an origin inside the scheduler.1046pub struct OriginPrivilegeCmp;10471048impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {1049 fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {1050 Some(Ordering::Equal)1051 }1052}10531054impl pallet_unique_scheduler::Config for Runtime {1055 type Event = Event;1056 type Origin = Origin;1057 type Currency = Balances;1058 type PalletsOrigin = OriginCaller;1059 type Call = Call;1060 type MaximumWeight = MaximumSchedulerWeight;1061 type ScheduleOrigin = EnsureSigned<AccountId>;1062 type MaxScheduledPerBlock = MaxScheduledPerBlock;1063 type WeightInfo = ();1064 type CallExecutor = SchedulerPaymentExecutor;1065 type OriginPrivilegeCmp = OriginPrivilegeCmp;1066 type PreimageProvider = ();1067 type NoPreimagePostponement = NoPreimagePostponement;1068}10691070type EvmSponsorshipHandler = (1071 UniqueEthSponsorshipHandler<Runtime>,1072 pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,1073);1074type SponsorshipHandler = (1075 UniqueSponsorshipHandler<Runtime>,1076 //pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,1077 pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,1078);10791080impl pallet_evm_transaction_payment::Config for Runtime {1081 type EvmSponsorshipHandler = EvmSponsorshipHandler;1082 type Currency = Balances;1083}10841085impl pallet_charge_transaction::Config for Runtime {1086 type SponsorshipHandler = SponsorshipHandler;1087}10881089// impl pallet_contract_helpers::Config for Runtime {1090// type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1091// }10921093parameter_types! {1094 // 0x842899ECF380553E8a4de75bF534cdf6fBF640491095 pub const HelpersContractAddress: H160 = H160([1096 0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,1097 ]);10981099 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f1100 pub const EvmCollectionHelpersAddress: H160 = H160([1101 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,1102 ]);1103}11041105impl pallet_evm_contract_helpers::Config for Runtime {1106 type ContractAddress = HelpersContractAddress;1107 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1108}1109601110construct_runtime!(61construct_runtime!(unique);1111 pub enum Runtime where1112 Block = Block,1113 NodeBlock = opaque::Block,1114 UncheckedExtrinsic = UncheckedExtrinsic1115 {1116 ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,1117 ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,11181119 Aura: pallet_aura::{Pallet, Config<T>} = 22,1120 AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,11211122 Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,1123 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,1124 Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,1125 TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,1126 Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,1127 Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,1128 System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,1129 Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,1130 // Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,1131 // Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,11321133 // XCM helpers.1134 XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,1135 PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,1136 CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,1137 DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,11381139 // Unique Pallets1140 Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,1141 Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,1142 Scheduler: pallet_unique_scheduler::{Pallet, Call, Storage, Event<T>} = 62,1143 // free = 631144 Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,1145 // ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,1146 Common: pallet_common::{Pallet, Storage, Event<T>} = 66,1147 Fungible: pallet_fungible::{Pallet, Storage} = 67,1148 Refungible: pallet_refungible::{Pallet, Storage} = 68,1149 Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,1150 Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,11511152 // Frontier1153 EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,1154 Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,11551156 EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,1157 EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,1158 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,1159 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,1160 }1161);11621163pub struct TransactionConverter;11641165impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {1166 fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {1167 UncheckedExtrinsic::new_unsigned(1168 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1169 )1170 }1171}11721173impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {1174 fn convert_transaction(1175 &self,1176 transaction: pallet_ethereum::Transaction,1177 ) -> opaque::UncheckedExtrinsic {1178 let extrinsic = UncheckedExtrinsic::new_unsigned(1179 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1180 );1181 let encoded = extrinsic.encode();1182 opaque::UncheckedExtrinsic::decode(&mut &encoded[..])1183 .expect("Encoded extrinsic is always valid")1184 }1185}11861187/// The address format for describing accounts.1188pub type Address = sp_runtime::MultiAddress<AccountId, ()>;1189/// Block header type as expected by this runtime.1190pub type Header = generic::Header<BlockNumber, BlakeTwo256>;1191/// Block type as expected by this runtime.1192pub type Block = generic::Block<Header, UncheckedExtrinsic>;1193/// A Block signed with a Justification1194pub type SignedBlock = generic::SignedBlock<Block>;1195/// BlockId type as expected by this runtime.1196pub type BlockId = generic::BlockId<Block>;1197/// The SignedExtension to the basic transaction logic.1198pub type SignedExtra = (1199 frame_system::CheckSpecVersion<Runtime>,1200 // system::CheckTxVersion<Runtime>,1201 frame_system::CheckGenesis<Runtime>,1202 frame_system::CheckEra<Runtime>,1203 frame_system::CheckNonce<Runtime>,1204 frame_system::CheckWeight<Runtime>,1205 pallet_charge_transaction::ChargeTransactionPayment<Runtime>,1206 //pallet_contract_helpers::ContractHelpersExtension<Runtime>,1207 pallet_ethereum::FakeTransactionFinalizer<Runtime>,1208);1209pub type SignedExtraScheduler = (1210 frame_system::CheckSpecVersion<Runtime>,1211 frame_system::CheckGenesis<Runtime>,1212 frame_system::CheckEra<Runtime>,1213 frame_system::CheckNonce<Runtime>,1214 frame_system::CheckWeight<Runtime>,1215 // pallet_charge_transaction::ChargeTransactionPayment<Runtime>,1216);1217/// Unchecked extrinsic type as expected by this runtime.1218pub type UncheckedExtrinsic =1219 fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;1220/// Extrinsic type that has already been checked.1221pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;1222/// Executive: handles dispatch to the various modules.1223pub type Executive = frame_executive::Executive<1224 Runtime,1225 Block,1226 frame_system::ChainContext<Runtime>,1227 Runtime,1228 AllPalletsReversedWithSystemFirst,1229>;12301231impl_opaque_keys! {1232 pub struct SessionKeys {1233 pub aura: Aura,1234 }1235}12361237impl fp_self_contained::SelfContainedCall for Call {1238 type SignedInfo = H160;12391240 fn is_self_contained(&self) -> bool {1241 match self {1242 Call::Ethereum(call) => call.is_self_contained(),1243 _ => false,1244 }1245 }12461247 fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {1248 match self {1249 Call::Ethereum(call) => call.check_self_contained(),1250 _ => None,1251 }1252 }12531254 fn validate_self_contained(1255 &self,1256 info: &Self::SignedInfo,1257 dispatch_info: &DispatchInfoOf<Call>,1258 len: usize,1259 ) -> Option<TransactionValidity> {1260 match self {1261 Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),1262 _ => None,1263 }1264 }12651266 fn pre_dispatch_self_contained(1267 &self,1268 info: &Self::SignedInfo,1269 ) -> Option<Result<(), TransactionValidityError>> {1270 match self {1271 Call::Ethereum(call) => call.pre_dispatch_self_contained(info),1272 _ => None,1273 }1274 }12751276 fn apply_self_contained(1277 self,1278 info: Self::SignedInfo,1279 ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {1280 match self {1281 call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(1282 Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),1283 )),1284 _ => None,1285 }1286 }1287}12881289macro_rules! dispatch_unique_runtime {1290 ($collection:ident.$method:ident($($name:ident),*)) => {{1291 let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);1292 let dispatch = collection.as_dyn();12931294 Ok::<_, DispatchError>(dispatch.$method($($name),*))1295 }};1296}1297621298impl_common_runtime_apis! {63impl_common_runtime_apis!();1299 #![custom_apis]13001301 impl rmrk_rpc::RmrkApi<1302 Block,1303 AccountId,1304 RmrkCollectionInfo<AccountId>,1305 RmrkInstanceInfo<AccountId>,1306 RmrkResourceInfo,1307 RmrkPropertyInfo,1308 RmrkBaseInfo<AccountId>,1309 RmrkPartType,1310 RmrkTheme1311 > for Runtime {1312 fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {1313 Ok(Default::default())1314 }13151316 fn collection_by_id(_collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {1317 Ok(Default::default())1318 }13191320 fn nft_by_id(_collection_id: RmrkCollectionId, _nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {1321 Ok(Default::default())1322 }13231324 fn account_tokens(_account_id: AccountId, _collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {1325 Ok(Default::default())1326 }13271328 fn nft_children(_collection_id: RmrkCollectionId, _nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {1329 Ok(Default::default())1330 }13311332 fn collection_properties(_collection_id: RmrkCollectionId, _filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {1333 Ok(Default::default())1334 }13351336 fn nft_properties(_collection_id: RmrkCollectionId, _nft_id: RmrkNftId, _filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {1337 Ok(Default::default())1338 }13391340 fn nft_resources(_collection_id: RmrkCollectionId, _nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {1341 Ok(Default::default())1342 }13431344 fn nft_resource_priority(_collection_id: RmrkCollectionId, _nft_id: RmrkNftId, _resource_id: RmrkResourceId) -> Result<Option<u32>, DispatchError> {1345 Ok(Default::default())1346 }13471348 fn base(_base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {1349 Ok(Default::default())1350 }13511352 fn base_parts(_base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {1353 Ok(Default::default())1354 }13551356 fn theme_names(_base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {1357 Ok(Default::default())1358 }13591360 fn theme(_base_id: RmrkBaseId, _theme_name: RmrkThemeName, _filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {1361 Ok(Default::default())1362 }1363 }1364}13651366struct CheckInherents;13671368impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {1369 fn check_inherents(1370 block: &Block,1371 relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,1372 ) -> sp_inherents::CheckInherentsResult {1373 let relay_chain_slot = relay_state_proof1374 .read_slot()1375 .expect("Could not read the relay chain slot from the proof");13761377 let inherent_data =1378 cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(1379 relay_chain_slot,1380 sp_std::time::Duration::from_secs(6),1381 )1382 .create_inherent_data()1383 .expect("Could not create the timestamp inherent data");13841385 inherent_data.check_extrinsics(block)1386 }1387}1388641389cumulus_pallet_parachain_system::register_validate_block!(65cumulus_pallet_parachain_system::register_validate_block!(1390 Runtime = Runtime,66 Runtime = Runtime,tests/package.jsondiffbeforeafterboth8 "@polkadot/typegen": "8.7.2-15",8 "@polkadot/typegen": "8.7.2-15",9 "@types/chai": "^4.3.1",9 "@types/chai": "^4.3.1",10 "@types/chai-as-promised": "^7.1.5",10 "@types/chai-as-promised": "^7.1.5",11 "@types/chai-like": "^1.1.1",11 "@types/mocha": "^9.1.1",12 "@types/mocha": "^9.1.1",12 "@types/node": "^17.0.35",13 "@types/node": "^17.0.35",13 "@typescript-eslint/eslint-plugin": "^5.26.0",14 "@typescript-eslint/eslint-plugin": "^5.26.0",96 "@polkadot/util-crypto": "9.4.1",97 "@polkadot/util-crypto": "9.4.1",97 "bignumber.js": "^9.0.2",98 "bignumber.js": "^9.0.2",98 "chai-as-promised": "^7.1.1",99 "chai-as-promised": "^7.1.1",100 "chai-like": "^1.1.1",99 "find-process": "^1.4.7",101 "find-process": "^1.4.7",100 "solc": "0.8.14-fixed",102 "solc": "0.8.14-fixed",101 "web3": "^1.7.3"103 "web3": "^1.7.3"tests/src/approve.test.tsdiffbeforeafterboth32 getCreatedCollectionCount,32 getCreatedCollectionCount,33 transferFromExpectSuccess,33 transferFromExpectSuccess,34 transferFromExpectFail,34 transferFromExpectFail,35 requirePallets,36 Pallets,35} from './util/helpers';37} from './util/helpers';363837chai.use(chaiAsPromised);39chai.use(chaiAsPromised);49 });51 });50 });52 });5354 it('[nft] Execute the extrinsic and check approvedList', async () => {55 const nftCollectionId = await createCollectionExpectSuccess();56 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');57 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);58 });5960 it('[fungible] Execute the extrinsic and check approvedList', async () => {61 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});62 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');63 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);64 });6566 it('[refungible] Execute the extrinsic and check approvedList', async function() {67 await requirePallets(this, [Pallets.ReFungible]);6869 const reFungibleCollectionId =70 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});71 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');72 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);73 });7475 it('[nft] Remove approval by using 0 amount', async () => {76 const nftCollectionId = await createCollectionExpectSuccess();77 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');78 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 1);79 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 0);80 });518152 it('Execute the extrinsic and check approvedList', async () => {82 it('[fungible] Remove approval by using 0 amount', async () => {53 const nftCollectionId = await createCollectionExpectSuccess();54 // nft55 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');56 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);57 // fungible58 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});83 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});59 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');84 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');60 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);85 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 1);61 // reFungible62 const reFungibleCollectionId =63 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});64 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');65 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);86 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 0);66 });87 });678868 it('Remove approval by using 0 amount', async () => {89 it('[refungible] Remove approval by using 0 amount', async function() {69 const nftCollectionId = await createCollectionExpectSuccess();70 // nft71 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');72 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 1);90 await requirePallets(this, [Pallets.ReFungible]);73 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 0);9174 // fungible75 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});76 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');77 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 1);78 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 0);79 // reFungible80 const reFungibleCollectionId =92 const reFungibleCollectionId =81 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});93 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});82 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');94 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');117 await approveExpectSuccess(collectionId, itemId, bob, charlie.address);129 await approveExpectSuccess(collectionId, itemId, bob, charlie.address);118 });130 });119131120 it('ReFungible up to an approved amount', async () => {132 it('ReFungible up to an approved amount', async function() {133 await requirePallets(this, [Pallets.ReFungible]);134121 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});135 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});122 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);136 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);151 await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'Fungible');165 await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'Fungible');152 });166 });153167154 it('ReFungible up to an approved amount', async () => {168 it('ReFungible up to an approved amount', async function() {169 await requirePallets(this, [Pallets.ReFungible]);170155 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});171 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});156 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);172 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);188 await transferFromExpectFail(collectionId, itemId, charlie, bob, alice, 1);204 await transferFromExpectFail(collectionId, itemId, charlie, bob, alice, 1);189 });205 });190206191 it('ReFungible up to an approved amount', async () => {207 it('ReFungible up to an approved amount', async function() {208 await requirePallets(this, [Pallets.ReFungible]);209192 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});210 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});193 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);211 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);250 await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, bob, charlie, 1);268 await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, bob, charlie, 1);251 });269 });252270253 it('ReFungible', async () => {271 it('ReFungible', async function() {272 await requirePallets(this, [Pallets.ReFungible]);273254 const reFungibleCollectionId =274 const reFungibleCollectionId =255 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});275 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});285 await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, charlie, 11);305 await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, charlie, 11);286 });306 });287307288 it('ReFungible', async () => {308 it('ReFungible', async function() {309 await requirePallets(this, [Pallets.ReFungible]);310289 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});311 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});290 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');312 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');325 await transferFromExpectSuccess(collectionId, itemId, bob, dave, alice, 1, 'Fungible');347 await transferFromExpectSuccess(collectionId, itemId, bob, dave, alice, 1, 'Fungible');326 });348 });327349328 it('ReFungible up to an approved amount', async () => {350 it('ReFungible up to an approved amount', async function() {351 await requirePallets(this, [Pallets.ReFungible]);352329 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});353 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});330 await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});354 await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});422 });446 });423 });447 });424448425 it('Approve for a collection that does not exist', async () => {449 it('[nft] Approve for a collection that does not exist', async () => {426 await usingApi(async (api: ApiPromise) => {450 await usingApi(async (api: ApiPromise) => {427 // nft428 const nftCollectionCount = await getCreatedCollectionCount(api);451 const nftCollectionCount = await getCreatedCollectionCount(api);429 await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);452 await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);430 // fungible431 const fungibleCollectionCount = await getCreatedCollectionCount(api);432 await approveExpectFail(fungibleCollectionCount + 1, 0, alice, bob);433 // reFungible434 const reFungibleCollectionCount = await getCreatedCollectionCount(api);435 await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);436 });453 });437 });454 });455456 it('[fungible] Approve for a collection that does not exist', async () => {457 await usingApi(async (api: ApiPromise) => {458 const fungibleCollectionCount = await getCreatedCollectionCount(api);459 await approveExpectFail(fungibleCollectionCount + 1, 0, alice, bob);460 });461 });462463 it('[refungible] Approve for a collection that does not exist', async function() {464 await requirePallets(this, [Pallets.ReFungible]);465466 await usingApi(async (api: ApiPromise) => {467 const reFungibleCollectionCount = await getCreatedCollectionCount(api);468 await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);469 });470 });471472 it('[nft] Approve for a collection that was destroyed', async () => {473 const nftCollectionId = await createCollectionExpectSuccess();474 await destroyCollectionExpectSuccess(nftCollectionId);475 await approveExpectFail(nftCollectionId, 1, alice, bob);476 });438477439 it('Approve for a collection that was destroyed', async () => {478 it('Approve for a collection that was destroyed', async () => {440 // nft441 const nftCollectionId = await createCollectionExpectSuccess();442 await destroyCollectionExpectSuccess(nftCollectionId);443 await approveExpectFail(nftCollectionId, 1, alice, bob);444 // fungible445 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});479 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});446 await destroyCollectionExpectSuccess(fungibleCollectionId);480 await destroyCollectionExpectSuccess(fungibleCollectionId);447 await approveExpectFail(fungibleCollectionId, 0, alice, bob);481 await approveExpectFail(fungibleCollectionId, 0, alice, bob);448 // reFungible449 const reFungibleCollectionId =450 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});451 await destroyCollectionExpectSuccess(reFungibleCollectionId);452 await approveExpectFail(reFungibleCollectionId, 1, alice, bob);453 });482 });483484 it('[refungible] Approve for a collection that was destroyed', async function() {485 await requirePallets(this, [Pallets.ReFungible]);486487 const reFungibleCollectionId =488 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});489 await destroyCollectionExpectSuccess(reFungibleCollectionId);490 await approveExpectFail(reFungibleCollectionId, 1, alice, bob);491 });492493 it('[nft] Approve transfer of a token that does not exist', async () => {494 const nftCollectionId = await createCollectionExpectSuccess();495 await approveExpectFail(nftCollectionId, 2, alice, bob);496 });454497455 it('Approve transfer of a token that does not exist', async () => {498 it('[refungible] Approve transfer of a token that does not exist', async function() {456 // nft457 const nftCollectionId = await createCollectionExpectSuccess();458 await approveExpectFail(nftCollectionId, 2, alice, bob);499 await requirePallets(this, [Pallets.ReFungible]);459 // reFungible500460 const reFungibleCollectionId =501 const reFungibleCollectionId =461 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});502 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});462 await approveExpectFail(reFungibleCollectionId, 2, alice, bob);503 await approveExpectFail(reFungibleCollectionId, 2, alice, bob);463 });504 });505506 it('[nft] Approve using the address that does not own the approved token', async () => {507 const nftCollectionId = await createCollectionExpectSuccess();508 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');509 await approveExpectFail(nftCollectionId, newNftTokenId, bob, alice);510 });511512 it('[fungible] Approve using the address that does not own the approved token', async () => {513 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});514 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');515 await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice);516 });464517465 it('Approve using the address that does not own the approved token', async () => {518 it('[refungible] Approve using the address that does not own the approved token', async function() {466 const nftCollectionId = await createCollectionExpectSuccess();467 // nft468 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');469 await approveExpectFail(nftCollectionId, newNftTokenId, bob, alice);470 // fungible471 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});519 await requirePallets(this, [Pallets.ReFungible]);472 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');520473 await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice);474 // reFungible475 const reFungibleCollectionId =521 const reFungibleCollectionId =476 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});522 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});477 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');523 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');478 await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, alice);524 await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, alice);479 });525 });480526481 it('should fail if approved more ReFungibles than owned', async () => {527 it('should fail if approved more ReFungibles than owned', async function() {528 await requirePallets(this, [Pallets.ReFungible]);529482 const nftCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});530 const nftCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});483 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'ReFungible');531 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'ReFungible');tests/src/burnItem.test.tsdiffbeforeafterboth25 getBalance,25 getBalance,26 setCollectionLimitsExpectSuccess,26 setCollectionLimitsExpectSuccess,27 isTokenExists,27 isTokenExists,28 requirePallets,29 Pallets,28} from './util/helpers';30} from './util/helpers';293130import chai from 'chai';32import chai from 'chai';80 });82 });81 });83 });828483 it('Burn item in ReFungible collection', async () => {85 it('Burn item in ReFungible collection', async function() {86 await requirePallets(this, [Pallets.ReFungible]);8784 const createMode = 'ReFungible';88 const createMode = 'ReFungible';85 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});89 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});99 });103 });100 });104 });101105102 it('Burn owned portion of item in ReFungible collection', async () => {106 it('Burn owned portion of item in ReFungible collection', async function() {107 await requirePallets(this, [Pallets.ReFungible]);108103 const createMode = 'ReFungible';109 const createMode = 'ReFungible';104 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});110 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});189 });195 });190196191 // TODO: burnFrom197 // TODO: burnFrom192 it('Burn item in ReFungible collection', async () => {198 it('Burn item in ReFungible collection', async function() {199 await requirePallets(this, [Pallets.ReFungible]);200193 const createMode = 'ReFungible';201 const createMode = 'ReFungible';194 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});202 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});tests/src/confirmSponsorship.test.tsdiffbeforeafterboth33 addCollectionAdminExpectSuccess,33 addCollectionAdminExpectSuccess,34 getCreatedCollectionCount,34 getCreatedCollectionCount,35 UNIQUE,35 UNIQUE,36 requirePallets,37 Pallets,36} from './util/helpers';38} from './util/helpers';37import {IKeyringPair} from '@polkadot/types/types';39import {IKeyringPair} from '@polkadot/types/types';3840124 });126 });125 });127 });126128127 it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async () => {129 it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async function() {130 await requirePallets(this, [Pallets.ReFungible]);131128 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});132 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});129 await setCollectionSponsorExpectSuccess(collectionId, bob.address);133 await setCollectionSponsorExpectSuccess(collectionId, bob.address);252 });256 });253 });257 });254258255 it('ReFungible: Sponsoring is rate limited', async () => {259 it('ReFungible: Sponsoring is rate limited', async function() {260 await requirePallets(this, [Pallets.ReFungible]);261256 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});262 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});257 await setCollectionSponsorExpectSuccess(collectionId, bob.address);263 await setCollectionSponsorExpectSuccess(collectionId, bob.address);tests/src/createCollection.test.tsdiffbeforeafterboth161617import {expect} from 'chai';17import {expect} from 'chai';18import usingApi, {executeTransaction, submitTransactionAsync} from './substrate/substrate-api';18import usingApi, {executeTransaction, submitTransactionAsync} from './substrate/substrate-api';19import {createCollectionWithPropsExpectFailure, createCollectionExpectFailure, createCollectionExpectSuccess, getCreateCollectionResult, getDetailedCollectionInfo, createCollectionWithPropsExpectSuccess} from './util/helpers';19import {createCollectionWithPropsExpectFailure, createCollectionExpectFailure, createCollectionExpectSuccess, getCreateCollectionResult, getDetailedCollectionInfo, createCollectionWithPropsExpectSuccess, requirePallets, Pallets} from './util/helpers';202021describe('integration test: ext. createCollection():', () => {21describe('integration test: ext. createCollection():', () => {22 it('Create new NFT collection', async () => {22 it('Create new NFT collection', async () => {34 it('Create new Fungible collection', async () => {34 it('Create new Fungible collection', async () => {35 await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});35 await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});36 });36 });37 it('Create new ReFungible collection', async () => {37 it('Create new ReFungible collection', async function() {38 await requirePallets(this, [Pallets.ReFungible]);3938 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});40 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});39 });41 });tests/src/createItem.test.tsdiffbeforeafterboth29 itApi,29 itApi,30 normalizeAccountId,30 normalizeAccountId,31 getCreateItemResult,31 getCreateItemResult,32 requirePallets,33 Pallets,32} from './util/helpers';34} from './util/helpers';333534const expect = chai.expect;36const expect = chai.expect;79 }81 }808281 });83 });82 it('Create new item in ReFungible collection', async () => {84 it('Create new item in ReFungible collection', async function() {85 await requirePallets(this, [Pallets.ReFungible]);8683 const createMode = 'ReFungible';87 const createMode = 'ReFungible';84 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});88 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});96 await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);100 await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);97 await createItemExpectSuccess(bob, newCollectionID, createMode);101 await createItemExpectSuccess(bob, newCollectionID, createMode);98 });102 });99 it('Create new item in ReFungible collection with collection admin permissions', async () => {103 it('Create new item in ReFungible collection with collection admin permissions', async function() {104 await requirePallets(this, [Pallets.ReFungible]);105100 const createMode = 'ReFungible';106 const createMode = 'ReFungible';101 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});107 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});175 });181 });176 });182 });177183178 it('Check total pieces of ReFungible token', async () => {184 it('Check total pieces of ReFungible token', async function() {185 await requirePallets(this, [Pallets.ReFungible]);186179 await usingApi(async api => {187 await usingApi(async api => {180 const createMode = 'ReFungible';188 const createMode = 'ReFungible';219 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});227 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});220 await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;228 await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;221 });229 });222 it('Regular user cannot create new item in ReFungible collection', async () => {230 it('Regular user cannot create new item in ReFungible collection', async function() {231 await requirePallets(this, [Pallets.ReFungible]);232223 const createMode = 'ReFungible';233 const createMode = 'ReFungible';224 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});234 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});296 });306 });297 });307 });298308299 it('Check total pieces for invalid Refungible token', async () => {309 it('Check total pieces for invalid Refungible token', async function() {310 await requirePallets(this, [Pallets.ReFungible]);311300 await usingApi(async api => {312 await usingApi(async api => {301 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});313 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});tests/src/createMultipleItems.test.tsdiffbeforeafterboth33 createCollectionWithPropsExpectSuccess,33 createCollectionWithPropsExpectSuccess,34 createMultipleItemsWithPropsExpectSuccess,34 createMultipleItemsWithPropsExpectSuccess,35 getTokenProperties,35 getTokenProperties,36 requirePallets,37 Pallets,38 checkPalletsPresence,36} from './util/helpers';39} from './util/helpers';374038chai.use(chaiAsPromised);41chai.use(chaiAsPromised);91 });94 });92 });95 });939694 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {97 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async function() {98 await requirePallets(this, [Pallets.ReFungible]);9995 await usingApi(async (api, privateKeyWrapper) => {100 await usingApi(async (api, privateKeyWrapper) => {96 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});101 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});272 });277 });273 });278 });274279275 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {280 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async function() {281 await requirePallets(this, [Pallets.ReFungible]);282276 await usingApi(async (api: ApiPromise) => {283 await usingApi(async (api: ApiPromise) => {277 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});284 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});335 });342 });336 });343 });337344338 it('Regular user cannot create items in active ReFungible collection', async () => {345 it('Regular user cannot create items in active ReFungible collection', async function() {346 await requirePallets(this, [Pallets.ReFungible]);347339 await usingApi(async (api: ApiPromise) => {348 await usingApi(async (api: ApiPromise) => {340 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});349 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});358 });367 });359 });368 });369370 it('Create NFTs that has reached the maximum data limit', async function() {371 await usingApi(async (api, privateKeyWrapper) => {372 const collectionId = await createCollectionWithPropsExpectSuccess({373 propPerm: [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],374 });375 const alice = privateKeyWrapper('//Alice');376 const args = [377 {NFT: {properties: [{key: 'key', value: 'A'.repeat(32769)}]}},378 {NFT: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},379 {NFT: {properties: [{key: 'key', value: 'C'.repeat(32769)}]}},380 ];381 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);382 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;383 });384 });360385361 it('Create NFT and Re-fungible tokens that has reached the maximum data limit', async () => {386 it('Create Refungible tokens that has reached the maximum data limit', async function() {387 await requirePallets(this, [Pallets.ReFungible]);388362 await usingApi(async (api, privateKeyWrapper) => {389 await usingApi(async api => {363 // NFT364 const collectionId = await createCollectionWithPropsExpectSuccess({365 propPerm: [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],366 });367 const alice = privateKeyWrapper('//Alice');368 const args = [369 {NFT: {properties: [{key: 'key', value: 'A'.repeat(32769)}]}},370 {NFT: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},371 {NFT: {properties: [{key: 'key', value: 'C'.repeat(32769)}]}},372 ];373 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);374 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;375376 // ReFungible377 const collectionIdReFungible =390 const collectionIdReFungible =378 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});391 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});379 {392 {403 await usingApi(async (api: ApiPromise) => {416 await usingApi(async (api: ApiPromise) => {404 const collectionId = await createCollectionExpectSuccess();417 const collectionId = await createCollectionExpectSuccess();418419 const types = ['NFT', 'Fungible'];420421 if (await checkPalletsPresence([Pallets.ReFungible])) {422 types.push('ReFungible');423 }424405 const createMultipleItemsTx = api.tx.unique425 const createMultipleItemsTx = api.tx.unique406 .createMultipleItems(collectionId, normalizeAccountId(alice.address), ['NFT', 'Fungible', 'ReFungible']);426 .createMultipleItems(collectionId, normalizeAccountId(alice.address), types);407 await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/nonfungible\.NotNonfungibleDataUsedToMintFungibleCollectionToken/);427 await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/nonfungible\.NotNonfungibleDataUsedToMintFungibleCollectionToken/);408 // garbage collection :-D // lol428 // garbage collection :-D // lol409 await destroyCollectionExpectSuccess(collectionId);429 await destroyCollectionExpectSuccess(collectionId);tests/src/createMultipleItemsEx.test.tsdiffbeforeafterboth161617import {expect} from 'chai';17import {expect} from 'chai';18import usingApi, {executeTransaction} from './substrate/substrate-api';18import usingApi, {executeTransaction} from './substrate/substrate-api';19import {addCollectionAdminExpectSuccess, createCollectionExpectSuccess, createCollectionWithPropsExpectSuccess, getBalance, getLastTokenId, getTokenProperties} from './util/helpers';19import {addCollectionAdminExpectSuccess, createCollectionExpectSuccess, createCollectionWithPropsExpectSuccess, getBalance, getLastTokenId, getTokenProperties, requirePallets, Pallets} from './util/helpers';202021describe.only('Integration Test: createMultipleItemsEx', () => {21describe('Integration Test: createMultipleItemsEx', () => {22 it('can initialize multiple NFT with different owners', async () => {22 it('can initialize multiple NFT with different owners', async () => {23 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});23 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});24 await usingApi(async (api, privateKeyWrapper) => {24 await usingApi(async (api, privateKeyWrapper) => {146 });146 });147 });147 });148148149 it('can initialize an RFT with multiple owners', async () => {149 it('can initialize an RFT with multiple owners', async function() {150 await requirePallets(this, [Pallets.ReFungible]);151150 await usingApi(async (api, privateKeyWrapper) => {152 await usingApi(async (api, privateKeyWrapper) => {151 const alice = privateKeyWrapper('//Alice');153 const alice = privateKeyWrapper('//Alice');178 });180 });179 });181 });180182181 it('can initialize multiple RFTs with the same owner', async () => {183 it('can initialize multiple RFTs with the same owner', async function() {184 await requirePallets(this, [Pallets.ReFungible]);185182 await usingApi(async (api, privateKeyWrapper) => {186 await usingApi(async (api, privateKeyWrapper) => {183 const alice = privateKeyWrapper('//Alice');187 const alice = privateKeyWrapper('//Alice');389 });393 });390 });394 });391392 it('fails when trying to set multiple owners when creating multiple refungibles', async () => {393 const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});394395 await usingApi(async (api, privateKeyWrapper) => {396 const alice = privateKeyWrapper('//Alice');397 const bob = privateKeyWrapper('//Bob');398 // Polkadot requires map, and yet requires keys to be JSON encoded399 const users = new Map();400 users.set(JSON.stringify({substrate: alice.address}), 1);401 users.set(JSON.stringify({substrate: bob.address}), 1);402403 // TODO: better error message?404 await expect(executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {405 RefungibleMultipleItems: [406 {users},407 {users},408 ],409 }))).to.be.rejectedWith(/^refungible\.NotRefungibleDataUsedToMintFungibleCollectionToken$/);410 });411 });412});395});413396tests/src/destroyCollection.test.tsdiffbeforeafterboth25 addCollectionAdminExpectSuccess,25 addCollectionAdminExpectSuccess,26 getCreatedCollectionCount,26 getCreatedCollectionCount,27 createItemExpectSuccess,27 createItemExpectSuccess,28 requirePallets,29 Pallets,28} from './util/helpers';30} from './util/helpers';293130chai.use(chaiAsPromised);32chai.use(chaiAsPromised);38 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});40 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});39 await destroyCollectionExpectSuccess(collectionId);41 await destroyCollectionExpectSuccess(collectionId);40 });42 });41 it('ReFungible collection can be destroyed', async () => {43 it('ReFungible collection can be destroyed', async function() {44 await requirePallets(this, [Pallets.ReFungible]);4542 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});46 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});43 await destroyCollectionExpectSuccess(collectionId);47 await destroyCollectionExpectSuccess(collectionId);tests/src/eth/api/CollectionHelpers.soldiffbeforeafterboth48 string memory name,48 string memory name,49 string memory description,49 string memory description,50 string memory tokenPrefix50 string memory tokenPrefix51 ) external view returns (address);51 ) external returns (address);525253 // Selector: createERC721MetadataCompatibleRFTCollection(string,string,string,string) a559638853 // Selector: createERC721MetadataCompatibleRFTCollection(string,string,string,string) a559638854 function createERC721MetadataCompatibleRFTCollection(54 function createERC721MetadataCompatibleRFTCollection(tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth22 );22 );23}23}2425// Selector: 6cf113cd26interface Collection is Dummy, ERC165 {27 // Set collection property.28 //29 // @param key Property key.30 // @param value Propery value.31 //32 // Selector: setCollectionProperty(string,bytes) 2f073f6633 function setCollectionProperty(string memory key, bytes memory value)34 external;3536 // Delete collection property.37 //38 // @param key Property key.39 //40 // Selector: deleteCollectionProperty(string) 7b7debce41 function deleteCollectionProperty(string memory key) external;4243 // Get collection property.44 //45 // @dev Throws error if key not found.46 //47 // @param key Property key.48 // @return bytes The property corresponding to the key.49 //50 // Selector: collectionProperty(string) cf24fd6d51 function collectionProperty(string memory key)52 external53 view54 returns (bytes memory);5556 // Set the sponsor of the collection.57 //58 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.59 //60 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.61 //62 // Selector: setCollectionSponsor(address) 7623402e63 function setCollectionSponsor(address sponsor) external;6465 // Collection sponsorship confirmation.66 //67 // @dev After setting the sponsor for the collection, it must be confirmed with this function.68 //69 // Selector: confirmCollectionSponsorship() 3c50e97a70 function confirmCollectionSponsorship() external;7172 // Set limits for the collection.73 // @dev Throws error if limit not found.74 // @param limit Name of the limit. Valid names:75 // "accountTokenOwnershipLimit",76 // "sponsoredDataSize",77 // "sponsoredDataRateLimit",78 // "tokenLimit",79 // "sponsorTransferTimeout",80 // "sponsorApproveTimeout"81 // @param value Value of the limit.82 //83 // Selector: setCollectionLimit(string,uint32) 6a3841db84 function setCollectionLimit(string memory limit, uint32 value) external;8586 // Set limits for the collection.87 // @dev Throws error if limit not found.88 // @param limit Name of the limit. Valid names:89 // "ownerCanTransfer",90 // "ownerCanDestroy",91 // "transfersEnabled"92 // @param value Value of the limit.93 //94 // Selector: setCollectionLimit(string,bool) 993b7fba95 function setCollectionLimit(string memory limit, bool value) external;9697 // Get contract address.98 //99 // Selector: contractAddress() f6b4dfb4100 function contractAddress() external view returns (address);101102 // Add collection admin by substrate address.103 // @param new_admin Substrate administrator address.104 //105 // Selector: addCollectionAdminSubstrate(uint256) 5730062b106 function addCollectionAdminSubstrate(uint256 newAdmin) external;107108 // Remove collection admin by substrate address.109 // @param admin Substrate administrator address.110 //111 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9112 function removeCollectionAdminSubstrate(uint256 admin) external;113114 // Add collection admin.115 // @param new_admin Address of the added administrator.116 //117 // Selector: addCollectionAdmin(address) 92e462c7118 function addCollectionAdmin(address newAdmin) external;119120 // Remove collection admin.121 //122 // @param new_admin Address of the removed administrator.123 //124 // Selector: removeCollectionAdmin(address) fafd7b42125 function removeCollectionAdmin(address admin) external;126127 // Toggle accessibility of collection nesting.128 //129 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'130 //131 // Selector: setCollectionNesting(bool) 112d4586132 function setCollectionNesting(bool enable) external;133134 // Toggle accessibility of collection nesting.135 //136 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'137 // @param collections Addresses of collections that will be available for nesting.138 //139 // Selector: setCollectionNesting(bool,address[]) 64872396140 function setCollectionNesting(bool enable, address[] memory collections)141 external;142143 // Set the collection access method.144 // @param mode Access mode145 // 0 for Normal146 // 1 for AllowList147 //148 // Selector: setCollectionAccess(uint8) 41835d4c149 function setCollectionAccess(uint8 mode) external;150151 // Add the user to the allowed list.152 //153 // @param user Address of a trusted user.154 //155 // Selector: addToCollectionAllowList(address) 67844fe6156 function addToCollectionAllowList(address user) external;157158 // Remove the user from the allowed list.159 //160 // @param user Address of a removed user.161 //162 // Selector: removeFromCollectionAllowList(address) 85c51acb163 function removeFromCollectionAllowList(address user) external;164165 // Switch permission for minting.166 //167 // @param mode Enable if "true".168 //169 // Selector: setCollectionMintMode(bool) 00018e84170 function setCollectionMintMode(bool mode) external;171172 // Check that account is the owner or admin of the collection173 //174 // @param user account to verify175 // @return "true" if account is the owner or admin176 //177 // Selector: verifyOwnerOrAdmin(address) c2282493178 function verifyOwnerOrAdmin(address user) external view returns (bool);179180 // Returns collection type181 //182 // @return `Fungible` or `NFT` or `ReFungible`183 //184 // Selector: uniqueCollectionType() d34b55b8185 function uniqueCollectionType() external returns (string memory);186}2418725// Selector: 79cc6790188// Selector: 79cc679026interface ERC20UniqueExtensions is Dummy, ERC165 {189interface ERC20UniqueExtensions is Dummy, ERC165 {27 // Selector: burnFrom(address,uint256) 79cc6790190 // Selector: burnFrom(address,uint256) 79cc679028 function burnFrom(address from, uint256 amount) external returns (bool);191 function burnFrom(address from, uint256 amount) external returns (bool);29}192}3031// Selector: 7d9262e632interface Collection is Dummy, ERC165 {33 // Set collection property.34 //35 // @param key Property key.36 // @param value Propery value.37 //38 // Selector: setCollectionProperty(string,bytes) 2f073f6639 function setCollectionProperty(string memory key, bytes memory value)40 external;4142 // Delete collection property.43 //44 // @param key Property key.45 //46 // Selector: deleteCollectionProperty(string) 7b7debce47 function deleteCollectionProperty(string memory key) external;4849 // Get collection property.50 //51 // @dev Throws error if key not found.52 //53 // @param key Property key.54 // @return bytes The property corresponding to the key.55 //56 // Selector: collectionProperty(string) cf24fd6d57 function collectionProperty(string memory key)58 external59 view60 returns (bytes memory);6162 // Set the sponsor of the collection.63 //64 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.65 //66 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.67 //68 // Selector: setCollectionSponsor(address) 7623402e69 function setCollectionSponsor(address sponsor) external;7071 // Collection sponsorship confirmation.72 //73 // @dev After setting the sponsor for the collection, it must be confirmed with this function.74 //75 // Selector: confirmCollectionSponsorship() 3c50e97a76 function confirmCollectionSponsorship() external;7778 // Set limits for the collection.79 // @dev Throws error if limit not found.80 // @param limit Name of the limit. Valid names:81 // "accountTokenOwnershipLimit",82 // "sponsoredDataSize",83 // "sponsoredDataRateLimit",84 // "tokenLimit",85 // "sponsorTransferTimeout",86 // "sponsorApproveTimeout"87 // @param value Value of the limit.88 //89 // Selector: setCollectionLimit(string,uint32) 6a3841db90 function setCollectionLimit(string memory limit, uint32 value) external;9192 // Set limits for the collection.93 // @dev Throws error if limit not found.94 // @param limit Name of the limit. Valid names:95 // "ownerCanTransfer",96 // "ownerCanDestroy",97 // "transfersEnabled"98 // @param value Value of the limit.99 //100 // Selector: setCollectionLimit(string,bool) 993b7fba101 function setCollectionLimit(string memory limit, bool value) external;102103 // Get contract address.104 //105 // Selector: contractAddress() f6b4dfb4106 function contractAddress() external view returns (address);107108 // Add collection admin by substrate address.109 // @param new_admin Substrate administrator address.110 //111 // Selector: addCollectionAdminSubstrate(uint256) 5730062b112 function addCollectionAdminSubstrate(uint256 newAdmin) external;113114 // Remove collection admin by substrate address.115 // @param admin Substrate administrator address.116 //117 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9118 function removeCollectionAdminSubstrate(uint256 admin) external;119120 // Add collection admin.121 // @param new_admin Address of the added administrator.122 //123 // Selector: addCollectionAdmin(address) 92e462c7124 function addCollectionAdmin(address newAdmin) external;125126 // Remove collection admin.127 //128 // @param new_admin Address of the removed administrator.129 //130 // Selector: removeCollectionAdmin(address) fafd7b42131 function removeCollectionAdmin(address admin) external;132133 // Toggle accessibility of collection nesting.134 //135 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'136 //137 // Selector: setCollectionNesting(bool) 112d4586138 function setCollectionNesting(bool enable) external;139140 // Toggle accessibility of collection nesting.141 //142 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'143 // @param collections Addresses of collections that will be available for nesting.144 //145 // Selector: setCollectionNesting(bool,address[]) 64872396146 function setCollectionNesting(bool enable, address[] memory collections)147 external;148149 // Set the collection access method.150 // @param mode Access mode151 // 0 for Normal152 // 1 for AllowList153 //154 // Selector: setCollectionAccess(uint8) 41835d4c155 function setCollectionAccess(uint8 mode) external;156157 // Add the user to the allowed list.158 //159 // @param user Address of a trusted user.160 //161 // Selector: addToCollectionAllowList(address) 67844fe6162 function addToCollectionAllowList(address user) external;163164 // Remove the user from the allowed list.165 //166 // @param user Address of a removed user.167 //168 // Selector: removeFromCollectionAllowList(address) 85c51acb169 function removeFromCollectionAllowList(address user) external;170171 // Switch permission for minting.172 //173 // @param mode Enable if "true".174 //175 // Selector: setCollectionMintMode(bool) 00018e84176 function setCollectionMintMode(bool mode) external;177}178193179// Selector: 942e8b22194// Selector: 942e8b22180interface ERC20 is Dummy, ERC165, ERC20Events {195interface ERC20 is Dummy, ERC165, ERC20Events {tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth250 function finishMinting() external returns (bool);250 function finishMinting() external returns (bool);251}251}252253// Selector: 6cf113cd254interface Collection is Dummy, ERC165 {255 // Set collection property.256 //257 // @param key Property key.258 // @param value Propery value.259 //260 // Selector: setCollectionProperty(string,bytes) 2f073f66261 function setCollectionProperty(string memory key, bytes memory value)262 external;263264 // Delete collection property.265 //266 // @param key Property key.267 //268 // Selector: deleteCollectionProperty(string) 7b7debce269 function deleteCollectionProperty(string memory key) external;270271 // Get collection property.272 //273 // @dev Throws error if key not found.274 //275 // @param key Property key.276 // @return bytes The property corresponding to the key.277 //278 // Selector: collectionProperty(string) cf24fd6d279 function collectionProperty(string memory key)280 external281 view282 returns (bytes memory);283284 // Set the sponsor of the collection.285 //286 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.287 //288 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.289 //290 // Selector: setCollectionSponsor(address) 7623402e291 function setCollectionSponsor(address sponsor) external;292293 // Collection sponsorship confirmation.294 //295 // @dev After setting the sponsor for the collection, it must be confirmed with this function.296 //297 // Selector: confirmCollectionSponsorship() 3c50e97a298 function confirmCollectionSponsorship() external;299300 // Set limits for the collection.301 // @dev Throws error if limit not found.302 // @param limit Name of the limit. Valid names:303 // "accountTokenOwnershipLimit",304 // "sponsoredDataSize",305 // "sponsoredDataRateLimit",306 // "tokenLimit",307 // "sponsorTransferTimeout",308 // "sponsorApproveTimeout"309 // @param value Value of the limit.310 //311 // Selector: setCollectionLimit(string,uint32) 6a3841db312 function setCollectionLimit(string memory limit, uint32 value) external;313314 // Set limits for the collection.315 // @dev Throws error if limit not found.316 // @param limit Name of the limit. Valid names:317 // "ownerCanTransfer",318 // "ownerCanDestroy",319 // "transfersEnabled"320 // @param value Value of the limit.321 //322 // Selector: setCollectionLimit(string,bool) 993b7fba323 function setCollectionLimit(string memory limit, bool value) external;324325 // Get contract address.326 //327 // Selector: contractAddress() f6b4dfb4328 function contractAddress() external view returns (address);329330 // Add collection admin by substrate address.331 // @param new_admin Substrate administrator address.332 //333 // Selector: addCollectionAdminSubstrate(uint256) 5730062b334 function addCollectionAdminSubstrate(uint256 newAdmin) external;335336 // Remove collection admin by substrate address.337 // @param admin Substrate administrator address.338 //339 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9340 function removeCollectionAdminSubstrate(uint256 admin) external;341342 // Add collection admin.343 // @param new_admin Address of the added administrator.344 //345 // Selector: addCollectionAdmin(address) 92e462c7346 function addCollectionAdmin(address newAdmin) external;347348 // Remove collection admin.349 //350 // @param new_admin Address of the removed administrator.351 //352 // Selector: removeCollectionAdmin(address) fafd7b42353 function removeCollectionAdmin(address admin) external;354355 // Toggle accessibility of collection nesting.356 //357 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'358 //359 // Selector: setCollectionNesting(bool) 112d4586360 function setCollectionNesting(bool enable) external;361362 // Toggle accessibility of collection nesting.363 //364 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'365 // @param collections Addresses of collections that will be available for nesting.366 //367 // Selector: setCollectionNesting(bool,address[]) 64872396368 function setCollectionNesting(bool enable, address[] memory collections)369 external;370371 // Set the collection access method.372 // @param mode Access mode373 // 0 for Normal374 // 1 for AllowList375 //376 // Selector: setCollectionAccess(uint8) 41835d4c377 function setCollectionAccess(uint8 mode) external;378379 // Add the user to the allowed list.380 //381 // @param user Address of a trusted user.382 //383 // Selector: addToCollectionAllowList(address) 67844fe6384 function addToCollectionAllowList(address user) external;385386 // Remove the user from the allowed list.387 //388 // @param user Address of a removed user.389 //390 // Selector: removeFromCollectionAllowList(address) 85c51acb391 function removeFromCollectionAllowList(address user) external;392393 // Switch permission for minting.394 //395 // @param mode Enable if "true".396 //397 // Selector: setCollectionMintMode(bool) 00018e84398 function setCollectionMintMode(bool mode) external;399400 // Check that account is the owner or admin of the collection401 //402 // @param user account to verify403 // @return "true" if account is the owner or admin404 //405 // Selector: verifyOwnerOrAdmin(address) c2282493406 function verifyOwnerOrAdmin(address user) external view returns (bool);407408 // Returns collection type409 //410 // @return `Fungible` or `NFT` or `ReFungible`411 //412 // Selector: uniqueCollectionType() d34b55b8413 function uniqueCollectionType() external returns (string memory);414}252415253// Selector: 780e9d63416// Selector: 780e9d63254interface ERC721Enumerable is Dummy, ERC165 {417interface ERC721Enumerable is Dummy, ERC165 {276 function totalSupply() external view returns (uint256);439 function totalSupply() external view returns (uint256);277}440}278279// Selector: 7d9262e6280interface Collection is Dummy, ERC165 {281 // Set collection property.282 //283 // @param key Property key.284 // @param value Propery value.285 //286 // Selector: setCollectionProperty(string,bytes) 2f073f66287 function setCollectionProperty(string memory key, bytes memory value)288 external;289290 // Delete collection property.291 //292 // @param key Property key.293 //294 // Selector: deleteCollectionProperty(string) 7b7debce295 function deleteCollectionProperty(string memory key) external;296297 // Get collection property.298 //299 // @dev Throws error if key not found.300 //301 // @param key Property key.302 // @return bytes The property corresponding to the key.303 //304 // Selector: collectionProperty(string) cf24fd6d305 function collectionProperty(string memory key)306 external307 view308 returns (bytes memory);309310 // Set the sponsor of the collection.311 //312 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.313 //314 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.315 //316 // Selector: setCollectionSponsor(address) 7623402e317 function setCollectionSponsor(address sponsor) external;318319 // Collection sponsorship confirmation.320 //321 // @dev After setting the sponsor for the collection, it must be confirmed with this function.322 //323 // Selector: confirmCollectionSponsorship() 3c50e97a324 function confirmCollectionSponsorship() external;325326 // Set limits for the collection.327 // @dev Throws error if limit not found.328 // @param limit Name of the limit. Valid names:329 // "accountTokenOwnershipLimit",330 // "sponsoredDataSize",331 // "sponsoredDataRateLimit",332 // "tokenLimit",333 // "sponsorTransferTimeout",334 // "sponsorApproveTimeout"335 // @param value Value of the limit.336 //337 // Selector: setCollectionLimit(string,uint32) 6a3841db338 function setCollectionLimit(string memory limit, uint32 value) external;339340 // Set limits for the collection.341 // @dev Throws error if limit not found.342 // @param limit Name of the limit. Valid names:343 // "ownerCanTransfer",344 // "ownerCanDestroy",345 // "transfersEnabled"346 // @param value Value of the limit.347 //348 // Selector: setCollectionLimit(string,bool) 993b7fba349 function setCollectionLimit(string memory limit, bool value) external;350351 // Get contract address.352 //353 // Selector: contractAddress() f6b4dfb4354 function contractAddress() external view returns (address);355356 // Add collection admin by substrate address.357 // @param new_admin Substrate administrator address.358 //359 // Selector: addCollectionAdminSubstrate(uint256) 5730062b360 function addCollectionAdminSubstrate(uint256 newAdmin) external;361362 // Remove collection admin by substrate address.363 // @param admin Substrate administrator address.364 //365 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9366 function removeCollectionAdminSubstrate(uint256 admin) external;367368 // Add collection admin.369 // @param new_admin Address of the added administrator.370 //371 // Selector: addCollectionAdmin(address) 92e462c7372 function addCollectionAdmin(address newAdmin) external;373374 // Remove collection admin.375 //376 // @param new_admin Address of the removed administrator.377 //378 // Selector: removeCollectionAdmin(address) fafd7b42379 function removeCollectionAdmin(address admin) external;380381 // Toggle accessibility of collection nesting.382 //383 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'384 //385 // Selector: setCollectionNesting(bool) 112d4586386 function setCollectionNesting(bool enable) external;387388 // Toggle accessibility of collection nesting.389 //390 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'391 // @param collections Addresses of collections that will be available for nesting.392 //393 // Selector: setCollectionNesting(bool,address[]) 64872396394 function setCollectionNesting(bool enable, address[] memory collections)395 external;396397 // Set the collection access method.398 // @param mode Access mode399 // 0 for Normal400 // 1 for AllowList401 //402 // Selector: setCollectionAccess(uint8) 41835d4c403 function setCollectionAccess(uint8 mode) external;404405 // Add the user to the allowed list.406 //407 // @param user Address of a trusted user.408 //409 // Selector: addToCollectionAllowList(address) 67844fe6410 function addToCollectionAllowList(address user) external;411412 // Remove the user from the allowed list.413 //414 // @param user Address of a removed user.415 //416 // Selector: removeFromCollectionAllowList(address) 85c51acb417 function removeFromCollectionAllowList(address user) external;418419 // Switch permission for minting.420 //421 // @param mode Enable if "true".422 //423 // Selector: setCollectionMintMode(bool) 00018e84424 function setCollectionMintMode(bool mode) external;425}426441427// Selector: d74d154f442// Selector: d74d154f428interface ERC721UniqueExtensions is Dummy, ERC165 {443interface ERC721UniqueExtensions is Dummy, ERC165 {tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth248 function finishMinting() external returns (bool);248 function finishMinting() external returns (bool);249}249}250251// Selector: 6cf113cd252interface Collection is Dummy, ERC165 {253 // Set collection property.254 //255 // @param key Property key.256 // @param value Propery value.257 //258 // Selector: setCollectionProperty(string,bytes) 2f073f66259 function setCollectionProperty(string memory key, bytes memory value)260 external;261262 // Delete collection property.263 //264 // @param key Property key.265 //266 // Selector: deleteCollectionProperty(string) 7b7debce267 function deleteCollectionProperty(string memory key) external;268269 // Get collection property.270 //271 // @dev Throws error if key not found.272 //273 // @param key Property key.274 // @return bytes The property corresponding to the key.275 //276 // Selector: collectionProperty(string) cf24fd6d277 function collectionProperty(string memory key)278 external279 view280 returns (bytes memory);281282 // Set the sponsor of the collection.283 //284 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.285 //286 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.287 //288 // Selector: setCollectionSponsor(address) 7623402e289 function setCollectionSponsor(address sponsor) external;290291 // Collection sponsorship confirmation.292 //293 // @dev After setting the sponsor for the collection, it must be confirmed with this function.294 //295 // Selector: confirmCollectionSponsorship() 3c50e97a296 function confirmCollectionSponsorship() external;297298 // Set limits for the collection.299 // @dev Throws error if limit not found.300 // @param limit Name of the limit. Valid names:301 // "accountTokenOwnershipLimit",302 // "sponsoredDataSize",303 // "sponsoredDataRateLimit",304 // "tokenLimit",305 // "sponsorTransferTimeout",306 // "sponsorApproveTimeout"307 // @param value Value of the limit.308 //309 // Selector: setCollectionLimit(string,uint32) 6a3841db310 function setCollectionLimit(string memory limit, uint32 value) external;311312 // Set limits for the collection.313 // @dev Throws error if limit not found.314 // @param limit Name of the limit. Valid names:315 // "ownerCanTransfer",316 // "ownerCanDestroy",317 // "transfersEnabled"318 // @param value Value of the limit.319 //320 // Selector: setCollectionLimit(string,bool) 993b7fba321 function setCollectionLimit(string memory limit, bool value) external;322323 // Get contract address.324 //325 // Selector: contractAddress() f6b4dfb4326 function contractAddress() external view returns (address);327328 // Add collection admin by substrate address.329 // @param new_admin Substrate administrator address.330 //331 // Selector: addCollectionAdminSubstrate(uint256) 5730062b332 function addCollectionAdminSubstrate(uint256 newAdmin) external;333334 // Remove collection admin by substrate address.335 // @param admin Substrate administrator address.336 //337 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9338 function removeCollectionAdminSubstrate(uint256 admin) external;339340 // Add collection admin.341 // @param new_admin Address of the added administrator.342 //343 // Selector: addCollectionAdmin(address) 92e462c7344 function addCollectionAdmin(address newAdmin) external;345346 // Remove collection admin.347 //348 // @param new_admin Address of the removed administrator.349 //350 // Selector: removeCollectionAdmin(address) fafd7b42351 function removeCollectionAdmin(address admin) external;352353 // Toggle accessibility of collection nesting.354 //355 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'356 //357 // Selector: setCollectionNesting(bool) 112d4586358 function setCollectionNesting(bool enable) external;359360 // Toggle accessibility of collection nesting.361 //362 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'363 // @param collections Addresses of collections that will be available for nesting.364 //365 // Selector: setCollectionNesting(bool,address[]) 64872396366 function setCollectionNesting(bool enable, address[] memory collections)367 external;368369 // Set the collection access method.370 // @param mode Access mode371 // 0 for Normal372 // 1 for AllowList373 //374 // Selector: setCollectionAccess(uint8) 41835d4c375 function setCollectionAccess(uint8 mode) external;376377 // Add the user to the allowed list.378 //379 // @param user Address of a trusted user.380 //381 // Selector: addToCollectionAllowList(address) 67844fe6382 function addToCollectionAllowList(address user) external;383384 // Remove the user from the allowed list.385 //386 // @param user Address of a removed user.387 //388 // Selector: removeFromCollectionAllowList(address) 85c51acb389 function removeFromCollectionAllowList(address user) external;390391 // Switch permission for minting.392 //393 // @param mode Enable if "true".394 //395 // Selector: setCollectionMintMode(bool) 00018e84396 function setCollectionMintMode(bool mode) external;397398 // Check that account is the owner or admin of the collection399 //400 // @param user account to verify401 // @return "true" if account is the owner or admin402 //403 // Selector: verifyOwnerOrAdmin(address) c2282493404 function verifyOwnerOrAdmin(address user) external view returns (bool);405406 // Returns collection type407 //408 // @return `Fungible` or `NFT` or `ReFungible`409 //410 // Selector: uniqueCollectionType() d34b55b8411 function uniqueCollectionType() external returns (string memory);412}250413251// Selector: 780e9d63414// Selector: 780e9d63252interface ERC721Enumerable is Dummy, ERC165 {415interface ERC721Enumerable is Dummy, ERC165 {274 function totalSupply() external view returns (uint256);437 function totalSupply() external view returns (uint256);275}438}276439277// Selector: 7d9262e6440// Selector: 7c3bef89278interface Collection is Dummy, ERC165 {279 // Set collection property.280 //281 // @param key Property key.282 // @param value Propery value.283 //284 // Selector: setCollectionProperty(string,bytes) 2f073f66285 function setCollectionProperty(string memory key, bytes memory value)286 external;287288 // Delete collection property.289 //290 // @param key Property key.291 //292 // Selector: deleteCollectionProperty(string) 7b7debce293 function deleteCollectionProperty(string memory key) external;294295 // Get collection property.296 //297 // @dev Throws error if key not found.298 //299 // @param key Property key.300 // @return bytes The property corresponding to the key.301 //302 // Selector: collectionProperty(string) cf24fd6d303 function collectionProperty(string memory key)304 external305 view306 returns (bytes memory);307308 // Set the sponsor of the collection.309 //310 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.311 //312 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.313 //314 // Selector: setCollectionSponsor(address) 7623402e315 function setCollectionSponsor(address sponsor) external;316317 // Collection sponsorship confirmation.318 //319 // @dev After setting the sponsor for the collection, it must be confirmed with this function.320 //321 // Selector: confirmCollectionSponsorship() 3c50e97a322 function confirmCollectionSponsorship() external;323324 // Set limits for the collection.325 // @dev Throws error if limit not found.326 // @param limit Name of the limit. Valid names:327 // "accountTokenOwnershipLimit",328 // "sponsoredDataSize",329 // "sponsoredDataRateLimit",330 // "tokenLimit",331 // "sponsorTransferTimeout",332 // "sponsorApproveTimeout"333 // @param value Value of the limit.334 //335 // Selector: setCollectionLimit(string,uint32) 6a3841db336 function setCollectionLimit(string memory limit, uint32 value) external;337338 // Set limits for the collection.339 // @dev Throws error if limit not found.340 // @param limit Name of the limit. Valid names:341 // "ownerCanTransfer",342 // "ownerCanDestroy",343 // "transfersEnabled"344 // @param value Value of the limit.345 //346 // Selector: setCollectionLimit(string,bool) 993b7fba347 function setCollectionLimit(string memory limit, bool value) external;348349 // Get contract address.350 //351 // Selector: contractAddress() f6b4dfb4352 function contractAddress() external view returns (address);353354 // Add collection admin by substrate address.355 // @param new_admin Substrate administrator address.356 //357 // Selector: addCollectionAdminSubstrate(uint256) 5730062b358 function addCollectionAdminSubstrate(uint256 newAdmin) external;359360 // Remove collection admin by substrate address.361 // @param admin Substrate administrator address.362 //363 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9364 function removeCollectionAdminSubstrate(uint256 admin) external;365366 // Add collection admin.367 // @param new_admin Address of the added administrator.368 //369 // Selector: addCollectionAdmin(address) 92e462c7370 function addCollectionAdmin(address newAdmin) external;371372 // Remove collection admin.373 //374 // @param new_admin Address of the removed administrator.375 //376 // Selector: removeCollectionAdmin(address) fafd7b42377 function removeCollectionAdmin(address admin) external;378379 // Toggle accessibility of collection nesting.380 //381 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'382 //383 // Selector: setCollectionNesting(bool) 112d4586384 function setCollectionNesting(bool enable) external;385386 // Toggle accessibility of collection nesting.387 //388 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'389 // @param collections Addresses of collections that will be available for nesting.390 //391 // Selector: setCollectionNesting(bool,address[]) 64872396392 function setCollectionNesting(bool enable, address[] memory collections)393 external;394395 // Set the collection access method.396 // @param mode Access mode397 // 0 for Normal398 // 1 for AllowList399 //400 // Selector: setCollectionAccess(uint8) 41835d4c401 function setCollectionAccess(uint8 mode) external;402403 // Add the user to the allowed list.404 //405 // @param user Address of a trusted user.406 //407 // Selector: addToCollectionAllowList(address) 67844fe6408 function addToCollectionAllowList(address user) external;409410 // Remove the user from the allowed list.411 //412 // @param user Address of a removed user.413 //414 // Selector: removeFromCollectionAllowList(address) 85c51acb415 function removeFromCollectionAllowList(address user) external;416417 // Switch permission for minting.418 //419 // @param mode Enable if "true".420 //421 // Selector: setCollectionMintMode(bool) 00018e84422 function setCollectionMintMode(bool mode) external;423}424425// Selector: d74d154f426interface ERC721UniqueExtensions is Dummy, ERC165 {441interface ERC721UniqueExtensions is Dummy, ERC165 {427 // @notice Transfer ownership of an RFT442 // @notice Transfer ownership of an RFT428 // @dev Throws unless `msg.sender` is the current owner. Throws if `to`443 // @dev Throws unless `msg.sender` is the current owner. Throws if `to`474 external489 external475 returns (bool);490 returns (bool);491492 // Returns EVM address for refungible token493 //494 // @param token ID of the token495 //496 // Selector: tokenContractAddress(uint256) ab76fac6497 function tokenContractAddress(uint256 token)498 external499 view500 returns (address);476}501}477502478interface UniqueRefungible is503interface UniqueRefungible istests/src/eth/api/UniqueRefungibleToken.soldiffbeforeafterboth22 );22 );23}23}2425// Selector: 042f110626interface ERC1633UniqueExtensions is Dummy, ERC165 {27 // Selector: setParentNFT(address,uint256) 042f110628 function setParentNFT(address collection, uint256 nftId)29 external30 returns (bool);31}3233// Selector: 5755c3f234interface ERC1633 is Dummy, ERC165 {35 // Selector: parentToken() 80a5400136 function parentToken() external view returns (address);3738 // Selector: parentTokenId() d7f083f339 function parentTokenId() external view returns (uint256);40}244125// Selector: 942e8b2242// Selector: 942e8b2226interface ERC20 is Dummy, ERC165, ERC20Events {43interface ERC20 is Dummy, ERC165, ERC20Events {115 Dummy,132 Dummy,116 ERC165,133 ERC165,117 ERC20,134 ERC20,118 ERC20UniqueExtensions135 ERC20UniqueExtensions,136 ERC1633,137 ERC1633UniqueExtensions119{}138{}120139tests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth60 .to.be.eq(newAdmin.address.toLocaleLowerCase());60 .to.be.eq(newAdmin.address.toLocaleLowerCase());61 });61 });62 63 itWeb3('Verify owner or admin', async ({api, web3, privateKeyWrapper}) => {64 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);65 const collectionHelper = evmCollectionHelpers(web3, owner);66 67 const result = await collectionHelper.methods68 .createNonfungibleCollection('A', 'B', 'C')69 .send();70 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);7172 const newAdmin = createEthAccount(web3);73 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);74 expect(await collectionEvm.methods.verifyOwnerOrAdmin(newAdmin).call()).to.be.false;75 await collectionEvm.methods.addCollectionAdmin(newAdmin).send();76 expect(await collectionEvm.methods.verifyOwnerOrAdmin(newAdmin).call()).to.be.true;77 });627863 itWeb3('(!negative tests!) Add admin by ADMIN is not allowed', async ({api, web3, privateKeyWrapper}) => {79 itWeb3('(!negative tests!) Add admin by ADMIN is not allowed', async ({api, web3, privateKeyWrapper}) => {64 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);80 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);tests/src/eth/collectionHelpersAbi.jsondiffbeforeafterboth61 ],61 ],62 "name": "createRefungibleCollection",62 "name": "createRefungibleCollection",63 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],63 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],64 "stateMutability": "view",64 "stateMutability": "nonpayable",65 "type": "function"65 "type": "function"66 },66 },67 {67 {tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth161617import {evmToAddress} from '@polkadot/util-crypto';17import {evmToAddress} from '@polkadot/util-crypto';18import {expect} from 'chai';18import {expect} from 'chai';19import {getCreatedCollectionCount, getDetailedCollectionInfo} from '../util/helpers';19import {getCreatedCollectionCount, getDetailedCollectionInfo, requirePallets, Pallets} from '../util/helpers';20import {20import {21 evmCollectionHelpers,21 evmCollectionHelpers,22 collectionIdToAddress,22 collectionIdToAddress,28} from './util/helpers';28} from './util/helpers';292930describe('Create RFT collection from EVM', () => {30describe('Create RFT collection from EVM', () => {31 before(async function() {32 await requirePallets(this, [Pallets.ReFungible]);33 });3431 itWeb3('Create collection', async ({api, web3, privateKeyWrapper}) => {35 itWeb3('Create collection', async ({api, web3, privateKeyWrapper}) => {32 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);36 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);146});150});147151148describe('(!negative tests!) Create RFT collection from EVM', () => {152describe('(!negative tests!) Create RFT collection from EVM', () => {153 before(async function() {154 await requirePallets(this, [Pallets.ReFungible]);155 });156149 itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3, privateKeyWrapper}) => {157 itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3, privateKeyWrapper}) => {150 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);158 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);tests/src/eth/fractionalizer/Fractionalizer.bindiffbeforeafterbothno changes
tests/src/eth/fractionalizer/Fractionalizer.soldiffbeforeafterbothno changes
tests/src/eth/fractionalizer/FractionalizerAbi.jsondiffbeforeafterbothno changes
tests/src/eth/fractionalizer/fractionalizer.test.tsdiffbeforeafterbothno changes
tests/src/eth/fungibleAbi.jsondiffbeforeafterboth301 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],301 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],302 "stateMutability": "nonpayable",302 "stateMutability": "nonpayable",303 "type": "function"303 "type": "function"304 }304 },305 {306 "inputs": [],307 "name": "uniqueCollectionType",308 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],309 "stateMutability": "nonpayable",310 "type": "function"311 },312 {313 "inputs": [314 { "internalType": "address", "name": "user", "type": "address" }315 ],316 "name": "verifyOwnerOrAdmin",317 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],318 "stateMutability": "view",319 "type": "function"320 }305]321]306322tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth526 "outputs": [],526 "outputs": [],527 "stateMutability": "nonpayable",527 "stateMutability": "nonpayable",528 "type": "function"528 "type": "function"529 }529 },530 {531 "inputs": [],532 "name": "uniqueCollectionType",533 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],534 "stateMutability": "nonpayable",535 "type": "function"536 },537 {538 "inputs": [539 { "internalType": "address", "name": "user", "type": "address" }540 ],541 "name": "verifyOwnerOrAdmin",542 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],543 "stateMutability": "view",544 "type": "function"545 }530]546]531547tests/src/eth/reFungible.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.161617import {createCollectionExpectSuccess, UNIQUE} from '../util/helpers';17import {createCollectionExpectSuccess, UNIQUE, requirePallets, Pallets} from '../util/helpers';18import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, tokenIdToAddress} from './util/helpers';18import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, tokenIdToAddress, uniqueRefungibleToken} from './util/helpers';19import reFungibleTokenAbi from './reFungibleTokenAbi.json';20import {expect} from 'chai';19import {expect} from 'chai';212022describe('Refungible: Information getting', () => {21describe('Refungible: Information getting', () => {22 before(async function() {23 await requirePallets(this, [Pallets.ReFungible]);24 });2523 itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {26 itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {24 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);27 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);84 await contract.methods.mint(caller, tokenId).send();87 await contract.methods.mint(caller, tokenId).send();858886 const tokenAddress = tokenIdToAddress(collectionId, tokenId);89 const tokenAddress = tokenIdToAddress(collectionId, tokenId);87 const tokenContract = new web3.eth.Contract(reFungibleTokenAbi as any, tokenAddress, {from: caller, ...GAS_ARGS});90 const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller);889189 await tokenContract.methods.repartition(2).send();92 await tokenContract.methods.repartition(2).send();90 await tokenContract.methods.transfer(receiver, 1).send();93 await tokenContract.methods.transfer(receiver, 1).send();108 await contract.methods.mint(caller, tokenId).send();111 await contract.methods.mint(caller, tokenId).send();109112110 const tokenAddress = tokenIdToAddress(collectionId, tokenId);113 const tokenAddress = tokenIdToAddress(collectionId, tokenId);111 const tokenContract = new web3.eth.Contract(reFungibleTokenAbi as any, tokenAddress, {from: caller, ...GAS_ARGS});114 const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller);112115113 await tokenContract.methods.repartition(2).send();116 await tokenContract.methods.repartition(2).send();114 await tokenContract.methods.transfer(receiver, 1).send();117 await tokenContract.methods.transfer(receiver, 1).send();120});123});121124122describe('Refungible: Plain calls', () => {125describe('Refungible: Plain calls', () => {126 before(async function() {127 await requirePallets(this, [Pallets.ReFungible]);128 });129123 itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {130 itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {124 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);131 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);250 await contract.methods.mint(caller, tokenId).send();257 await contract.methods.mint(caller, tokenId).send();251258252 const address = tokenIdToAddress(collectionId, tokenId);259 const address = tokenIdToAddress(collectionId, tokenId);253 const tokenContract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: caller, ...GAS_ARGS});260 const tokenContract = uniqueRefungibleToken(web3, address, caller);254 await tokenContract.methods.repartition(15).send();261 await tokenContract.methods.repartition(15).send();255262256 {263 {345 await contract.methods.mint(caller, tokenId).send();352 await contract.methods.mint(caller, tokenId).send();346353347 const tokenAddress = tokenIdToAddress(collectionId, tokenId);354 const tokenAddress = tokenIdToAddress(collectionId, tokenId);348 const tokenContract = new web3.eth.Contract(reFungibleTokenAbi as any, tokenAddress, {from: caller, ...GAS_ARGS});355 const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller);349356350 await tokenContract.methods.repartition(2).send();357 await tokenContract.methods.repartition(2).send();351 await tokenContract.methods.transfer(receiver, 1).send();358 await tokenContract.methods.transfer(receiver, 1).send();377 await contract.methods.mint(caller, tokenId).send();384 await contract.methods.mint(caller, tokenId).send();378385379 const tokenAddress = tokenIdToAddress(collectionId, tokenId);386 const tokenAddress = tokenIdToAddress(collectionId, tokenId);380 const tokenContract = new web3.eth.Contract(reFungibleTokenAbi as any, tokenAddress, {from: caller, ...GAS_ARGS});387 const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller);381388382 await tokenContract.methods.repartition(2).send();389 await tokenContract.methods.repartition(2).send();383 390399});406});400407401describe('RFT: Fees', () => {408describe('RFT: Fees', () => {409 before(async function() {410 await requirePallets(this, [Pallets.ReFungible]);411 });412402 itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {413 itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {403 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);414 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);435});446});436447437describe('Common metadata', () => {448describe('Common metadata', () => {449 before(async function() {450 await requirePallets(this, [Pallets.ReFungible]);451 });452438 itWeb3('Returns collection name', async ({api, web3, privateKeyWrapper}) => {453 itWeb3('Returns collection name', async ({api, web3, privateKeyWrapper}) => {439 const collection = await createCollectionExpectSuccess({454 const collection = await createCollectionExpectSuccess({tests/src/eth/reFungibleAbi.jsondiffbeforeafterboth480 "stateMutability": "view",480 "stateMutability": "view",481 "type": "function"481 "type": "function"482 },482 },483 {484 "inputs": [485 { "internalType": "uint256", "name": "token", "type": "uint256" }486 ],487 "name": "tokenContractAddress",488 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],489 "stateMutability": "view",490 "type": "function"491 },483 {492 {484 "inputs": [493 "inputs": [485 { "internalType": "address", "name": "owner", "type": "address" },494 { "internalType": "address", "name": "owner", "type": "address" },526 "outputs": [],535 "outputs": [],527 "stateMutability": "nonpayable",536 "stateMutability": "nonpayable",528 "type": "function"537 "type": "function"529 }538 },539 {540 "inputs": [],541 "name": "uniqueCollectionType",542 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],543 "stateMutability": "nonpayable",544 "type": "function"545 },546 {547 "inputs": [548 { "internalType": "address", "name": "user", "type": "address" }549 ],550 "name": "verifyOwnerOrAdmin",551 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],552 "stateMutability": "view",553 "type": "function"554 }530]555]531556tests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.161617import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE} from '../util/helpers';17import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE, requirePallets, Pallets} from '../util/helpers';18import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth} from './util/helpers';18import {collectionIdFromAddress, collectionIdToAddress, createEthAccount, createEthAccountWithBalance, createNonfungibleCollection, createRefungibleCollection, evmCollection, evmCollectionHelpers, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth, uniqueNFT, uniqueRefungible, uniqueRefungibleToken} from './util/helpers';19import reFungibleTokenAbi from './reFungibleTokenAbi.json';201921import chai from 'chai';20import chai from 'chai';22import chaiAsPromised from 'chai-as-promised';21import chaiAsPromised from 'chai-as-promised';23chai.use(chaiAsPromised);22chai.use(chaiAsPromised);24const expect = chai.expect;23const expect = chai.expect;252426describe('Refungible token: Information getting', () => {25describe('Refungible token: Information getting', () => {26 before(async function() {27 await requirePallets(this, [Pallets.ReFungible]);28 });2927 itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {30 itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {28 const alice = privateKeyWrapper('//Alice');31 const alice = privateKeyWrapper('//Alice');293234 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;37 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;353836 const address = tokenIdToAddress(collectionId, tokenId);39 const address = tokenIdToAddress(collectionId, tokenId);37 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: caller, ...GAS_ARGS});40 const contract = uniqueRefungibleToken(web3, address, caller);38 const totalSupply = await contract.methods.totalSupply().call();41 const totalSupply = await contract.methods.totalSupply().call();394240 expect(totalSupply).to.equal('200');43 expect(totalSupply).to.equal('200');50 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;53 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;515452 const address = tokenIdToAddress(collectionId, tokenId);55 const address = tokenIdToAddress(collectionId, tokenId);53 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: caller, ...GAS_ARGS});56 const contract = uniqueRefungibleToken(web3, address, caller);54 const balance = await contract.methods.balanceOf(caller).call();57 const balance = await contract.methods.balanceOf(caller).call();555856 expect(balance).to.equal('200');59 expect(balance).to.equal('200');66 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;69 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;677068 const address = tokenIdToAddress(collectionId, tokenId);71 const address = tokenIdToAddress(collectionId, tokenId);69 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: caller, ...GAS_ARGS});72 const contract = uniqueRefungibleToken(web3, address, caller);70 const decimals = await contract.methods.decimals().call();73 const decimals = await contract.methods.decimals().call();717472 expect(decimals).to.equal('0');75 expect(decimals).to.equal('0');757876// FIXME: Need erc721 for ReFubgible.79// FIXME: Need erc721 for ReFubgible.77describe('Check ERC721 token URI for ReFungible', () => {80describe('Check ERC721 token URI for ReFungible', () => {81 before(async function() {82 await requirePallets(this, [Pallets.ReFungible]);83 });8478 itWeb3('Empty tokenURI', async ({web3, api, privateKeyWrapper}) => {85 itWeb3('Empty tokenURI', async ({web3, api, privateKeyWrapper}) => {79 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);86 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);80 const helper = evmCollectionHelpers(web3, owner);87 const helper = evmCollectionHelpers(web3, owner);81 let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', '').send();88 let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', '').send();82 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);89 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);83 const receiver = createEthAccount(web3);90 const receiver = createEthAccount(web3);84 const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});91 const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});85 9286 const nextTokenId = await contract.methods.nextTokenId().call();93 const nextTokenId = await contract.methods.nextTokenId().call();87 expect(nextTokenId).to.be.equal('1');94 expect(nextTokenId).to.be.equal('1');88 result = await contract.methods.mint(95 result = await contract.methods.mint(115 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);122 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);116 const receiver = createEthAccount(web3);123 const receiver = createEthAccount(web3);117 const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});124 const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});118 125119 const nextTokenId = await contract.methods.nextTokenId().call();126 const nextTokenId = await contract.methods.nextTokenId().call();120 expect(nextTokenId).to.be.equal('1');127 expect(nextTokenId).to.be.equal('1');121 result = await contract.methods.mint(128 result = await contract.methods.mint(122 receiver,129 receiver,123 nextTokenId,130 nextTokenId,124 ).send();131 ).send();125 132126 // Set URL133 // Set URL127 await contract.methods.setProperty(nextTokenId, 'url', Buffer.from('Token URI')).send();134 await contract.methods.setProperty(nextTokenId, 'url', Buffer.from('Token URI')).send();128 135129 const events = normalizeEvents(result.events);136 const events = normalizeEvents(result.events);130 const address = collectionIdToAddress(collectionId);137 const address = collectionIdToAddress(collectionId);131138151 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);158 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);152 const receiver = createEthAccount(web3);159 const receiver = createEthAccount(web3);153 const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});160 const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});154 161155 const nextTokenId = await contract.methods.nextTokenId().call();162 const nextTokenId = await contract.methods.nextTokenId().call();156 expect(nextTokenId).to.be.equal('1');163 expect(nextTokenId).to.be.equal('1');157 result = await contract.methods.mint(164 result = await contract.methods.mint(158 receiver,165 receiver,159 nextTokenId,166 nextTokenId,160 ).send();167 ).send();161 168162 const events = normalizeEvents(result.events);169 const events = normalizeEvents(result.events);163 const address = collectionIdToAddress(collectionId);170 const address = collectionIdToAddress(collectionId);164171184 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);191 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);185 const receiver = createEthAccount(web3);192 const receiver = createEthAccount(web3);186 const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});193 const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});187 194188 const nextTokenId = await contract.methods.nextTokenId().call();195 const nextTokenId = await contract.methods.nextTokenId().call();189 expect(nextTokenId).to.be.equal('1');196 expect(nextTokenId).to.be.equal('1');190 result = await contract.methods.mint(197 result = await contract.methods.mint(191 receiver,198 receiver,192 nextTokenId,199 nextTokenId,193 ).send();200 ).send();194 201195 // Set suffix202 // Set suffix196 const suffix = '/some/suffix';203 const suffix = '/some/suffix';197 await contract.methods.setProperty(nextTokenId, 'suffix', Buffer.from(suffix)).send();204 await contract.methods.setProperty(nextTokenId, 'suffix', Buffer.from(suffix)).send();216});223});217224218describe('Refungible: Plain calls', () => {225describe('Refungible: Plain calls', () => {226 before(async function() {227 await requirePallets(this, [Pallets.ReFungible]);228 });229219 itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {230 itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {220 const alice = privateKeyWrapper('//Alice');231 const alice = privateKeyWrapper('//Alice');221232229240230 const spender = createEthAccount(web3);241 const spender = createEthAccount(web3);231242232 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});243 const contract = uniqueRefungibleToken(web3, address, owner);233244234 {245 {235 const result = await contract.methods.approve(spender, 100).send({from: owner});246 const result = await contract.methods.approve(spender, 100).send({from: owner});270 const receiver = createEthAccount(web3);281 const receiver = createEthAccount(web3);271282272 const address = tokenIdToAddress(collectionId, tokenId);283 const address = tokenIdToAddress(collectionId, tokenId);273 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});284 const contract = uniqueRefungibleToken(web3, address, owner);274285275 await contract.methods.approve(spender, 100).send();286 await contract.methods.approve(spender, 100).send();276287324 await transferBalanceToEth(api, alice, receiver);335 await transferBalanceToEth(api, alice, receiver);325336326 const address = tokenIdToAddress(collectionId, tokenId);337 const address = tokenIdToAddress(collectionId, tokenId);327 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});338 const contract = uniqueRefungibleToken(web3, address, owner);328339329 {340 {330 const result = await contract.methods.transfer(receiver, 50).send({from: owner});341 const result = await contract.methods.transfer(receiver, 50).send({from: owner});367 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;378 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;368379369 const address = tokenIdToAddress(collectionId, tokenId);380 const address = tokenIdToAddress(collectionId, tokenId);370 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});381 const contract = uniqueRefungibleToken(web3, address, owner);371382372 await contract.methods.repartition(200).send({from: owner});383 await contract.methods.repartition(200).send({from: owner});373 expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(200);384 expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(200);374 await contract.methods.transfer(receiver, 110).send({from: owner});385 await contract.methods.transfer(receiver, 110).send({from: owner});375 expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(90);386 expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(90);376 expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(110);387 expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(110);377 388378 await expect(contract.methods.repartition(80).send({from: owner})).to.eventually.be.rejected;389 await expect(contract.methods.repartition(80).send({from: owner})).to.eventually.be.rejected;379390380 await contract.methods.transfer(receiver, 90).send({from: owner});391 await contract.methods.transfer(receiver, 90).send({from: owner});397 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;408 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;398409399 const address = tokenIdToAddress(collectionId, tokenId);410 const address = tokenIdToAddress(collectionId, tokenId);400 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});411 const contract = uniqueRefungibleToken(web3, address, owner);401412402 const result = await contract.methods.repartition(200).send();413 const result = await contract.methods.repartition(200).send();403 const events = normalizeEvents(result.events);414 const events = normalizeEvents(result.events);426 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;437 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;427438428 const address = tokenIdToAddress(collectionId, tokenId);439 const address = tokenIdToAddress(collectionId, tokenId);429 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});440 const contract = uniqueRefungibleToken(web3, address, owner);430441431 const result = await contract.methods.repartition(50).send();442 const result = await contract.methods.repartition(50).send();432 const events = normalizeEvents(result.events);443 const events = normalizeEvents(result.events);456467457 const address = tokenIdToAddress(collectionId, tokenId);468 const address = tokenIdToAddress(collectionId, tokenId);458469459 const tokenContract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: caller, ...GAS_ARGS});470 const tokenContract = uniqueRefungibleToken(web3, address, caller);460 await tokenContract.methods.repartition(2).send();471 await tokenContract.methods.repartition(2).send();461 await tokenContract.methods.transfer(receiver, 1).send();472 await tokenContract.methods.transfer(receiver, 1).send();462473463 const events = await recordEvents(contract, async () => 474 const events = await recordEvents(contract, async () =>464 await tokenContract.methods.burnFrom(caller, 1).send());475 await tokenContract.methods.burnFrom(caller, 1).send());465 expect(events).to.deep.equal([476 expect(events).to.deep.equal([466 {477 {477});488});478489479describe('Refungible: Fees', () => {490describe('Refungible: Fees', () => {491 before(async function() {492 await requirePallets(this, [Pallets.ReFungible]);493 });494480 itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {495 itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {481 const alice = privateKeyWrapper('//Alice');496 const alice = privateKeyWrapper('//Alice');482497488 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;503 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;489504490 const address = tokenIdToAddress(collectionId, tokenId);505 const address = tokenIdToAddress(collectionId, tokenId);491 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});506 const contract = uniqueRefungibleToken(web3, address, owner);492507493 const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, 100).send({from: owner}));508 const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, 100).send({from: owner}));494 expect(cost < BigInt(0.2 * Number(UNIQUE)));509 expect(cost < BigInt(0.2 * Number(UNIQUE)));505 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;520 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;506521507 const address = tokenIdToAddress(collectionId, tokenId);522 const address = tokenIdToAddress(collectionId, tokenId);508 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});523 const contract = uniqueRefungibleToken(web3, address, owner);509524510 await contract.methods.approve(spender, 100).send({from: owner});525 await contract.methods.approve(spender, 100).send({from: owner});511526524 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;539 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;525540526 const address = tokenIdToAddress(collectionId, tokenId);541 const address = tokenIdToAddress(collectionId, tokenId);527 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});542 const contract = uniqueRefungibleToken(web3, address, owner);528543529 const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, 100).send({from: owner}));544 const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, 100).send({from: owner}));530 expect(cost < BigInt(0.2 * Number(UNIQUE)));545 expect(cost < BigInt(0.2 * Number(UNIQUE)));531 });546 });532});547});533548534describe('Refungible: Substrate calls', () => {549describe('Refungible: Substrate calls', () => {550 before(async function() {551 await requirePallets(this, [Pallets.ReFungible]);552 });553535 itWeb3('Events emitted for approve()', async ({web3, api, privateKeyWrapper}) => {554 itWeb3('Events emitted for approve()', async ({web3, api, privateKeyWrapper}) => {536 const alice = privateKeyWrapper('//Alice');555 const alice = privateKeyWrapper('//Alice');537556542 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId;561 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId;543562544 const address = tokenIdToAddress(collectionId, tokenId);563 const address = tokenIdToAddress(collectionId, tokenId);545 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address);564 const contract = uniqueRefungibleToken(web3, address);546565547 const events = await recordEvents(contract, async () => {566 const events = await recordEvents(contract, async () => {548 expect(await approve(api, collectionId, tokenId, alice, {Ethereum: receiver}, 100n)).to.be.true;567 expect(await approve(api, collectionId, tokenId, alice, {Ethereum: receiver}, 100n)).to.be.true;573 expect(await approve(api, collectionId, tokenId, alice, bob.address, 100n)).to.be.true;592 expect(await approve(api, collectionId, tokenId, alice, bob.address, 100n)).to.be.true;574593575 const address = tokenIdToAddress(collectionId, tokenId);594 const address = tokenIdToAddress(collectionId, tokenId);576 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address);595 const contract = uniqueRefungibleToken(web3, address);577596578 const events = await recordEvents(contract, async () => {597 const events = await recordEvents(contract, async () => {579 expect(await transferFrom(api, collectionId, tokenId, bob, alice, {Ethereum: receiver}, 51n)).to.be.true;598 expect(await transferFrom(api, collectionId, tokenId, bob, alice, {Ethereum: receiver}, 51n)).to.be.true;611 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId;630 const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId;612631613 const address = tokenIdToAddress(collectionId, tokenId);632 const address = tokenIdToAddress(collectionId, tokenId);614 const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address);633 const contract = uniqueRefungibleToken(web3, address);615634616 const events = await recordEvents(contract, async () => {635 const events = await recordEvents(contract, async () => {617 expect(await transfer(api, collectionId, tokenId, alice, {Ethereum: receiver}, 51n)).to.be.true;636 expect(await transfer(api, collectionId, tokenId, alice, {Ethereum: receiver}, 51n)).to.be.true;628 },647 },629 },648 },630 ]);649 ]);650 });651});652653describe('ERC 1633 implementation', () => {654 itWeb3('Parent NFT token address and id', async ({api, web3, privateKeyWrapper}) => {655 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);656657 const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);658 const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);659 const nftTokenId = await nftContract.methods.nextTokenId().call();660 await nftContract.methods.mint(owner, nftTokenId).send();661 const nftCollectionId = collectionIdFromAddress(nftCollectionAddress);662663 const {collectionIdAddress, collectionId} = await createRefungibleCollection(api, web3, owner);664 const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);665 const refungibleTokenId = await refungibleContract.methods.nextTokenId().call();666 await refungibleContract.methods.mint(owner, refungibleTokenId).send();667668 const rftTokenAddress = tokenIdToAddress(collectionId, refungibleTokenId);669 const refungibleTokenContract = uniqueRefungibleToken(web3, rftTokenAddress, owner);670 await refungibleTokenContract.methods.setParentNFT(nftCollectionAddress, nftTokenId).send();671672 const tokenAddress = await refungibleTokenContract.methods.parentToken().call();673 const tokenId = await refungibleTokenContract.methods.parentTokenId().call();674 const nftTokenAddress = tokenIdToAddress(nftCollectionId, nftTokenId);675 expect(tokenAddress).to.be.equal(nftTokenAddress);676 expect(tokenId).to.be.equal(nftTokenId);677 });678679 itWeb3('Default parent token address and id', async ({api, web3, privateKeyWrapper}) => {680 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);681682 const {collectionIdAddress, collectionId} = await createRefungibleCollection(api, web3, owner);683 const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);684 const refungibleTokenId = await refungibleContract.methods.nextTokenId().call();685 await refungibleContract.methods.mint(owner, refungibleTokenId).send();686687 const rftTokenAddress = tokenIdToAddress(collectionId, refungibleTokenId);688 const refungibleTokenContract = uniqueRefungibleToken(web3, rftTokenAddress, owner);689690 const tokenAddress = await refungibleTokenContract.methods.parentToken().call();691 const tokenId = await refungibleTokenContract.methods.parentTokenId().call();692 expect(tokenAddress).to.be.equal(rftTokenAddress);693 expect(tokenId).to.be.equal(refungibleTokenId);631 });694 });632});695});633696tests/src/eth/reFungibleTokenAbi.jsondiffbeforeafterboth102 "stateMutability": "view",102 "stateMutability": "view",103 "type": "function"103 "type": "function"104 },104 },105 {106 "inputs": [],107 "name": "parentToken",108 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],109 "stateMutability": "view",110 "type": "function"111 },112 {113 "inputs": [],114 "name": "parentTokenId",115 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],116 "stateMutability": "view",117 "type": "function"118 },105 {119 {106 "inputs": [120 "inputs": [107 { "internalType": "uint256", "name": "amount", "type": "uint256" }121 { "internalType": "uint256", "name": "amount", "type": "uint256" }111 "stateMutability": "nonpayable",125 "stateMutability": "nonpayable",112 "type": "function"126 "type": "function"113 },127 },128 {129 "inputs": [130 { "internalType": "address", "name": "collection", "type": "address" },131 { "internalType": "uint256", "name": "nftId", "type": "uint256" }132 ],133 "name": "setParentNFT",134 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],135 "stateMutability": "nonpayable",136 "type": "function"137 },114 {138 {115 "inputs": [139 "inputs": [116 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }140 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }tests/src/eth/scheduling.test.tsdiffbeforeafterboth161617import {expect} from 'chai';17import {expect} from 'chai';18import {createEthAccountWithBalance, deployFlipper, GAS_ARGS, itWeb3, subToEth, transferBalanceToEth} from './util/helpers';18import {createEthAccountWithBalance, deployFlipper, GAS_ARGS, itWeb3, subToEth, transferBalanceToEth} from './util/helpers';19import {scheduleExpectSuccess, waitNewBlocks} from '../util/helpers';19import {scheduleExpectSuccess, waitNewBlocks, requirePallets, Pallets} from '../util/helpers';202021describe('Scheduing EVM smart contracts', () => {21describe('Scheduing EVM smart contracts', () => {22 before(async function() {23 await requirePallets(this, [Pallets.Scheduler]);24 });2522 itWeb3('Successfully schedules and periodically executes an EVM contract', async ({api, web3, privateKeyWrapper}) => {26 itWeb3('Successfully schedules and periodically executes an EVM contract', async ({api, web3, privateKeyWrapper}) => {23 const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);27 const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);tests/src/eth/util/helpers.tsdiffbeforeafterboth32import fungibleAbi from '../fungibleAbi.json';32import fungibleAbi from '../fungibleAbi.json';33import nonFungibleAbi from '../nonFungibleAbi.json';33import nonFungibleAbi from '../nonFungibleAbi.json';34import refungibleAbi from '../reFungibleAbi.json';34import refungibleAbi from '../reFungibleAbi.json';35import refungibleTokenAbi from '../reFungibleTokenAbi.json';35import contractHelpersAbi from './contractHelpersAbi.json';36import contractHelpersAbi from './contractHelpersAbi.json';363737export const GAS_ARGS = {gas: 2500000};38export const GAS_ARGS = {gas: 2500000};102 return Web3.utils.toChecksumAddress('0x' + buf.toString('hex'));103 return Web3.utils.toChecksumAddress('0x' + buf.toString('hex'));103}104}105106export function tokenIdFromAddress(address: string) {107 if (!address.startsWith('0x'))108 throw 'address not starts with "0x"';109 if (address.length > 42)110 throw 'address length is more than 20 bytes';111 return {112 collectionId: Number('0x' + address.substring(address.length - 16, address.length - 8)),113 tokenId: Number('0x' + address.substring(address.length - 8)),114 };115}116104export function tokenIdToCross(collection: number, token: number): CrossAccountId {117export function tokenIdToCross(collection: number, token: number): CrossAccountId {105 return {118 return {128 expect(result.success).to.be.true;141 expect(result.success).to.be.true;129}142}143144export async function createRefungibleCollection(api: ApiPromise, web3: Web3, owner: string) {145 const collectionHelper = evmCollectionHelpers(web3, owner);146 const result = await collectionHelper.methods147 .createRefungibleCollection('A', 'B', 'C')148 .send();149 return await getCollectionAddressFromResult(api, result);150}151152153export async function createNonfungibleCollection(api: ApiPromise, web3: Web3, owner: string) {154 const collectionHelper = evmCollectionHelpers(web3, owner);155 const result = await collectionHelper.methods156 .createNonfungibleCollection('A', 'B', 'C')157 .send();158 return await getCollectionAddressFromResult(api, result);159}160161export function uniqueNFT(web3: Web3, address: string, owner: string) {162 return new web3.eth.Contract(nonFungibleAbi as any, address, {163 from: owner,164 ...GAS_ARGS,165 });166}167168export function uniqueRefungible(web3: Web3, collectionAddress: string, owner: string) {169 return new web3.eth.Contract(refungibleAbi as any, collectionAddress, {170 from: owner,171 ...GAS_ARGS,172 });173}174175export function uniqueRefungibleToken(web3: Web3, tokenAddress: string, owner: string | undefined = undefined) {176 return new web3.eth.Contract(refungibleTokenAbi as any, tokenAddress, {177 from: owner,178 ...GAS_ARGS,179 });180}130181131export async function itWeb3(name: string, cb: (apis: { web3: Web3, api: ApiPromise, privateKeyWrapper: (account: string) => IKeyringPair }) => any, opts: { only?: boolean, skip?: boolean } = {}) {182export async function itWeb3(name: string, cb: (apis: { web3: Web3, api: ApiPromise, privateKeyWrapper: (account: string) => IKeyringPair }) => any, opts: { only?: boolean, skip?: boolean } = {}) {132 let i: any = it;183 let i: any = it;199 return Web3.utils.toChecksumAddress(subToEthLowercase(eth));250 return Web3.utils.toChecksumAddress(subToEthLowercase(eth));200}251}252253export interface CompiledContract {254 abi: any,255 object: string,256}201257202export function compileContract(name: string, src: string) {258export function compileContract(name: string, src: string) : CompiledContract {203 const out = JSON.parse(solc.compile(JSON.stringify({259 const out = JSON.parse(solc.compile(JSON.stringify({204 language: 'Solidity',260 language: 'Solidity',205 sources: {261 sources: {tests/src/fungible.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.161617import {default as usingApi} from './substrate/substrate-api';18import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';19import {18import {U128_MAX} from './util/helpers';20 getBalance,21 createMultipleItemsExpectSuccess,22 isTokenExists,23 getLastTokenId,24 getAllowance,25 approve,26 transferFrom,27 createCollection,28 transfer,29 burnItem,30 normalizeAccountId,31 CrossAccountId,32 createFungibleItemExpectSuccess,33 U128_MAX,34 burnFromExpectSuccess,35} from './util/helpers';361920import {usingPlaygrounds} from './util/playgrounds';2137import chai from 'chai';22import chai from 'chai';38import chaiAsPromised from 'chai-as-promised';23import chaiAsPromised from 'chai-as-promised';39chai.use(chaiAsPromised);24chai.use(chaiAsPromised);442945describe('integration test: Fungible functionality:', () => {30describe('integration test: Fungible functionality:', () => {46 before(async () => {31 before(async () => {47 await usingApi(async (api, privateKeyWrapper) => {32 await usingPlaygrounds(async (helper, privateKey) => {48 alice = privateKeyWrapper('//Alice');33 alice = privateKey('//Alice');49 bob = privateKeyWrapper('//Bob');34 bob = privateKey('//Bob');50 });35 });51 });36 });523753 it('Create fungible collection and token', async () => {38 it('Create fungible collection and token', async () => {54 await usingApi(async api => {39 await usingPlaygrounds(async helper => {55 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}});40 const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'trest'});56 expect(createCollectionResult.success).to.be.true;41 const defaultTokenId = await collection.getLastTokenId();57 const collectionId = createCollectionResult.collectionId;58 const defaultTokenId = await getLastTokenId(api, collectionId);42 expect(defaultTokenId).to.be.equal(0);4359 const aliceTokenId = await createFungibleItemExpectSuccess(alice, collectionId, {Value: U128_MAX}, alice.address);44 await collection.mint(alice, {Substrate: alice.address}, U128_MAX);60 const aliceBalance = await getBalance(api, collectionId, alice, aliceTokenId); 45 const aliceBalance = await collection.getBalance({Substrate: alice.address});61 const itemCountAfter = await getLastTokenId(api, collectionId);46 const itemCountAfter = await collection.getLastTokenId();62 4763 // What to expect64 // tslint:disable-next-line:no-unused-expression65 expect(itemCountAfter).to.be.equal(defaultTokenId);48 expect(itemCountAfter).to.be.equal(defaultTokenId);66 expect(aliceBalance).to.be.equal(U128_MAX);49 expect(aliceBalance).to.be.equal(U128_MAX);67 });50 });68 });51 });69 52 70 it('RPC method tokenOnewrs for fungible collection and token', async () => {53 it('RPC method tokenOnewrs for fungible collection and token', async () => {71 await usingApi(async (api, privateKeyWrapper) => {54 await usingPlaygrounds(async (helper, privateKey) => {72 const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};55 const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};73 const facelessCrowd = Array.from(Array(7).keys()).map(i => normalizeAccountId(privateKeyWrapper(i.toString())));56 const facelessCrowd = Array(7).fill(0).map((_, i) => ({Substrate: privateKey(`//Alice+${i}`).address}));5758 const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});5960 await collection.mint(alice, {Substrate: alice.address}, U128_MAX);6162 await collection.transfer(alice, {Substrate: bob.address}, 1000n);63 await collection.transfer(alice, ethAcc, 900n);74 64 75 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}});76 const collectionId = createCollectionResult.collectionId;77 const aliceTokenId = await createFungibleItemExpectSuccess(alice, collectionId, {Value: U128_MAX}, alice.address);78 79 await transfer(api, collectionId, aliceTokenId, alice, bob, 1000n);80 await transfer(api, collectionId, aliceTokenId, alice, ethAcc, 900n);81 82 for (let i = 0; i < 7; i++) {65 for (let i = 0; i < 7; i++) {83 await transfer(api, collectionId, aliceTokenId, alice, facelessCrowd[i], 1);66 await collection.transfer(alice, facelessCrowd[i], 1n);84 } 67 } 85 86 const owners = await api.rpc.unique.tokenOwners(collectionId, aliceTokenId);87 const ids = (owners.toJSON() as CrossAccountId[]).map(s => normalizeAccountId(s));88 const aliceID = normalizeAccountId(alice);89 const bobId = normalizeAccountId(bob);906869 const owners = await collection.getTop10Owners();7091 // What to expect71 // What to expect92 // tslint:disable-next-line:no-unused-expression72 expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]);93 expect(ids).to.deep.include.members([aliceID, ethAcc, bobId, ...facelessCrowd]);94 expect(owners.length == 10).to.be.true;73 expect(owners.length).to.be.equal(10);95 74 96 const eleven = privateKeyWrapper('11');75 const eleven = privateKey('//ALice+11');97 expect(await transfer(api, collectionId, aliceTokenId, alice, eleven, 10n)).to.be.true;76 expect(await collection.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true;98 expect((await api.rpc.unique.tokenOwners(collectionId, aliceTokenId)).length).to.be.equal(10);77 expect((await collection.getTop10Owners()).length).to.be.equal(10);99 });78 });100 });79 });101 80 102 it('Transfer token', async () => {81 it('Transfer token', async () => {103 await usingApi(async api => {82 await usingPlaygrounds(async helper => {104 const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};83 const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};105 const collectionId = (await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}})).collectionId;84 const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});106 const tokenId = await createFungibleItemExpectSuccess(alice, collectionId, {Value: 500n}, alice.address);85 await collection.mint(alice, {Substrate: alice.address}, 500n);10786108 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(500n);87 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(500n);109 expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;88 expect(await collection.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true;110 expect(await transfer(api, collectionId, tokenId, alice, ethAcc, 140n)).to.be.true;89 expect(await collection.transfer(alice, ethAcc, 140n)).to.be.true;11190112 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(300n);91 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(300n);113 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n);92 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(60n);114 expect(await getBalance(api, collectionId, ethAcc, tokenId)).to.be.equal(140n);93 expect(await collection.getBalance(ethAcc)).to.be.equal(140n);94115 await expect(transfer(api, collectionId, tokenId, alice, bob, 350n)).to.eventually.be.rejected;95 await expect(collection.transfer(alice, {Substrate: bob.address}, 350n)).to.eventually.be.rejected;116 });96 });117 });97 });11898119 it('Tokens multiple creation', async () => {99 it('Tokens multiple creation', async () => {120 await usingApi(async api => {100 await usingPlaygrounds(async helper => {121 const collectionId = (await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}})).collectionId;101 const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});122 102123 const args = [103 await collection.mintWithOneOwner(alice, {Substrate: alice.address}, [124 {Fungible: {Value: 500n}},104 {value: 500n},125 {Fungible: {Value: 400n}},105 {value: 400n},126 {Fungible: {Value: 300n}},106 {value: 300n},127 ];107 ]);128 108129 await createMultipleItemsExpectSuccess(alice, collectionId, args);109 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1200n);130 expect(await getBalance(api, collectionId, alice, 0)).to.be.equal(1200n);131 }); 110 });132 });111 });133112134 it('Burn some tokens ', async () => {113 it('Burn some tokens ', async () => {135 await usingApi(async api => { 114 await usingPlaygrounds(async helper => {136 const collectionId = (await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}})).collectionId;115 const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});137 const tokenId = (await createFungibleItemExpectSuccess(alice, collectionId, {Value: 500n}, alice.address));116 await collection.mint(alice, {Substrate: alice.address}, 500n);117138 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;118 expect(await collection.isTokenExists(0)).to.be.true;139 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(500n);119 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(500n);140 expect(await burnItem(api, alice, collectionId, tokenId, 499n)).to.be.true;120 expect(await collection.burnTokens(alice, 499n)).to.be.true;141 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;121 expect(await collection.isTokenExists(0)).to.be.true;142 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(1n);122 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n);143 });123 });144 });124 });145 125 146 it('Burn all tokens ', async () => {126 it('Burn all tokens ', async () => {147 await usingApi(async api => { 127 await usingPlaygrounds(async helper => {148 const collectionId = (await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}})).collectionId;128 const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});149 const tokenId = (await createFungibleItemExpectSuccess(alice, collectionId, {Value: 500n}, alice.address));129 await collection.mint(alice, {Substrate: alice.address}, 500n);130150 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;131 expect(await collection.isTokenExists(0)).to.be.true;151 expect(await burnItem(api, alice, collectionId, tokenId, 500n)).to.be.true;132 expect(await collection.burnTokens(alice, 500n)).to.be.true;152 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;133 expect(await collection.isTokenExists(0)).to.be.true;153 134154 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n);135 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(0n);155 expect((await api.rpc.unique.totalPieces(collectionId, tokenId)).value.toBigInt()).to.be.equal(0n);136 expect(await collection.getTotalPieces()).to.be.equal(0n);156 });137 });157 });138 });158139159 it('Set allowance for token', async () => {140 it('Set allowance for token', async () => {160 await usingApi(async api => {141 await usingPlaygrounds(async helper => {161 const collectionId = (await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}})).collectionId;142 const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});162 const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};143 const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};144 await collection.mint(alice, {Substrate: alice.address}, 100n);145146 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(100n);163 147 164 const tokenId = (await createFungibleItemExpectSuccess(alice, collectionId, {Value: 100n}, alice.address));148 expect(await collection.approveTokens(alice, {Substrate: bob.address}, 60n)).to.be.true;149 expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(60n);165 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);150 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(0n);166151167 expect(await approve(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;152 expect(await collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: bob.address}, 20n)).to.be.true;168 expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(60n);169 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(0n);170 171 expect(await transferFrom(api, collectionId, tokenId, bob, alice, bob, 20n)).to.be.true;172 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(80n);153 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(80n);173 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(20n);154 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(20n);174 expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(40n);155 expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(40n);175 156176 await burnFromExpectSuccess(bob, alice, collectionId, tokenId, 10n);157 await collection.burnTokensFrom(bob, {Substrate: alice.address}, 10n);177 158178 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(70n);159 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(70n);179 expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(30n);160 expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(30n);180 expect(await transferFrom(api, collectionId, tokenId, bob, alice, ethAcc, 10n)).to.be.true;161 expect(await collection.transferFrom(bob, {Substrate: alice.address}, ethAcc, 10n)).to.be.true;181 expect(await getBalance(api, collectionId, ethAcc, tokenId)).to.be.equal(10n);162 expect(await collection.getBalance(ethAcc)).to.be.equal(10n);182 });163 });183 });164 });184});165});tests/src/interfaces/augment-api-query.tsdiffbeforeafterboth266 * 266 * 267 * Currently used to store RMRK data.267 * Currently used to store RMRK data.268 **/268 **/269 tokenAuxProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: UpDataStructsPropertyScope | 'None' | 'Rmrk' | number | Uint8Array, arg4: Bytes | string | Uint8Array) => Observable<Option<Bytes>>, [u32, u32, UpDataStructsPropertyScope, Bytes]> & QueryableStorageEntry<ApiType, [u32, u32, UpDataStructsPropertyScope, Bytes]>;269 tokenAuxProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: UpDataStructsPropertyScope | 'None' | 'Rmrk' | 'Eth' | number | Uint8Array, arg4: Bytes | string | Uint8Array) => Observable<Option<Bytes>>, [u32, u32, UpDataStructsPropertyScope, Bytes]> & QueryableStorageEntry<ApiType, [u32, u32, UpDataStructsPropertyScope, Bytes]>;270 /**270 /**271 * Used to enumerate token's children.271 * Used to enumerate token's children.272 **/272 **/tests/src/interfaces/default/types.tsdiffbeforeafterboth2521export interface UpDataStructsPropertyScope extends Enum {2521export interface UpDataStructsPropertyScope extends Enum {2522 readonly isNone: boolean;2522 readonly isNone: boolean;2523 readonly isRmrk: boolean;2523 readonly isRmrk: boolean;2524 readonly isEth: boolean;2524 readonly type: 'None' | 'Rmrk';2525 readonly type: 'None' | 'Rmrk' | 'Eth';2525}2526}252625272527/** @name UpDataStructsRpcCollection */2528/** @name UpDataStructsRpcCollection */tests/src/interfaces/lookup.tsdiffbeforeafterboth2978 * Lookup397: up_data_structs::PropertyScope2978 * Lookup397: up_data_structs::PropertyScope2979 **/2979 **/2980 UpDataStructsPropertyScope: {2980 UpDataStructsPropertyScope: {2981 _enum: ['None', 'Rmrk']2981 _enum: ['None', 'Rmrk', 'Eth']2982 },2982 },2983 /**2983 /**2984 * Lookup399: pallet_nonfungible::pallet::Error<T>2984 * Lookup399: pallet_nonfungible::pallet::Error<T>tests/src/interfaces/types-lookup.tsdiffbeforeafterboth3126 export interface UpDataStructsPropertyScope extends Enum {3126 export interface UpDataStructsPropertyScope extends Enum {3127 readonly isNone: boolean;3127 readonly isNone: boolean;3128 readonly isRmrk: boolean;3128 readonly isRmrk: boolean;3129 readonly isEth: boolean;3129 readonly type: 'None' | 'Rmrk';3130 readonly type: 'None' | 'Rmrk' | 'Eth';3130 }3131 }313131323132 /** @name PalletNonfungibleError (399) */3133 /** @name PalletNonfungibleError (399) */tests/src/limits.test.tsdiffbeforeafterboth27 transferExpectSuccess,27 transferExpectSuccess,28 getFreeBalance,28 getFreeBalance,29 waitNewBlocks, burnItemExpectSuccess,29 waitNewBlocks, burnItemExpectSuccess,30 requirePallets,31 Pallets,30} from './util/helpers';32} from './util/helpers';31import {expect} from 'chai';33import {expect} from 'chai';323467describe('Number of tokens per address (ReFungible)', () => {69describe('Number of tokens per address (ReFungible)', () => {68 let alice: IKeyringPair;70 let alice: IKeyringPair;697170 before(async () => {72 before(async function() {73 await requirePallets(this, [Pallets.ReFungible]);7471 await usingApi(async (api, privateKeyWrapper) => {75 await usingApi(async (api, privateKeyWrapper) => {72 alice = privateKeyWrapper('//Alice');76 alice = privateKeyWrapper('//Alice');367 let bob: IKeyringPair;371 let bob: IKeyringPair;368 let charlie: IKeyringPair;372 let charlie: IKeyringPair;369373370 before(async () => {374 before(async function() {375 await requirePallets(this, [Pallets.ReFungible]);376371 await usingApi(async (api, privateKeyWrapper) => {377 await usingApi(async (api, privateKeyWrapper) => {372 alice = privateKeyWrapper('//Alice');378 alice = privateKeyWrapper('//Alice');tests/src/nesting/nest.test.tsdiffbeforeafterboth17 transferExpectSuccess,17 transferExpectSuccess,18 transferFromExpectSuccess,18 transferFromExpectSuccess,19 setCollectionLimitsExpectSuccess,19 setCollectionLimitsExpectSuccess,20 requirePallets,21 Pallets,20} from '../util/helpers';22} from '../util/helpers';21import {IKeyringPair} from '@polkadot/types/types';23import {IKeyringPair} from '@polkadot/types/types';2224311313312 // ---------- Re-Fungible ----------314 // ---------- Re-Fungible ----------313315314 it('ReFungible: allows an Owner to nest/unnest their token', async () => {316 it('ReFungible: allows an Owner to nest/unnest their token', async function() {317 await requirePallets(this, [Pallets.ReFungible]);318315 await usingApi(async api => {319 await usingApi(async api => {316 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});320 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});333 });337 });334 });338 });335339336 it('ReFungible: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {340 it('ReFungible: allows an Owner to nest/unnest their token (Restricted nesting)', async function() {341 await requirePallets(this, [Pallets.ReFungible]);342337 await usingApi(async api => {343 await usingApi(async api => {338 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});344 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});715721716 // ---------- Re-Fungible ----------722 // ---------- Re-Fungible ----------717723718 it('ReFungible: disallows to nest token if nesting is disabled', async () => {724 it('ReFungible: disallows to nest token if nesting is disabled', async function() {725 await requirePallets(this, [Pallets.ReFungible]);726719 await usingApi(async api => {727 await usingApi(async api => {720 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});728 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});745 });753 });746 });754 });747755748 it('ReFungible: disallows a non-Owner to nest someone else\'s token', async () => {756 it('ReFungible: disallows a non-Owner to nest someone else\'s token', async function() {757 await requirePallets(this, [Pallets.ReFungible]);758749 await usingApi(async api => {759 await usingApi(async api => {750 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});760 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});773 });783 });774 });784 });775785776 it('ReFungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {786 it('ReFungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async function() {787 await requirePallets(this, [Pallets.ReFungible]);788777 await usingApi(async api => {789 await usingApi(async api => {778 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});790 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});800 });812 });801 });813 });802814803 it('ReFungible: disallows to nest token to an unlisted collection', async () => {815 it('ReFungible: disallows to nest token to an unlisted collection', async function() {816 await requirePallets(this, [Pallets.ReFungible]);817804 await usingApi(async api => {818 await usingApi(async api => {805 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});819 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});tests/src/nesting/properties.test.tsdiffbeforeafterboth8 createItemExpectSuccess,8 createItemExpectSuccess,9 getCreateCollectionResult,9 getCreateCollectionResult,10 transferExpectSuccess,10 transferExpectSuccess,11 requirePallets,12 Pallets,11} from '../util/helpers';13} from '../util/helpers';12import {IKeyringPair} from '@polkadot/types/types';14import {IKeyringPair} from '@polkadot/types/types';13import {tokenIdToAddress} from '../eth/util/helpers';15import {tokenIdToAddress} from '../eth/util/helpers';64 await testMakeSureSuppliesRequired({type: 'NFT'});66 await testMakeSureSuppliesRequired({type: 'NFT'});65 });67 });666867 it('Makes sure collectionById supplies required fields for ReFungible', async () => {69 it('Makes sure collectionById supplies required fields for ReFungible', async function() {70 await requirePallets(this, [Pallets.ReFungible]);7168 await testMakeSureSuppliesRequired({type: 'ReFungible'});72 await testMakeSureSuppliesRequired({type: 'ReFungible'});69 });73 });120 it('Sets properties for a NFT collection', async () => {124 it('Sets properties for a NFT collection', async () => {121 await testSetsPropertiesForCollection('NFT');125 await testSetsPropertiesForCollection('NFT');122 });126 });123 it('Sets properties for a ReFungible collection', async () => {127 it('Sets properties for a ReFungible collection', async function() {128 await requirePallets(this, [Pallets.ReFungible]);129124 await testSetsPropertiesForCollection('ReFungible');130 await testSetsPropertiesForCollection('ReFungible');125 });131 });178 it('Check valid names for NFT collection properties keys', async () => {184 it('Check valid names for NFT collection properties keys', async () => {179 await testCheckValidNames('NFT');185 await testCheckValidNames('NFT');180 });186 });181 it('Check valid names for ReFungible collection properties keys', async () => {187 it('Check valid names for ReFungible collection properties keys', async function() {188 await requirePallets(this, [Pallets.ReFungible]);189182 await testCheckValidNames('ReFungible');190 await testCheckValidNames('ReFungible');183 });191 });209 it('Changes properties of a NFT collection', async () => {217 it('Changes properties of a NFT collection', async () => {210 await testChangesProperties({type: 'NFT'});218 await testChangesProperties({type: 'NFT'});211 });219 });212 it('Changes properties of a ReFungible collection', async () => {220 it('Changes properties of a ReFungible collection', async function() {221 await requirePallets(this, [Pallets.ReFungible]);222213 await testChangesProperties({type: 'ReFungible'});223 await testChangesProperties({type: 'ReFungible'});214 });224 });238 it('Deletes properties of a NFT collection', async () => {248 it('Deletes properties of a NFT collection', async () => {239 await testDeleteProperties({type: 'NFT'});249 await testDeleteProperties({type: 'NFT'});240 });250 });241 it('Deletes properties of a ReFungible collection', async () => {251 it('Deletes properties of a ReFungible collection', async function() {252 await requirePallets(this, [Pallets.ReFungible]);253242 await testDeleteProperties({type: 'ReFungible'});254 await testDeleteProperties({type: 'ReFungible'});243 });255 });269 it('Fails to set properties in a NFT collection if not its onwer/administrator', async () => {281 it('Fails to set properties in a NFT collection if not its onwer/administrator', async () => {270 await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'NFT'});282 await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'NFT'});271 });283 });272 it('Fails to set properties in a ReFungible collection if not its onwer/administrator', async () => {284 it('Fails to set properties in a ReFungible collection if not its onwer/administrator', async function() {285 await requirePallets(this, [Pallets.ReFungible]);286273 await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'ReFungible'});287 await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'ReFungible'});274 });288 });307 it('Fails to set properties that exceed the limits (NFT)', async () => {321 it('Fails to set properties that exceed the limits (NFT)', async () => {308 await testFailsSetPropertiesThatExeedLimits({type: 'NFT'});322 await testFailsSetPropertiesThatExeedLimits({type: 'NFT'});309 });323 });310 it('Fails to set properties that exceed the limits (ReFungible)', async () => {324 it('Fails to set properties that exceed the limits (ReFungible)', async function() {325 await requirePallets(this, [Pallets.ReFungible]);326311 await testFailsSetPropertiesThatExeedLimits({type: 'ReFungible'});327 await testFailsSetPropertiesThatExeedLimits({type: 'ReFungible'});312 });328 });337 it('Fails to set more properties than it is allowed (NFT)', async () => {353 it('Fails to set more properties than it is allowed (NFT)', async () => {338 await testFailsSetMorePropertiesThanAllowed({type: 'NFT'});354 await testFailsSetMorePropertiesThanAllowed({type: 'NFT'});339 });355 });340 it('Fails to set more properties than it is allowed (ReFungible)', async () => {356 it('Fails to set more properties than it is allowed (ReFungible)', async function() {357 await requirePallets(this, [Pallets.ReFungible]);358341 await testFailsSetMorePropertiesThanAllowed({type: 'ReFungible'});359 await testFailsSetMorePropertiesThanAllowed({type: 'ReFungible'});342 });360 });392 it('Fails to set properties with invalid names (NFT)', async () => {410 it('Fails to set properties with invalid names (NFT)', async () => {393 await testFailsSetPropertiesWithInvalidNames({type: 'NFT'});411 await testFailsSetPropertiesWithInvalidNames({type: 'NFT'});394 });412 });395 it('Fails to set properties with invalid names (ReFungible)', async () => {413 it('Fails to set properties with invalid names (ReFungible)', async function() {414 await requirePallets(this, [Pallets.ReFungible]);415396 await testFailsSetPropertiesWithInvalidNames({type: 'ReFungible'});416 await testFailsSetPropertiesWithInvalidNames({type: 'ReFungible'});397 });417 });443 it('Sets access rights to properties of a collection (NFT)', async () => {463 it('Sets access rights to properties of a collection (NFT)', async () => {444 await testSetsAccessRightsToProperties({type: 'NFT'});464 await testSetsAccessRightsToProperties({type: 'NFT'});445 });465 });446 it('Sets access rights to properties of a collection (ReFungible)', async () => {466 it('Sets access rights to properties of a collection (ReFungible)', async function() {467 await requirePallets(this, [Pallets.ReFungible]);468447 await testSetsAccessRightsToProperties({type: 'ReFungible'});469 await testSetsAccessRightsToProperties({type: 'ReFungible'});448 });470 });472 it('Changes access rights to properties of a NFT collection', async () => {494 it('Changes access rights to properties of a NFT collection', async () => {473 await testChangesAccessRightsToProperty({type: 'NFT'});495 await testChangesAccessRightsToProperty({type: 'NFT'});474 });496 });475 it('Changes access rights to properties of a ReFungible collection', async () => {497 it('Changes access rights to properties of a ReFungible collection', async function() {498 await requirePallets(this, [Pallets.ReFungible]);499476 await testChangesAccessRightsToProperty({type: 'ReFungible'});500 await testChangesAccessRightsToProperty({type: 'ReFungible'});477 });501 });502 it('Prevents from setting access rights to properties of a NFT collection if not an onwer/admin', async () => {526 it('Prevents from setting access rights to properties of a NFT collection if not an onwer/admin', async () => {503 await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'NFT'});527 await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'NFT'});504 });528 });505 it('Prevents from setting access rights to properties of a ReFungible collection if not an onwer/admin', async () => {529 it('Prevents from setting access rights to properties of a ReFungible collection if not an onwer/admin', async function() {530 await requirePallets(this, [Pallets.ReFungible]);531506 await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'ReFungible'});532 await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'ReFungible'});507 });533 });531 it('Prevents from adding too many possible properties (NFT)', async () => {557 it('Prevents from adding too many possible properties (NFT)', async () => {532 await testPreventFromAddingTooManyPossibleProperties({type: 'NFT'});558 await testPreventFromAddingTooManyPossibleProperties({type: 'NFT'});533 });559 });534 it('Prevents from adding too many possible properties (ReFungible)', async () => {560 it('Prevents from adding too many possible properties (ReFungible)', async function() {561 await requirePallets(this, [Pallets.ReFungible]);562535 await testPreventFromAddingTooManyPossibleProperties({type: 'ReFungible'});563 await testPreventFromAddingTooManyPossibleProperties({type: 'ReFungible'});536 });564 });560 it('Prevents access rights to be modified if constant (NFT)', async () => {588 it('Prevents access rights to be modified if constant (NFT)', async () => {561 await testPreventAccessRightsModifiedIfConstant({type: 'NFT'});589 await testPreventAccessRightsModifiedIfConstant({type: 'NFT'});562 });590 });563 it('Prevents access rights to be modified if constant (ReFungible)', async () => {591 it('Prevents access rights to be modified if constant (ReFungible)', async function() {592 await requirePallets(this, [Pallets.ReFungible]);593564 await testPreventAccessRightsModifiedIfConstant({type: 'ReFungible'});594 await testPreventAccessRightsModifiedIfConstant({type: 'ReFungible'});565 });595 });608 it('Prevents adding properties with invalid names (NFT)', async () => {638 it('Prevents adding properties with invalid names (NFT)', async () => {609 await testPreventsAddingPropertiesWithInvalidNames({type: 'NFT'});639 await testPreventsAddingPropertiesWithInvalidNames({type: 'NFT'});610 });640 });611 it('Prevents adding properties with invalid names (ReFungible)', async () => {641 it('Prevents adding properties with invalid names (ReFungible)', async function() {642 await requirePallets(this, [Pallets.ReFungible]);643612 await testPreventsAddingPropertiesWithInvalidNames({type: 'ReFungible'});644 await testPreventsAddingPropertiesWithInvalidNames({type: 'ReFungible'});613 });645 });651 it('Reads yet empty properties of a token (NFT)', async () => {683 it('Reads yet empty properties of a token (NFT)', async () => {652 await testReadsYetEmptyProperties({type: 'NFT'});684 await testReadsYetEmptyProperties({type: 'NFT'});653 });685 });654 it('Reads yet empty properties of a token (ReFungible)', async () => {686 it('Reads yet empty properties of a token (ReFungible)', async function() {687 await requirePallets(this, [Pallets.ReFungible]);688655 await testReadsYetEmptyProperties({type: 'ReFungible'});689 await testReadsYetEmptyProperties({type: 'ReFungible'});656 });690 });696 it('Assigns properties to a token according to permissions (NFT)', async () => {730 it('Assigns properties to a token according to permissions (NFT)', async () => {697 await testAssignPropertiesAccordingToPermissions({type: 'NFT'}, 1);731 await testAssignPropertiesAccordingToPermissions({type: 'NFT'}, 1);698 });732 });699 it('Assigns properties to a token according to permissions (ReFungible)', async () => {733 it('Assigns properties to a token according to permissions (ReFungible)', async function() {734 await requirePallets(this, [Pallets.ReFungible]);735700 await testAssignPropertiesAccordingToPermissions({type: 'ReFungible'}, 100);736 await testAssignPropertiesAccordingToPermissions({type: 'ReFungible'}, 100);701 });737 });749 it('Changes properties of a token according to permissions (NFT)', async () => {785 it('Changes properties of a token according to permissions (NFT)', async () => {750 await testChangesPropertiesAccordingPermission({type: 'NFT'}, 1);786 await testChangesPropertiesAccordingPermission({type: 'NFT'}, 1);751 });787 });752 it('Changes properties of a token according to permissions (ReFungible)', async () => {788 it('Changes properties of a token according to permissions (ReFungible)', async function() {789 await requirePallets(this, [Pallets.ReFungible]);790753 await testChangesPropertiesAccordingPermission({type: 'ReFungible'}, 100);791 await testChangesPropertiesAccordingPermission({type: 'ReFungible'}, 100);754 });792 });802 it('Deletes properties of a token according to permissions (NFT)', async () => {840 it('Deletes properties of a token according to permissions (NFT)', async () => {803 await testDeletePropertiesAccordingPermission({type: 'NFT'}, 1);841 await testDeletePropertiesAccordingPermission({type: 'NFT'}, 1);804 });842 });805 it('Deletes properties of a token according to permissions (ReFungible)', async () => {843 it('Deletes properties of a token according to permissions (ReFungible)', async function() {844 await requirePallets(this, [Pallets.ReFungible]);845806 await testDeletePropertiesAccordingPermission({type: 'ReFungible'}, 100);846 await testDeletePropertiesAccordingPermission({type: 'ReFungible'}, 100);807 });847 });1029 it('Forbids changing/deleting properties of a token if the user is outside of permissions (NFT)', async () => {1069 it('Forbids changing/deleting properties of a token if the user is outside of permissions (NFT)', async () => {1030 await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'NFT'}, 1);1070 await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'NFT'}, 1);1031 });1071 });1032 it('Forbids changing/deleting properties of a token if the user is outside of permissions (ReFungible)', async () => {1072 it('Forbids changing/deleting properties of a token if the user is outside of permissions (ReFungible)', async function() {1073 await requirePallets(this, [Pallets.ReFungible]);10741033 await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'ReFungible'}, 100);1075 await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'ReFungible'}, 100);1034 });1076 });1062 it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (NFT)', async () => {1104 it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (NFT)', async () => {1063 await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'NFT'}, 1);1105 await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'NFT'}, 1);1064 });1106 });1065 it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (ReFungible)', async () => {1107 it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (ReFungible)', async function() {1108 await requirePallets(this, [Pallets.ReFungible]);11091066 await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'ReFungible'}, 100);1110 await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'ReFungible'}, 100);1067 });1111 });1096 it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (NFT)', async () => {1140 it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (NFT)', async () => {1097 await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'NFT'}, 1);1141 await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'NFT'}, 1);1098 });1142 });1099 it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (ReFungible)', async () => {1143 it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (ReFungible)', async function() {1144 await requirePallets(this, [Pallets.ReFungible]);11451100 await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'ReFungible'}, 100);1146 await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'ReFungible'}, 100);1101 });1147 });1140 it('Forbids adding too many properties to a token (NFT)', async () => {1186 it('Forbids adding too many properties to a token (NFT)', async () => {1141 await testForbidsAddingTooManyProperties({type: 'NFT'}, 1);1187 await testForbidsAddingTooManyProperties({type: 'NFT'}, 1);1142 });1188 });1143 it('Forbids adding too many properties to a token (ReFungible)', async () => {1189 it('Forbids adding too many properties to a token (ReFungible)', async function() {1190 await requirePallets(this, [Pallets.ReFungible]);11911144 await testForbidsAddingTooManyProperties({type: 'ReFungible'}, 100);1192 await testForbidsAddingTooManyProperties({type: 'ReFungible'}, 100);1145 });1193 });1149 let collection: number;1197 let collection: number;1150 let token: number;1198 let token: number;115111991152 before(async () => {1200 before(async function() {1201 await requirePallets(this, [Pallets.ReFungible]);12021153 await usingApi(async (api, privateKeyWrapper) => {1203 await usingApi(async (api, privateKeyWrapper) => {1154 alice = privateKeyWrapper('//Alice');1204 alice = privateKeyWrapper('//Alice');tests/src/nesting/rules-smoke.test.tsdiffbeforeafterboth1import {expect} from 'chai';1import {expect} from 'chai';2import {tokenIdToAddress} from '../eth/util/helpers';2import {tokenIdToAddress} from '../eth/util/helpers';3import usingApi, {executeTransaction} from '../substrate/substrate-api';3import usingApi, {executeTransaction} from '../substrate/substrate-api';4import {createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, CrossAccountId, getCreateCollectionResult} from '../util/helpers';4import {createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, CrossAccountId, getCreateCollectionResult, requirePallets, Pallets} from '../util/helpers';5import {IKeyringPair} from '@polkadot/types/types';5import {IKeyringPair} from '@polkadot/types/types';667describe('nesting check', () => {7describe('nesting check', () => {47 });47 });48 });48 });494950 it('called for refungible', async () => {50 it('called for refungible', async function() {51 await requirePallets(this, [Pallets.ReFungible]);5251 await usingApi(async api => {53 await usingApi(async api => {52 const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});54 const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});tests/src/nesting/unnest.test.tsdiffbeforeafterboth10 setCollectionPermissionsExpectSuccess,10 setCollectionPermissionsExpectSuccess,11 transferExpectSuccess,11 transferExpectSuccess,12 transferFromExpectSuccess,12 transferFromExpectSuccess,13 requirePallets,14 Pallets,13} from '../util/helpers';15} from '../util/helpers';14import {IKeyringPair} from '@polkadot/types/types';16import {IKeyringPair} from '@polkadot/types/types';151780 });82 });81 });83 });828483 it('ReFungible: allows the owner to successfully unnest a token', async () => {85 it('ReFungible: allows the owner to successfully unnest a token', async function() {86 await requirePallets(this, [Pallets.ReFungible]);8784 await usingApi(async api => {88 await usingApi(async api => {85 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});89 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});tests/src/nextSponsoring.test.tsdiffbeforeafterboth27 transferExpectSuccess,27 transferExpectSuccess,28 normalizeAccountId,28 normalizeAccountId,29 getNextSponsored,29 getNextSponsored,30 requirePallets,31 Pallets,30} from './util/helpers';32} from './util/helpers';313332chai.use(chaiAsPromised);34chai.use(chaiAsPromised);89 });91 });90 });92 });919392 it('ReFungible', async () => {94 it('ReFungible', async function() {95 await requirePallets(this, [Pallets.ReFungible]);9693 await usingApi(async (api: ApiPromise) => {97 await usingApi(async (api: ApiPromise) => {9498tests/src/pallet-presence.test.tsdiffbeforeafterboth49 'inflation',49 'inflation',50 'unique',50 'unique',51 'nonfungible',51 'nonfungible',52 'refungible',53 'scheduler',54 'charging',52 'charging',55];53];565466 await usingApi(async api => {64 await usingApi(async api => {67 const chain = await api.rpc.system.chain();65 const chain = await api.rpc.system.chain();6667 const refungible = 'refungible';68 const scheduler = 'scheduler';69 const rmrkPallets = ['rmrkcore', 'rmrkequip'];687069 if (!chain.eq('UNIQUE')) {71 if (chain.eq('OPAL by UNIQUE')) {70 requiredPallets.push(...['rmrkcore', 'rmrkequip']);72 requiredPallets.push(refungible, scheduler, ...rmrkPallets);71 }73 } else if (chain.eq('QUARTZ by UNIQUE')) {74 // Insert Quartz additional pallets here75 } else if (chain.eq('UNIQUE')) {76 // Insert Unique additional pallets here77 }72 });78 });73 });79 });7480tests/src/refungible.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.161617import {default as usingApi, submitTransactionAsync} from './substrate/substrate-api';18import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';1819import { usingPlaygrounds } from './util/playgrounds';19import {20import {20 createCollectionExpectSuccess,21 getModuleNames,21 getBalance,22 Pallets,22 createMultipleItemsExpectSuccess,23 requirePallets,23 isTokenExists,24 getLastTokenId,25 getAllowance,26 approve,27 transferFrom,28 createCollection,29 createRefungibleToken,30 transfer,31 burnItem,32 repartitionRFT,33 createCollectionWithPropsExpectSuccess,34 getDetailedCollectionInfo,35 normalizeAccountId,36 CrossAccountId,37 getCreateItemsResult,38 getDestroyItemsResult,39} from './util/helpers';24} from './util/helpers';402541import chai from 'chai';26import chai from 'chai';46let alice: IKeyringPair;31let alice: IKeyringPair;47let bob: IKeyringPair;32let bob: IKeyringPair;483349describe('integration test: Refungible functionality:', () => {34describe('integration test: Refungible functionality:', async () => {50 before(async () => {35 before(async function() {51 await usingApi(async (api, privateKeyWrapper) => {36 await requirePallets(this, [Pallets.ReFungible]);3738 await usingPlaygrounds(async (helper, privateKey) => {52 alice = privateKeyWrapper('//Alice');39 alice = privateKey('//Alice');53 bob = privateKeyWrapper('//Bob');40 bob = privateKey('//Bob');41 if (!getModuleNames(helper.api!).includes(Pallets.ReFungible)) this.skip();54 });42 });55 });43 });5644 57 it('Create refungible collection and token', async () => {45 it('Create refungible collection and token', async () => {58 await usingApi(async api => {46 await usingPlaygrounds(async helper => {59 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});47 const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});4860 expect(createCollectionResult.success).to.be.true;49 const itemCountBefore = await collection.getLastTokenId();61 const collectionId = createCollectionResult.collectionId;50 const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);62 51 63 const itemCountBefore = await getLastTokenId(api, collectionId);52 const itemCountAfter = await collection.getLastTokenId();64 const result = await createRefungibleToken(api, alice, collectionId, 100n);65 53 66 const itemCountAfter = await getLastTokenId(api, collectionId);67 68 // What to expect54 // What to expect69 // tslint:disable-next-line:no-unused-expression55 expect(token?.tokenId).to.be.gte(itemCountBefore);70 expect(result.success).to.be.true;71 expect(itemCountAfter).to.be.equal(itemCountBefore + 1);56 expect(itemCountAfter).to.be.equal(itemCountBefore + 1);72 expect(collectionId).to.be.equal(result.collectionId);57 expect(itemCountAfter.toString()).to.be.equal(token?.tokenId.toString());73 expect(itemCountAfter.toString()).to.be.equal(result.itemId.toString());74 });58 });75 });59 });76 60 77 it('RPC method tokenOnewrs for refungible collection and token', async () => {61 it('RPC method tokenOnewrs for refungible collection and token', async () => {78 await usingApi(async (api, privateKeyWrapper) => {62 await usingPlaygrounds(async (helper, privateKey) => {79 const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};63 const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};80 const facelessCrowd = Array.from(Array(7).keys()).map(i => normalizeAccountId(privateKeyWrapper(i.toString())));64 const facelessCrowd = Array(7).fill(0).map((_, i) => ({Substrate: privateKey(`//Alice+${i}`).address}));6566 const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});6768 const token = await collection.mintToken(alice, {Substrate: alice.address}, 10_000n);6970 await token.transfer(alice, {Substrate: bob.address}, 1000n);71 await token.transfer(alice, ethAcc, 900n);81 72 82 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});83 const collectionId = createCollectionResult.collectionId;84 85 const result = await createRefungibleToken(api, alice, collectionId, 10_000n);86 const aliceTokenId = result.itemId;87 88 89 await transfer(api, collectionId, aliceTokenId, alice, bob, 1000n);90 await transfer(api, collectionId, aliceTokenId, alice, ethAcc, 900n);91 92 for (let i = 0; i < 7; i++) {73 for (let i = 0; i < 7; i++) {93 await transfer(api, collectionId, aliceTokenId, alice, facelessCrowd[i], 50*(i+1));74 await token.transfer(alice, facelessCrowd[i], 50n * BigInt(i + 1));94 } 75 } 95 7696 const owners = await api.rpc.unique.tokenOwners(collectionId, aliceTokenId);77 const owners = await token.getTop10Owners();97 const ids = (owners.toJSON() as CrossAccountId[]).map(s => normalizeAccountId(s));7898 99 const aliceID = normalizeAccountId(alice);100 const bobId = normalizeAccountId(bob);101 102 // What to expect79 // What to expect103 // tslint:disable-next-line:no-unused-expression80 expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]);104 expect(ids).to.deep.include.members([aliceID, ethAcc, bobId, ...facelessCrowd]);105 expect(owners.length).to.be.equal(10);81 expect(owners.length).to.be.equal(10);106 82 107 const eleven = privateKeyWrapper('11');83 const eleven = privateKey('//ALice+11');108 expect(await transfer(api, collectionId, aliceTokenId, alice, eleven, 10n)).to.be.true;84 expect(await token.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true;109 expect((await api.rpc.unique.tokenOwners(collectionId, aliceTokenId)).length).to.be.equal(10);85 expect((await token.getTop10Owners()).length).to.be.equal(10);110 });86 });111 });87 });112 88 113 it('Transfer token pieces', async () => {89 it('Transfer token pieces', async () => {114 await usingApi(async api => {90 await usingPlaygrounds(async helper => {115 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;91 const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});116 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;92 const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);11793118 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);94 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);119 expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;95 expect(await token.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true;12096 121 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(40n);97 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(40n);122 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n);98 expect(await token.getBalance({Substrate: bob.address})).to.be.equal(60n);123 await expect(transfer(api, collectionId, tokenId, alice, bob, 41n)).to.eventually.be.rejected;99 100 await expect(token.transfer(alice, {Substrate: bob.address}, 41n)).to.eventually.be.rejected;124 });101 });125 });102 });126103127 it('Create multiple tokens', async () => {104 it('Create multiple tokens', async () => {128 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});105 await usingPlaygrounds(async helper => {106 const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});129 const args = [107 // TODO: fix mintMultipleTokens108 // await collection.mintMultipleTokens(alice, [130 {ReFungible: {pieces: 1}},109 // {owner: {Substrate: alice.address}, pieces: 1n},131 {ReFungible: {pieces: 2}},110 // {owner: {Substrate: alice.address}, pieces: 2n},132 {ReFungible: {pieces: 100}},111 // {owner: {Substrate: alice.address}, pieces: 100n},133 ];112 // ]);134 await createMultipleItemsExpectSuccess(alice, collectionId, args);113 await helper.rft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, [135114 {pieces: 1n}, 136 await usingApi(async api => { 115 {pieces: 2n}, 116 {pieces: 100n},137 const tokenId = await getLastTokenId(api, collectionId);117 ]);118 const lastTokenId = await collection.getLastTokenId();138 expect(tokenId).to.be.equal(3);119 expect(lastTokenId).to.be.equal(3);139 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);120 expect(await collection.getTokenBalance(lastTokenId, {Substrate: alice.address})).to.be.equal(100n);140 });121 });141 });122 });142123143 it('Burn some pieces', async () => {124 it('Burn some pieces', async () => {144 await usingApi(async api => { 125 await usingPlaygrounds(async helper => {145 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;126 const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});146 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;127 const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);147 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;128 expect(await collection.isTokenExists(token.tokenId)).to.be.true;148 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);129 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);149 expect(await burnItem(api, alice, collectionId, tokenId, 99n)).to.be.true;130 expect((await token.burn(alice, 99n)).success).to.be.true;150 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;131 expect(await collection.isTokenExists(token.tokenId)).to.be.true;151 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(1n);132 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(1n);152 });133 });153 });134 });154135155 it('Burn all pieces', async () => {136 it('Burn all pieces', async () => {156 await usingApi(async api => { 137 await usingPlaygrounds(async helper => { 157 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;138 const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});158 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;139 const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);159 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;140 141 expect(await collection.isTokenExists(token.tokenId)).to.be.true;160 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);142 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);143161 expect(await burnItem(api, alice, collectionId, tokenId, 100n)).to.be.true;144 expect((await token.burn(alice, 100n)).success).to.be.true;162 expect(await isTokenExists(api, collectionId, tokenId)).to.be.false;145 expect(await collection.isTokenExists(token.tokenId)).to.be.false;163 });146 });164 });147 });165148166 it('Burn some pieces for multiple users', async () => {149 it('Burn some pieces for multiple users', async () => {167 await usingApi(async api => { 150 await usingPlaygrounds(async helper => {168 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;151 const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});169 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;152 const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);170 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;171153172 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);154 expect(await collection.isTokenExists(token.tokenId)).to.be.true;173 expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;174175 155 176 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(40n);156 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);177 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n);157 expect(await token.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true;178 expect(await burnItem(api, alice, collectionId, tokenId, 40n)).to.be.true;179158180 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n);159 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(40n);181 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;160 expect(await token.getBalance({Substrate: bob.address})).to.be.equal(60n);182 expect(await burnItem(api, bob, collectionId, tokenId, 59n)).to.be.true;183161184 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(1n);162 expect((await token.burn(alice, 40n)).success).to.be.true;163164 expect(await collection.isTokenExists(token.tokenId)).to.be.true;165 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(0n);166185 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;167 expect((await token.burn(bob, 59n)).success).to.be.true;168186 expect(await burnItem(api, bob, collectionId, tokenId, 1n)).to.be.true;169 expect(await token.getBalance({Substrate: bob.address})).to.be.equal(1n);170 expect(await collection.isTokenExists(token.tokenId)).to.be.true;171187 172 expect((await token.burn(bob, 1n)).success).to.be.true;173188 expect(await isTokenExists(api, collectionId, tokenId)).to.be.false;174 expect(await collection.isTokenExists(token.tokenId)).to.be.false;189 });175 });190 });176 });191177192 it('Set allowance for token', async () => {178 it('Set allowance for token', async () => {193 await usingApi(async api => {179 await usingPlaygrounds(async helper => {194 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;180 const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});195 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;181 const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);182 183 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);196184197 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);185 expect(await token.approve(alice, {Substrate: bob.address}, 60n)).to.be.true;186 expect(await token.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(60n);198187199 expect(await approve(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;188 expect(await token.transferFrom(bob, {Substrate: alice.address}, {Substrate: bob.address}, 20n)).to.be.true;200 expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(60n);201202 expect(await transferFrom(api, collectionId, tokenId, bob, alice, bob, 20n)).to.be.true;203 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(80n);189 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(80n);204 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(20n);190 expect(await token.getBalance({Substrate: bob.address})).to.be.equal(20n);205 expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(40n);191 expect(await token.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(40n);206 });192 });207 });193 });208194209 it('Repartition', async () => {195 it('Repartition', async () => {210 await usingApi(async api => {196 await usingPlaygrounds(async helper => {211 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;197 const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});212 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;198 const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);213199214 expect(await repartitionRFT(api, collectionId, alice, tokenId, 200n)).to.be.true;200 expect(await token.repartition(alice, 200n)).to.be.true;201 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(200n);202 expect(await token.getTotalPieces()).to.be.equal(200n);203 204 expect(await token.transfer(alice, {Substrate: bob.address}, 110n)).to.be.true;215 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(200n);205 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(90n);206 expect(await token.getBalance({Substrate: bob.address})).to.be.equal(110n);207 208 await expect(token.repartition(alice, 80n)).to.eventually.be.rejected;209 210 expect(await token.transfer(alice, {Substrate: bob.address}, 90n)).to.be.true;211 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(0n);212 expect(await token.getBalance({Substrate: bob.address})).to.be.equal(200n);216213217 expect(await transfer(api, collectionId, tokenId, alice, bob, 110n)).to.be.true;214 expect(await token.repartition(bob, 150n)).to.be.true;218 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(90n);215 await expect(token.transfer(bob, {Substrate: alice.address}, 160n)).to.eventually.be.rejected;219 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(110n);220216221 await expect(repartitionRFT(api, collectionId, alice, tokenId, 80n)).to.eventually.be.rejected;222223 expect(await transfer(api, collectionId, tokenId, alice, bob, 90n)).to.be.true;224 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n);225 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(200n);226227 expect(await repartitionRFT(api, collectionId, bob, tokenId, 150n)).to.be.true;228 await expect(transfer(api, collectionId, tokenId, bob, alice, 160n)).to.eventually.be.rejected;229 });217 });230 });218 });231219232 it('Repartition with increased amount', async () => {220 it('Repartition with increased amount', async () => {233 await usingApi(async api => {221 await usingPlaygrounds(async helper => {234 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;222 const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});235 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;223 const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);236237 const tx = api.tx.unique.repartition(collectionId, tokenId, 200n);224 await token.repartition(alice, 200n);238 const events = await submitTransactionAsync(alice, tx);225 const chainEvents = helper.chainLog.slice(-1)[0].events.map((x: any) => x.event);239 const substrateEvents = getCreateItemsResult(events);240 expect(substrateEvents).to.include.deep.members([226 expect(chainEvents).to.include.deep.members([{241 {227 method: 'ItemCreated',242 success: true,228 section: 'common',229 index: '0x4202',243 collectionId,230 data: [ 231 collection.collectionId.toString(), 244 itemId: tokenId,232 token.tokenId.toString(), 245 recipient: {Substrate: alice.address},233 {Substrate: alice.address}, 246 amount: 100,234 '100',247 },235 ],248 ]);236 }]);249 });237 });250 });238 });251239252 it('Repartition with decreased amount', async () => {240 it('Repartition with decreased amount', async () => {253 await usingApi(async api => {241 await usingPlaygrounds(async helper => {254 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;242 const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});255 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;243 const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);256257 const tx = api.tx.unique.repartition(collectionId, tokenId, 50n);244 await token.repartition(alice, 50n);258 const events = await submitTransactionAsync(alice, tx);245 const chainEvents = helper.chainLog.slice(-1)[0].events.map((x: any) => x.event);259 const substrateEvents = getDestroyItemsResult(events);260 expect(substrateEvents).to.include.deep.members([246 expect(chainEvents).to.include.deep.members([{261 {247 method: 'ItemDestroyed',262 success: true,248 section: 'common',249 index: '0x4203',263 collectionId,250 data: [ 251 collection.collectionId.toString(), 264 itemId: tokenId,252 token.tokenId.toString(), 265 owner: {Substrate: alice.address},253 {Substrate: alice.address}, 266 amount: 50,254 '50',267 },255 ],268 ]);256 }]);269 });257 });270 });258 });271});272273describe('Test Refungible properties:', () => {274 before(async () => {275 await usingApi(async (api, privateKeyWrapper) => {276 alice = privateKeyWrapper('//Alice');277 bob = privateKeyWrapper('//Bob');278 });279 });280 259 281 it('Сreate new collection with properties', async () => {260 it('Create new collection with properties', async () => {282 await usingApi(async api => {261 await usingPlaygrounds(async helper => {283 const properties = [{key: 'key1', value: 'val1'}];262 const properties = [{key: 'key1', value: 'val1'}];284 const propertyPermissions = [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}];263 const tokenPropertyPermissions = [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}];285 const collectionId = await createCollectionWithPropsExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'ReFungible'},264 const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test', properties, tokenPropertyPermissions});286 properties: properties,287 propPerm: propertyPermissions, 288 });289 const collection = (await getDetailedCollectionInfo(api, collectionId))!;265 const info = await collection.getData();290 expect(collection.properties.toHuman()).to.be.deep.equal(properties);266 expect(info?.raw.properties).to.be.deep.equal(properties);291 expect(collection.tokenPropertyPermissions.toHuman()).to.be.deep.equal(propertyPermissions);267 expect(info?.raw.tokenPropertyPermissions).to.be.deep.equal(tokenPropertyPermissions);292 });268 });293 });269 });294});270});271295272tests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth161617import chai from 'chai';17import chai from 'chai';18import chaiAsPromised from 'chai-as-promised';18import chaiAsPromised from 'chai-as-promised';19import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';20import {createCollectionExpectSuccess, destroyCollectionExpectSuccess, getAdminList, normalizeAccountId, queryCollectionExpectSuccess} from './util/helpers';19import {usingPlaygrounds} from './util/playgrounds';212022chai.use(chaiAsPromised);21chai.use(chaiAsPromised);23const expect = chai.expect;22const expect = chai.expect;242325describe('Integration Test removeCollectionAdmin(collection_id, account_id):', () => {24describe('Integration Test removeCollectionAdmin(collection_id, account_id):', () => {26 it('Remove collection admin.', async () => {25 it('Remove collection admin.', async () => {27 await usingApi(async (api, privateKeyWrapper) => {26 await usingPlaygrounds(async (helper, privateKey) => {28 const collectionId = await createCollectionExpectSuccess();27 const alice = privateKey('//Alice');29 const alice = privateKeyWrapper('//Alice');28 const bob = privateKey('//Bob');30 const bob = privateKeyWrapper('//Bob');29 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});31 const collection = await queryCollectionExpectSuccess(api, collectionId);30 const collectionInfo = await collection.getData();32 expect(collection.owner.toString()).to.be.deep.eq(alice.address);31 expect(collectionInfo?.raw.owner.toString()).to.be.deep.eq(alice.address);33 // first - add collection admin Bob32 // first - add collection admin Bob34 const addAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));33 await collection.addAdmin(alice, {Substrate: bob.address});35 await submitTransactionAsync(alice, addAdminTx);363437 const adminListAfterAddAdmin = await getAdminList(api, collectionId);35 const adminListAfterAddAdmin = await collection.getAdmins();38 expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));36 expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(bob.address)});393740 // then remove bob from admins of collection38 // then remove bob from admins of collection41 const removeAdminTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));39 await collection.removeAdmin(alice, {Substrate: bob.address});42 await submitTransactionAsync(alice, removeAdminTx);434044 const adminListAfterRemoveAdmin = await getAdminList(api, collectionId);41 const adminListAfterRemoveAdmin = await collection.getAdmins();45 expect(adminListAfterRemoveAdmin).not.to.be.deep.contains(normalizeAccountId(bob.address));42 expect(adminListAfterRemoveAdmin).not.to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(bob.address)});46 });43 });47 });44 });484549 it('Remove admin from collection that has no admins', async () => {46 it('Remove admin from collection that has no admins', async () => {50 await usingApi(async (api, privateKeyWrapper) => {47 await usingPlaygrounds(async (helper, privateKey) => {51 const alice = privateKeyWrapper('//Alice');48 const alice = privateKey('//Alice');52 const collectionId = await createCollectionExpectSuccess();49 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});535054 const adminListBeforeAddAdmin = await getAdminList(api, collectionId);51 const adminListBeforeAddAdmin = await collection.getAdmins();55 expect(adminListBeforeAddAdmin).to.have.lengthOf(0);52 expect(adminListBeforeAddAdmin).to.have.lengthOf(0);565354 // await expect(collection.removeAdmin(alice, {Substrate: alice.address})).to.be.rejectedWith('Unable to remove collection admin');57 const tx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(alice.address));55 await collection.removeAdmin(alice, {Substrate: alice.address});58 await submitTransactionAsync(alice, tx);59 });56 });60 });57 });61});58});625963describe('Negative Integration Test removeCollectionAdmin(collection_id, account_id):', () => {60describe('Negative Integration Test removeCollectionAdmin(collection_id, account_id):', () => {64 it('Can\'t remove collection admin from not existing collection', async () => {61 it('Can\'t remove collection admin from not existing collection', async () => {65 await usingApi(async (api, privateKeyWrapper) => {62 await usingPlaygrounds(async (helper, privateKey) => {66 // tslint:disable-next-line: no-bitwise63 // tslint:disable-next-line: no-bitwise67 const collectionId = (1 << 32) - 1;64 const collectionId = (1 << 32) - 1;68 const alice = privateKeyWrapper('//Alice');65 const alice = privateKey('//Alice');69 const bob = privateKeyWrapper('//Bob');66 const bob = privateKey('//Bob');706771 const changeOwnerTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));72 await expect(submitTransactionExpectFailAsync(alice, changeOwnerTx)).to.be.rejected;68 await expect(helper.collection.removeAdmin(alice, collectionId, {Substrate: bob.address})).to.be.rejected;736974 // Verifying that nothing bad happened (network is live, new collections can be created, etc.)70 // Verifying that nothing bad happened (network is live, new collections can be created, etc.)75 await createCollectionExpectSuccess();71 await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});76 });72 });77 });73 });787479 it('Can\'t remove collection admin from deleted collection', async () => {75 it('Can\'t remove collection admin from deleted collection', async () => {80 await usingApi(async (api, privateKeyWrapper) => {76 await usingPlaygrounds(async (helper, privateKey) => {81 // tslint:disable-next-line: no-bitwise82 const collectionId = await createCollectionExpectSuccess();83 const alice = privateKeyWrapper('//Alice');77 const alice = privateKey('//Alice');84 const bob = privateKeyWrapper('//Bob');78 const bob = privateKey('//Bob');8586 await destroyCollectionExpectSuccess(collectionId);79 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});878088 const changeOwnerTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));81 expect(await collection.burn(alice)).to.be.true;8289 await expect(submitTransactionExpectFailAsync(alice, changeOwnerTx)).to.be.rejected;83 await expect(helper.collection.removeAdmin(alice, collection.collectionId, {Substrate: bob.address})).to.be.rejected;908491 // Verifying that nothing bad happened (network is live, new collections can be created, etc.)85 // Verifying that nothing bad happened (network is live, new collections can be created, etc.)92 await createCollectionExpectSuccess();86 await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});93 });87 });94 });88 });958996 it('Regular user can\'t remove collection admin', async () => {90 it('Regular user can\'t remove collection admin', async () => {97 await usingApi(async (api, privateKeyWrapper) => {91 await usingPlaygrounds(async (helper, privateKey) => {98 const collectionId = await createCollectionExpectSuccess();99 const alice = privateKeyWrapper('//Alice');92 const alice = privateKey('//Alice');100 const bob = privateKeyWrapper('//Bob');93 const bob = privateKey('//Bob');101 const charlie = privateKeyWrapper('//Charlie');94 const charlie = privateKey('//Charlie');102103 const addAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));95 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});104 await submitTransactionAsync(alice, addAdminTx);10596106 const changeOwnerTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));97 await collection.addAdmin(alice, {Substrate: bob.address});98107 await expect(submitTransactionExpectFailAsync(charlie, changeOwnerTx)).to.be.rejected;99 await expect(collection.removeAdmin(charlie, {Substrate: bob.address})).to.be.rejected;108100109 // Verifying that nothing bad happened (network is live, new collections can be created, etc.)101 // Verifying that nothing bad happened (network is live, new collections can be created, etc.)110 await createCollectionExpectSuccess();102 await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});111 });103 });112 });104 });113105114 it('Admin can\'t remove collection admin.', async () => {106 it('Admin can\'t remove collection admin.', async () => {115 await usingApi(async (api, privateKeyWrapper) => {107 await usingPlaygrounds(async (helper, privateKey) => {116 const collectionId = await createCollectionExpectSuccess();117 const alice = privateKeyWrapper('//Alice');108 const alice = privateKey('//Alice');118 const bob = privateKeyWrapper('//Bob');109 const bob = privateKey('//Bob');119 const charlie = privateKeyWrapper('//Charlie');110 const charlie = privateKey('//Charlie');120121 const addBobAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));111 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});112 122 await submitTransactionAsync(alice, addBobAdminTx);113 await collection.addAdmin(alice, {Substrate: bob.address});123 const addCharlieAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));114 await collection.addAdmin(alice, {Substrate: charlie.address});124 await submitTransactionAsync(alice, addCharlieAdminTx);125115126 const adminListAfterAddAdmin = await getAdminList(api, collectionId);116 const adminListAfterAddAdmin = await collection.getAdmins();127 expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));117 expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(bob.address)});128 expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(charlie.address));118 expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(charlie.address)});129119130 const removeAdminTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));131 await expect(submitTransactionExpectFailAsync(charlie, removeAdminTx)).to.be.rejected;120 await expect(collection.removeAdmin(charlie, {Substrate: bob.address})).to.be.rejected;132121133 const adminListAfterRemoveAdmin = await getAdminList(api, collectionId);122 const adminListAfterRemoveAdmin = await collection.getAdmins();134 expect(adminListAfterRemoveAdmin).to.be.deep.contains(normalizeAccountId(bob.address));123 expect(adminListAfterRemoveAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(bob.address)});135 expect(adminListAfterRemoveAdmin).to.be.deep.contains(normalizeAccountId(charlie.address));124 expect(adminListAfterRemoveAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(charlie.address)});136 });125 });137 });126 });138});127});tests/src/rmrk/acceptNft.test.tsdiffbeforeafterboth8} from './util/tx';8} from './util/tx';9import {NftIdTuple} from './util/fetch';9import {NftIdTuple} from './util/fetch';10import {isNftChildOfAnother, expectTxFailure} from './util/helpers';10import {isNftChildOfAnother, expectTxFailure} from './util/helpers';11import {requirePallets, Pallets} from '../util/helpers';111212describe('integration test: accept NFT', () => {13describe('integration test: accept NFT', () => {13 let api: any;14 let api: any;14 before(async () => { api = await getApiConnection(); });15 before(async function() {1516 api = await getApiConnection();17 await requirePallets(this, [Pallets.RmrkCore]);18 });19 20 tests/src/rmrk/addResource.test.tsdiffbeforeafterboth12 addNftComposableResource,12 addNftComposableResource,13} from './util/tx';13} from './util/tx';14import {RmrkTraitsResourceResourceInfo as ResourceInfo} from '@polkadot/types/lookup';14import {RmrkTraitsResourceResourceInfo as ResourceInfo} from '@polkadot/types/lookup';15import {requirePallets, Pallets} from '../util/helpers';151616describe('integration test: add NFT resource', () => {17describe('integration test: add NFT resource', () => {17 const Alice = '//Alice';18 const Alice = '//Alice';24 const nonexistentId = 99999;25 const nonexistentId = 99999;252626 let api: any;27 let api: any;27 before(async () => {28 before(async function() {28 api = await getApiConnection();29 api = await getApiConnection();30 await requirePallets(this, [Pallets.RmrkCore]);29 });31 });303231 it('add resource', async () => {33 it('add resource', async () => {tests/src/rmrk/addTheme.test.tsdiffbeforeafterboth3import {createBase, addTheme} from './util/tx';3import {createBase, addTheme} from './util/tx';4import {expectTxFailure} from './util/helpers';4import {expectTxFailure} from './util/helpers';5import {getThemeNames} from './util/fetch';5import {getThemeNames} from './util/fetch';6import {requirePallets, Pallets} from '../util/helpers';677describe('integration test: add Theme to Base', () => {8describe('integration test: add Theme to Base', () => {8 let api: any;9 let api: any;9 before(async () => { api = await getApiConnection(); });10 before(async function() {11 api = await getApiConnection();12 await requirePallets(this, [Pallets.RmrkEquip]);13 });101411 const alice = '//Alice';15 const alice = '//Alice';tests/src/rmrk/burnNft.test.tsdiffbeforeafterboth556import chai from 'chai';6import chai from 'chai';7import chaiAsPromised from 'chai-as-promised';7import chaiAsPromised from 'chai-as-promised';8import {requirePallets, Pallets} from '../util/helpers';899chai.use(chaiAsPromised);10chai.use(chaiAsPromised);10const expect = chai.expect;11const expect = chai.expect;14 const Bob = '//Bob';15 const Bob = '//Bob';151616 let api: any;17 let api: any;17 before(async () => {18 before(async function() {18 api = await getApiConnection();19 api = await getApiConnection();20 await requirePallets(this, [Pallets.RmrkCore]);19 });21 });222023tests/src/rmrk/changeCollectionIssuer.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';3import {4import {4 changeIssuer,5 changeIssuer,10 const Bob = '//Bob';11 const Bob = '//Bob';111212 let api: any;13 let api: any;13 before(async () => {14 before(async function() {14 api = await getApiConnection();15 api = await getApiConnection();16 await requirePallets(this, [Pallets.RmrkCore]);15 });17 });1819tests/src/rmrk/createBase.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {createCollection, createBase} from './util/tx';3import {createCollection, createBase} from './util/tx';344describe('integration test: create new Base', () => {5describe('integration test: create new Base', () => {5 let api: any;6 let api: any;6 before(async () => { api = await getApiConnection(); });7 before(async function() {8 api = await getApiConnection();9 await requirePallets(this, [Pallets.RmrkCore, Pallets.RmrkEquip]);10 });7118 const alice = '//Alice';12 const alice = '//Alice';tests/src/rmrk/createCollection.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {createCollection} from './util/tx';3import {createCollection} from './util/tx';344describe('Integration test: create new collection', () => {5describe('Integration test: create new collection', () => {5 let api: any;6 let api: any;6 before(async () => { api = await getApiConnection(); });7 before(async function () {8 api = await getApiConnection();9 await requirePallets(this, [Pallets.RmrkCore]);10 });1112tests/src/rmrk/deleteCollection.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';3import {createCollection, deleteCollection} from './util/tx';4import {createCollection, deleteCollection} from './util/tx';455describe('integration test: delete collection', () => {6describe('integration test: delete collection', () => {6 let api: any;7 let api: any;7 before(async () => {8 before(async function () {8 api = await getApiConnection();9 api = await getApiConnection();10 await requirePallets(this, [Pallets.RmrkCore]);9 });11 });101211 const Alice = '//Alice';13 const Alice = '//Alice';tests/src/rmrk/equipNft.test.tsdiffbeforeafterboth1import {ApiPromise} from '@polkadot/api';1import {ApiPromise} from '@polkadot/api';2import {expect} from 'chai';2import {expect} from 'chai';3import {getApiConnection} from '../substrate/substrate-api';3import {getApiConnection} from '../substrate/substrate-api';4import {requirePallets, Pallets} from '../util/helpers';4import {getNft, getParts, NftIdTuple} from './util/fetch';5import {getNft, getParts, NftIdTuple} from './util/fetch';5import {expectTxFailure} from './util/helpers';6import {expectTxFailure} from './util/helpers';6import {7import {123124124 let api: any;125 let api: any;126 125 before(async () => {127 before(async function () {126 api = await getApiConnection();128 api = await getApiConnection();129 await requirePallets(this, [Pallets.RmrkCore, Pallets.RmrkEquip]);127 });130 });128131129 it('equip nft', async () => {132 it('equip nft', async () => {tests/src/rmrk/getOwnedNfts.test.tsdiffbeforeafterboth1import {expect} from 'chai';1import {expect} from 'chai';2import {getApiConnection} from '../substrate/substrate-api';2import {getApiConnection} from '../substrate/substrate-api';3import {requirePallets, Pallets} from '../util/helpers';3import {getOwnedNfts} from './util/fetch';4import {getOwnedNfts} from './util/fetch';4import {mintNft, createCollection} from './util/tx';5import {mintNft, createCollection} from './util/tx';566describe('integration test: get owned NFTs', () => {7describe('integration test: get owned NFTs', () => {7 let api: any;8 let api: any;9 8 before(async () => { api = await getApiConnection(); });10 before(async function () {11 api = await getApiConnection();12 await requirePallets(this, [Pallets.RmrkCore]);13 });14915tests/src/rmrk/lockCollection.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';3import {createCollection, lockCollection, mintNft} from './util/tx';4import {createCollection, lockCollection, mintNft} from './util/tx';458 const Max = 5;9 const Max = 5;91010 let api: any;11 let api: any;11 before(async () => {12 before(async function () {12 api = await getApiConnection();13 api = await getApiConnection();14 await requirePallets(this, [Pallets.RmrkCore]);13 });15 });141615 it('lock collection', async () => {17 it('lock collection', async () => {tests/src/rmrk/mintNft.test.tsdiffbeforeafterboth1import {expect} from 'chai';1import {expect} from 'chai';2import {getApiConnection} from '../substrate/substrate-api';2import {getApiConnection} from '../substrate/substrate-api';3import {requirePallets, Pallets} from '../util/helpers';3import {getNft} from './util/fetch';4import {getNft} from './util/fetch';4import {expectTxFailure} from './util/helpers';5import {expectTxFailure} from './util/helpers';5import {createCollection, mintNft} from './util/tx';6import {createCollection, mintNft} from './util/tx';677describe('integration test: mint new NFT', () => {8describe('integration test: mint new NFT', () => {8 let api: any;9 let api: any;10 9 before(async () => { api = await getApiConnection(); });11 before(async function () {12 api = await getApiConnection();13 await requirePallets(this, [Pallets.RmrkCore]);14 });151016tests/src/rmrk/rejectNft.test.tsdiffbeforeafterboth8} from './util/tx';8} from './util/tx';9import {getChildren, NftIdTuple} from './util/fetch';9import {getChildren, NftIdTuple} from './util/fetch';10import {isNftChildOfAnother, expectTxFailure} from './util/helpers';10import {isNftChildOfAnother, expectTxFailure} from './util/helpers';11import {requirePallets, Pallets} from '../util/helpers';111212describe('integration test: reject NFT', () => {13describe('integration test: reject NFT', () => {13 let api: any;14 let api: any;14 before(async () => { api = await getApiConnection(); });15 before(async function () {16 api = await getApiConnection();17 await requirePallets(this, [Pallets.RmrkCore]);18 });1920tests/src/rmrk/removeResource.test.tsdiffbeforeafterboth1import {expect} from 'chai';1import {expect} from 'chai';2import privateKey from '../substrate/privateKey';2import privateKey from '../substrate/privateKey';3import {executeTransaction, getApiConnection} from '../substrate/substrate-api';3import {executeTransaction, getApiConnection} from '../substrate/substrate-api';4import {requirePallets, Pallets} from '../util/helpers';4import {getNft, NftIdTuple} from './util/fetch';5import {getNft, NftIdTuple} from './util/fetch';5import {expectTxFailure} from './util/helpers';6import {expectTxFailure} from './util/helpers';6import {7import {16describe('Integration test: remove nft resource', () => {17describe('Integration test: remove nft resource', () => {17 let api: any;18 let api: any;18 let ss58Format: string;19 let ss58Format: string;19 before(async () => {20 before(async function() {20 api = await getApiConnection();21 api = await getApiConnection();21 ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;22 ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;23 await requirePallets(this, [Pallets.RmrkCore]);22 });24 });232524 const Alice = '//Alice';26 const Alice = '//Alice';tests/src/rmrk/rmrkIsolation.test.tsdiffbeforeafterboth6 getCreateCollectionResult,6 getCreateCollectionResult,7 getDetailedCollectionInfo,7 getDetailedCollectionInfo,8 getGenericResult,8 getGenericResult,9 requirePallets,9 normalizeAccountId,10 normalizeAccountId,11 Pallets,10} from '../util/helpers';12} from '../util/helpers';11import {IKeyringPair} from '@polkadot/types/types';13import {IKeyringPair} from '@polkadot/types/types';12import {ApiPromise} from '@polkadot/api';14import {ApiPromise} from '@polkadot/api';59describe('RMRK External Integration Test', async () => {61describe('RMRK External Integration Test', async () => {60 const it_rmrk = (await isUnique() ? it : it.skip);62 const it_rmrk = (await isUnique() ? it : it.skip);616362 before(async () => {64 before(async function() {63 await usingApi(async (api, privateKeyWrapper) => {65 await usingApi(async (api, privateKeyWrapper) => {64 alice = privateKeyWrapper('//Alice');66 alice = privateKeyWrapper('//Alice');6567 await requirePallets(this, [Pallets.RmrkCore]);66 67 });68 });68 });69 });tests/src/rmrk/sendNft.test.tsdiffbeforeafterboth3import {createCollection, mintNft, sendNft} from './util/tx';3import {createCollection, mintNft, sendNft} from './util/tx';4import {NftIdTuple} from './util/fetch';4import {NftIdTuple} from './util/fetch';5import {isNftChildOfAnother, expectTxFailure} from './util/helpers';5import {isNftChildOfAnother, expectTxFailure} from './util/helpers';6import {requirePallets, Pallets} from '../util/helpers';677describe('integration test: send NFT', () => {8describe('integration test: send NFT', () => {8 let api: any;9 let api: any;9 before(async () => { api = await getApiConnection(); });10 before(async function () {11 api = await getApiConnection();12 await requirePallets(this, [Pallets.RmrkCore]);13 });101411 const maxNftId = 0xFFFFFFFF;15 const maxNftId = 0xFFFFFFFF;tests/src/rmrk/setCollectionProperty.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';3import {createCollection, setPropertyCollection} from './util/tx';4import {createCollection, setPropertyCollection} from './util/tx';457 const Bob = '//Bob';8 const Bob = '//Bob';899 let api: any;10 let api: any;10 before(async () => {11 before(async function () {11 api = await getApiConnection();12 api = await getApiConnection();13 await requirePallets(this, [Pallets.RmrkCore]);12 });14 });131514 it('set collection property', async () => {16 it('set collection property', async () => {tests/src/rmrk/setEquippableList.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';3import {createCollection, createBase, setEquippableList} from './util/tx';4import {createCollection, createBase, setEquippableList} from './util/tx';455describe("integration test: set slot's Equippable List", () => {6describe("integration test: set slot's Equippable List", () => {6 let api: any;7 let api: any;7 before(async () => { api = await getApiConnection(); });8 before(async function () {9 api = await getApiConnection();10 await requirePallets(this, [Pallets.RmrkCore]);11 });8129 const alice = '//Alice';13 const alice = '//Alice';tests/src/rmrk/setNftProperty.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {NftIdTuple} from './util/fetch';3import {NftIdTuple} from './util/fetch';3import {expectTxFailure} from './util/helpers';4import {expectTxFailure} from './util/helpers';4import {createCollection, mintNft, sendNft, setNftProperty} from './util/tx';5import {createCollection, mintNft, sendNft, setNftProperty} from './util/tx';566describe('integration test: set NFT property', () => {7describe('integration test: set NFT property', () => {7 let api: any;8 let api: any;8 before(async () => { api = await getApiConnection(); });9 before(async function () {10 api = await getApiConnection();11 await requirePallets(this, [Pallets.RmrkCore]);12 });91310 const alice = '//Alice';14 const alice = '//Alice';tests/src/rmrk/setResourcePriorities.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';3import {mintNft, createCollection, setResourcePriorities} from './util/tx';4import {mintNft, createCollection, setResourcePriorities} from './util/tx';455describe('integration test: set NFT resource priorities', () => {6describe('integration test: set NFT resource priorities', () => {6 let api: any;7 let api: any;7 before(async () => { api = await getApiConnection(); });8 before(async function () {9 api = await getApiConnection();10 await requirePallets(this, [Pallets.RmrkCore]);11 });8129 const alice = '//Alice';13 const alice = '//Alice';tests/src/setCollectionSponsor.test.tsdiffbeforeafterboth23 setCollectionSponsorExpectFailure,23 setCollectionSponsorExpectFailure,24 addCollectionAdminExpectSuccess,24 addCollectionAdminExpectSuccess,25 getCreatedCollectionCount,25 getCreatedCollectionCount,26 requirePallets,27 Pallets,26} from './util/helpers';28} from './util/helpers';27import {IKeyringPair} from '@polkadot/types/types';29import {IKeyringPair} from '@polkadot/types/types';283050 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});52 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});51 await setCollectionSponsorExpectSuccess(collectionId, bob.address);53 await setCollectionSponsorExpectSuccess(collectionId, bob.address);52 });54 });53 it('Set ReFungible collection sponsor', async () => {55 it('Set ReFungible collection sponsor', async function() {56 await requirePallets(this, [Pallets.ReFungible]);5754 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});58 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});55 await setCollectionSponsorExpectSuccess(collectionId, bob.address);59 await setCollectionSponsorExpectSuccess(collectionId, bob.address);tests/src/transfer.test.tsdiffbeforeafterboth35 getBalance as getTokenBalance,35 getBalance as getTokenBalance,36 transferFromExpectSuccess,36 transferFromExpectSuccess,37 transferFromExpectFail,37 transferFromExpectFail,38 requirePallets,39 Pallets,38} from './util/helpers';40} from './util/helpers';39import {41import {40 subToEth,42 subToEth,41 itWeb3, 43 itWeb3, 42} from './eth/util/helpers';44} from './eth/util/helpers';45import {request} from 'https';434644let alice: IKeyringPair;47let alice: IKeyringPair;45let bob: IKeyringPair;48let bob: IKeyringPair;89 });92 });90 });93 });9495 it('[nft] User can transfer owned token', async () => {96 const nftCollectionId = await createCollectionExpectSuccess();97 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');98 await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 'NFT');99 });9110092 it('User can transfer owned token', async () => {101 it('[fungible] User can transfer owned token', async () => {93 await usingApi(async (api, privateKeyWrapper) => {94 // nft95 const nftCollectionId = await createCollectionExpectSuccess();96 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');97 await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 'NFT');98 // fungible99 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});102 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});100 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');103 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');101 await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob, 1, 'Fungible');104 await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob, 1, 'Fungible');102 // reFungible103 const reFungibleCollectionId = await104 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});105 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');106 await transferExpectSuccess(107 reFungibleCollectionId,108 newReFungibleTokenId,109 alice,110 bob,111 100,112 'ReFungible',113 );114 });115 });105 });106107 it('[refungible] User can transfer owned token', async function() {108 await requirePallets(this, [Pallets.ReFungible]);109110 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});111 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');112 await transferExpectSuccess(113 reFungibleCollectionId,114 newReFungibleTokenId,115 alice,116 bob,117 100,118 'ReFungible',119 );120 });121122 it('[nft] Collection admin can transfer owned token', async () => {123 const nftCollectionId = await createCollectionExpectSuccess();124 await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);125 const newNftTokenId = await createItemExpectSuccess(bob, nftCollectionId, 'NFT', bob.address);126 await transferExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, 1, 'NFT');127 });116128117 it('Collection admin can transfer owned token', async () => {129 it('[fungible] Collection admin can transfer owned token', async () => {118 await usingApi(async (api, privateKeyWrapper) => {119 // nft120 const nftCollectionId = await createCollectionExpectSuccess();121 await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);122 const newNftTokenId = await createItemExpectSuccess(bob, nftCollectionId, 'NFT', bob.address);123 await transferExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, 1, 'NFT');124 // fungible125 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});130 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});126 await addCollectionAdminExpectSuccess(alice, fungibleCollectionId, bob.address);131 await addCollectionAdminExpectSuccess(alice, fungibleCollectionId, bob.address);127 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible', bob.address);132 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible', bob.address);128 await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, 1, 'Fungible');133 await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, 1, 'Fungible');129 // reFungible130 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});131 await addCollectionAdminExpectSuccess(alice, reFungibleCollectionId, bob.address);132 const newReFungibleTokenId = await createItemExpectSuccess(bob, reFungibleCollectionId, 'ReFungible', bob.address);133 await transferExpectSuccess(134 reFungibleCollectionId,135 newReFungibleTokenId,136 bob,137 alice,138 100,139 'ReFungible',140 );141 });142 });134 });135136 it('[refungible] Collection admin can transfer owned token', async function() {137 await requirePallets(this, [Pallets.ReFungible]);138139 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});140 await addCollectionAdminExpectSuccess(alice, reFungibleCollectionId, bob.address);141 const newReFungibleTokenId = await createItemExpectSuccess(bob, reFungibleCollectionId, 'ReFungible', bob.address);142 await transferExpectSuccess(143 reFungibleCollectionId,144 newReFungibleTokenId,145 bob,146 alice,147 100,148 'ReFungible',149 );150 });143});151});144152145describe('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => {153describe('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => {151 });159 });152 });160 });161153 it('Transfer with not existed collection_id', async () => {162 it('[nft] Transfer with not existed collection_id', async () => {154 await usingApi(async (api) => {163 await usingApi(async (api) => {155 // nft156 const nftCollectionCount = await getCreatedCollectionCount(api);164 const nftCollectionCount = await getCreatedCollectionCount(api);157 await transferExpectFailure(nftCollectionCount + 1, 1, alice, bob, 1);165 await transferExpectFailure(nftCollectionCount + 1, 1, alice, bob, 1);158 // fungible159 const fungibleCollectionCount = await getCreatedCollectionCount(api);160 await transferExpectFailure(fungibleCollectionCount + 1, 0, alice, bob, 1);161 // reFungible162 const reFungibleCollectionCount = await getCreatedCollectionCount(api);163 await transferExpectFailure(reFungibleCollectionCount + 1, 1, alice, bob, 1);164 });166 });165 });167 });166 it('Transfer with deleted collection_id', async () => {168167 // nft169 it('[fungible] Transfer with not existed collection_id', async () => {170 await usingApi(async (api) => {171 const fungibleCollectionCount = await getCreatedCollectionCount(api);172 await transferExpectFailure(fungibleCollectionCount + 1, 0, alice, bob, 1);173 });174 });175176 it('[refungible] Transfer with not existed collection_id', async function() {177 await requirePallets(this, [Pallets.ReFungible]);178179 await usingApi(async (api) => {180 const reFungibleCollectionCount = await getCreatedCollectionCount(api);181 await transferExpectFailure(reFungibleCollectionCount + 1, 1, alice, bob, 1);182 });168 const nftCollectionId = await createCollectionExpectSuccess();183 });169 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');184170 await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId);185 it('[nft] Transfer with deleted collection_id', async () => {171 await destroyCollectionExpectSuccess(nftCollectionId);186 const nftCollectionId = await createCollectionExpectSuccess();172 await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);187 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');173 // fungible188 await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId);189 await destroyCollectionExpectSuccess(nftCollectionId);190 await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);191 });192193 it('[fungible] Transfer with deleted collection_id', async () => {174 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});194 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});175 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');195 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');176 await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);196 await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);177 await destroyCollectionExpectSuccess(fungibleCollectionId);197 await destroyCollectionExpectSuccess(fungibleCollectionId);178 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);198 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);179 // reFungible199 });200201 it('[refungible] Transfer with deleted collection_id', async function() {202 await requirePallets(this, [Pallets.ReFungible]);203180 const reFungibleCollectionId = await204 const reFungibleCollectionId = await181 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});205 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});189 bob,213 bob,190 1,214 1,191 );215 );192 });216 });217218 it('[nft] Transfer with not existed item_id', async () => {219 const nftCollectionId = await createCollectionExpectSuccess();220 await transferExpectFailure(nftCollectionId, 2, alice, bob, 1);221 });222223 it('[fungible] Transfer with not existed item_id', async () => {224 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});225 await transferExpectFailure(fungibleCollectionId, 2, alice, bob, 1);226 });227228 it('[refungible] Transfer with not existed item_id', async function() {229 await requirePallets(this, [Pallets.ReFungible]);230231 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});232 await transferExpectFailure(233 reFungibleCollectionId,234 2,235 alice,236 bob,237 1,238 );239 });240241 it('[nft] Transfer with deleted item_id', async () => {242 const nftCollectionId = await createCollectionExpectSuccess();243 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');244 await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1);245 await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);246 });247193 it('Transfer with not existed item_id', async () => {248 it('[fungible] Transfer with deleted item_id', async () => {194 // nft195 const nftCollectionId = await createCollectionExpectSuccess();196 await transferExpectFailure(nftCollectionId, 2, alice, bob, 1);197 // fungible198 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});249 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});199 await transferExpectFailure(fungibleCollectionId, 2, alice, bob, 1);250 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');200 // reFungible201 const reFungibleCollectionId = await251 await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);202 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});203 await transferExpectFailure(252 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);204 reFungibleCollectionId,205 2,206 alice,207 bob,208 1,209 );210 });253 });254211 it('Transfer with deleted item_id', async () => {255 it('[refungible] Transfer with deleted item_id', async function() {212 // nft213 const nftCollectionId = await createCollectionExpectSuccess();214 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');215 await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1);216 await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);217 // fungible218 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});256 await requirePallets(this, [Pallets.ReFungible]);219 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');257220 await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);221 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);222 // reFungible223 const reFungibleCollectionId = await258 const reFungibleCollectionId = await224 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});259 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});225 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');260 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');233 );268 );234 });269 });270271 it('[nft] Transfer with recipient that is not owner', async () => {272 const nftCollectionId = await createCollectionExpectSuccess();273 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');274 await transferExpectFailure(nftCollectionId, newNftTokenId, charlie, bob, 1);275 });276277 it('[fungible] Transfer with recipient that is not owner', async () => {278 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});279 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');280 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, charlie, bob, 1);281 });282235 it('Transfer with recipient that is not owner', async () => {283 it('[refungible] Transfer with recipient that is not owner', async function() {236 // nft237 const nftCollectionId = await createCollectionExpectSuccess();238 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');239 await transferExpectFailure(nftCollectionId, newNftTokenId, charlie, bob, 1);240 // fungible241 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});284 await requirePallets(this, [Pallets.ReFungible]);242 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');285243 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, charlie, bob, 1);244 // reFungible245 const reFungibleCollectionId = await286 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});246 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});247 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');287 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');276 });316 });277 });317 });278318279 it('RFT', async () => {319 it('RFT', async function() {320 await requirePallets(this, [Pallets.ReFungible]);321280 await usingApi(async (api: ApiPromise) => {322 await usingApi(async (api: ApiPromise) => {281 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});323 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});tests/src/transferFrom.test.tsdiffbeforeafterboth31 burnItemExpectSuccess,31 burnItemExpectSuccess,32 setCollectionLimitsExpectSuccess,32 setCollectionLimitsExpectSuccess,33 getCreatedCollectionCount,33 getCreatedCollectionCount,34 requirePallets,35 Pallets,34} from './util/helpers';36} from './util/helpers';353736chai.use(chaiAsPromised);38chai.use(chaiAsPromised);49 });51 });50 });52 });5354 it('[nft] Execute the extrinsic and check nftItemList - owner of token', async () => {55 const nftCollectionId = await createCollectionExpectSuccess();56 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');57 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);5859 await transferFromExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, charlie, 1, 'NFT');60 });516152 it('Execute the extrinsic and check nftItemList - owner of token', async () => {62 it('[fungible] Execute the extrinsic and check nftItemList - owner of token', async () => {53 await usingApi(async () => {54 // nft55 const nftCollectionId = await createCollectionExpectSuccess();56 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');57 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);5859 await transferFromExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, charlie, 1, 'NFT');6061 // fungible62 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});63 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});63 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');64 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');64 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);65 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);65 await transferFromExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1, 'Fungible');66 await transferFromExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1, 'Fungible');6667 // reFungible68 const reFungibleCollectionId = await69 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});70 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');71 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 100);72 await transferFromExpectSuccess(73 reFungibleCollectionId,74 newReFungibleTokenId,75 bob,76 alice,77 charlie,78 100,79 'ReFungible',80 );81 });82 });67 });6869 it('[refungible] Execute the extrinsic and check nftItemList - owner of token', async function() {70 await requirePallets(this, [Pallets.ReFungible]);7172 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});73 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');74 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 100);75 await transferFromExpectSuccess(76 reFungibleCollectionId,77 newReFungibleTokenId,78 bob,79 alice,80 charlie,81 100,82 'ReFungible',83 );84 });838584 it('Should reduce allowance if value is big', async () => {86 it('Should reduce allowance if value is big', async () => {85 await usingApi(async (api, privateKeyWrapper) => {87 await usingApi(async (api, privateKeyWrapper) => {119 });121 });120 });122 });121123122 it('transferFrom for a collection that does not exist', async () => {124 it('[nft] transferFrom for a collection that does not exist', async () => {123 await usingApi(async (api: ApiPromise) => {125 await usingApi(async (api: ApiPromise) => {124 // nft125 const nftCollectionCount = await getCreatedCollectionCount(api);126 const nftCollectionCount = await getCreatedCollectionCount(api);126 await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);127 await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);127128128 await transferFromExpectFail(nftCollectionCount + 1, 1, bob, alice, charlie, 1);129 await transferFromExpectFail(nftCollectionCount + 1, 1, bob, alice, charlie, 1);129130 // fungible131 const fungibleCollectionCount = await getCreatedCollectionCount(api);132 await approveExpectFail(fungibleCollectionCount + 1, 0, alice, bob);133134 await transferFromExpectFail(fungibleCollectionCount + 1, 0, bob, alice, charlie, 1);135 // reFungible136 const reFungibleCollectionCount = await getCreatedCollectionCount(api);137 await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);138139 await transferFromExpectFail(reFungibleCollectionCount + 1, 1, bob, alice, charlie, 1);140 });130 });141 });131 });132133 it('[fungible] transferFrom for a collection that does not exist', async () => {134 await usingApi(async (api: ApiPromise) => {135 const fungibleCollectionCount = await getCreatedCollectionCount(api);136 await approveExpectFail(fungibleCollectionCount + 1, 0, alice, bob);137138 await transferFromExpectFail(fungibleCollectionCount + 1, 0, bob, alice, charlie, 1);139 });140 });141142 it('[refungible] transferFrom for a collection that does not exist', async function() {143 await requirePallets(this, [Pallets.ReFungible]);144145 await usingApi(async (api: ApiPromise) => {146 const reFungibleCollectionCount = await getCreatedCollectionCount(api);147 await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);148149 await transferFromExpectFail(reFungibleCollectionCount + 1, 1, bob, alice, charlie, 1);150 });151 });142152143 /* it('transferFrom for a collection that was destroyed', async () => {153 /* it('transferFrom for a collection that was destroyed', async () => {144 await usingApi(async (api: ApiPromise) => {154 await usingApi(async (api: ApiPromise) => {158 });168 });159 }); */169 }); */170171 it('[nft] transferFrom for not approved address', async () => {172 const nftCollectionId = await createCollectionExpectSuccess();173 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');174175 await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 1);176 });160177161 it('transferFrom for not approved address', async () => {178 it('[fungible] transferFrom for not approved address', async () => {162 await usingApi(async () => {163 // nft164 const nftCollectionId = await createCollectionExpectSuccess();165 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');166167 await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 1);168169 // fungible170 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});179 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});171 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');180 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');172 await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1);181 await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1);173 // reFungible174 const reFungibleCollectionId = await175 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});176 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');177 await transferFromExpectFail(178 reFungibleCollectionId,179 newReFungibleTokenId,180 bob,181 alice,182 charlie,183 1,184 );185 });186 });182 });183184 it('[refungible] transferFrom for not approved address', async function() {185 await requirePallets(this, [Pallets.ReFungible]);186187 const reFungibleCollectionId = await188 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});189 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');190 await transferFromExpectFail(191 reFungibleCollectionId,192 newReFungibleTokenId,193 bob,194 alice,195 charlie,196 1,197 );198 });199200 it('[nft] transferFrom incorrect token count', async () => {201 const nftCollectionId = await createCollectionExpectSuccess();202 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');203 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);204205 await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 2);206 });187207188 it('transferFrom incorrect token count', async () => {208 it('[fungible] transferFrom incorrect token count', async () => {189 await usingApi(async () => {190 // nft191 const nftCollectionId = await createCollectionExpectSuccess();192 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');193 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);194195 await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 2);196197 // fungible198 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});209 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});199 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');210 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');200 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);211 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);201 await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 2);212 await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 2);202 // reFungible203 const reFungibleCollectionId = await204 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});205 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');206 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);207 await transferFromExpectFail(208 reFungibleCollectionId,209 newReFungibleTokenId,210 bob,211 alice,212 charlie,213 2,214 );215 });216 });213 });214215 it('[refungible] transferFrom incorrect token count', async function() {216 await requirePallets(this, [Pallets.ReFungible]);217218 const reFungibleCollectionId = await219 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});220 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');221 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);222 await transferFromExpectFail(223 reFungibleCollectionId,224 newReFungibleTokenId,225 bob,226 alice,227 charlie,228 2,229 );230 });231232 it('[nft] execute transferFrom from account that is not owner of collection', async () => {233 await usingApi(async (api, privateKeyWrapper) => {234 const dave = privateKeyWrapper('//Dave');235 const nftCollectionId = await createCollectionExpectSuccess();236 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');237 try {238 await approveExpectFail(nftCollectionId, newNftTokenId, dave, bob);239 await transferFromExpectFail(nftCollectionId, newNftTokenId, dave, alice, charlie, 1);240 } catch (e) {241 // tslint:disable-next-line:no-unused-expression242 expect(e).to.be.exist;243 }244245 // await transferFromExpectFail(nftCollectionId, newNftTokenId, Dave, Alice, Charlie, 1);246 });247 });217248218 it('execute transferFrom from account that is not owner of collection', async () => {249 it('[fungible] execute transferFrom from account that is not owner of collection', async () => {219 await usingApi(async (api, privateKeyWrapper) => {250 await usingApi(async (api, privateKeyWrapper) => {220 const dave = privateKeyWrapper('//Dave');251 const dave = privateKeyWrapper('//Dave');221 // nft252222 const nftCollectionId = await createCollectionExpectSuccess();223 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');224 try {225 await approveExpectFail(nftCollectionId, newNftTokenId, dave, bob);226 await transferFromExpectFail(nftCollectionId, newNftTokenId, dave, alice, charlie, 1);227 } catch (e) {228 // tslint:disable-next-line:no-unused-expression229 expect(e).to.be.exist;230 }231232 // await transferFromExpectFail(nftCollectionId, newNftTokenId, Dave, Alice, Charlie, 1);233234 // fungible235 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});253 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});236 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');254 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');237 try {255 try {241 // tslint:disable-next-line:no-unused-expression259 // tslint:disable-next-line:no-unused-expression242 expect(e).to.be.exist;260 expect(e).to.be.exist;243 }261 }244 // reFungible245 const reFungibleCollectionId = await246 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});247 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');248 try {249 await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, dave, bob);250 await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, dave, alice, charlie, 1);251 } catch (e) {252 // tslint:disable-next-line:no-unused-expression253 expect(e).to.be.exist;254 }255 });262 });256 });263 });264265 it('[refungible] execute transferFrom from account that is not owner of collection', async function() {266 await requirePallets(this, [Pallets.ReFungible]);267268 await usingApi(async (api, privateKeyWrapper) => {269 const dave = privateKeyWrapper('//Dave');270 const reFungibleCollectionId = await271 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});272 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');273 try {274 await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, dave, bob);275 await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, dave, alice, charlie, 1);276 } catch (e) {277 // tslint:disable-next-line:no-unused-expression278 expect(e).to.be.exist;279 }280 });281 });257 it('transferFrom burnt token before approve NFT', async () => {282 it('transferFrom burnt token before approve NFT', async () => {258 await usingApi(async () => {283 await usingApi(async () => {259 // nft284 // nft276301277 });302 });278 });303 });279 it('transferFrom burnt token before approve ReFungible', async () => {304 it('transferFrom burnt token before approve ReFungible', async function() {305 await requirePallets(this, [Pallets.ReFungible]);306280 await usingApi(async () => {307 await usingApi(async () => {281 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});308 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});308335309 });336 });310 });337 });311 it('transferFrom burnt token after approve ReFungible', async () => {338 it('transferFrom burnt token after approve ReFungible', async function() {339 await requirePallets(this, [Pallets.ReFungible]);340312 await usingApi(async () => {341 await usingApi(async () => {313 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});342 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});tests/src/util/helpers.tsdiffbeforeafterboth28import {hexToStr, strToUTF16, utf16ToStr} from './util';28import {hexToStr, strToUTF16, utf16ToStr} from './util';29import {UpDataStructsRpcCollection, UpDataStructsCreateItemData, UpDataStructsProperty} from '@polkadot/types/lookup';29import {UpDataStructsRpcCollection, UpDataStructsCreateItemData, UpDataStructsProperty} from '@polkadot/types/lookup';30import {UpDataStructsTokenChild} from '../interfaces';30import {UpDataStructsTokenChild} from '../interfaces';31import {Context} from 'mocha';313232chai.use(chaiAsPromised);33chai.use(chaiAsPromised);33const expect = chai.expect;34const expect = chai.expect;39};40};414243export enum Pallets {44 Inflation = 'inflation',45 RmrkCore = 'rmrkcore',46 RmrkEquip = 'rmrkequip',47 ReFungible = 'refungible',48 Fungible = 'fungible',49 NFT = 'nonfungible',50 Scheduler = 'scheduler',51}5253export async function isUnique(): Promise<boolean> {54 return usingApi(async api => {55 const chain = await api.rpc.system.chain();5657 return chain.eq('UNIQUE');58 });59}6061export async function isQuartz(): Promise<boolean> {62 return usingApi(async api => {63 const chain = await api.rpc.system.chain();64 65 return chain.eq('QUARTZ');66 });67}6869let modulesNames: any;70export function getModuleNames(api: ApiPromise): string[] {71 if (typeof modulesNames === 'undefined') 72 modulesNames = api.runtimeMetadata.asLatest.pallets.map(m => m.name.toString().toLowerCase());73 return modulesNames;74}7576export async function missingRequiredPallets(requiredPallets: string[]): Promise<string[]> {77 return await usingApi(async api => {78 const pallets = getModuleNames(api);7980 return requiredPallets.filter(p => !pallets.includes(p));81 });82}8384export async function checkPalletsPresence(requiredPallets: string[]): Promise<boolean> {85 return (await missingRequiredPallets(requiredPallets)).length == 0;86}8788export async function requirePallets(mocha: Context, requiredPallets: string[]) {89 const missingPallets = await missingRequiredPallets(requiredPallets);9091 if (missingPallets.length > 0) {92 const skippingTestMsg = `\tSkipping test "${mocha.test?.title}".`;93 const missingPalletsMsg = `\tThe following pallets are missing:\n\t- ${missingPallets.join('\n\t- ')}`;94 const skipMsg = `${skippingTestMsg}\n${missingPalletsMsg}`;9596 console.error('\x1b[38:5:208m%s\x1b[0m', skipMsg);9798 mocha.skip();99 }100}4010141export function normalizeAccountId(input: string | AccountId | CrossAccountId | IKeyringPair): CrossAccountId {102export function normalizeAccountId(input: string | AccountId | CrossAccountId | IKeyringPair): CrossAccountId {42 if (typeof input === 'string') {103 if (typeof input === 'string') {tests/src/util/playgrounds/index.tsdiffbeforeafterbothno changes
tests/src/util/playgrounds/unique.tsdiffbeforeafterbothno changes
tests/yarn.lockdiffbeforeafterboth963 dependencies:963 dependencies:964 "@types/chai" "*"964 "@types/chai" "*"965965966"@types/chai-like@^1.1.1":967 version "1.1.1"968 resolved "https://registry.yarnpkg.com/@types/chai-like/-/chai-like-1.1.1.tgz#c454039b0a2f92664fb5b7b7a2a66c3358783ae7"969 integrity sha512-s46EZsupBuVhLn66DbRee5B0SELLmL4nFXVrBiV29BxLGm9Sh7Bful623j3AfiQRu2zAP4cnlZ3ETWB3eWc4bA==970 dependencies:971 "@types/chai" "*"972966"@types/chai@*", "@types/chai@^4.3.1":973"@types/chai@*", "@types/chai@^4.3.1":967 version "4.3.1"974 version "4.3.1"968 resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.1.tgz#e2c6e73e0bdeb2521d00756d099218e9f5d90a04"975 resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.1.tgz#e2c6e73e0bdeb2521d00756d099218e9f5d90a04"1544 integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==1551 integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==1545 dependencies:1552 dependencies:1546 check-error "^1.0.2"1553 check-error "^1.0.2"15541555chai-like@^1.1.1:1556 version "1.1.1"1557 resolved "https://registry.yarnpkg.com/chai-like/-/chai-like-1.1.1.tgz#8c558a414c34514e814d497c772547ceb7958f64"1558 integrity sha512-VKa9z/SnhXhkT1zIjtPACFWSoWsqVoaz1Vg+ecrKo5DCKVlgL30F/pEyEvXPBOVwCgLZcWUleCM/C1okaKdTTA==154715591548chai@^4.3.6:1560chai@^4.3.6:1549 version "4.3.6"1561 version "4.3.6"