git.delta.rocks / unique-network / refs/commits / 0954b32db3b2

difftreelog

Merge branch 'develop' into feature/transferfromtests

Greg Zaitsev2021-02-09parents: #4f05952 #2109c86.patch.diff
in: master

43 files changed

added.devcontainer/Dockerfilediffbeforeafterboth
--- /dev/null
+++ b/.devcontainer/Dockerfile
@@ -0,0 +1,14 @@
+FROM mcr.microsoft.com/vscode/devcontainers/rust:0-1
+
+RUN apt-get update && export DEBIAN_FRONTEND=noninteractive && \
+    apt-get -y install --no-install-recommends libssl-dev pkg-config libclang-dev clang
+
+USER vscode
+
+RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash && \
+    export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")" && \
+    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \
+    nvm install v12.20.1 && \
+    rustup toolchain install nightly-2020-10-01 && \
+    rustup default nightly-2020-10-01 && \
+    rustup target add wasm32-unknown-unknown
\ No newline at end of file
added.devcontainer/devcontainer.jsondiffbeforeafterboth
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,18 @@
+{
+	"name": "Rust",
+	"build": {
+		"dockerfile": "Dockerfile"
+	},
+	"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
+	"settings": { 
+		"terminal.integrated.shell.linux": "/bin/bash",
+		"lldb.executable": "/usr/bin/lldb",
+		"files.watcherExclude": {
+			"**/target/**": true
+		}
+	},
+	"extensions": [
+		"matklad.rust-analyzer"
+	],
+	"remoteUser": "vscode"
+}
modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -543,9 +543,9 @@
 
 [[package]]
 name = "bumpalo"
-version = "3.5.0"
+version = "3.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f07aa6688c702439a1be0307b6a94dffe1168569e45b9500c1372bc580740d59"
+checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9"
 
 [[package]]
 name = "byte-slice-cast"
@@ -985,9 +985,9 @@
 
 [[package]]
 name = "ctor"
-version = "0.1.18"
+version = "0.1.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10bcb9d7dcbf7002aaffbb53eac22906b64cdcc127971dcc387d8eb7c95d5560"
+checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19"
 dependencies = [
  "quote",
  "syn",
@@ -1032,9 +1032,9 @@
 
 [[package]]
 name = "data-encoding"
-version = "2.3.1"
+version = "2.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "993a608597367c6377b258c25d7120740f00ed23a2252b729b1932dd7866f908"
+checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57"
 
 [[package]]
 name = "derive_more"
@@ -1151,7 +1151,7 @@
  "ed25519",
  "rand 0.7.3",
  "serde",
- "sha2 0.9.2",
+ "sha2 0.9.3",
  "zeroize",
 ]
 
@@ -1342,9 +1342,9 @@
 
 [[package]]
 name = "flate2"
-version = "1.0.19"
+version = "1.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129"
+checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0"
 dependencies = [
  "cfg-if 1.0.0",
  "crc32fast",
@@ -1907,7 +1907,7 @@
  "http 0.2.3",
  "indexmap",
  "slab",
- "tokio 0.2.24",
+ "tokio 0.2.25",
  "tokio-util",
  "tracing",
  "tracing-futures",
@@ -2064,9 +2064,9 @@
 
 [[package]]
 name = "httparse"
-version = "1.3.4"
+version = "1.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
+checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691"
 
 [[package]]
 name = "httpdate"
@@ -2129,9 +2129,9 @@
  "httparse",
  "httpdate",
  "itoa",
- "pin-project 1.0.4",
+ "pin-project 1.0.5",
  "socket2",
- "tokio 0.2.24",
+ "tokio 0.2.25",
  "tower-service",
  "tracing",
  "want 0.3.0",
@@ -2150,7 +2150,7 @@
  "log",
  "rustls 0.18.1",
  "rustls-native-certs",
- "tokio 0.2.24",
+ "tokio 0.2.25",
  "tokio-rustls",
  "webpki",
 ]
@@ -2553,9 +2553,9 @@
 
 [[package]]
 name = "libc"
-version = "0.2.82"
+version = "0.2.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
+checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3"
 
 [[package]]
 name = "libloading"
@@ -2606,7 +2606,7 @@
  "libp2p-yamux",
  "parity-multiaddr",
  "parking_lot 0.11.1",
- "pin-project 1.0.4",
+ "pin-project 1.0.5",
  "smallvec 1.6.1",
  "wasm-timer",
 ]
@@ -2631,13 +2631,13 @@
  "multistream-select",
  "parity-multiaddr",
  "parking_lot 0.11.1",
- "pin-project 1.0.4",
+ "pin-project 1.0.5",
  "prost",
  "prost-build",
  "rand 0.7.3",
  "ring",
  "rw-stream-sink",
- "sha2 0.9.2",
+ "sha2 0.9.3",
  "smallvec 1.6.1",
  "thiserror",
  "unsigned-varint 0.6.0",
@@ -2715,7 +2715,7 @@
  "prost-build",
  "rand 0.7.3",
  "regex",
- "sha2 0.9.2",
+ "sha2 0.9.3",
  "smallvec 1.6.1",
  "unsigned-varint 0.6.0",
  "wasm-timer",
@@ -2755,7 +2755,7 @@
  "prost",
  "prost-build",
  "rand 0.7.3",
- "sha2 0.9.2",
+ "sha2 0.9.3",
  "smallvec 1.6.1",
  "uint",
  "unsigned-varint 0.6.0",
@@ -2817,7 +2817,7 @@
  "prost",
  "prost-build",
  "rand 0.7.3",
- "sha2 0.9.2",
+ "sha2 0.9.3",
  "snow",
  "static_assertions",
  "x25519-dalek",
@@ -2864,7 +2864,7 @@
 dependencies = [
  "futures 0.3.12",
  "log",
- "pin-project 1.0.4",
+ "pin-project 1.0.5",
  "rand 0.7.3",
  "salsa20",
  "sha3",
@@ -2892,9 +2892,9 @@
 
 [[package]]
 name = "libp2p-swarm"
-version = "0.27.1"
+version = "0.27.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4f89ebb4d8953bda12623e9871959fe728dea3bf6eae0421dc9c42dc821e488"
+checksum = "7955b973e1fd2bd61ffd43ce261c1223f61f4aacd5bae362a924993f9a25fd98"
 dependencies = [
  "either",
  "futures 0.3.12",
@@ -3074,9 +3074,9 @@
 
 [[package]]
 name = "lru"
-version = "0.6.3"
+version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3aae342b73d57ad0b8b364bd12584819f2c1fe9114285dfcf8b0722607671635"
+checksum = "fe2382d8ed3918ea4ba70d98d5b74e47a168e0331965f3f17cdbc748bdebc5a3"
 dependencies = [
  "hashbrown",
 ]
@@ -3310,7 +3310,7 @@
  "digest 0.9.0",
  "generic-array 0.14.4",
  "multihash-derive",
- "sha2 0.9.2",
+ "sha2 0.9.3",
  "unsigned-varint 0.5.1",
 ]
 
@@ -3343,7 +3343,7 @@
  "bytes 1.0.1",
  "futures 0.3.12",
  "log",
- "pin-project 1.0.4",
+ "pin-project 1.0.5",
  "smallvec 1.6.1",
  "unsigned-varint 0.6.0",
 ]
@@ -4269,11 +4269,11 @@
 
 [[package]]
 name = "pin-project"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95b70b68509f17aa2857863b6fa00bf21fc93674c7a8893de2f469f6aa7ca2f2"
+checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63"
 dependencies = [
- "pin-project-internal 1.0.4",
+ "pin-project-internal 1.0.5",
 ]
 
 [[package]]
@@ -4289,9 +4289,9 @@
 
 [[package]]
 name = "pin-project-internal"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "caa25a6393f22ce819b0f50e0be89287292fda8d425be38ee0ca14c4931d9e71"
+checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4862,9 +4862,9 @@
 
 [[package]]
 name = "ring"
-version = "0.16.19"
+version = "0.16.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "024a1e66fea74c66c66624ee5622a7ff0e4b73a13b4f5c326ddb50c708944226"
+checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
 dependencies = [
  "cc",
  "libc",
@@ -5114,7 +5114,7 @@
  "structopt",
  "thiserror",
  "tiny-bip39",
- "tokio 0.2.24",
+ "tokio 0.2.25",
 ]
 
 [[package]]
@@ -6037,9 +6037,9 @@
 
 [[package]]
 name = "sha-1"
-version = "0.9.2"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce3cdf1b5e620a498ee6f2a171885ac7e22f0e12089ec4b3d22b84921792507c"
+checksum = "f4b312c3731e3fe78a185e6b9b911a7aa715b8e31cce117975219aab2acf285d"
 dependencies = [
  "block-buffer 0.9.0",
  "cfg-if 1.0.0",
@@ -6062,9 +6062,9 @@
 
 [[package]]
 name = "sha2"
-version = "0.9.2"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e7aab86fe2149bad8c507606bdb3f4ef5e7b2380eb92350f56122cca72a42a8"
+checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de"
 dependencies = [
  "block-buffer 0.9.0",
  "cfg-if 1.0.0",
@@ -6171,7 +6171,7 @@
  "rand_core 0.5.1",
  "ring",
  "rustc_version",
- "sha2 0.9.2",
+ "sha2 0.9.3",
  "subtle 2.4.0",
  "x25519-dalek",
 ]
@@ -6200,7 +6200,7 @@
  "httparse",
  "log",
  "rand 0.7.3",
- "sha-1 0.9.2",
+ "sha-1 0.9.3",
 ]
 
 [[package]]
@@ -6428,7 +6428,7 @@
  "schnorrkel",
  "secrecy",
  "serde",
- "sha2 0.9.2",
+ "sha2 0.9.3",
  "sp-debug-derive",
  "sp-externalities",
  "sp-runtime-interface",
@@ -6973,7 +6973,7 @@
  "hyper 0.13.9",
  "log",
  "prometheus",
- "tokio 0.2.24",
+ "tokio 0.2.25",
 ]
 
 [[package]]
@@ -7083,9 +7083,9 @@
 
 [[package]]
 name = "thread_local"
-version = "1.1.2"
+version = "1.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8208a331e1cb318dd5bd76951d2b8fc48ca38a69f5f4e4af1b6a9f8c6236915"
+checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
 dependencies = [
  "once_cell",
 ]
@@ -7122,7 +7122,7 @@
  "pbkdf2 0.4.0",
  "rand 0.7.3",
  "rustc-hash",
- "sha2 0.9.2",
+ "sha2 0.9.3",
  "thiserror",
  "unicode-normalization",
  "zeroize",
@@ -7178,9 +7178,9 @@
 
 [[package]]
 name = "tokio"
-version = "0.2.24"
+version = "0.2.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "099837d3464c16a808060bb3f02263b412f6fafcb5d01c533d309985fbeebe48"
+checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092"
 dependencies = [
  "bytes 0.5.6",
  "fnv",
@@ -7302,7 +7302,7 @@
 dependencies = [
  "futures-core",
  "rustls 0.18.1",
- "tokio 0.2.24",
+ "tokio 0.2.25",
  "webpki",
 ]
 
@@ -7412,7 +7412,7 @@
  "futures-sink",
  "log",
  "pin-project-lite 0.1.11",
- "tokio 0.2.24",
+ "tokio 0.2.25",
 ]
 
 [[package]]
@@ -7432,9 +7432,9 @@
 
 [[package]]
 name = "tracing"
-version = "0.1.22"
+version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3"
+checksum = "f7d40a22fd029e33300d8d89a5cc8ffce18bb7c587662f54629e94c9de5487f3"
 dependencies = [
  "cfg-if 1.0.0",
  "log",
@@ -7445,9 +7445,9 @@
 
 [[package]]
 name = "tracing-attributes"
-version = "0.1.11"
+version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada"
+checksum = "43f080ea7e4107844ef4766459426fa2d5c1ada2e47edba05dc7fa99d9629f47"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -7518,9 +7518,9 @@
 
 [[package]]
 name = "trie-db"
-version = "0.22.2"
+version = "0.22.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cc176c377eb24d652c9c69c832c832019011b6106182bf84276c66b66d5c9a6"
+checksum = "ec051edf7f0fc9499a2cb0947652cab2148b9d7f61cee7605e312e9f970dacaf"
 dependencies = [
  "hash-db",
  "hashbrown",
@@ -8032,18 +8032,18 @@
 
 [[package]]
 name = "wast"
-version = "32.0.0"
+version = "33.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c24a3ee360d01d60ed0a0f960ab76a6acce64348cdb0bf8699c2a866fad57c7c"
+checksum = "1d04fe175c7f78214971293e7d8875673804e736092206a3a4544dbc12811c1b"
 dependencies = [
  "leb128",
 ]
 
 [[package]]
 name = "wat"
-version = "1.0.33"
+version = "1.0.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e8f7f34773fa6318e8897283abf7941c1f250faae4e1a52f82df09c3bad7cce"
+checksum = "7ec9c6ee01ae07a26adadcdfed22c7a97e0b8cbee9c06e0e96076ece5aeb5cfe"
 dependencies = [
  "wast",
 ]
modifiedDockerfilediffbeforeafterboth
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,9 +1,9 @@
 # ===== BUILD ======
 
-FROM phusion/baseimage:0.10.2 as builder
+FROM phusion/baseimage:18.04-1.0.0 as builder
 LABEL maintainer="gz@usetech.com"
 
-ENV WASM_TOOLCHAIN=nightly-2020-10-01
+ENV WASM_TOOLCHAIN=nightly-2021-01-27
 
 ARG PROFILE=release
 
@@ -37,7 +37,7 @@
 
 # ===== RUN ======
 
-FROM phusion/baseimage:0.10.2
+FROM phusion/baseimage:18.04-1.0.0
 ARG PROFILE=release
 
 COPY --from=builder /nft_parachain/target/$PROFILE/nft /usr/local/bin
modifiedREADME.mddiffbeforeafterboth
--- a/README.md
+++ b/README.md
@@ -56,7 +56,7 @@
 
 ```bash
 rustup toolchain install 1.49.0
-rustup toolchain install nightly-2020-10-01
+rustup toolchain install nightly-2020-01-27
 rustup default nightly-2021-01-27
 ```
 
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -54,6 +54,7 @@
 mod default_weights;
 
 pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;
+pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;
 pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;
 pub const MAX_TOKEN_OWNERSHIP: u32 = 10_000_000;
 
@@ -71,8 +72,7 @@
     NFT,
     // decimal points
     Fungible(DecimalPoints),
-    // decimal points
-    ReFungible(DecimalPoints),
+    ReFungible,
 }
 
 impl Default for CollectionMode {
@@ -87,7 +87,7 @@
             CollectionMode::Invalid => 0,
             CollectionMode::NFT => 1,
             CollectionMode::Fungible(_) => 2,
-            CollectionMode::ReFungible(_) => 3,
+            CollectionMode::ReFungible => 3,
         }
     }
 }
@@ -266,6 +266,7 @@
 pub struct CreateReFungibleData {
     pub const_data: Vec<u8>,
     pub variable_data: Vec<u8>,
+    pub pieces: u128,
 }
 
 #[derive(Encode, Decode, Debug, Clone, PartialEq)]
@@ -377,7 +378,9 @@
         /// Collection limit bounds per collection exceeded
         CollectionLimitBoundsExceeded,
         /// Schema data size limit bound exceeded
-        SchemaDataLimitExceeded
+        SchemaDataLimitExceeded,
+        /// Maximum refungibility exceeded
+        WrongRefungiblePieces
 	}
 }
 
@@ -548,7 +551,6 @@
 
             let decimal_points = match mode {
                 CollectionMode::Fungible(points) => points,
-                CollectionMode::ReFungible(points) => points,
                 _ => 0
             };
 
@@ -933,7 +935,7 @@
 
             Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner)?;
             Self::validate_create_item_args(&target_collection, &data)?;
-            Self::create_item_no_validation(collection_id, &target_collection, owner, data)?;
+            Self::create_item_no_validation(collection_id, owner, data)?;
 
             Ok(())
         }
@@ -973,7 +975,7 @@
                 Self::validate_create_item_args(&target_collection, data)?;
             }
             for data in &items_data {
-                Self::create_item_no_validation(collection_id, &target_collection, owner.clone(), data.clone())?;
+                Self::create_item_no_validation(collection_id, owner.clone(), data.clone())?;
             }
 
             Ok(())
@@ -1012,7 +1014,7 @@
             {
                 CollectionMode::NFT => Self::burn_nft_item(collection_id, item_id)?,
                 CollectionMode::Fungible(_)  => Self::burn_fungible_item(&sender, collection_id, value)?,
-                CollectionMode::ReFungible(_)  => Self::burn_refungible_item(collection_id, item_id, &sender)?,
+                CollectionMode::ReFungible  => Self::burn_refungible_item(collection_id, item_id, &sender)?,
                 _ => ()
             };
 
@@ -1122,8 +1124,8 @@
 
             // Check approval
             let mut approval: u128 = 0;
-            if <Allowances<T>>::contains_key(collection_id, (item_id, &from, &recipient)) {
-                approval = <Allowances<T>>::get(collection_id, (item_id, &from, &recipient));
+            if <Allowances<T>>::contains_key(collection_id, (item_id, &from, &sender)) {
+                approval = <Allowances<T>>::get(collection_id, (item_id, &from, &sender));
                 ensure!(approval >= value, Error::<T>::TokenValueNotEnough);
                 appoved_transfer = true;
             }
@@ -1144,17 +1146,17 @@
 
             // Reduce approval by transferred amount or remove if remaining approval drops to 0
             if approval.checked_sub(value).unwrap_or(0) > 0 {
-                <Allowances<T>>::insert(collection_id, (item_id, &from, &recipient), approval - value);
+                <Allowances<T>>::insert(collection_id, (item_id, &from, &sender), approval - value);
             }
             else {
-                <Allowances<T>>::remove(collection_id, (item_id, &from, &recipient));
+                <Allowances<T>>::remove(collection_id, (item_id, &from, &sender));
             }
 
             match target_collection.mode
             {
                 CollectionMode::NFT => Self::transfer_nft(collection_id, item_id, from, recipient)?,
                 CollectionMode::Fungible(_)  => Self::transfer_fungible(collection_id, value, &from, &recipient)?,
-                CollectionMode::ReFungible(_)  => Self::transfer_refungible(collection_id, item_id, value, from.clone(), recipient)?,
+                CollectionMode::ReFungible  => Self::transfer_refungible(collection_id, item_id, value, from.clone(), recipient)?,
                 _ => ()
             };
 
@@ -1211,7 +1213,7 @@
             match target_collection.mode
             {
                 CollectionMode::NFT => Self::set_nft_variable_data(collection_id, item_id, data)?,
-                CollectionMode::ReFungible(_)  => Self::set_re_fungible_variable_data(collection_id, item_id, data)?,
+                CollectionMode::ReFungible  => Self::set_re_fungible_variable_data(collection_id, item_id, data)?,
                 CollectionMode::Fungible(_) => fail!(Error::<T>::CantStoreMetadataInFungibleTokens),
                 _ => fail!(Error::<T>::UnexpectedCollectionType)
             };
@@ -1551,7 +1553,7 @@
         {
             CollectionMode::NFT => Self::transfer_nft(collection_id, item_id, sender.clone(), recipient)?,
             CollectionMode::Fungible(_)  => Self::transfer_fungible(collection_id, value, &sender, &recipient)?,
-            CollectionMode::ReFungible(_)  => Self::transfer_refungible(collection_id, item_id, value, sender.clone(), recipient)?,
+            CollectionMode::ReFungible  => Self::transfer_refungible(collection_id, item_id, value, sender.clone(), recipient)?,
             _ => ()
         };
 
@@ -1603,12 +1605,16 @@
                     fail!(Error::<T>::NotFungibleDataUsedToMintFungibleCollectionToken);
                 }
             },
-            CollectionMode::ReFungible(_) => {
+            CollectionMode::ReFungible => {
                 if let CreateItemData::ReFungible(data) = data {
 
                     // check sizes
                     ensure!(ChainLimit::get().custom_data_limit >= data.const_data.len() as u32, Error::<T>::TokenConstDataLimitExceeded);
                     ensure!(ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32, Error::<T>::TokenVariableDataLimitExceeded);
+
+                    // Check refungibility limits
+                    ensure!(data.pieces <= MAX_REFUNGIBLE_PIECES, Error::<T>::WrongRefungiblePieces);
+                    ensure!(data.pieces > 0, Error::<T>::WrongRefungiblePieces);
                 } else {
                     fail!(Error::<T>::NotReFungibleDataUsedToMintReFungibleCollectionToken);
                 }
@@ -1619,7 +1625,7 @@
         Ok(())
     }
 
-    fn create_item_no_validation(collection_id: CollectionId, collection: &CollectionType<T::AccountId>, owner: T::AccountId, data: CreateItemData) -> DispatchResult {
+    fn create_item_no_validation(collection_id: CollectionId, owner: T::AccountId, data: CreateItemData) -> DispatchResult {
         match data
         {
             CreateItemData::NFT(data) => {
@@ -1636,8 +1642,7 @@
             },
             CreateItemData::ReFungible(data) => {
                 let mut owner_list = Vec::new();
-                let value = (10 as u128).pow(collection.decimal_points as u32);
-                owner_list.push(Ownership {owner: owner.clone(), fraction: value});
+                owner_list.push(Ownership {owner: owner.clone(), fraction: data.pieces});
 
                 let item = ReFungibleItemType {
                     owner: owner_list,
@@ -1866,7 +1871,7 @@
             CollectionMode::Fungible(_) => {
                 <FungibleItemList<T>>::contains_key(collection_id, &subject)
             }
-            CollectionMode::ReFungible(_) => {
+            CollectionMode::ReFungible => {
                 <ReFungibleItemList<T>>::get(collection_id, item_id)
                     .owner
                     .iter()
@@ -1895,7 +1900,7 @@
         {
             CollectionMode::NFT => <NftItemList<T>>::contains_key(collection_id, item_id),
             CollectionMode::Fungible(_)  => <FungibleItemList<T>>::contains_key(collection_id, owner),
-            CollectionMode::ReFungible(_)  => <ReFungibleItemList<T>>::contains_key(collection_id, item_id),
+            CollectionMode::ReFungible  => <ReFungibleItemList<T>>::contains_key(collection_id, item_id),
             _ => false
         };
 
@@ -2421,7 +2426,7 @@
 
                             sponsored
                         }
-                        CollectionMode::ReFungible(_) => {
+                        CollectionMode::ReFungible => {
     
                             // get correct limit
                             let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
modifiedpallets/nft/src/mock.rsdiffbeforeafterboth
--- a/pallets/nft/src/mock.rs
+++ b/pallets/nft/src/mock.rs
@@ -1,26 +1,21 @@
 // Creating mock runtime here
 
-use crate::{Module, Trait};
-
-use pallet_contracts::{
-	ContractAddressFor, TrieId, TrieIdGenerator,
-};
+use crate::{Module, Config};
 
 use frame_support::{
     impl_outer_origin, parameter_types,
-    weights::{
-      //  constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight},
-        Weight, IdentityFee,
-    },
+    weights::{Weight, IdentityFee},
 };
 use frame_system as system;
-use transaction_payment;
+use system::limits::{BlockLength, BlockWeights};
+use transaction_payment::{self, CurrencyAdapter};
 use sp_core::H256;
 use sp_runtime::{
     testing::Header,
-    traits::{BlakeTwo256, IdentityLookup, Saturating},
+    traits::{BlakeTwo256, IdentityLookup},
     Perbill,
 };
+use pallet_contracts::WeightInfo;
 pub use pallet_balances;
 
 impl_outer_origin! {
@@ -34,14 +29,12 @@
 pub struct Test;
 parameter_types! {
     pub const BlockHashCount: u64 = 250;
-    pub const MaximumBlockWeight: Weight = 1024;
-    pub const MaximumBlockLength: u32 = 2 * 1024;
-    pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
-    pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get()
-    .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get();
+	pub TestBlockWeights: BlockWeights = BlockWeights::default();
+	pub TestBlockLength: BlockLength = BlockLength::default();
+	pub SS58Prefix: u8 = 0;
 }
 
-impl system::Trait for Test {
+impl system::Config for Test {
 	type BaseCallFilter = ();
 	type Origin = Origin;
 	type Call = ();
@@ -54,18 +47,15 @@
 	type Header = Header;
 	type Event = ();
 	type BlockHashCount = BlockHashCount;
-	type MaximumBlockWeight = MaximumBlockWeight;
+	type BlockWeights = TestBlockWeights;
 	type DbWeight = ();
-	type BlockExecutionWeight = ();
-	type ExtrinsicBaseWeight = ();
-	type MaximumExtrinsicWeight = MaximumBlockWeight;
-	type MaximumBlockLength = MaximumBlockLength;
-	type AvailableBlockRatio = AvailableBlockRatio;
+	type BlockLength = TestBlockLength;
 	type Version = ();
 	type PalletInfo = ();
 	type AccountData = pallet_balances::AccountData<u64>;
 	type OnNewAccount = ();
 	type OnKilledAccount = ();
+	type SS58Prefix = SS58Prefix;
 	type SystemWeightInfo = ();
 }
 
@@ -75,7 +65,7 @@
 }
 
 type System = frame_system::Module<Test>;
-impl pallet_balances::Trait for Test {
+impl pallet_balances::Config for Test {
     type AccountStore = System;
     type Balance = u64;
     type DustRemoval = ();
@@ -88,9 +78,9 @@
 parameter_types! {
 	pub const TransactionByteFee: u64 = 1;
 }
-impl transaction_payment::Trait for Test {
-	type Currency = pallet_balances::Module<Test>;
-	type OnTransactionPayment = ();
+
+impl transaction_payment::Config for Test {
+	type OnChargeTransaction = CurrencyAdapter<pallet_balances::Module<Test>, ()>;
 	type TransactionByteFee = TransactionByteFee;
 	type WeightToFee = IdentityFee<u64>;
 	type FeeMultiplierUpdate = ();
@@ -100,7 +90,7 @@
 parameter_types! {
 	pub const MinimumPeriod: u64 = 1;
 }
-impl pallet_timestamp::Trait for Test {
+impl pallet_timestamp::Config for Test {
 	type Moment = u64;
 	type OnTimestampSet = ();
 	type MinimumPeriod = MinimumPeriod;
@@ -112,49 +102,45 @@
 
 parameter_types! {
 	pub const TombstoneDeposit: u64 = 1;
-	pub const RentByteFee: u64 = 1;
-	pub const RentDepositOffset: u64 = 1;
+	pub const DepositPerContract: u64 = 1;
+	pub const DepositPerStorageByte: u64 = 1;
+	pub const DepositPerStorageItem: u64 = 1;
+	pub RentFraction: Perbill = Perbill::from_rational_approximation(1u32, 30 * 24 * 60 * 10);
 	pub const SurchargeReward: u64 = 1;
-}
-
-pub struct DummyTrieIdGenerator;
-impl TrieIdGenerator<u64> for DummyTrieIdGenerator {
-	fn trie_id(account_id: &u64) -> TrieId {
-		let new_seed = *account_id + 1;
-		let mut res = vec![];
-		res.extend_from_slice(&new_seed.to_le_bytes());
-		res.extend_from_slice(&account_id.to_le_bytes());
-		res
-	}
-}
-
-pub struct DummyContractAddressFor;
-impl ContractAddressFor<H256, u64> for DummyContractAddressFor {
-	fn contract_address_for(_code_hash: &H256, _data: &[u8], origin: &u64) -> u64 {
-		*origin + 1
-	}
+	pub const SignedClaimHandicap: u32 = 2;
+	pub const MaxDepth: u32 = 32;
+	pub const MaxValueSize: u32 = 16 * 1024;
+	pub DeletionWeightLimit: Weight = Perbill::from_percent(10) *
+		TestBlockWeights::get().max_block;
+	pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (
+		<Test as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -
+		<Test as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)
+	)) / 5) as u32;
 }
 
-impl pallet_contracts::Trait for Test {
+impl pallet_contracts::Config for Test {
 	type Time = Timestamp;
 	type Randomness = Randomness;
 	type Currency = pallet_balances::Module<Test>;
 	type Event = ();
-	type DetermineContractAddress = DummyContractAddressFor;
-	type TrieIdGenerator = DummyTrieIdGenerator;
 	type RentPayment = ();
-	type SignedClaimHandicap = pallet_contracts::DefaultSignedClaimHandicap;
+	type SignedClaimHandicap = SignedClaimHandicap;
 	type TombstoneDeposit = TombstoneDeposit;
-	type StorageSizeOffset = pallet_contracts::DefaultStorageSizeOffset;
-	type RentByteFee = RentByteFee;
-	type RentDepositOffset = RentDepositOffset;
+	type DepositPerContract = DepositPerContract;
+	type DepositPerStorageByte = DepositPerStorageByte;
+	type DepositPerStorageItem = DepositPerStorageItem;
+	type RentFraction = RentFraction;
 	type SurchargeReward = SurchargeReward;
-	type MaxDepth = pallet_contracts::DefaultMaxDepth;
-	type MaxValueSize = pallet_contracts::DefaultMaxValueSize;
+	type DeletionWeightLimit = DeletionWeightLimit;
+	type MaxDepth = MaxDepth;
+	type DeletionQueueDepth = DeletionQueueDepth;
+	type MaxValueSize = MaxValueSize;
+	type ChainExtension = ();
 	type WeightPrice = ();
+	type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;
 }
 
-impl Trait for Test {
+impl Config for Test {
 	type Event = ();
 	type WeightInfo = ();
 
modifiedpallets/nft/src/tests.rsdiffbeforeafterboth
before · pallets/nft/src/tests.rs
1// Tests to be written here2use super::*;3use crate::mock::*;4use crate::{AccessMode, CollectionMode,5    Ownership, ChainLimits, CreateItemData, CreateNftData, CreateFungibleData, CreateReFungibleData,6    CollectionId, TokenId, MAX_DECIMAL_POINTS};7use frame_support::{assert_noop, assert_ok};8use frame_system::{ RawOrigin };910fn default_collection_numbers_limit() -> u32 {11    1012}1314fn default_limits() {15    assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits {16            collection_numbers_limit: default_collection_numbers_limit(),17            account_token_ownership_limit: 10,18            collections_admins_limit: 5,19            custom_data_limit: 2048,20            nft_sponsor_transfer_timeout: 15,21            fungible_sponsor_transfer_timeout: 15,22            refungible_sponsor_transfer_timeout: 15,23            const_on_chain_schema_limit: 1024,24            offchain_schema_limit: 1024,25            variable_on_chain_schema_limit: 1024,26        }));27}2829fn default_nft_data() -> CreateNftData {30    CreateNftData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] }31}3233fn default_fungible_data () -> CreateFungibleData {34    CreateFungibleData { value: 5 }35}3637fn default_re_fungible_data () -> CreateReFungibleData {38    CreateReFungibleData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] }39}4041fn create_test_collection_for_owner(mode: &CollectionMode, owner: u64, id: CollectionId) -> CollectionId {42    let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();43    let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();44    let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();4546    let origin1 = Origin::signed(owner);47    assert_ok!(TemplateModule::create_collection(48            origin1.clone(),49            col_name1.clone(),50            col_desc1.clone(),51            token_prefix1.clone(),52            mode.clone()53        ));5455    let saved_col_name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();56    let saved_description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();57    let saved_prefix: Vec<u8> = b"token_prefix1\0".to_vec();58    assert_eq!(TemplateModule::collection(id).owner, owner);59    assert_eq!(TemplateModule::collection(id).name, saved_col_name);60    assert_eq!(TemplateModule::collection(id).mode, *mode);61    assert_eq!(TemplateModule::collection(id).description, saved_description);62    assert_eq!(TemplateModule::collection(id).token_prefix, saved_prefix);63    id64}6566fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {67    create_test_collection_for_owner(&mode, 1, id)68}6970fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {71    let origin1 = Origin::signed(1);72    assert_ok!(TemplateModule::create_item(73            origin1.clone(),74            collection_id,75            1,76            data.clone()77        ));7879}8081// Use cases tests region82// #region8384#[test]85fn set_version_schema() {86    new_test_ext().execute_with(|| {87        default_limits();88        let origin1 = Origin::signed(1);89        let collection_id = create_test_collection(&CollectionMode::NFT, 1);90        91        assert_ok!(TemplateModule::set_schema_version(origin1, collection_id, SchemaVersion::Unique));92        assert_eq!(TemplateModule::collection(collection_id).schema_version, SchemaVersion::Unique);93    });94}9596#[test]97fn create_fungible_collection_fails_with_large_decimal_numbers() {98    new_test_ext().execute_with(|| {99        default_limits();100101        let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();102        let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();103        let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();104105        let origin1 = Origin::signed(1);106        assert_noop!(TemplateModule::create_collection(107            origin1,108            col_name1,109            col_desc1,110            token_prefix1,111            CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1)112        ), Error::<Test>::CollectionDecimalPointLimitExceeded);113    });    114}115116#[test]117fn create_re_fungible_collection_fails_with_large_decimal_numbers() {118    new_test_ext().execute_with(|| {119        default_limits();120121        let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();122        let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();123        let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();124125        let origin1 = Origin::signed(1);126        assert_noop!(TemplateModule::create_collection(127            origin1,128            col_name1,129            col_desc1,130            token_prefix1,131            CollectionMode::ReFungible(MAX_DECIMAL_POINTS + 1)132        ), Error::<Test>::CollectionDecimalPointLimitExceeded);133    });134}135136#[test]137fn create_nft_item() {138    new_test_ext().execute_with(|| {139        default_limits();140        let collection_id = create_test_collection(&CollectionMode::NFT, 1);141        142        let data = default_nft_data();143        create_test_item(collection_id, &data.clone().into());144        assert_eq!(TemplateModule::nft_item_id(collection_id, 1).const_data, data.const_data);145        assert_eq!(TemplateModule::nft_item_id(collection_id, 1).variable_data, data.variable_data);146    });147}148149// Use cases tests region150// #region151#[test]152fn create_nft_multiple_items() {153    new_test_ext().execute_with(|| {154        default_limits();155        156        create_test_collection(&CollectionMode::NFT, 1);157158        let origin1 = Origin::signed(1);159160        let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];161162        assert_ok!(TemplateModule::create_multiple_items(163            origin1.clone(),164            1,165            1,166            items_data.clone().into_iter().map(|d| { d.into() }).collect()167        ));168        for (index, data) in items_data.iter().enumerate() {169            assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as TokenId).const_data.to_vec(), data.const_data);170            assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as TokenId).variable_data.to_vec(), data.variable_data);171        }172    });173}174175#[test]176fn create_refungible_item() {177    new_test_ext().execute_with(|| {178        default_limits();179        let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);180181        let data = default_re_fungible_data();182        create_test_item(collection_id, &data.clone().into());183        assert_eq!(184            TemplateModule::refungible_item_id(collection_id, 1).const_data,185            data.const_data186        );187        assert_eq!(188            TemplateModule::refungible_item_id(collection_id, 1).variable_data,189            data.variable_data190        );191        assert_eq!(192            TemplateModule::refungible_item_id(collection_id, 1).owner[0],193            Ownership {194                owner: 1,195                fraction: 1000196            }197        );198    });199}200201#[test]202fn create_multiple_refungible_items() {203    new_test_ext().execute_with(|| {204        default_limits();205        206        create_test_collection(&CollectionMode::ReFungible(3), 1);207208        let origin1 = Origin::signed(1);209210        let items_data = vec![default_re_fungible_data(), default_re_fungible_data(), default_re_fungible_data()];211212        assert_ok!(TemplateModule::create_multiple_items(213            origin1.clone(),214            1,215            1,216            items_data.clone().into_iter().map(|d| { d.into() }).collect()217        ));218        for (index, data) in items_data.iter().enumerate() {219220            let item = TemplateModule::refungible_item_id(1, (index + 1) as TokenId);221            assert_eq!(item.const_data.to_vec(), data.const_data);222            assert_eq!(item.variable_data.to_vec(), data.variable_data);223            assert_eq!(224                item.owner[0],225                Ownership {226                    owner: 1,227                    fraction: 1000228                }229            );230        }231    });232}233234#[test]235fn create_fungible_item() {236    new_test_ext().execute_with(|| {237        default_limits();238        239        let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);240241        let data = default_fungible_data();242        create_test_item(collection_id, &data.into());243244        assert_eq!(TemplateModule::fungible_item_id(collection_id, 1).value, 5);245    });246}247248//#[test]249// fn create_multiple_fungible_items() {250//     new_test_ext().execute_with(|| {251//         default_limits();252253//         create_test_collection(&CollectionMode::Fungible(3), 1);254255//         let origin1 = Origin::signed(1);256257//         let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];258259//         assert_ok!(TemplateModule::create_multiple_items(260//             origin1.clone(),261//             1,262//             1,263//             items_data.clone().into_iter().map(|d| { d.into() }).collect()264//         ));265        266//         for (index, _) in items_data.iter().enumerate() {267//             assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as TokenId).value, 5);268//         }269//         assert_eq!(TemplateModule::balance_count(1, 1), 3000);270//         assert_eq!(TemplateModule::address_tokens(1, 1), [1, 2, 3]);271//     });272// }273274#[test]275fn transfer_fungible_item() {276    new_test_ext().execute_with(|| {277        default_limits();278        279        let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);280281        let origin1 = Origin::signed(1);282        let origin2 = Origin::signed(2);283284        let data = default_fungible_data();285        create_test_item(collection_id, &data.into());286287        assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 5);288        assert_eq!(TemplateModule::balance_count(1, 1), 5);289290        // change owner scenario291        assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 5));292        assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 0);293        assert_eq!(TemplateModule::balance_count(1, 1), 0);294        assert_eq!(TemplateModule::balance_count(1, 2), 5);295296        // split item scenario297        assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 3));298        assert_eq!(TemplateModule::balance_count(1, 2), 2);299        assert_eq!(TemplateModule::balance_count(1, 3), 3);300301        // split item and new owner has account scenario302        assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 1));303        assert_eq!(TemplateModule::fungible_item_id(1, 2).value, 1);304        assert_eq!(TemplateModule::fungible_item_id(1, 3).value, 4);305        assert_eq!(TemplateModule::balance_count(1, 2), 1);306        assert_eq!(TemplateModule::balance_count(1, 3), 4);307    });308}309310#[test]311fn transfer_refungible_item() {312    new_test_ext().execute_with(|| {313        default_limits();314        315        let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);316317        let data = default_re_fungible_data();318        create_test_item(collection_id, &data.clone().into());319320        let origin1 = Origin::signed(1);321        let origin2 = Origin::signed(2);322        assert_eq!(323            TemplateModule::refungible_item_id(collection_id, 1).const_data,324            data.const_data325        );326        assert_eq!(327            TemplateModule::refungible_item_id(collection_id, 1).variable_data,328            data.variable_data329        );330        assert_eq!(331            TemplateModule::refungible_item_id(collection_id, 1).owner[0],332            Ownership {333                owner: 1,334                fraction: 1000335            }336        );337        assert_eq!(TemplateModule::balance_count(1, 1), 1000);338        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);339340        // change owner scenario341        assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1000));342        assert_eq!(343            TemplateModule::refungible_item_id(1, 1).owner[0],344            Ownership {345                owner: 2,346                fraction: 1000347            }348        );349        assert_eq!(TemplateModule::balance_count(1, 1), 0);350        assert_eq!(TemplateModule::balance_count(1, 2), 1000);351        // assert_eq!(TemplateModule::address_tokens(1, 1), []);352        assert_eq!(TemplateModule::address_tokens(1, 2), [1]);353354        // split item scenario355        assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 500));356        assert_eq!(357            TemplateModule::refungible_item_id(1, 1).owner[0],358            Ownership {359                owner: 2,360                fraction: 500361            }362        );363        assert_eq!(364            TemplateModule::refungible_item_id(1, 1).owner[1],365            Ownership {366                owner: 3,367                fraction: 500368            }369        );370        assert_eq!(TemplateModule::balance_count(1, 2), 500);371        assert_eq!(TemplateModule::balance_count(1, 3), 500);372        assert_eq!(TemplateModule::address_tokens(1, 2), [1]);373        assert_eq!(TemplateModule::address_tokens(1, 3), [1]);374375        // split item and new owner has account scenario376        assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 200));377        assert_eq!(378            TemplateModule::refungible_item_id(1, 1).owner[0],379            Ownership {380                owner: 2,381                fraction: 300382            }383        );384        assert_eq!(385            TemplateModule::refungible_item_id(1, 1).owner[1],386            Ownership {387                owner: 3,388                fraction: 700389            }390        );391        assert_eq!(TemplateModule::balance_count(1, 2), 300);392        assert_eq!(TemplateModule::balance_count(1, 3), 700);393        assert_eq!(TemplateModule::address_tokens(1, 2), [1]);394        assert_eq!(TemplateModule::address_tokens(1, 3), [1]);395    });396}397398#[test]399fn transfer_nft_item() {400    new_test_ext().execute_with(|| {401        default_limits();402        403        let collection_id = create_test_collection(&CollectionMode::NFT, 1);404405        let data = default_nft_data();406        create_test_item(collection_id, &data.into());407        assert_eq!(TemplateModule::balance_count(1, 1), 1);408        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);409410        let origin1 = Origin::signed(1);411        // default scenario412        assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1000));413        assert_eq!(TemplateModule::nft_item_id(1, 1).owner, 2);414        assert_eq!(TemplateModule::balance_count(1, 1), 0);415        assert_eq!(TemplateModule::balance_count(1, 2), 1);416        // assert_eq!(TemplateModule::address_tokens(1, 1), []);417        assert_eq!(TemplateModule::address_tokens(1, 2), [1]);418    });419}420421#[test]422fn nft_approve_and_transfer_from() {423    new_test_ext().execute_with(|| {424        default_limits();425        426        let collection_id = create_test_collection(&CollectionMode::NFT, 1);427428        let data = default_nft_data();429        create_test_item(collection_id, &data.into());430431        let origin1 = Origin::signed(1);432        let origin2 = Origin::signed(2);433434        assert_eq!(TemplateModule::balance_count(1, 1), 1);435        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);436437        // neg transfer438        assert_noop!(TemplateModule::transfer_from(439            origin2.clone(),440            1,441            2,442            1,443            1,444            1), Error::<Test>::NoPermission);445446        // do approve447        assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 5));448        assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);449        assert_eq!(450            TemplateModule::approved(1, (1, 1, 2)),451            5452        );453454        assert_ok!(TemplateModule::transfer_from(455            origin2.clone(),456            1,457            2,458            1,459            1,460            1461        ));462        assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 4);463    });464}465466#[test]467fn nft_approve_and_transfer_from_white_list() {468    new_test_ext().execute_with(|| {469        default_limits();470        471        let collection_id = create_test_collection(&CollectionMode::NFT, 1);472473        let origin1 = Origin::signed(1);474        let origin2 = Origin::signed(2);475476        let data = default_nft_data();477        create_test_item(collection_id, &data.clone().into());478479        assert_eq!(TemplateModule::nft_item_id(1, 1).const_data, data.const_data);480        assert_eq!(TemplateModule::balance_count(1, 1), 1);481        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);482483        assert_ok!(TemplateModule::set_mint_permission(484            origin1.clone(),485            1,486            true487        ));488        assert_ok!(TemplateModule::set_public_access_mode(489            origin1.clone(),490            1,491            AccessMode::WhiteList492        ));493        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));494        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));495        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));496497        // do approve498        assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 5));499        assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);500        assert_ok!(TemplateModule::approve(origin1.clone(), 3, 1, 1, 5));501        assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 5);502503        assert_ok!(TemplateModule::transfer_from(504            origin2.clone(),505            1,506            3,507            1,508            1,509            1510        ));511        assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 4);512    });513}514515#[test]516fn refungible_approve_and_transfer_from() {517    new_test_ext().execute_with(|| {518        default_limits();519        520        let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);521        522        let origin1 = Origin::signed(1);523        let origin2 = Origin::signed(2);524525        let data = default_re_fungible_data();526        create_test_item(collection_id, &data.into());527528        assert_eq!(TemplateModule::balance_count(1, 1), 1000);529        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);530531        assert_ok!(TemplateModule::set_mint_permission(532            origin1.clone(),533            1,534            true535        ));536        assert_ok!(TemplateModule::set_public_access_mode(537            origin1.clone(),538            1,539            AccessMode::WhiteList540        ));541        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));542        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));543        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));544545        // do approve546        assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 5));547        assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);548        assert_ok!(TemplateModule::approve(origin1.clone(), 3, 1, 1, 1000));549        assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 1000);550551        assert_ok!(TemplateModule::transfer_from(552            origin2.clone(),553            1,554            3,555            1,556            1,557            100558        ));559        assert_eq!(TemplateModule::balance_count(1, 1), 900);560        assert_eq!(TemplateModule::balance_count(1, 3), 100);561        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);562        assert_eq!(TemplateModule::address_tokens(1, 3), [1]);563564        assert_eq!(565            TemplateModule::approved(1, (1, 1, 3)),566            900567        );568    });569}570571#[test]572fn fungible_approve_and_transfer_from() {573    new_test_ext().execute_with(|| {574        default_limits();575        576        let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);577        578        let data = default_fungible_data();579        create_test_item(collection_id, &data.into());580581        let origin1 = Origin::signed(1);582        let origin2 = Origin::signed(2);583584        assert_eq!(TemplateModule::balance_count(1, 1), 5);585586        assert_ok!(TemplateModule::set_mint_permission(587            origin1.clone(),588            1,589            true590        ));591        assert_ok!(TemplateModule::set_public_access_mode(592            origin1.clone(),593            1,594            AccessMode::WhiteList595        ));596        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));597        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));598        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));599600        // do approve601        assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 5));602        assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);603        assert_ok!(TemplateModule::approve(origin1.clone(), 3, 1, 1, 5));604        assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 5);605        assert_eq!(606            TemplateModule::approved(1, (1, 1, 2)),607            5608        );609610        assert_ok!(TemplateModule::transfer_from(611            origin2.clone(),612            1,613            3,614            1,615            1,616            4617        ));618        assert_eq!(TemplateModule::balance_count(1, 1), 1);619        assert_eq!(TemplateModule::balance_count(1, 3), 4);620621        assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);622        assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 1);623624        assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 5));625        assert_noop!(TemplateModule::transfer_from(626            origin2.clone(),627            1,628            3,629            1,630            1,631            4632        ), Error::<Test>::TokenValueNotEnough);633    });634}635636#[test]637fn change_collection_owner() {638    new_test_ext().execute_with(|| {639        default_limits();640        641        let collection_id = create_test_collection(&CollectionMode::NFT, 1);642        643        let origin1 = Origin::signed(1);644        assert_ok!(TemplateModule::change_collection_owner(645            origin1.clone(),646            collection_id,647            2648        ));649        assert_eq!(TemplateModule::collection(collection_id).owner, 2);650    });651}652653#[test]654fn destroy_collection() {655    new_test_ext().execute_with(|| {656        default_limits();657        658        let collection_id = create_test_collection(&CollectionMode::NFT, 1);659        660        let origin1 = Origin::signed(1);661        assert_ok!(TemplateModule::destroy_collection(origin1.clone(), collection_id));662    });663}664665#[test]666fn burn_nft_item() {667    new_test_ext().execute_with(|| {668        default_limits();669        670        let collection_id = create_test_collection(&CollectionMode::NFT, 1);671672        let origin1 = Origin::signed(1);673        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));674        675        let data = default_nft_data();676        create_test_item(collection_id, &data.into());677678        // check balance (collection with id = 1, user id = 1)679        assert_eq!(TemplateModule::balance_count(1, 1), 1);680681        // burn item682        assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 5));683        assert_noop!(684            TemplateModule::burn_item(origin1.clone(), 1, 1, 5),685            Error::<Test>::TokenNotFound686        );687688        assert_eq!(TemplateModule::balance_count(1, 1), 0);689    });690}691692#[test]693fn burn_fungible_item() {694    new_test_ext().execute_with(|| {695        default_limits();696        697        let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);698        699        let origin1 = Origin::signed(1);700        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));701        702        let data = default_fungible_data();703        create_test_item(collection_id, &data.into());704705        // check balance (collection with id = 1, user id = 1)706        assert_eq!(TemplateModule::balance_count(1, 1), 5);707708        // burn item709        assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 5));710        assert_noop!(711            TemplateModule::burn_item(origin1.clone(), 1, 1, 5),712            Error::<Test>::TokenNotFound713        );714715        assert_eq!(TemplateModule::balance_count(1, 1), 0);716    });717}718719#[test]720fn burn_refungible_item() {721    new_test_ext().execute_with(|| {722        default_limits();723        724        let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);725        let origin1 = Origin::signed(1);726727        assert_ok!(TemplateModule::set_mint_permission(728            origin1.clone(),729            collection_id,730            true731        ));732        assert_ok!(TemplateModule::set_public_access_mode(733            origin1.clone(),734            collection_id,735            AccessMode::WhiteList736        ));737        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));738739        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));740        741        let data = default_re_fungible_data();742        create_test_item(collection_id, &data.into());743744        // check balance (collection with id = 1, user id = 2)745        assert_eq!(TemplateModule::balance_count(1, 1), 1000);746747        // burn item748        assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 1000));749        assert_noop!(750            TemplateModule::burn_item(origin1.clone(), 1, 1, 1000),751            Error::<Test>::TokenNotFound752        );753754        assert_eq!(TemplateModule::balance_count(1, 1), 0);755    });756}757758#[test]759fn add_collection_admin() {760    new_test_ext().execute_with(|| {761        default_limits();762        763        let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);764        create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);765        create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);766        767        let origin1 = Origin::signed(1);768769        // collection admin770        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 2));771        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 3));772773        assert_eq!(TemplateModule::admin_list_collection(collection1_id).contains(&2), true);774        assert_eq!(TemplateModule::admin_list_collection(collection1_id).contains(&3), true);775    });776}777778#[test]779fn remove_collection_admin() {780    new_test_ext().execute_with(|| {781        default_limits();782        783        let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);784        create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);785        create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);786787        let origin1 = Origin::signed(1);788        let origin2 = Origin::signed(2);789790        // collection admin791        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 2));792        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 3));793794        assert_eq!(TemplateModule::admin_list_collection(1).contains(&2), true);795        assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), true);796797        // remove admin798        assert_ok!(TemplateModule::remove_collection_admin(799            origin2.clone(),800            1,801            3802        ));803        assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), false);804    });805}806807#[test]808fn balance_of() {809    new_test_ext().execute_with(|| {810        default_limits();811        812        let nft_collection_id = create_test_collection(&CollectionMode::NFT, 1);813        let fungible_collection_id = create_test_collection(&CollectionMode::Fungible(3), 2);814        let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible(3), 3);815        816        // check balance before817        assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 0);818        assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 0);819        assert_eq!(TemplateModule::balance_count(re_fungible_collection_id, 1), 0);820821        let nft_data = default_nft_data();822        create_test_item(nft_collection_id, &nft_data.into());823        824        let fungible_data = default_fungible_data();825        create_test_item(fungible_collection_id, &fungible_data.into());826        827        let re_fungible_data = default_re_fungible_data();828        create_test_item(re_fungible_collection_id, &re_fungible_data.into());829830        // check balance (collection with id = 1, user id = 1)831        assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 1);832        assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 5);833        assert_eq!(TemplateModule::balance_count(re_fungible_collection_id, 1), 1000);834        assert_eq!(TemplateModule::nft_item_id(nft_collection_id, 1).owner, 1);835        assert_eq!(TemplateModule::fungible_item_id(fungible_collection_id, 1).value, 5);836        assert_eq!(TemplateModule::refungible_item_id(re_fungible_collection_id, 1).owner[0].owner, 1);837    });838}839840#[test]841fn approve() {842    new_test_ext().execute_with(|| {843        default_limits();844        845        let collection_id = create_test_collection(&CollectionMode::NFT, 1);846        847        let data = default_nft_data();848        create_test_item(collection_id, &data.into());849850        let origin1 = Origin::signed(1);851        852        // approve853        assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 1));854        assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);855    });856}857858#[test]859fn transfer_from() {860    new_test_ext().execute_with(|| {861        default_limits();862        863        let collection_id = create_test_collection(&CollectionMode::NFT, 1);864        let origin1 = Origin::signed(1);865        let origin2 = Origin::signed(2);866867        let data = default_nft_data();868        create_test_item(collection_id, &data.into());869870        // approve871        assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 1));872        assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);873874        assert_ok!(TemplateModule::set_mint_permission(875            origin1.clone(),876            1,877            true878        ));879        assert_ok!(TemplateModule::set_public_access_mode(880            origin1.clone(),881            1,882            AccessMode::WhiteList883        ));884        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));885        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));886        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));887888        assert_ok!(TemplateModule::transfer_from(889            origin2.clone(),890            1,891            2,892            1,893            1,894            1895        ));896897        // after transfer898        assert_eq!(TemplateModule::balance_count(1, 1), 0);899        assert_eq!(TemplateModule::balance_count(1, 2), 1);900    });901}902903// #endregion904905// Coverage tests region906// #region907908#[test]909fn owner_can_add_address_to_white_list() {910    new_test_ext().execute_with(|| {911        default_limits();912        913        let collection_id = create_test_collection(&CollectionMode::NFT, 1);914915        let origin1 = Origin::signed(1);916        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));917        assert_eq!(TemplateModule::white_list(collection_id, 2), true);918    });919}920921#[test]922fn admin_can_add_address_to_white_list() {923    new_test_ext().execute_with(|| {924        default_limits();925        926        let collection_id = create_test_collection(&CollectionMode::NFT, 1);927        let origin1 = Origin::signed(1);928        let origin2 = Origin::signed(2);929930        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));931        assert_ok!(TemplateModule::add_to_white_list(origin2.clone(), collection_id, 3));932        assert_eq!(TemplateModule::white_list(collection_id, 3), true);933    });934}935936#[test]937fn nonprivileged_user_cannot_add_address_to_white_list() {938    new_test_ext().execute_with(|| {939        default_limits();940        941        let collection_id = create_test_collection(&CollectionMode::NFT, 1);942943        let origin2 = Origin::signed(2);944        assert_noop!(945            TemplateModule::add_to_white_list(origin2.clone(), collection_id, 3),946            Error::<Test>::NoPermission947        );948    });949}950951#[test]952fn nobody_can_add_address_to_white_list_of_nonexisting_collection() {953    new_test_ext().execute_with(|| {954        default_limits();955956        let origin1 = Origin::signed(1);957958        assert_noop!(959            TemplateModule::add_to_white_list(origin1.clone(), 1, 2),960            Error::<Test>::CollectionNotFound961        );962    });963}964965#[test]966fn nobody_can_add_address_to_white_list_of_deleted_collection() {967    new_test_ext().execute_with(|| {968        default_limits();969        970        let collection_id = create_test_collection(&CollectionMode::NFT, 1);971972        let origin1 = Origin::signed(1);973        assert_ok!(TemplateModule::destroy_collection(origin1.clone(), collection_id));974        assert_noop!(975            TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2),976            Error::<Test>::CollectionNotFound977        );978    });979}980981// If address is already added to white list, nothing happens982#[test]983fn address_is_already_added_to_white_list() {984    new_test_ext().execute_with(|| {985        default_limits();986        987        let collection_id = create_test_collection(&CollectionMode::NFT, 1);988        let origin1 = Origin::signed(1);989        990        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));991        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));992        assert_eq!(TemplateModule::white_list(collection_id, 2), true);993    });994}995996#[test]997fn owner_can_remove_address_from_white_list() {998    new_test_ext().execute_with(|| {999        default_limits();1000        1001        let collection_id = create_test_collection(&CollectionMode::NFT, 1);10021003        let origin1 = Origin::signed(1);1004        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1005        assert_ok!(TemplateModule::remove_from_white_list(1006            origin1.clone(),1007            collection_id,1008            21009        ));1010        assert_eq!(TemplateModule::white_list(collection_id, 2), false);1011    });1012}10131014#[test]1015fn admin_can_remove_address_from_white_list() {1016    new_test_ext().execute_with(|| {1017        default_limits();1018        1019        let collection_id = create_test_collection(&CollectionMode::NFT, 1);1020        let origin1 = Origin::signed(1);1021        let origin2 = Origin::signed(2);10221023        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));10241025        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 3));1026        assert_ok!(TemplateModule::remove_from_white_list(1027            origin2.clone(),1028            collection_id,1029            31030        ));1031        assert_eq!(TemplateModule::white_list(collection_id, 3), false);1032    });1033}10341035#[test]1036fn nonprivileged_user_cannot_remove_address_from_white_list() {1037    new_test_ext().execute_with(|| {1038        default_limits();1039        1040        let collection_id = create_test_collection(&CollectionMode::NFT, 1);1041        let origin1 = Origin::signed(1);1042        let origin2 = Origin::signed(2);10431044        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1045        assert_noop!(1046            TemplateModule::remove_from_white_list(origin2.clone(), collection_id, 2),1047            Error::<Test>::NoPermission1048        );1049        assert_eq!(TemplateModule::white_list(collection_id, 2), true);1050    });1051}10521053#[test]1054fn nobody_can_remove_address_from_white_list_of_nonexisting_collection() {1055    new_test_ext().execute_with(|| {1056        default_limits();1057        let origin1 = Origin::signed(1);10581059        assert_noop!(1060            TemplateModule::remove_from_white_list(origin1.clone(), 1, 2),1061            Error::<Test>::CollectionNotFound1062        );1063    });1064}10651066#[test]1067fn nobody_can_remove_address_from_white_list_of_deleted_collection() {1068    new_test_ext().execute_with(|| {1069        default_limits();1070        1071        let collection_id = create_test_collection(&CollectionMode::NFT, 1);1072        let origin1 = Origin::signed(1);1073        let origin2 = Origin::signed(2);10741075        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1076        assert_ok!(TemplateModule::destroy_collection(origin1.clone(), collection_id));1077        assert_noop!(1078            TemplateModule::remove_from_white_list(origin2.clone(), collection_id, 2),1079            Error::<Test>::CollectionNotFound1080        );1081        assert_eq!(TemplateModule::white_list(collection_id, 2), false);1082    });1083}10841085// If address is already removed from white list, nothing happens1086#[test]1087fn address_is_already_removed_from_white_list() {1088    new_test_ext().execute_with(|| {1089        default_limits();1090        1091        let collection_id = create_test_collection(&CollectionMode::NFT, 1);1092        let origin1 = Origin::signed(1);10931094        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1095        assert_ok!(TemplateModule::remove_from_white_list(1096            origin1.clone(),1097            collection_id,1098            21099        ));1100        assert_ok!(TemplateModule::remove_from_white_list(1101            origin1.clone(),1102            collection_id,1103            21104        ));1105        assert_eq!(TemplateModule::white_list(collection_id, 2), false);1106    });1107}11081109// If Public Access mode is set to WhiteList, tokens can’t be transferred from a non-whitelisted address with transfer or transferFrom (2 tests)1110#[test]1111fn white_list_test_1() {1112    new_test_ext().execute_with(|| {1113        default_limits();1114        1115        let collection_id = create_test_collection(&CollectionMode::NFT, 1);11161117        let origin1 = Origin::signed(1);1118        1119        let data = default_nft_data();1120        create_test_item(collection_id, &data.into());11211122        assert_ok!(TemplateModule::set_public_access_mode(1123            origin1.clone(),1124            collection_id,1125            AccessMode::WhiteList1126        ));1127        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));11281129        assert_noop!(1130            TemplateModule::transfer(origin1.clone(), 3, 1, 1, 1),1131            Error::<Test>::AddresNotInWhiteList1132        );1133    });1134}11351136#[test]1137fn white_list_test_2() {1138    new_test_ext().execute_with(|| {1139        default_limits();1140        1141        let collection_id = create_test_collection(&CollectionMode::NFT, 1);1142        let origin1 = Origin::signed(1);1143        1144        let data = default_nft_data();1145        create_test_item(collection_id, &data.into());11461147        assert_ok!(TemplateModule::set_public_access_mode(1148            origin1.clone(),1149            collection_id,1150            AccessMode::WhiteList1151        ));1152        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));1153        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));11541155        // do approve1156        assert_ok!(TemplateModule::approve(origin1.clone(), 1, 1, 1, 1));1157        assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 1);11581159        assert_ok!(TemplateModule::remove_from_white_list(1160            origin1.clone(),1161            1,1162            11163        ));11641165        assert_noop!(1166            TemplateModule::transfer_from(origin1.clone(), 1, 3, 1, 1, 1),1167            Error::<Test>::AddresNotInWhiteList1168        );1169    });1170}11711172// If Public Access mode is set to WhiteList, tokens can’t be transferred to a non-whitelisted address with transfer or transferFrom (2 tests)1173#[test]1174fn white_list_test_3() {1175    new_test_ext().execute_with(|| {1176        default_limits();1177        1178        let collection_id = create_test_collection(&CollectionMode::NFT, 1);11791180        let origin1 = Origin::signed(1);1181        1182        let data = default_nft_data();1183        create_test_item(collection_id, &data.into());11841185        assert_ok!(TemplateModule::set_public_access_mode(1186            origin1.clone(),1187            collection_id,1188            AccessMode::WhiteList1189        ));1190        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));11911192        assert_noop!(1193            TemplateModule::transfer(origin1.clone(), 3, 1, 1, 1),1194            Error::<Test>::AddresNotInWhiteList1195        );1196    });1197}11981199#[test]1200fn white_list_test_4() {1201    new_test_ext().execute_with(|| {1202        default_limits();1203        1204        let collection_id = create_test_collection(&CollectionMode::NFT, 1);12051206        let origin1 = Origin::signed(1);12071208        let data = default_nft_data();1209        create_test_item(collection_id, &data.into());12101211        assert_ok!(TemplateModule::set_public_access_mode(1212            origin1.clone(),1213            collection_id,1214            AccessMode::WhiteList1215        ));1216        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 1));1217        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));12181219        // do approve1220        assert_ok!(TemplateModule::approve(origin1.clone(), 1, 1, 1, 1));1221        assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 1);12221223        assert_ok!(TemplateModule::remove_from_white_list(1224            origin1.clone(),1225            collection_id,1226            21227        ));12281229        assert_noop!(1230            TemplateModule::transfer_from(origin1.clone(), 1, 3, 1, 1, 1),1231            Error::<Test>::AddresNotInWhiteList1232        );1233    });1234}12351236// If Public Access mode is set to WhiteList, tokens can’t be destroyed by a non-whitelisted address (even if it owned them before enabling WhiteList mode)1237#[test]1238fn white_list_test_5() {1239    new_test_ext().execute_with(|| {1240        default_limits();1241        1242        let collection_id = create_test_collection(&CollectionMode::NFT, 1);12431244        let origin1 = Origin::signed(1);12451246        let data = default_nft_data();1247        create_test_item(collection_id, &data.into());12481249        assert_ok!(TemplateModule::set_public_access_mode(1250            origin1.clone(),1251            collection_id,1252            AccessMode::WhiteList1253        ));1254        assert_noop!(1255            TemplateModule::burn_item(origin1.clone(), 1, 1, 5),1256            Error::<Test>::AddresNotInWhiteList1257        );1258    });1259}12601261// If Public Access mode is set to WhiteList, token transfers can’t be Approved by a non-whitelisted address (see Approve method).1262#[test]1263fn white_list_test_6() {1264    new_test_ext().execute_with(|| {1265        default_limits();1266        1267        let collection_id = create_test_collection(&CollectionMode::NFT, 1);12681269        let origin1 = Origin::signed(1);12701271        let data = default_nft_data();1272        create_test_item(collection_id, &data.into());12731274        assert_ok!(TemplateModule::set_public_access_mode(1275            origin1.clone(),1276            collection_id,1277            AccessMode::WhiteList1278        ));12791280        // do approve1281        assert_noop!(1282            TemplateModule::approve(origin1.clone(), 1, 1, 1, 5),1283            Error::<Test>::AddresNotInWhiteList1284        );1285    });1286}12871288// If Public Access mode is set to WhiteList, tokens can be transferred from a whitelisted address with transfer or transferFrom (2 tests) and1289//          tokens can be transferred from a whitelisted address with transfer or transferFrom (2 tests)1290#[test]1291fn white_list_test_7() {1292    new_test_ext().execute_with(|| {1293        default_limits();1294        1295        let collection_id = create_test_collection(&CollectionMode::NFT, 1);12961297        let data = default_nft_data();1298        create_test_item(collection_id, &data.into());1299        1300        let origin1 = Origin::signed(1);13011302        assert_ok!(TemplateModule::set_public_access_mode(1303            origin1.clone(),1304            collection_id,1305            AccessMode::WhiteList1306        ));1307        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 1));1308        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));13091310        assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1));1311    });1312}13131314#[test]1315fn white_list_test_8() {1316    new_test_ext().execute_with(|| {1317        default_limits();1318        1319        let collection_id = create_test_collection(&CollectionMode::NFT, 1);13201321        let data = default_nft_data();1322        create_test_item(collection_id, &data.into());1323        1324        let origin1 = Origin::signed(1);13251326        assert_ok!(TemplateModule::set_public_access_mode(1327            origin1.clone(),1328            collection_id,1329            AccessMode::WhiteList1330        ));1331        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 1));1332        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));13331334        // do approve1335        assert_ok!(TemplateModule::approve(origin1.clone(), 1, 1, 1, 5));1336        assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 5);13371338        assert_ok!(TemplateModule::transfer_from(1339            origin1.clone(),1340            1,1341            2,1342            1,1343            1,1344            11345        ));1346    });1347}13481349// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens can be created by owner.1350#[test]1351fn white_list_test_9() {1352    new_test_ext().execute_with(|| {1353        default_limits();1354        1355        let collection_id = create_test_collection(&CollectionMode::NFT, 1);1356        let origin1 = Origin::signed(1);13571358        assert_ok!(TemplateModule::set_public_access_mode(1359            origin1.clone(),1360            collection_id,1361            AccessMode::WhiteList1362        ));1363        assert_ok!(TemplateModule::set_mint_permission(1364            origin1.clone(),1365            collection_id,1366            false1367        ));13681369        let data = default_nft_data();1370        create_test_item(collection_id, &data.into());1371    });1372}13731374// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens can be created by admin.1375#[test]1376fn white_list_test_10() {1377    new_test_ext().execute_with(|| {1378        default_limits();1379        1380        let collection_id = create_test_collection(&CollectionMode::NFT, 1);13811382        let origin1 = Origin::signed(1);1383        let origin2 = Origin::signed(2);13841385        assert_ok!(TemplateModule::set_public_access_mode(1386            origin1.clone(),1387            collection_id,1388            AccessMode::WhiteList1389        ));1390        assert_ok!(TemplateModule::set_mint_permission(1391            origin1.clone(),1392            collection_id,1393            false1394        ));13951396        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));13971398        assert_ok!(TemplateModule::create_item(1399            origin2.clone(),1400            collection_id,1401            2,1402            default_nft_data().into()1403        ));1404    });1405}14061407// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens cannot be created by non-privileged and white listed address.1408#[test]1409fn white_list_test_11() {1410    new_test_ext().execute_with(|| {1411        default_limits();1412        1413        let collection_id = create_test_collection(&CollectionMode::NFT, 1);14141415        let origin1 = Origin::signed(1);1416        let origin2 = Origin::signed(2);14171418        assert_ok!(TemplateModule::set_public_access_mode(1419            origin1.clone(),1420            collection_id,1421            AccessMode::WhiteList1422        ));1423        assert_ok!(TemplateModule::set_mint_permission(1424            origin1.clone(),1425            collection_id,1426            false1427        ));1428        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));14291430        assert_noop!(1431            TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1432            Error::<Test>::PublicMintingNotAllowed1433        );1434    });1435}14361437// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens cannot be created by non-privileged and non-white listed address.1438#[test]1439fn white_list_test_12() {1440    new_test_ext().execute_with(|| {1441        default_limits();1442        1443        let collection_id = create_test_collection(&CollectionMode::NFT, 1);14441445        let origin1 = Origin::signed(1);1446        let origin2 = Origin::signed(2);14471448        assert_ok!(TemplateModule::set_public_access_mode(1449            origin1.clone(),1450            collection_id,1451            AccessMode::WhiteList1452        ));1453        assert_ok!(TemplateModule::set_mint_permission(1454            origin1.clone(),1455            collection_id,1456            false1457        ));14581459        assert_noop!(1460            TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1461            Error::<Test>::PublicMintingNotAllowed1462        );1463    });1464}14651466// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens can be created by owner.1467#[test]1468fn white_list_test_13() {1469    new_test_ext().execute_with(|| {1470        default_limits();1471        1472        let collection_id = create_test_collection(&CollectionMode::NFT, 1);14731474        let origin1 = Origin::signed(1);14751476        assert_ok!(TemplateModule::set_public_access_mode(1477            origin1.clone(),1478            collection_id,1479            AccessMode::WhiteList1480        ));1481        assert_ok!(TemplateModule::set_mint_permission(1482            origin1.clone(),1483            collection_id,1484            true1485        ));14861487        let data = default_nft_data();1488        create_test_item(collection_id, &data.into());1489    });1490}14911492// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens can be created by admin.1493#[test]1494fn white_list_test_14() {1495    new_test_ext().execute_with(|| {1496        default_limits();1497        1498        let collection_id = create_test_collection(&CollectionMode::NFT, 1);14991500        let origin1 = Origin::signed(1);1501        let origin2 = Origin::signed(2);15021503        assert_ok!(TemplateModule::set_public_access_mode(1504            origin1.clone(),1505            collection_id,1506            AccessMode::WhiteList1507        ));1508        assert_ok!(TemplateModule::set_mint_permission(1509            origin1.clone(),1510            collection_id,1511            true1512        ));15131514        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));15151516        assert_ok!(TemplateModule::create_item(1517            origin2.clone(),1518            1,1519            2,1520            default_nft_data().into()1521        ));1522    });1523}15241525// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens cannot be created by non-privileged and non-white listed address.1526#[test]1527fn white_list_test_15() {1528    new_test_ext().execute_with(|| {1529        default_limits();1530        1531        let collection_id = create_test_collection(&CollectionMode::NFT, 1);15321533        let origin1 = Origin::signed(1);1534        let origin2 = Origin::signed(2);15351536        assert_ok!(TemplateModule::set_public_access_mode(1537            origin1.clone(),1538            collection_id,1539            AccessMode::WhiteList1540        ));1541        assert_ok!(TemplateModule::set_mint_permission(1542            origin1.clone(),1543            collection_id,1544            true1545        ));15461547        assert_noop!(1548            TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1549            Error::<Test>::AddresNotInWhiteList1550        );1551    });1552}15531554// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens can be created by non-privileged and white listed address.1555#[test]1556fn white_list_test_16() {1557    new_test_ext().execute_with(|| {1558        default_limits();1559        1560        let collection_id = create_test_collection(&CollectionMode::NFT, 1);15611562        let origin1 = Origin::signed(1);1563        let origin2 = Origin::signed(2);15641565        assert_ok!(TemplateModule::set_public_access_mode(1566            origin1.clone(),1567            collection_id,1568            AccessMode::WhiteList1569        ));1570        assert_ok!(TemplateModule::set_mint_permission(1571            origin1.clone(),1572            collection_id,1573            true1574        ));1575        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));15761577        assert_ok!(TemplateModule::create_item(1578            origin2.clone(),1579            1,1580            2,1581            default_nft_data().into()1582        ));1583    });1584}15851586// Total number of collections. Positive test1587#[test]1588fn total_number_collections_bound() {1589    new_test_ext().execute_with(|| {1590        default_limits();1591        1592        create_test_collection(&CollectionMode::NFT, 1);1593    });1594}15951596// Total number of collections. Negotive test1597#[test]1598fn total_number_collections_bound_neg() {1599    new_test_ext().execute_with(|| {1600        default_limits();16011602        let origin1 = Origin::signed(1);16031604        for i in 0..default_collection_numbers_limit() {1605            create_test_collection(&CollectionMode::NFT, i + 1);1606        }16071608        let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();1609        let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();1610        let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();16111612        // 11-th collection in chain. Expects error1613        assert_noop!(TemplateModule::create_collection(1614            origin1.clone(),1615            col_name1.clone(),1616            col_desc1.clone(),1617            token_prefix1.clone(),1618            CollectionMode::NFT1619        ), Error::<Test>::TotalCollectionsLimitExceeded);1620    });1621}16221623// Owned tokens by a single address. Positive test1624#[test]1625fn owned_tokens_bound() {1626    new_test_ext().execute_with(|| {1627        default_limits();1628        1629        let collection_id = create_test_collection(&CollectionMode::NFT, 1);16301631        let data = default_nft_data();1632        create_test_item(collection_id, &data.clone().into());1633        create_test_item(collection_id, &data.into());1634    });1635}16361637// Owned tokens by a single address. Negotive test1638#[test]1639fn owned_tokens_bound_neg() {1640    new_test_ext().execute_with(|| {1641        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1642            collection_numbers_limit: 10,1643            account_token_ownership_limit: 1,1644            collections_admins_limit: 5,1645            custom_data_limit: 2048,1646            nft_sponsor_transfer_timeout: 15,1647            fungible_sponsor_transfer_timeout: 15,1648            refungible_sponsor_transfer_timeout: 15,1649            const_on_chain_schema_limit: 1024,1650            offchain_schema_limit: 1024,1651            variable_on_chain_schema_limit: 1024,1652        }));1653        1654        let collection_id = create_test_collection(&CollectionMode::NFT, 1);16551656        let origin1 = Origin::signed(1);1657        let data = default_nft_data();1658        create_test_item(collection_id, &data.clone().into());16591660        assert_noop!(TemplateModule::create_item(1661            origin1.clone(),1662            1,1663            1,1664            data.into()1665        ),  Error::<Test>::AddressOwnershipLimitExceeded);1666    });1667}16681669// Number of collection admins. Positive test1670#[test]1671fn collection_admins_bound() {1672    new_test_ext().execute_with(|| {1673        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1674            collection_numbers_limit: 10,1675            account_token_ownership_limit: 10,1676            collections_admins_limit: 2,1677            custom_data_limit: 2048,1678            nft_sponsor_transfer_timeout: 15,1679            fungible_sponsor_transfer_timeout: 15,1680            refungible_sponsor_transfer_timeout: 15,1681            const_on_chain_schema_limit: 1024,1682            offchain_schema_limit: 1024,1683            variable_on_chain_schema_limit: 1024,1684        }));1685        1686        let collection_id = create_test_collection(&CollectionMode::NFT, 1);16871688        let origin1 = Origin::signed(1);1689        1690        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));1691        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 3));1692    });1693}16941695// Number of collection admins. Negotive test1696#[test]1697fn collection_admins_bound_neg() {1698    new_test_ext().execute_with(|| {1699        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1700            collection_numbers_limit: 10,1701            account_token_ownership_limit: 1,1702            collections_admins_limit: 1,1703            custom_data_limit: 2048,1704            nft_sponsor_transfer_timeout: 15,1705            fungible_sponsor_transfer_timeout: 15,1706            refungible_sponsor_transfer_timeout: 15,1707            const_on_chain_schema_limit: 1024,1708            offchain_schema_limit: 1024,1709            variable_on_chain_schema_limit: 1024,1710        }));1711        1712        let collection_id = create_test_collection(&CollectionMode::NFT, 1);17131714        let origin1 = Origin::signed(1);17151716        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));1717        assert_noop!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 3), Error::<Test>::CollectionAdminsLimitExceeded);1718    });1719}17201721// NFT custom data size. Negative test const_data.1722#[test]1723fn custom_data_size_nft_const_data_bound_neg() {1724    new_test_ext().execute_with(|| {1725        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1726            collection_numbers_limit: 10,1727            account_token_ownership_limit: 10,1728            collections_admins_limit: 5,1729            custom_data_limit: 2,1730            nft_sponsor_transfer_timeout: 15,1731            fungible_sponsor_transfer_timeout: 15,1732            refungible_sponsor_transfer_timeout: 15,1733            const_on_chain_schema_limit: 1024,1734            offchain_schema_limit: 1024,1735            variable_on_chain_schema_limit: 1024,1736        }));1737        1738        let collection_id = create_test_collection(&CollectionMode::NFT, 1);17391740        let origin1 = Origin::signed(1);1741        let too_big_const_data = CreateItemData::NFT(CreateNftData{1742            const_data: vec![1, 2, 3, 4],1743            variable_data: vec![]1744        });17451746        assert_noop!(TemplateModule::create_item(1747            origin1.clone(),1748            collection_id,1749            1,1750            too_big_const_data1751        ), Error::<Test>::TokenConstDataLimitExceeded);1752    });1753}17541755// NFT custom data size. Negative test variable_data.1756#[test]1757fn custom_data_size_nft_variable_data_bound_neg() {1758    new_test_ext().execute_with(|| {1759        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1760            collection_numbers_limit: 10,1761            account_token_ownership_limit: 10,1762            collections_admins_limit: 5,1763            custom_data_limit: 2,1764            nft_sponsor_transfer_timeout: 15,1765            fungible_sponsor_transfer_timeout: 15,1766            refungible_sponsor_transfer_timeout: 15,1767            const_on_chain_schema_limit: 1024,1768            offchain_schema_limit: 1024,1769            variable_on_chain_schema_limit: 1024,1770        }));17711772        let collection_id = create_test_collection(&CollectionMode::NFT, 1);17731774        let origin1 = Origin::signed(1);1775        let too_big_const_data = CreateItemData::NFT(CreateNftData{1776            const_data: vec![],1777            variable_data: vec![1, 2, 3, 4]1778        });17791780        assert_noop!(TemplateModule::create_item(1781            origin1.clone(),1782            collection_id,1783            1,1784            too_big_const_data1785        ), Error::<Test>::TokenVariableDataLimitExceeded);1786    });1787}17881789// Re fungible custom data size. Negative test const_data.1790#[test]1791fn custom_data_size_re_fungible_const_data_bound_neg() {1792    new_test_ext().execute_with(|| {1793        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1794            collection_numbers_limit: 10,1795            account_token_ownership_limit: 10,1796            collections_admins_limit: 5,1797            custom_data_limit: 2,1798            nft_sponsor_transfer_timeout: 15,1799            fungible_sponsor_transfer_timeout: 15,1800            refungible_sponsor_transfer_timeout: 15,1801            const_on_chain_schema_limit: 1024,1802            offchain_schema_limit: 1024,1803            variable_on_chain_schema_limit: 1024,1804        }));18051806        let collection_id = create_test_collection(&CollectionMode::NFT, 1);18071808        let origin1 = Origin::signed(1);1809        let too_big_const_data = CreateItemData::NFT(CreateNftData{1810            const_data: vec![1, 2, 3, 4],1811            variable_data: vec![]1812        });18131814        assert_noop!(TemplateModule::create_item(1815            origin1.clone(),1816            collection_id,1817            1,1818            too_big_const_data1819        ), Error::<Test>::TokenConstDataLimitExceeded);1820    });1821}18221823// Re fungible custom data size. Negative test variable_data.1824#[test]1825fn custom_data_size_re_fungible_variable_data_bound_neg() {1826    new_test_ext().execute_with(|| {1827        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1828            collection_numbers_limit: 10,1829            account_token_ownership_limit: 10,1830            collections_admins_limit: 5,1831            custom_data_limit: 2,1832            nft_sponsor_transfer_timeout: 15,1833            fungible_sponsor_transfer_timeout: 15,1834            refungible_sponsor_transfer_timeout: 15,1835            const_on_chain_schema_limit: 1024,1836            offchain_schema_limit: 1024,1837            variable_on_chain_schema_limit: 1024,1838        }));18391840        let collection_id = create_test_collection(&CollectionMode::NFT, 1);18411842        let origin1 = Origin::signed(1);1843        let too_big_const_data = CreateItemData::NFT(CreateNftData{1844            const_data: vec![],1845            variable_data: vec![1, 2, 3, 4]1846        });18471848        assert_noop!(TemplateModule::create_item(1849            origin1.clone(),1850            collection_id,1851            1,1852            too_big_const_data1853        ), Error::<Test>::TokenVariableDataLimitExceeded);1854    });1855}1856// #endregion18571858#[test]1859fn set_const_on_chain_schema() {1860    new_test_ext().execute_with(|| {1861        default_limits();18621863        let collection_id = create_test_collection(&CollectionMode::NFT, 1);18641865        let origin1 = Origin::signed(1);1866        assert_ok!(TemplateModule::set_const_on_chain_schema(origin1, collection_id, b"test const on chain schema".to_vec()));18671868        assert_eq!(TemplateModule::collection(collection_id).const_on_chain_schema, b"test const on chain schema".to_vec());1869        assert_eq!(TemplateModule::collection(collection_id).variable_on_chain_schema, b"".to_vec());1870    });1871}18721873#[test]1874fn set_variable_on_chain_schema() {1875    new_test_ext().execute_with(|| {1876        default_limits();1877        1878        let collection_id = create_test_collection(&CollectionMode::NFT, 1);18791880        let origin1 = Origin::signed(1);1881        assert_ok!(TemplateModule::set_variable_on_chain_schema(origin1, collection_id, b"test variable on chain schema".to_vec()));18821883        assert_eq!(TemplateModule::collection(collection_id).const_on_chain_schema, b"".to_vec());1884        assert_eq!(TemplateModule::collection(collection_id).variable_on_chain_schema, b"test variable on chain schema".to_vec());1885    });1886}18871888#[test]1889fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {1890    new_test_ext().execute_with(|| {1891        default_limits();18921893        let collection_id = create_test_collection(&CollectionMode::NFT, 1);18941895        let origin1 = Origin::signed(1);1896        1897        let data = default_nft_data();1898        create_test_item(1, &data.into());1899        1900        let variable_data = b"test set_variable_meta_data method.".to_vec();1901        assert_ok!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data.clone()));19021903        assert_eq!(TemplateModule::nft_item_id(collection_id, 1).variable_data, variable_data);1904    });1905}19061907#[test]1908fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {1909    new_test_ext().execute_with(|| {1910        default_limits();19111912        let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);19131914        let origin1 = Origin::signed(1);19151916        let data = default_re_fungible_data();1917        create_test_item(1, &data.into());19181919        let variable_data = b"test set_variable_meta_data method.".to_vec();1920        assert_ok!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data.clone()));19211922        assert_eq!(TemplateModule::refungible_item_id(collection_id, 1).variable_data, variable_data);1923    });1924}192519261927#[test]1928fn set_variable_meta_data_on_fungible_token_fails() {1929    new_test_ext().execute_with(|| {1930        default_limits();19311932        let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);19331934        let origin1 = Origin::signed(1);19351936        let data = default_fungible_data();1937        create_test_item(1, &data.into());19381939        let variable_data = b"test set_variable_meta_data method.".to_vec();1940        assert_noop!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data.clone()), Error::<Test>::CantStoreMetadataInFungibleTokens);1941    });1942}19431944#[test]1945fn set_variable_meta_data_on_nft_token_fails_for_big_data() {1946    new_test_ext().execute_with(|| {1947        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1948            collection_numbers_limit: default_collection_numbers_limit(),1949            account_token_ownership_limit: 10,1950            collections_admins_limit: 5,1951            custom_data_limit: 10,1952            nft_sponsor_transfer_timeout: 15,1953            fungible_sponsor_transfer_timeout: 15,1954            refungible_sponsor_transfer_timeout: 15,1955            const_on_chain_schema_limit: 1024,1956            offchain_schema_limit: 1024,1957            variable_on_chain_schema_limit: 1024,1958        }));19591960        let collection_id = create_test_collection(&CollectionMode::NFT, 1);19611962        let origin1 = Origin::signed(1);19631964        let data = default_nft_data();1965        create_test_item(1, &data.into());19661967        let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();1968        assert_noop!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data), Error::<Test>::TokenVariableDataLimitExceeded);1969    });1970}19711972#[test]1973fn set_variable_meta_data_on_re_fungible_token_fails_for_big_data() {1974    new_test_ext().execute_with(|| {1975        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1976            collection_numbers_limit: default_collection_numbers_limit(),1977            account_token_ownership_limit: 10,1978            collections_admins_limit: 5,1979            custom_data_limit: 10,1980            nft_sponsor_transfer_timeout: 15,1981            fungible_sponsor_transfer_timeout: 15,1982            refungible_sponsor_transfer_timeout: 15,1983            const_on_chain_schema_limit: 1024,1984            offchain_schema_limit: 1024,1985            variable_on_chain_schema_limit: 1024,1986        }));198719881989        let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);19901991        let origin1 = Origin::signed(1);19921993        let data = default_re_fungible_data();1994        create_test_item(1, &data.into());19951996        let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();1997        assert_noop!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data), Error::<Test>::TokenVariableDataLimitExceeded);1998    });1999}
modifiedruntime_types.jsondiffbeforeafterboth
--- a/runtime_types.json
+++ b/runtime_types.json
@@ -1,27 +1,4 @@
 {
-    "Schedule": {
-      "version": "u32",
-      "put_code_per_byte_cost": "Gas",
-      "grow_mem_cost": "Gas",
-      "regular_op_cost": "Gas",
-      "return_data_per_byte_cost": "Gas",
-      "event_data_per_byte_cost": "Gas",
-      "event_per_topic_cost": "Gas",
-      "event_base_cost": "Gas",
-      "call_base_cost": "Gas",
-      "instantiate_base_cost": "Gas",
-      "dispatch_base_cost": "Gas",
-      "sandbox_data_read_cost": "Gas",
-      "sandbox_data_write_cost": "Gas",
-      "transfer_cost": "Gas",
-      "instantiate_cost": "Gas",
-      "max_event_topics": "u32",
-      "max_stack_height": "u32",
-      "max_memory_pages": "u32",
-      "max_table_size": "u32",
-      "enable_println": "bool",
-      "max_subject_len": "u32"
-    },
     "AccessMode": {
       "_enum": [
         "Normal",
@@ -34,7 +11,7 @@
         "Invalid": null,
         "NFT": null,
         "Fungible": "DecimalPoints",
-        "ReFungible": "DecimalPoints"
+        "ReFungible": null
       }
     },
     "Ownership": {
@@ -84,7 +61,8 @@
     },
     "CreateReFungibleData": {
       "const_data": "Vec<u8>",
-      "variable_data": "Vec<u8>" 
+      "variable_data": "Vec<u8>",
+      "pieces": "u128"
     },
     "CreateItemData": {
       "_enum": {
@@ -102,27 +80,21 @@
     "CollectionId": "u32",
     "TokenId": "u32",
     "ChainLimits": {
-      "collection_numbers_limit": "u32",
-      "account_token_ownership_limit": "u32",
-      "collections_admins_limit": "u64",
-      "custom_data_limit": "u32",
-      "nft_sponsor_timeout": "u32",
-      "fungible_sponsor_timeout": "u32",
-      "refungible_sponsor_timeout": "u32"
+      "CollectionNumbersLimit": "u32",
+      "AccountTokenOwnershipLimit": "u32",
+      "CollectionAdminsLimit": "u64",
+      "CustomDataLimit": "u32",
+      "NftSponsorTimeout": "u32",
+      "FungibleSponsorTimeout": "u32",
+      "RefungibleSponsorTimeout": "u32",
+      "OffchainSchemaLimit": "u32",
+      "VariableOnChainSchemaLimit": "u32",
+      "ConstOnChainSchemaLimit": "u32"
     },
     "CollectionLimits": {
       "AccountTokenOwnershipLimit": "u32",
       "SponsoredMintSize": "u32",
       "TokenLimit": "u32",
       "SponsorTimeout": "u32"
-    },
-    "AccountInfo": "AccountInfoWithProviders",
-    "AccountInfoWithProviders": {
-      "nonce": "Index",
-      "consumers": "RefCount",
-      "providers": "RefCount",
-      "data": "AccountData"
     }
-
-  }
-  
\ No newline at end of file
+}
\ No newline at end of file
addedtests/.vscode/settings.jsondiffbeforeafterboth
--- /dev/null
+++ b/tests/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+    "mocha.enabled": true
+}
\ No newline at end of file
modifiedtests/README.mddiffbeforeafterboth
--- a/tests/README.md
+++ b/tests/README.md
@@ -2,8 +2,8 @@
 
 ## How to run
 
-1. Run `npm install`.
+1. Run `yarn install`.
 2. Setup a test node. You can do it using `docker-compose up -d` in parent directory.
 3. Optional step - configure tests with env variables or by editing [configuration file](src/config.ts).
-4. Run `npm test`.
+4. Run `yarn test`.
 
modifiedtests/package.jsondiffbeforeafterboth
--- a/tests/package.json
+++ b/tests/package.json
@@ -22,10 +22,13 @@
     "load": "mocha --timeout 9999999 -r ts-node/register ./**/*.load.ts",
     "testAddCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/addCollectionAdmin.test.ts",
     "testSetSchemaVersion": "mocha --timeout 9999999 -r ts-node/register ./**/setSchemaVersion.test.ts",
+    "testSetVariableMetaData": "mocha --timeout 9999999 -r ts-node/register ./**/setVariableMetaData.test.ts",
     "testSetCollectionLimits": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionLimits.test.ts",
     "testRemoveCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/removeCollectionAdmin.test.ts",
+    "testRemoveFromWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/removeFromWhiteList.test.ts",
     "testConnection": "mocha --timeout 9999999 -r ts-node/register ./**/connection.test.ts",
     "testCollection": "mocha --timeout 9999999 -r ts-node/register ./**/createCollection.test.ts",
+    "testCreateMultipleItems": "mocha --timeout 9999999 -r ts-node/register ./**/createMultipleItems.test.ts",
     "testApprove": "mocha --timeout 9999999 -r ts-node/register ./**/approve.test.ts",
     "testTransferFrom": "mocha --timeout 9999999 -r ts-node/register ./**/transferFrom.test.ts",
     "testCreateCollection": "mocha --timeout 9999999 -r ts-node/register ./**/createCollection.test.ts",
@@ -33,7 +36,10 @@
     "testAddToContractWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/addToContractWhiteList.test.ts",
     "testTransfer": "mocha --timeout 9999999 -r ts-node/register ./**/transfer.test.ts",
     "testBurnItem": "mocha --timeout 9999999 -r ts-node/register ./**/burnItem.test.ts",
-    "testCreditFeesToTreasury": "mocha --timeout 9999999 -r ts-node/register ./**/creditFeesToTreasury.test.ts"
+    "testSetMintPermission": "mocha --timeout 9999999 -r ts-node/register ./**/setMintPermission.test.ts",
+    "testCreditFeesToTreasury": "mocha --timeout 9999999 -r ts-node/register ./**/creditFeesToTreasury.test.ts",
+    "testEnableContractSponsoring": "mocha --timeout 9999999 -r ts-node/register ./**/enableContractSponsoring.test.ts",
+    "testSetContractSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setContractSponsoringRateLimit.test.ts"
   },
   "author": "",
   "license": "SEE LICENSE IN ../LICENSE",
modifiedtests/src/addCollectionAdmin.test.tsdiffbeforeafterboth
--- a/tests/src/addCollectionAdmin.test.ts
+++ b/tests/src/addCollectionAdmin.test.ts
@@ -1,4 +1,9 @@
-import { ApiPromise } from '@polkadot/api';
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { ApiPromise } from '@polkadot/api';
 import BN from 'bn.js';
 import chai from 'chai';
 import chaiAsPromised from 'chai-as-promised';
@@ -98,7 +103,7 @@
     });
   });
 
-  it('Add an admin to a collection that has reached the maximum number of admins limit', async () => {
+  it.only('Add an admin to a collection that has reached the maximum number of admins limit', async () => {
     await usingApi(async (api: ApiPromise) => {
       const Alice = privateKey('//Alice');
       const accounts = [
@@ -112,18 +117,18 @@
       ];
       const collectionId = await createCollectionExpectSuccess();
 
-      const chainLimit = await api.query.nft.chainLimit() as unknown as { collections_admins_limit: BN };
-      const chainLimitNumber = chainLimit.collections_admins_limit.toNumber();
-      expect(chainLimitNumber).to.be.equal(5);
+      const chainLimit = await api.query.nft.chainLimit() as unknown as { CollectionAdminsLimit: BN };
+      const chainAdminLimit = chainLimit.CollectionAdminsLimit.toNumber();
+      expect(chainAdminLimit).to.be.equal(5);
 
-      for (let i = 0; i < chainLimitNumber; i++) {
+      for (let i = 0; i < chainAdminLimit; i++) {
         const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, accounts[i]);
         await submitTransactionAsync(Alice, changeAdminTx);
         const adminListAfterAddAdmin: any = (await api.query.nft.adminList(collectionId));
         expect(adminListAfterAddAdmin).to.be.contains(accounts[i]);
       }
 
-      const tx = api.tx.nft.addCollectionAdmin(collectionId, accounts[chainLimitNumber]);
+      const tx = api.tx.nft.addCollectionAdmin(collectionId, accounts[chainAdminLimit]);
       await expect(submitTransactionExpectFailAsync(Alice, tx)).to.be.rejected;
     });
   });
modifiedtests/src/addToContractWhiteList.test.tsdiffbeforeafterboth
--- a/tests/src/addToContractWhiteList.test.ts
+++ b/tests/src/addToContractWhiteList.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 import chai from "chai";
 import chaiAsPromised from 'chai-as-promised';
 import usingApi, { submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api";
modifiedtests/src/addToWhiteList.test.tsdiffbeforeafterboth
--- a/tests/src/addToWhiteList.test.ts
+++ b/tests/src/addToWhiteList.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 import { IKeyringPair } from '@polkadot/types/types';
 import chai from 'chai';
 import chaiAsPromised from 'chai-as-promised';
modifiedtests/src/approve.test.tsdiffbeforeafterboth
--- a/tests/src/approve.test.ts
+++ b/tests/src/approve.test.ts
@@ -34,7 +34,7 @@
       await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob);
       // reFungible
       const reFungibleCollectionId =
-        await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+        await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
       await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob);
     });
@@ -56,7 +56,7 @@
       await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 0);
       // reFungible
       const reFungibleCollectionId =
-        await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+        await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
       await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob, 1);
       await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob, 0);
@@ -95,7 +95,7 @@
       await approveExpectFail(fungibleCollectionId, 1, Alice, Bob);
       // reFungible
       const reFungibleCollectionId =
-        await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+        await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       await destroyCollectionExpectSuccess(reFungibleCollectionId);
       await approveExpectFail(reFungibleCollectionId, 1, Alice, Bob);
     });
@@ -113,7 +113,7 @@
       await approveExpectFail(fungibleCollectionId, 2, Alice, Bob);
       // reFungible
       const reFungibleCollectionId =
-        await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+        await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       await approveExpectFail(reFungibleCollectionId, 2, Alice, Bob);
     });
   });
@@ -132,7 +132,7 @@
       await approveExpectFail(fungibleCollectionId, newFungibleTokenId, Bob, Alice);
       // reFungible
       const reFungibleCollectionId =
-        await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+        await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
       await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, Bob, Alice);
     });
modifiedtests/src/burnItem.test.tsdiffbeforeafterboth
--- a/tests/src/burnItem.test.ts
+++ b/tests/src/burnItem.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api';
 import { Keyring } from "@polkadot/api";
 import { IKeyringPair } from "@polkadot/types/types";
@@ -70,7 +75,7 @@
   });
   it('Burn item in ReFungible collection', async () => {
     const createMode = 'ReFungible';
-    const collectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 2 }});
+    const collectionId = await createCollectionExpectSuccess({mode: {type: createMode }});
     const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
 
     await usingApi(async (api) => {
@@ -91,7 +96,7 @@
 
   it('Burn owned portion of item in ReFungible collection', async () => {
     const createMode = 'ReFungible';
-    const collectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 2 }});
+    const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
     const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
 
     await usingApi(async (api) => {
@@ -107,7 +112,7 @@
       const tx = api.tx.nft.burnItem(collectionId, tokenId, 0);
       const events2 = await submitTransactionAsync(bob, tx);
       const result2 = getGenericResult(events2);
-  
+
       // Get balances 
       const balance: any = (await api.query.nft.reFungibleItemList(collectionId, tokenId)).toJSON();
       // console.log(balance);
modifiedtests/src/change-collection-owner.test.tsdiffbeforeafterboth
--- a/tests/src/change-collection-owner.test.ts
+++ b/tests/src/change-collection-owner.test.ts
@@ -1,4 +1,9 @@
-import chai from 'chai';
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import chai from 'chai';
 import chaiAsPromised from 'chai-as-promised';
 import privateKey from './substrate/privateKey';
 import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api";
modifiedtests/src/confirmSponsorship.test.tsdiffbeforeafterboth
--- a/tests/src/confirmSponsorship.test.ts
+++ b/tests/src/confirmSponsorship.test.ts
@@ -115,7 +115,7 @@
   });
 
   it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async () => {
-    const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0 }});
+    const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     await setCollectionSponsorExpectSuccess(collectionId, bob.address);
     await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
 
@@ -247,7 +247,7 @@
   });
 
   it('ReFungible: Sponsoring is rate limited', async () => {
-    const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0 }});
+    const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     await setCollectionSponsorExpectSuccess(collectionId, bob.address);
     await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
 
modifiedtests/src/contracts.test.tsdiffbeforeafterboth
--- a/tests/src/contracts.test.ts
+++ b/tests/src/contracts.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 import chai from "chai";
 import chaiAsPromised from 'chai-as-promised';
 import usingApi, { submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api";
modifiedtests/src/createCollection.test.tsdiffbeforeafterboth
--- a/tests/src/createCollection.test.ts
+++ b/tests/src/createCollection.test.ts
@@ -28,7 +28,7 @@
     await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
   });
   it('Create new ReFungible collection', async () => {
-    await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+    await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
   });
 });
 
modifiedtests/src/createItem.test.tsdiffbeforeafterboth
--- a/tests/src/createItem.test.ts
+++ b/tests/src/createItem.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 import { default as usingApi } from './substrate/substrate-api';
 import { Keyring } from "@polkadot/api";
 import { IKeyringPair } from "@polkadot/types/types";
@@ -28,7 +33,7 @@
   });
   it('Create new item in ReFungible collection', async () => {
     const createMode = 'ReFungible';
-    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});
+    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
     await createItemExpectSuccess(alice, newCollectionID, createMode);
   });
 });
modifiedtests/src/createMultipleItems.test.tsdiffbeforeafterboth
--- a/tests/src/createMultipleItems.test.ts
+++ b/tests/src/createMultipleItems.test.ts
@@ -2,68 +2,177 @@
 // This file is subject to the terms and conditions defined in
 // file 'LICENSE', which is part of this source code package.
 //
+import { ApiPromise } from '@polkadot/api';
+import BN from 'bn.js';
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import privateKey from './substrate/privateKey';
+import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api';
+import {
+  createCollectionExpectSuccess,
+  destroyCollectionExpectSuccess,
+  IReFungibleTokenDataType,
+} from './util/helpers';
 
-import { assert } from 'chai';
-import { alicesPublicKey } from './accounts';
-import privateKey from './substrate/privateKey';
-import usingApi from './substrate/substrate-api';
-import waitNewBlocks from './substrate/wait-new-blocks';
+chai.use(chaiAsPromised);
+const expect = chai.expect;
 
-const idCollection = 12;
+interface ITokenDataType {
+  Owner: number[];
+  ConstData: number[];
+  VariableData: number[];
+}
 
-describe.skip('integration test: ext. createMultipleItems():', () => {
-  it('Create two NFT tokens in active NFT collection', async () => {
-    await usingApi(async (api) => {
-      const AitemListIndex = await api.query.nft.itemListIndex(idCollection);
-      console.log(`itemListIndex count (before): ${AitemListIndex}`);
-      const args = ['NFT', 'NFT'];
-      const alicePrivateKey = privateKey('//Alice');
-      const createMultipleItems = await api.tx.nft
-      .createMultipleItems(idCollection, alicesPublicKey, args)
-      .signAndSend(alicePrivateKey);
-      // tslint:disable-next-line: no-unused-expression
-      assert.exists(createMultipleItems, 'createMultipleItems is neither `null` or `undefined`');
-      console.log(`Ext. createMultipleItems submitted with hash: ${createMultipleItems}`);
-      await waitNewBlocks(api);
-      const BitemListIndex = await api.query.nft.itemListIndex(idCollection);
-      console.log(`itemListIndex count (after): ${BitemListIndex}`);
-      if (BitemListIndex === AitemListIndex) { assert.fail('Corret token not added in collection!'); }
+describe('Integration Test createMultipleItems(collection_id, owner, items_data):', () => {
+  it('Create  0x31, 0x32, 0x33 items in active NFT collection and verify tokens data in chain', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      expect(itemsListIndexBefore.toNumber()).to.be.equal(0);
+      const Alice = privateKey('//Alice');
+      const args = [{ nft: ['0x31', '0x31'] }, { nft: ['0x32', '0x32'] }, { nft: ['0x33', '0x33'] }];
+      const createMultipleItemsTx = await api.tx.nft
+        .createMultipleItems(collectionId, Alice.address, args);
+      await submitTransactionAsync(Alice, createMultipleItemsTx);
+      const itemsListIndexAfter = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      expect(itemsListIndexAfter.toNumber()).to.be.equal(3);
+      const token1Data = await api.query.nft.nftItemList(collectionId, 1) as unknown as ITokenDataType;
+      const token2Data = await api.query.nft.nftItemList(collectionId, 2) as unknown as ITokenDataType;
+      const token3Data = await api.query.nft.nftItemList(collectionId, 3) as unknown as ITokenDataType;
+
+      expect(token1Data.Owner.toString()).to.be.equal(Alice.address);
+      expect(token2Data.Owner.toString()).to.be.equal(Alice.address);
+      expect(token3Data.Owner.toString()).to.be.equal(Alice.address);
+
+      expect(token1Data.ConstData.toString()).to.be.equal('0x31');
+      expect(token2Data.ConstData.toString()).to.be.equal('0x32');
+      expect(token3Data.ConstData.toString()).to.be.equal('0x33');
+
+      expect(token1Data.VariableData.toString()).to.be.equal('0x31');
+      expect(token2Data.VariableData.toString()).to.be.equal('0x32');
+      expect(token3Data.VariableData.toString()).to.be.equal('0x33');
     });
   });
-  it('(!negative test!) Create two Fungible tokens in active NFT collection', async () => {
-    await usingApi(async (api) => {
-      const AitemListIndex = await api.query.nft.itemListIndex(idCollection);
-      console.log(`itemListIndex count (before): ${AitemListIndex}`);
-      const args = ['Fungible', 'Fungible'];
-      const alicePrivateKey = privateKey('//Alice');
-      const createMultipleItems = await api.tx.nft
-      .createMultipleItems(idCollection, alicesPublicKey, args)
-      .signAndSend(alicePrivateKey);
-      // tslint:disable-next-line: no-unused-expression
-      assert.exists(createMultipleItems, 'createMultipleItems is neither `null` or `undefined`');
-      console.log(`Ext. createMultipleItems submitted with hash: ${createMultipleItems}`);
-      await waitNewBlocks(api);
-      const BitemListIndex = await api.query.nft.itemListIndex(idCollection);
-      console.log(`itemListIndex count (after): ${BitemListIndex}`);
-      if (BitemListIndex > AitemListIndex) { assert.fail('Incorrect token added in collection!'); }
+
+  it('Create  0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+      const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      expect(itemsListIndexBefore.toNumber()).to.be.equal(0);
+      const Alice = privateKey('//Alice');
+      const args = [
+        {refungible: {const_data: [0x31], variable_data: [0x31], pieces: 1}},
+        {refungible: {const_data: [0x32], variable_data: [0x32], pieces: 1}},
+        {refungible: {const_data: [0x33], variable_data: [0x33], pieces: 1}},
+      ];
+      const createMultipleItemsTx = await api.tx.nft
+        .createMultipleItems(collectionId, Alice.address, args);
+      await submitTransactionAsync(Alice, createMultipleItemsTx);
+      const itemsListIndexAfter = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      expect(itemsListIndexAfter.toNumber()).to.be.equal(3);
+      const token1Data = await api.query.nft.reFungibleItemList(collectionId, 1) as unknown as IReFungibleTokenDataType;
+      const token2Data = await api.query.nft.reFungibleItemList(collectionId, 2) as unknown as IReFungibleTokenDataType;
+      const token3Data = await api.query.nft.reFungibleItemList(collectionId, 3) as unknown as IReFungibleTokenDataType;
+
+      expect(token1Data.Owner[0].Owner.toString()).to.be.equal(Alice.address);
+      expect(token1Data.Owner[0].Fraction.toNumber()).to.be.equal(1);
+
+      expect(token2Data.Owner[0].Owner.toString()).to.be.equal(Alice.address);
+      expect(token2Data.Owner[0].Fraction.toNumber()).to.be.equal(1);
+
+      expect(token3Data.Owner[0].Owner.toString()).to.be.equal(Alice.address);
+      expect(token3Data.Owner[0].Fraction.toNumber()).to.be.equal(1);
+
+      expect(token1Data.ConstData.toString()).to.be.equal('0x31');
+      expect(token2Data.ConstData.toString()).to.be.equal('0x32');
+      expect(token3Data.ConstData.toString()).to.be.equal('0x33');
+
+      expect(token1Data.VariableData.toString()).to.be.equal('0x31');
+      expect(token2Data.VariableData.toString()).to.be.equal('0x32');
+      expect(token3Data.VariableData.toString()).to.be.equal('0x33');
     });
   });
-  it('(!negative test!) Create two ReFungible tokens in active NFT collection', async () => {
-    await usingApi(async (api) => {
-      const AitemListIndex = await api.query.nft.itemListIndex(idCollection);
-      console.log(`itemListIndex count (before): ${AitemListIndex}`);
-      const args = ['ReFungible', 'ReFungible'];
-      const alicePrivateKey = privateKey('//Alice');
-      const createMultipleItems = await api.tx.nft
-      .createMultipleItems(idCollection, alicesPublicKey, args)
-      .signAndSend(alicePrivateKey);
-      // tslint:disable-next-line: no-unused-expression
-      assert.exists(createMultipleItems, 'createMultipleItems is neither `null` or `undefined`');
-      console.log(`Ext. createMultipleItems submitted with hash: ${createMultipleItems}`);
-      await waitNewBlocks(api);
-      const BitemListIndex = await api.query.nft.itemListIndex(idCollection);
-      console.log(`itemListIndex count (after): ${BitemListIndex}`);
-      if (BitemListIndex > AitemListIndex) { assert.fail('Incorrect token added in collection!'); }
+});
+
+describe('Negative Integration Test createMultipleItems(collection_id, owner, items_data):', () => {
+  it('Create token with not existing type', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const Alice = privateKey('//Alice');
+      try {
+        const args = [{ invalid: null }, { invalid: null }, { invalid: null }];
+        const createMultipleItemsTx = await api.tx.nft
+          .createMultipleItems(collectionId, Alice.address, args);
+        await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;
+      } catch (e) {
+        // tslint:disable-next-line:no-unused-expression
+        expect(e).to.be.exist;
+      }
+    });
+  });
+
+  it('Create token in not existing collection', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;
+      const Alice = privateKey('//Alice');
+      const createMultipleItemsTx = await api.tx.nft
+        .createMultipleItems(collectionId, Alice.address, ['NFT', 'NFT', 'NFT']);
+      await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;
+    });
+  });
+
+  it('Create NFT and Re-fungible tokens that has reached the maximum data limit', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      // NFT
+      const collectionId = await createCollectionExpectSuccess();
+      const Alice = privateKey('//Alice');
+      const args = [
+        { nft: ['A'.repeat(2049), 'A'.repeat(2049)] },
+        { nft: ['B'.repeat(2049), 'B'.repeat(2049)] },
+        { nft: ['C'.repeat(2049), 'C'.repeat(2049)] },
+      ];
+      const createMultipleItemsTx = await api.tx.nft
+        .createMultipleItems(collectionId, Alice.address, args);
+      await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;
+
+      // ReFungible
+      const collectionIdReFungible =
+        await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+      const argsReFungible = [
+        { ReFungible: ['1'.repeat(2049), '1'.repeat(2049)] },
+        { ReFungible: ['2'.repeat(2049), '2'.repeat(2049)] },
+        { ReFungible: ['3'.repeat(2049), '3'.repeat(2049)] },
+      ];
+      const createMultipleItemsTxFungible = await api.tx.nft
+        .createMultipleItems(collectionIdReFungible, Alice.address, argsReFungible);
+      await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTxFungible)).to.be.rejected;
+    });
+  });
+
+  it('Create tokens with different types', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const Alice = privateKey('//Alice');
+      const createMultipleItemsTx = await api.tx.nft
+        .createMultipleItems(collectionId, Alice.address, ['NFT', 'Fungible', 'ReFungible']);
+      await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;
+      // garbage collection :-D
+      await destroyCollectionExpectSuccess(collectionId);
+    });
+  });
+
+  it('Create tokens with different data limits <> maximum data limit', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const Alice = privateKey('//Alice');
+      const args = [
+        { nft: ['A', 'A'] },
+        { nft: ['B', 'B'.repeat(2049)] },
+        { nft: ['C'.repeat(2049), 'C'] },
+      ];
+      const createMultipleItemsTx = await api.tx.nft
+        .createMultipleItems(collectionId, Alice.address, args);
+      await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;
     });
   });
 });
modifiedtests/src/destroyCollection.test.tsdiffbeforeafterboth
--- a/tests/src/destroyCollection.test.ts
+++ b/tests/src/destroyCollection.test.ts
@@ -1,12 +1,14 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 import chai from 'chai';
 import chaiAsPromised from 'chai-as-promised';
-import { default as usingApi, submitTransactionAsync } from "./substrate/substrate-api";
-import { createCollectionExpectSuccess, createCollectionExpectFailure, destroyCollectionExpectSuccess, destroyCollectionExpectFailure } from "./util/helpers";
-import type { AccountId, EventRecord } from '@polkadot/types/interfaces';
-import privateKey from './substrate/privateKey';
+import { default as usingApi } from "./substrate/substrate-api";
+import { createCollectionExpectSuccess, destroyCollectionExpectSuccess, destroyCollectionExpectFailure } from "./util/helpers";
 
 chai.use(chaiAsPromised);
-const expect = chai.expect;
 
 describe('integration test: ext. destroyCollection():', () => {
   it('NFT collection can be destroyed', async () => {
@@ -18,7 +20,7 @@
     await destroyCollectionExpectSuccess(collectionId);
   });
   it('ReFungible collection can be destroyed', async () => {
-    const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+    const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     await destroyCollectionExpectSuccess(collectionId);
   });
 });
addedtests/src/enableContractSponsoring.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/enableContractSponsoring.test.ts
@@ -0,0 +1,89 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { IKeyringPair } from '@polkadot/types/types';
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import privateKey from './substrate/privateKey';
+import usingApi from './substrate/substrate-api';
+import { deployFlipper, getFlipValue, toggleFlipValueExpectSuccess } from './util/contracthelpers';
+import {
+  enableContractSponsoringExpectFailure,
+  enableContractSponsoringExpectSuccess,
+  findUnusedAddress,
+  setContractSponsoringRateLimitExpectSuccess,
+} from './util/helpers';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+describe('Integration Test enableContractSponsoring', () => {
+  it('ensure tx fee is paid from endowment', async () => {
+    await usingApi(async (api) => {
+      const user = await findUnusedAddress(api);
+
+      const [flipper, deployer] = await deployFlipper(api);
+      await enableContractSponsoringExpectSuccess(deployer, flipper.address, true);
+      await setContractSponsoringRateLimitExpectSuccess(deployer, flipper.address, 1);
+      await toggleFlipValueExpectSuccess(user, flipper);
+
+      expect(await getFlipValue(flipper, deployer)).to.be.false;
+    });
+  });
+
+  it('ensure it can be enabled twice', async () => {
+    await usingApi(async (api) => {
+      const [flipper, deployer] = await deployFlipper(api);
+
+      await enableContractSponsoringExpectSuccess(deployer, flipper.address, true);
+      await enableContractSponsoringExpectSuccess(deployer, flipper.address, true);
+    });
+  });
+
+  it('ensure it can be disabled twice', async () => {
+    await usingApi(async (api) => {
+      const [flipper, deployer] = await deployFlipper(api);
+
+      await enableContractSponsoringExpectSuccess(deployer, flipper.address, true);
+      await enableContractSponsoringExpectSuccess(deployer, flipper.address, false);
+      await enableContractSponsoringExpectSuccess(deployer, flipper.address, false);
+    });
+  });
+
+  it('ensure it can be re-enabled', async () => {
+    await usingApi(async (api) => {
+      const [flipper, deployer] = await deployFlipper(api);
+
+      await enableContractSponsoringExpectSuccess(deployer, flipper.address, true);
+      await enableContractSponsoringExpectSuccess(deployer, flipper.address, false);
+      await enableContractSponsoringExpectSuccess(deployer, flipper.address, true);
+    });
+  });
+
+});
+
+describe('Negative Integration Test enableContractSponsoring', () => {
+  let alice: IKeyringPair;
+
+  before(async () => {
+    alice = privateKey('//Alice');
+  });
+
+  it('fails when called for non-contract address', async () => {
+    await usingApi(async (api) => {
+      const user = await findUnusedAddress(api);
+
+      await enableContractSponsoringExpectFailure(alice, user.address, true);
+    });
+  });
+
+  it('fails when called by non-owning user', async () => {
+    await usingApi(async (api) => {
+      const [flipper, _] = await deployFlipper(api);
+
+      await enableContractSponsoringExpectFailure(alice, flipper.address, true);
+    });
+  });
+});
modifiedtests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth
--- a/tests/src/removeCollectionAdmin.test.ts
+++ b/tests/src/removeCollectionAdmin.test.ts
@@ -1,5 +1,9 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 import { ApiPromise } from '@polkadot/api';
-import BN from 'bn.js';
 import chai from 'chai';
 import chaiAsPromised from 'chai-as-promised';
 import privateKey from './substrate/privateKey';
addedtests/src/removeFromWhiteList.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/removeFromWhiteList.test.ts
@@ -0,0 +1,89 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import { default as usingApi } from './substrate/substrate-api';
+import {
+  createCollectionExpectSuccess,
+  destroyCollectionExpectSuccess,
+  enableWhiteListExpectSuccess,
+  addToWhiteListExpectSuccess,
+  removeFromWhiteListExpectSuccess,
+  isWhitelisted,
+  findNotExistingCollection,
+  removeFromWhiteListExpectFailure,
+  disableWhiteListExpectSuccess,
+} from './util/helpers';
+import { IKeyringPair } from '@polkadot/types/types';
+import privateKey from './substrate/privateKey';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+describe('Integration Test removeFromWhiteList', () => {
+  let alice: IKeyringPair;
+  let bob: IKeyringPair;
+
+  before(async () => {
+    await usingApi(async (api) => {
+      alice = privateKey('//Alice');
+      bob = privateKey('//Bob');
+    });
+  });
+
+  it('ensure bob is not in whitelist after removal', async () => {
+    await usingApi(async () => {
+      const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+      await enableWhiteListExpectSuccess(alice, collectionId);
+      await addToWhiteListExpectSuccess(alice, collectionId, bob.address);
+
+      await removeFromWhiteListExpectSuccess(alice, collectionId, bob.address);
+      expect(await isWhitelisted(collectionId, bob.address)).to.be.false;
+    });
+  });
+
+  it('allows removal from collection with unset whitelist status', async () => {
+    await usingApi(async () => {
+      const collectionWithoutWhitelistId = await createCollectionExpectSuccess();
+      await enableWhiteListExpectSuccess(alice, collectionWithoutWhitelistId);
+      await addToWhiteListExpectSuccess(alice, collectionWithoutWhitelistId, bob.address);
+      await disableWhiteListExpectSuccess(alice, collectionWithoutWhitelistId);
+
+      await removeFromWhiteListExpectSuccess(alice, collectionWithoutWhitelistId, bob.address);
+    });
+  });
+});
+
+describe('Negative Integration Test removeFromWhiteList', () => {
+  let alice: IKeyringPair;
+  let bob: IKeyringPair;
+
+  before(async () => {
+    await usingApi(async (api) => {
+      alice = privateKey('//Alice');
+      bob = privateKey('//Bob');
+    });
+  });
+
+  it('fails on removal from not existing collection', async () => {
+    await usingApi(async (api) => {
+      const collectionId = await findNotExistingCollection(api);
+
+      await removeFromWhiteListExpectFailure(alice, collectionId, bob.address);
+    });
+  });
+
+  it('fails on removal from removed collection', async () => {
+    await usingApi(async () => {
+      const collectionId = await createCollectionExpectSuccess();
+      await enableWhiteListExpectSuccess(alice, collectionId);
+      await addToWhiteListExpectSuccess(alice, collectionId, bob.address);
+      await destroyCollectionExpectSuccess(collectionId);
+
+      await removeFromWhiteListExpectFailure(alice, collectionId, bob.address);
+    });
+  });
+});
modifiedtests/src/setCollectionLimits.test.tsdiffbeforeafterboth
--- a/tests/src/setCollectionLimits.test.ts
+++ b/tests/src/setCollectionLimits.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 // https://unique-network.readthedocs.io/en/latest/jsapi.html#setchainlimits
 import { ApiPromise, Keyring } from '@polkadot/api';
 import { IKeyringPair } from '@polkadot/types/types';
modifiedtests/src/setCollectionSponsor.test.tsdiffbeforeafterboth
--- a/tests/src/setCollectionSponsor.test.ts
+++ b/tests/src/setCollectionSponsor.test.ts
@@ -9,7 +9,6 @@
 import { createCollectionExpectSuccess, setCollectionSponsorExpectSuccess, destroyCollectionExpectSuccess, setCollectionSponsorExpectFailure } from "./util/helpers";
 import { Keyring } from "@polkadot/api";
 import { IKeyringPair } from "@polkadot/types/types";
-import type { AccountId } from '@polkadot/types/interfaces';
 
 chai.use(chaiAsPromised);
 const expect = chai.expect;
@@ -34,7 +33,7 @@
     await setCollectionSponsorExpectSuccess(collectionId, bob.address);
   });
   it('Set ReFungible collection sponsor', async () => {
-    const collectionId = await createCollectionExpectSuccess({ mode: {type: 'ReFungible', decimalPoints: 0} });
+    const collectionId = await createCollectionExpectSuccess({ mode: {type: 'ReFungible'} });
     await setCollectionSponsorExpectSuccess(collectionId, bob.address);
   });
 
addedtests/src/setConstOnChainSchema.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/setConstOnChainSchema.test.ts
@@ -0,0 +1,96 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { Keyring } from '@polkadot/api';
+import { IKeyringPair } from '@polkadot/types/types';
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api';
+import {
+  createCollectionExpectSuccess,
+  destroyCollectionExpectSuccess,
+} from './util/helpers';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+let Alice: IKeyringPair;
+let Bob: IKeyringPair;
+let Shema: any;
+let largeShema: any;
+
+before(async () => {
+  await usingApi(async (api) => {
+    const keyring = new Keyring({ type: 'sr25519' });
+    Alice = keyring.addFromUri('//Alice');
+    Bob = keyring.addFromUri('//Bob');
+    Shema = '0x31';
+    largeShema = new Array(4097).fill(0xff);
+
+  });
+});
+describe('Integration Test ext. setConstOnChainSchema()', () => {
+
+  it('Run extrinsic with parameters of the collection id, set the scheme', async () => {
+      await usingApi(async (api) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const collection: any = (await api.query.nft.collection(collectionId));
+      expect(collection.Owner.toString()).to.be.eq(Alice.address);
+      const setShema = api.tx.nft.setConstOnChainSchema(collectionId, Shema);
+      await submitTransactionAsync(Alice, setShema);
+    });
+  });
+
+  it('Checking collection data using the ConstOnChainSchema parameter', async () => {
+      await usingApi(async (api) => {
+        const collectionId = await createCollectionExpectSuccess();
+        const setShema = api.tx.nft.setConstOnChainSchema(collectionId, Shema);
+        await submitTransactionAsync(Alice, setShema);
+        const collection: any = (await api.query.nft.collection(collectionId));
+        expect(collection.ConstOnChainSchema.toString()).to.be.eq(Shema);
+
+    });
+  });
+});
+
+describe('Negative Integration Test ext. setConstOnChainSchema()', () => {
+
+  it('Set a non-existent collection', async () => {
+    await usingApi(async (api) => {
+      // tslint:disable-next-line: radix
+      const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;
+      const setShema = api.tx.nft.setConstOnChainSchema(collectionId, Shema);
+      await expect(submitTransactionExpectFailAsync(Alice, setShema)).to.be.rejected;
+    });
+  });
+
+  it('Set a previously deleted collection', async () => {
+    await usingApi(async (api) => {
+      const collectionId = await createCollectionExpectSuccess();
+      await destroyCollectionExpectSuccess(collectionId);
+      const setShema = api.tx.nft.setConstOnChainSchema(collectionId, Shema);
+      await expect(submitTransactionExpectFailAsync(Alice, setShema)).to.be.rejected;
+    });
+  });
+
+  it('Set invalid data in schema (size too large:> 1024b)', async () => {
+    await usingApi(async (api) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const setShema = api.tx.nft.setConstOnChainSchema(collectionId, largeShema);
+      await expect(submitTransactionExpectFailAsync(Alice, setShema)).to.be.rejected;
+    });
+  });
+
+  it('Execute method not on behalf of the collection owner', async () => {
+    await usingApi(async (api) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const collection: any = (await api.query.nft.collection(collectionId));
+      expect(collection.Owner.toString()).to.be.eq(Alice.address);
+      const setShema = api.tx.nft.setConstOnChainSchema(collectionId, Shema);
+      await expect(submitTransactionExpectFailAsync(Bob, setShema)).to.be.rejected;
+    });
+  });
+
+});
addedtests/src/setContractSponsoringRateLimit.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/setContractSponsoringRateLimit.test.ts
@@ -0,0 +1,67 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { IKeyringPair } from '@polkadot/types/types';
+import privateKey from './substrate/privateKey';
+import usingApi from './substrate/substrate-api';
+import waitNewBlocks from './substrate/wait-new-blocks';
+import { deployFlipper, toggleFlipValueExpectFailure, toggleFlipValueExpectSuccess } from './util/contracthelpers';
+import {
+  enableContractSponsoringExpectSuccess,
+  findUnusedAddress,
+  setContractSponsoringRateLimitExpectFailure,
+  setContractSponsoringRateLimitExpectSuccess,
+} from './util/helpers';
+
+describe('Integration Test setContractSponsoringRateLimit', () => {
+  it('ensure sponsored contract can\'t be called twice without pause for free', async () => {
+    await usingApi(async (api) => {
+      const user = await findUnusedAddress(api);
+
+      const [flipper, deployer] = await deployFlipper(api);
+      await enableContractSponsoringExpectSuccess(deployer, flipper.address, true);
+      await setContractSponsoringRateLimitExpectSuccess(deployer, flipper.address, 10);
+      await toggleFlipValueExpectSuccess(user, flipper);
+      await toggleFlipValueExpectFailure(user, flipper);
+    });
+  });
+
+  it('ensure sponsored contract can be called twice with pause for free', async () => {
+    await usingApi(async (api) => {
+      const user = await findUnusedAddress(api);
+
+      const [flipper, deployer] = await deployFlipper(api);
+      await enableContractSponsoringExpectSuccess(deployer, flipper.address, true);
+      await setContractSponsoringRateLimitExpectSuccess(deployer, flipper.address, 1);
+      await toggleFlipValueExpectSuccess(user, flipper);
+      await waitNewBlocks(api, 1);
+      await toggleFlipValueExpectSuccess(user, flipper);
+    });
+  });
+});
+
+describe('Negative Integration Test setContractSponsoringRateLimit', () => {
+  let alice: IKeyringPair;
+
+  before(async () => {
+    alice = privateKey('//Alice');
+  });
+
+  it('fails when called for non-contract address', async () => {
+    await usingApi(async (api) => {
+      const user = await findUnusedAddress(api);
+
+      await setContractSponsoringRateLimitExpectFailure(alice, user.address, 1);
+    });
+  });
+
+  it('fails when called by non-owning user', async () => {
+    await usingApi(async (api) => {
+      const [flipper, _] = await deployFlipper(api);
+
+      await setContractSponsoringRateLimitExpectFailure(alice, flipper.address, 1);
+    });
+  });
+});
addedtests/src/setMintPermission.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/setMintPermission.test.ts
@@ -0,0 +1,103 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { IKeyringPair } from '@polkadot/types/types';
+import privateKey from './substrate/privateKey';
+import usingApi from './substrate/substrate-api';
+import {
+  addToWhiteListExpectSuccess,
+  createCollectionExpectSuccess,
+  createItemExpectFailure,
+  createItemExpectSuccess,
+  destroyCollectionExpectSuccess,
+  enableWhiteListExpectSuccess,
+  findNotExistingCollection,
+  setMintPermissionExpectFailure,
+  setMintPermissionExpectSuccess,
+} from './util/helpers';
+
+describe('Integration Test setMintPermission', () => {
+  let alice: IKeyringPair;
+  let bob: IKeyringPair;
+
+  before(async () => {
+    await usingApi(async () => {
+      alice = privateKey('//Alice');
+      bob = privateKey('//Bob');
+    });
+  });
+
+  it('ensure white-listed non-privileged address can mint tokens', async () => {
+    await usingApi(async () => {
+      const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+      await enableWhiteListExpectSuccess(alice, collectionId);
+      await setMintPermissionExpectSuccess(alice, collectionId, true);
+      await addToWhiteListExpectSuccess(alice, collectionId, bob.address);
+
+      await createItemExpectSuccess(bob, collectionId, 'NFT');
+    });
+  });
+
+  it('can be enabled twice', async () => {
+    await usingApi(async () => {
+      const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+      await setMintPermissionExpectSuccess(alice, collectionId, true);
+      await setMintPermissionExpectSuccess(alice, collectionId, true);
+    });
+  });
+
+  it('can be disabled twice', async () => {
+    await usingApi(async () => {
+      const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+      await setMintPermissionExpectSuccess(alice, collectionId, true);
+      await setMintPermissionExpectSuccess(alice, collectionId, false);
+      await setMintPermissionExpectSuccess(alice, collectionId, false);
+    });
+  });
+});
+
+describe('Negative Integration Test setMintPermission', () => {
+  let alice: IKeyringPair;
+  let bob: IKeyringPair;
+
+  before(async () => {
+    await usingApi(async () => {
+      alice = privateKey('//Alice');
+      bob = privateKey('//Bob');
+    });
+  });
+
+  it('fails on not existing collection', async () => {
+    await usingApi(async (api) => {
+      const nonExistingCollection = await findNotExistingCollection(api);
+      await setMintPermissionExpectFailure(alice, nonExistingCollection, true);
+    });
+  });
+
+  it('fails on removed collection', async () => {
+    await usingApi(async () => {
+      const removedCollectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+      await destroyCollectionExpectSuccess(removedCollectionId);
+
+      await setMintPermissionExpectFailure(alice, removedCollectionId, true);
+    });
+  });
+
+  it('fails when not collection owner tries to set mint status', async () => {
+    const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+    await enableWhiteListExpectSuccess(alice, collectionId);
+    await setMintPermissionExpectFailure(bob, collectionId, true);
+  });
+
+  it('ensure non-white-listed non-privileged address can\'t mint tokens', async () => {
+    await usingApi(async () => {
+      const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+      await enableWhiteListExpectSuccess(alice, collectionId);
+      await setMintPermissionExpectSuccess(alice, collectionId, true);
+
+      await createItemExpectFailure(bob, collectionId, 'NFT');
+    });
+  });
+});
modifiedtests/src/setPublicAccessMode.test.tsdiffbeforeafterboth
--- a/tests/src/setPublicAccessMode.test.ts
+++ b/tests/src/setPublicAccessMode.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 // https://unique-network.readthedocs.io/en/latest/jsapi.html#setschemaversion
 import { ApiPromise, Keyring } from '@polkadot/api';
 import { IKeyringPair } from '@polkadot/types/types';
modifiedtests/src/setSchemaVersion.test.tsdiffbeforeafterboth
--- a/tests/src/setSchemaVersion.test.ts
+++ b/tests/src/setSchemaVersion.test.ts
@@ -1,7 +1,11 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 // https://unique-network.readthedocs.io/en/latest/jsapi.html#setschemaversion
 import { ApiPromise, Keyring } from '@polkadot/api';
 import { IKeyringPair } from '@polkadot/types/types';
-import BN from 'bn.js';
 import chai from 'chai';
 import chaiAsPromised from 'chai-as-promised';
 import usingApi, {submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';
@@ -98,12 +102,16 @@
 
   it('execute setSchemaVersion with not correct schema version', async () => {
     await usingApi(async (api: ApiPromise) => {
+      const consoleError = console.error;
+      console.error = (message: string) => {};
       try {
         tx = api.tx.nft.setSchemaVersion(collectionIdForTesting, 'Test');
         await submitTransactionAsync(alice, tx);
       } catch (e) {
         // tslint:disable-next-line:no-unused-expression
         expect(e).to.be.exist;
+      } finally {
+        console.error = consoleError;
       }
     });
   });
addedtests/src/setVariableMetaData.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/setVariableMetaData.test.ts
@@ -0,0 +1,109 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { IKeyringPair } from '@polkadot/types/types';
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import privateKey from './substrate/privateKey';
+import usingApi from './substrate/substrate-api';
+import {
+  burnItemExpectSuccess,
+  createCollectionExpectSuccess,
+  createItemExpectSuccess,
+  destroyCollectionExpectSuccess,
+  findNotExistingCollection,
+  setVariableMetaDataExpectFailure,
+  setVariableMetaDataExpectSuccess,
+} from './util/helpers';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+describe('Integration Test setVariableMetaData', () => {
+  const data = [1, 2, 254, 255];
+
+  let alice: IKeyringPair;
+  let collectionId: number;
+  let tokenId: number;
+  before(async () => {
+    await usingApi(async () => {
+      alice = privateKey('//Alice');
+      collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+      tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');
+    });
+  });
+
+  it('execute setVariableMetaData', async () => {
+    await setVariableMetaDataExpectSuccess(alice, collectionId, tokenId, data);
+  });
+
+  it('verify data was set', async () => {
+    await usingApi(async api => {
+      const item: any = await api.query.nft.nftItemList(collectionId, tokenId);
+
+      expect(Array.from(item.VariableData)).to.deep.equal(Array.from(data));
+    });
+  });
+});
+
+describe('Negative Integration Test setVariableMetaData', () => {
+  let data = [1];
+
+  let alice: IKeyringPair;
+  let bob: IKeyringPair;
+
+  let validCollectionId: number;
+  let validTokenId: number;
+
+  before(async () => {
+    await usingApi(async () => {
+      alice = privateKey('//Alice');
+      bob = privateKey('//Bob');
+
+      validCollectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+      validTokenId = await createItemExpectSuccess(alice, validCollectionId, 'NFT');
+    });
+  });
+
+  it('fails on not existing collection id', async () => {
+    await usingApi(async api => {
+      let nonExistingCollectionId = await findNotExistingCollection(api);
+      await setVariableMetaDataExpectFailure(alice, nonExistingCollectionId, 1, data);
+    });
+  });
+  it('fails on removed collection id', async () => {
+    const removedCollectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+    const removedCollectionTokenId = await createItemExpectSuccess(alice, removedCollectionId, 'NFT');
+
+    await destroyCollectionExpectSuccess(removedCollectionId);
+    await setVariableMetaDataExpectFailure(alice, removedCollectionId, removedCollectionTokenId, data);
+  });
+  it('fails on removed token', async () => {
+    const removedTokenCollectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+    const removedTokenId = await createItemExpectSuccess(alice, removedTokenCollectionId, 'NFT');
+    await burnItemExpectSuccess(alice, removedTokenCollectionId, removedTokenId);
+
+    await setVariableMetaDataExpectFailure(alice, removedTokenCollectionId, removedTokenId, data);
+  });
+  it('fails on not existing token', async () => {
+    const nonExistingTokenId = validTokenId + 1;
+
+    await setVariableMetaDataExpectFailure(alice, validCollectionId, nonExistingTokenId, data);
+  });
+  it('fails on too long data', async () => {
+    const tooLongData = new Array(4097).fill(0xff);
+
+    await setVariableMetaDataExpectFailure(alice, validCollectionId, validTokenId, tooLongData);
+  });
+  it('fails on fungible token', async () => {
+    const fungibleCollectionId = await createCollectionExpectSuccess({ mode: { type: 'Fungible', decimalPoints: 0 } });
+    const fungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
+
+    await setVariableMetaDataExpectFailure(alice, fungibleCollectionId, fungibleTokenId, data);
+  });
+  it('fails on bad sender', async () => {
+    await setVariableMetaDataExpectFailure(bob, validCollectionId, validTokenId, data);
+  });
+});
addedtests/src/setVariableOnChainSchema.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/setVariableOnChainSchema.test.ts
@@ -0,0 +1,96 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { Keyring } from '@polkadot/api';
+import { IKeyringPair } from '@polkadot/types/types';
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api';
+import {
+  createCollectionExpectSuccess,
+  destroyCollectionExpectSuccess,
+} from './util/helpers';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+let Alice: IKeyringPair;
+let Bob: IKeyringPair;
+let Schema: any;
+let largeSchema: any;
+
+before(async () => {
+  await usingApi(async (api) => {
+    const keyring = new Keyring({ type: 'sr25519' });
+    Alice = keyring.addFromUri('//Alice');
+    Bob = keyring.addFromUri('//Bob');
+    Schema = '0x31';
+    largeSchema = new Array(4097).fill(0xff);
+
+  });
+});
+describe('Integration Test ext. setVariableOnChainSchema()', () => {
+
+  it('Run extrinsic with parameters of the collection id, set the scheme', async () => {
+      await usingApi(async (api) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const collection: any = (await api.query.nft.collection(collectionId));
+      expect(collection.Owner.toString()).to.be.eq(Alice.address);
+      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
+      await submitTransactionAsync(Alice, setSchema);
+    });
+  });
+
+  it('Checking collection data using the setVariableOnChainSchema parameter', async () => {
+      await usingApi(async (api) => {
+        const collectionId = await createCollectionExpectSuccess();
+        const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
+        await submitTransactionAsync(Alice, setSchema);
+        const collection: any = (await api.query.nft.collection(collectionId));
+        expect(collection.VariableOnChainSchema.toString()).to.be.eq(Schema);
+
+    });
+  });
+});
+
+describe('Negative Integration Test ext. setVariableOnChainSchema()', () => {
+
+  it('Set a non-existent collection', async () => {
+    await usingApi(async (api) => {
+      // tslint:disable-next-line: radix
+      const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;
+      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
+      await expect(submitTransactionExpectFailAsync(Alice, setSchema)).to.be.rejected;
+    });
+  });
+
+  it('Set a previously deleted collection', async () => {
+    await usingApi(async (api) => {
+      const collectionId = await createCollectionExpectSuccess();
+      await destroyCollectionExpectSuccess(collectionId);
+      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
+      await expect(submitTransactionExpectFailAsync(Alice, setSchema)).to.be.rejected;
+    });
+  });
+
+  it('Set invalid data in schema (size too large:> 1024b)', async () => {
+    await usingApi(async (api) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, largeSchema);
+      await expect(submitTransactionExpectFailAsync(Alice, setSchema)).to.be.rejected;
+    });
+  });
+
+  it('Execute method not on behalf of the collection owner', async () => {
+    await usingApi(async (api) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const collection: any = (await api.query.nft.collection(collectionId));
+      expect(collection.Owner.toString()).to.be.eq(Alice.address);
+      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
+      await expect(submitTransactionExpectFailAsync(Bob, setSchema)).to.be.rejected;
+    });
+  });
+
+});
modifiedtests/src/substrate/substrate-api.tsdiffbeforeafterboth
--- a/tests/src/substrate/substrate-api.ts
+++ b/tests/src/substrate/substrate-api.ts
@@ -24,12 +24,17 @@
 
   // TODO: Remove, this is temporary: Filter unneeded API output 
   // (Jaco promised it will be removed in the next version)
-  // const consoleLog = console.log;
-  // console.log = (message: string) => {
-  //   if (!(message.includes("API/INIT: Capabilities detected") || message.includes("2021-"))) {
-  //     consoleLog(message);
-  //   }
-  // };
+  const consoleLog = console.log;
+  console.log = (message: string) => {
+    if (message.includes("API/INIT: Capabilities detected") || message.includes("2021-")) {}
+    else if (message.includes("StorageChangeSet:: WebSocket is not connected") || message.includes("2021-")) {}
+    else consoleLog(message);
+  };
+  const consoleErr = console.error;
+  console.error = (message: string) => {
+    if (message.includes("StorageChangeSet:: WebSocket is not connected") || message.includes("2021-")) {}
+    else consoleErr(message);
+  };
 
   try {
     await promisifySubstrate(api, async () => {
@@ -40,7 +45,8 @@
     })();
   } finally {
     await api.disconnect();
-    // console.log = consoleLog;
+    console.log = consoleLog;
+    console.error = consoleErr;
   }
 }
 
@@ -115,11 +121,11 @@
       await transaction.signAndSend(sender, ({ events = [], status }) => {
         const transactionStatus = getTransactionStatus(events, status);
 
-        console.log('transactionStatus', transactionStatus, 'events', events);
+        // console.log('transactionStatus', transactionStatus, 'events', events);
 
-        if (transactionStatus == TransactionStatus.Success) {
+        if (transactionStatus === TransactionStatus.Success) {
           resolve(events);
-        } else if (transactionStatus == TransactionStatus.Fail) {
+        } else if (transactionStatus === TransactionStatus.Fail) {
           reject(events);
         }
       });
modifiedtests/src/toggleContractWhiteList.test.tsdiffbeforeafterboth
--- a/tests/src/toggleContractWhiteList.test.ts
+++ b/tests/src/toggleContractWhiteList.test.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 import chai from "chai";
 import chaiAsPromised from 'chai-as-promised';
 import usingApi, { submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api";
modifiedtests/src/transfer.test.tsdiffbeforeafterboth
--- a/tests/src/transfer.test.ts
+++ b/tests/src/transfer.test.ts
@@ -63,7 +63,7 @@
     });
   });
 
-  it('Create collection, balance transfers and check balance', async () => {
+  it('User can transfer owned token', async () => {
     await usingApi(async (api) => {
       const Alice = privateKey('//Alice');
       const Bob = privateKey('//Bob');
@@ -77,10 +77,10 @@
       await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 1, 'Fungible');
       // reFungible
       const reFungibleCollectionId = await
-        createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+        createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
       await transferExpectSuccess(reFungibleCollectionId,
-        newReFungibleTokenId, Alice, Bob, 1, 'ReFungible');
+        newReFungibleTokenId, Alice, Bob, 100, 'ReFungible');
     });
   });
 });
@@ -119,7 +119,7 @@
     await transferExpectFail(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 1, 'Fungible');
     // reFungible
     const reFungibleCollectionId = await
-      createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+      createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
     await destroyCollectionExpectSuccess(reFungibleCollectionId);
     await transferExpectFail(reFungibleCollectionId,
@@ -134,7 +134,7 @@
     await transferExpectFail(fungibleCollectionId, 2, Alice, Bob, 1, 'Fungible');
     // reFungible
     const reFungibleCollectionId = await
-      createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+      createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     await transferExpectFail(reFungibleCollectionId,
       2, Alice, Bob, 1, 'ReFungible');
   });
@@ -151,7 +151,7 @@
     await transferExpectFail(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 1, 'Fungible');
     // reFungible
     const reFungibleCollectionId = await
-      createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+      createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
     await burnItemExpectSuccess(Alice, reFungibleCollectionId, newReFungibleTokenId, 1);
     await transferExpectFail(reFungibleCollectionId,
@@ -168,7 +168,7 @@
     await transferExpectFail(fungibleCollectionId, newFungibleTokenId, Charlie, Bob, 1, 'Fungible');
     // reFungible
     const reFungibleCollectionId = await
-      createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+      createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
     await transferExpectFail(reFungibleCollectionId,
       newReFungibleTokenId, Charlie, Bob, 1, 'ReFungible');
modifiedtests/src/transferFrom.test.tsdiffbeforeafterboth
--- a/tests/src/transferFrom.test.ts
+++ b/tests/src/transferFrom.test.ts
@@ -41,11 +41,11 @@
       await transferFromExpectSuccess(fungibleCollectionId, newFungibleTokenId, Bob, Alice, Charlie, 1, 'Fungible');
       // reFungible
       const reFungibleCollectionId = await
-        createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+        createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
-      await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob);
+      await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob, 100);
       await transferFromExpectSuccess(reFungibleCollectionId,
-        newReFungibleTokenId, Bob, Alice, Charlie, 1, 'ReFungible');
+        newReFungibleTokenId, Bob, Alice, Charlie, 100, 'ReFungible');
     });
   });
 });
@@ -110,7 +110,7 @@
       await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, Bob, Alice, Charlie, 1);
       // reFungible
       const reFungibleCollectionId = await
-        createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+        createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
       await transferFromExpectFail(reFungibleCollectionId,
         newReFungibleTokenId, Bob, Alice, Charlie, 1);
@@ -136,7 +136,7 @@
       await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, Bob, Alice, Charlie, 2);
       // reFungible
       const reFungibleCollectionId = await
-        createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+        createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
       await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob);
       await transferFromExpectFail(reFungibleCollectionId,
@@ -149,7 +149,7 @@
       const Alice = privateKey('//Alice');
       const Bob = privateKey('//Bob');
       const Charlie = privateKey('//Charlie');
-      const Dave = privateKey('//DAVE');
+      const Dave = privateKey('//Dave');
       // nft
       const nftCollectionId = await createCollectionExpectSuccess();
       const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
@@ -175,7 +175,7 @@
       }
       // reFungible
       const reFungibleCollectionId = await
-        createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
+        createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible');
       try {
         await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, Dave, Bob);
modifiedtests/src/types.tsdiffbeforeafterboth
--- a/tests/src/types.ts
+++ b/tests/src/types.ts
@@ -1,3 +1,8 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 import BN from 'bn.js';
 
 export interface ICollectionInterface {
modifiedtests/src/util/contracthelpers.tsdiffbeforeafterboth
--- a/tests/src/util/contracthelpers.ts
+++ b/tests/src/util/contracthelpers.ts
@@ -5,7 +5,7 @@
 
 import chai from "chai";
 import chaiAsPromised from 'chai-as-promised';
-import { submitTransactionAsync } from "../substrate/substrate-api";
+import { submitTransactionAsync, submitTransactionExpectFailAsync } from "../substrate/substrate-api";
 import fs from "fs";
 import { Abi, BlueprintPromise as Blueprint, CodePromise, ContractPromise as Contract } from "@polkadot/api-contract";
 import { IKeyringPair } from "@polkadot/types/types";
@@ -14,7 +14,7 @@
 chai.use(chaiAsPromised);
 const expect = chai.expect;
 import { BigNumber } from 'bignumber.js';
-import { findUnusedAddress } from '../util/helpers';
+import { findUnusedAddress, getGenericResult } from '../util/helpers';
 
 const value = 0;
 const gasLimit = '200000000000';
@@ -92,6 +92,19 @@
   return (result.result.asOk.data[0] == 0x00) ? false : true;
 }
 
+export async function toggleFlipValueExpectSuccess(sender: IKeyringPair, contract: Contract) {
+  const tx = contract.tx.flip(value, gasLimit);
+  const events = await submitTransactionAsync(sender, tx);
+  const result = getGenericResult(events);
+
+  expect(result.success).to.be.true;
+}
+
+export async function toggleFlipValueExpectFailure(sender: IKeyringPair, contract: Contract) {
+  const tx = contract.tx.flip(value, gasLimit);
+  await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
+}
+
 function instantiateTransferContract(alice: IKeyringPair, blueprint: Blueprint) : Promise<any> {
   return new Promise<any>(async (resolve, reject) => {
     const unsub = await blueprint.tx
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -51,7 +51,7 @@
   Value: BN;
 }
 
-interface IReFungibleTokenDataType {
+export interface IReFungibleTokenDataType {
   Owner: IReFungibleOwner[];
   ConstData: number[];
   VariableData: number[];
@@ -124,21 +124,6 @@
 
 interface ReFungible {
   type: 'ReFungible';
-  decimalPoints: number;
-}
-
-interface Nft {
-  type: 'NFT'
-}
-
-interface Fungible {
-  type: 'Fungible',
-  decimalPoints: number
-}
-
-interface ReFungible {
-  type: 'ReFungible',
-  decimalPoints: number
 }
 
 type CollectionMode = Nft | Fungible | ReFungible | Invalid;
@@ -174,7 +159,7 @@
     } else if (mode.type === 'Fungible') {
       modeprm = {fungible: mode.decimalPoints};
     } else if (mode.type === 'ReFungible') {
-      modeprm = {refungible: mode.decimalPoints};
+      modeprm = {refungible: null};
     } else if (mode.type === 'Invalid') {
       modeprm = {invalid: null};
     }
@@ -216,7 +201,7 @@
   } else if (mode.type === 'Fungible') {
     modeprm = {fungible: mode.decimalPoints};
   } else if (mode.type === 'ReFungible') {
-    modeprm = {refungible: mode.decimalPoints};
+    modeprm = {refungible: null};
   } else if (mode.type === 'Invalid') {
     modeprm = {invalid: null};
   }
@@ -253,6 +238,12 @@
   return unused;
 }
 
+export async function findNotExistingCollection(api: ApiPromise): Promise<number> {
+  const totalNumber = parseInt((await api.query.nft.createdCollectionCount()).toString(), 10) as unknown as number;
+  const newCollection: number = totalNumber + 1;
+  return newCollection;
+}
+
 function getDestroyResult(events: EventRecord[]): boolean {
   let success: boolean = false;
   events.forEach(({ phase, event: { data, method, section } }) => {
@@ -379,6 +370,63 @@
   });
 }
 
+export async function enableContractSponsoringExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, enable: boolean) {
+  await usingApi(async (api) => {
+    const tx = api.tx.nft.enableContractSponsoring(contractAddress, enable);
+    const events = await submitTransactionAsync(sender, tx);
+    const result = getGenericResult(events);
+
+    expect(result.success).to.be.true;
+  });
+}
+
+export async function enableContractSponsoringExpectFailure(sender: IKeyringPair, contractAddress: AccountId | string, enable: boolean) {
+  await usingApi(async (api) => {
+    const tx = api.tx.nft.enableContractSponsoring(contractAddress, enable);
+    const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
+    const result = getGenericResult(events);
+
+    expect(result.success).to.be.false;
+  });
+}
+
+export async function setContractSponsoringRateLimitExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, rateLimit: number) {
+  await usingApi(async (api) => {
+    const tx = api.tx.nft.setContractSponsoringRateLimit(contractAddress, rateLimit);
+    const events = await submitTransactionAsync(sender, tx);
+    const result = getGenericResult(events);
+
+    expect(result.success).to.be.true;
+  });
+}
+
+export async function setContractSponsoringRateLimitExpectFailure(sender: IKeyringPair, contractAddress: AccountId | string, rateLimit: number) {
+  await usingApi(async (api) => {
+    const tx = api.tx.nft.setContractSponsoringRateLimit(contractAddress, rateLimit);
+    const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
+    const result = getGenericResult(events);
+
+    expect(result.success).to.be.false;
+  });
+}
+
+export async function setVariableMetaDataExpectSuccess(sender: IKeyringPair, collectionId: number, itemId: number, data: number[]) {
+  await usingApi(async (api) => {
+    const tx = api.tx.nft.setVariableMetaData(collectionId, itemId, '0x' + Buffer.from(data).toString('hex'));
+    const events = await submitTransactionAsync(sender, tx);
+    const result = getGenericResult(events);
+
+    expect(result.success).to.be.true;
+  });
+}
+
+export async function setVariableMetaDataExpectFailure(sender: IKeyringPair, collectionId: number, itemId: number, data: number[]) {
+  await usingApi(async (api) => {
+    const tx = api.tx.nft.setVariableMetaData(collectionId, itemId, '0x' + Buffer.from(data).toString('hex'));
+    await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
+  });
+}
+
 export interface CreateFungibleData extends Struct {
   readonly value: u128;
 }
@@ -440,7 +488,7 @@
     }
     const transferFromTx = await api.tx.nft.transferFrom(
       accountFrom.address, accountTo.address, collectionId, tokenId, value);
-    const events = await submitTransactionAsync(accountFrom, transferFromTx);
+    const events = await submitTransactionAsync(accountApproved, transferFromTx);
     const result = getCreateItemResult(events);
     // tslint:disable-next-line:no-unused-expression
     expect(result.success).to.be.true;
@@ -558,6 +606,9 @@
     if (createMode === 'Fungible') {
       const createData = {fungible: {value: 10}};
       tx = api.tx.nft.createItem(collectionId, owner, createData);
+    } else if (createMode === 'ReFungible') {
+      const createData = {refungible: {const_data: [], variable_data: [], pieces: 100}};
+      tx = api.tx.nft.createItem(collectionId, owner, createData);
     } else {
       tx = api.tx.nft.createItem(collectionId, owner, createMode);
     }
@@ -583,11 +634,25 @@
   return newItemId;
 }
 
-export async function enableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) {
+export async function createItemExpectFailure(
+  sender: IKeyringPair, collectionId: number, createMode: string, owner: string = sender.address) {
+  await usingApi(async (api) => {
+    const tx = api.tx.nft.createItem(collectionId, owner, createMode);
+    const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
+    const result = getCreateItemResult(events);
+
+    expect(result.success).to.be.false;
+  });
+}
+
+export async function setPublicAccessModeExpectSuccess(
+  sender: IKeyringPair, collectionId: number,
+  accessMode: 'Normal' | 'WhiteList',
+) {
   await usingApi(async (api) => {
 
     // Run the transaction
-    const tx = api.tx.nft.setPublicAccessMode(collectionId, 'WhiteList');
+    const tx = api.tx.nft.setPublicAccessMode(collectionId, accessMode);
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -597,15 +662,23 @@
     // What to expect
     // tslint:disable-next-line:no-unused-expression
     expect(result.success).to.be.true;
-    expect(collection.Access).to.be.equal('WhiteList');
+    expect(collection.Access).to.be.equal(accessMode);
   });
 }
 
-export async function enablePublicMintingExpectSuccess(sender: IKeyringPair, collectionId: number) {
+export async function enableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) {
+  await setPublicAccessModeExpectSuccess(sender, collectionId, 'WhiteList');
+}
+
+export async function disableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) {
+  await setPublicAccessModeExpectSuccess(sender, collectionId, 'Normal');
+}
+
+export async function setMintPermissionExpectSuccess(sender: IKeyringPair, collectionId: number, enabled: boolean) {
   await usingApi(async (api) => {
 
     // Run the transaction
-    const tx = api.tx.nft.setMintPermission(collectionId, true);
+    const tx = api.tx.nft.setMintPermission(collectionId, enabled);
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -613,9 +686,33 @@
     const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
 
     // What to expect
+    // tslint:disable-next-line:no-unused-expression
     expect(result.success).to.be.true;
-    expect(collection.MintMode).to.be.equal(true);
+    expect(collection.MintMode).to.be.equal(enabled);
+  });
+}
+
+export async function enablePublicMintingExpectSuccess(sender: IKeyringPair, collectionId: number) {
+  await setMintPermissionExpectSuccess(sender, collectionId, true);
+}
+
+export async function setMintPermissionExpectFailure(sender: IKeyringPair, collectionId: number, enabled: boolean) {
+  await usingApi(async (api) => {
+    // Run the transaction
+    const tx = api.tx.nft.setMintPermission(collectionId, enabled);
+    const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
+    const result = getCreateCollectionResult(events);
+    // tslint:disable-next-line:no-unused-expression
+    expect(result.success).to.be.false;
+  });
+}
+
+export async function isWhitelisted(collectionId: number, address: string) {
+  let whitelisted: boolean = false;
+  await usingApi(async (api) => {
+    whitelisted = (await api.query.nft.whiteList(collectionId, address)).toJSON() as unknown as boolean;
   });
+  return whitelisted;
 }
 
 export async function addToWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number, address: string) {
@@ -640,6 +737,32 @@
   });
 }
 
+export async function removeFromWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number, address: string) {
+  await usingApi(async (api) => {
+    // Run the transaction
+    const tx = api.tx.nft.removeFromWhiteList(collectionId, address);
+    const events = await submitTransactionAsync(sender, tx);
+    const result = getGenericResult(events);
+
+    // What to expect
+    // tslint:disable-next-line:no-unused-expression
+    expect(result.success).to.be.true;
+  });
+}
+
+export async function removeFromWhiteListExpectFailure(sender: IKeyringPair, collectionId: number, address: string) {
+  await usingApi(async (api) => {
+    // Run the transaction
+    const tx = api.tx.nft.removeFromWhiteList(collectionId, address);
+    const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
+    const result = getGenericResult(events);
+
+    // What to expect
+    // tslint:disable-next-line:no-unused-expression
+    expect(result.success).to.be.false;
+  });
+}
+
 export const getDetailedCollectionInfo = async (api: ApiPromise, collectionId: number)
   : Promise<ICollectionInterface | null> => {
   return await api.query.nft.collection(collectionId) as unknown as ICollectionInterface;