git.delta.rocks / unique-network / refs/commits / bda8c76d3c78

difftreelog

Merge remote-tracking branch 'origin/develop' into develop

kpozdnikin2020-12-29parents: #ac63732 #3e2b774.patch.diff
in: master
# Conflicts:
#	tests/src/contracts.test.ts

49 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -12,11 +12,11 @@
 
 [[package]]
 name = "addr2line"
-version = "0.13.0"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072"
+checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423"
 dependencies = [
- "gimli 0.22.0",
+ "gimli 0.23.0",
 ]
 
 [[package]]
@@ -55,7 +55,7 @@
  "aes",
  "block-cipher",
  "ghash",
- "subtle 2.3.0",
+ "subtle 2.4.0",
 ]
 
 [[package]]
@@ -95,10 +95,16 @@
 checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217"
 
 [[package]]
+name = "ahash"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
+
+[[package]]
 name = "aho-corasick"
-version = "0.7.14"
+version = "0.7.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b476ce7103678b0c6d3d395dbbae31d48ff910bd28be979ba5d48c6351131d0d"
+checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
 dependencies = [
  "memchr",
 ]
@@ -134,9 +140,9 @@
 
 [[package]]
 name = "anyhow"
-version = "1.0.33"
+version = "1.0.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c"
+checksum = "2c0df63cb2955042487fad3aefd2c6e3ae7389ac5dc1beb28921de0b69f779d4"
 
 [[package]]
 name = "approx"
@@ -149,9 +155,9 @@
 
 [[package]]
 name = "arc-swap"
-version = "0.4.7"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034"
+checksum = "dabe5a181f83789739c194cbe5a897dde195078fac08568d09221fd6137a7ba8"
 
 [[package]]
 name = "arrayref"
@@ -170,9 +176,9 @@
 
 [[package]]
 name = "arrayvec"
-version = "0.5.1"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
+checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
 
 [[package]]
 name = "asn1_der"
@@ -206,36 +212,36 @@
 
 [[package]]
 name = "async-executor"
-version = "1.3.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d373d78ded7d0b3fa8039375718cde0aace493f2e34fb60f51cbf567562ca801"
+checksum = "eb877970c7b440ead138f6321a3b5395d6061183af779340b65e20c0fede9146"
 dependencies = [
  "async-task",
  "concurrent-queue",
  "fastrand",
  "futures-lite",
- "once_cell 1.4.1",
+ "once_cell 1.5.2",
  "vec-arena",
 ]
 
 [[package]]
 name = "async-global-executor"
-version = "1.4.0"
+version = "1.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0659b83a146398616883aa5199cdd1b055ec088a83c9a338eab3534f33f0622e"
+checksum = "73079b49cd26b8fd5a15f68fc7707fc78698dc2a3d61430f2a7a9430230dfa04"
 dependencies = [
  "async-executor",
  "async-io",
  "futures-lite",
  "num_cpus",
- "once_cell 1.4.1",
+ "once_cell 1.5.2",
 ]
 
 [[package]]
 name = "async-io"
-version = "1.1.10"
+version = "1.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d54bc4c1c7292475efb2253227dbcfad8fe1ca4c02bc62c510cc2f3da5c4704e"
+checksum = "9315f8f07556761c3e48fec2e6b276004acf426e6dc068b2c2251854d65ee0fd"
 dependencies = [
  "concurrent-queue",
  "fastrand",
@@ -243,7 +249,7 @@
  "libc",
  "log",
  "nb-connect",
- "once_cell 1.4.1",
+ "once_cell 1.5.2",
  "parking",
  "polling",
  "vec-arena",
@@ -261,16 +267,34 @@
 ]
 
 [[package]]
+name = "async-process"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c8cea09c1fb10a317d1b5af8024eeba256d6554763e85ecd90ff8df31c7bbda"
+dependencies = [
+ "async-io",
+ "blocking",
+ "cfg-if 0.1.10",
+ "event-listener",
+ "futures-lite",
+ "once_cell 1.5.2",
+ "signal-hook",
+ "winapi 0.3.9",
+]
+
+[[package]]
 name = "async-std"
-version = "1.6.5"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9fa76751505e8df1c7a77762f60486f60c71bbd9b8557f4da6ad47d083732ed"
+checksum = "8f9f84f1280a2b436a2c77c2582602732b6c2f4321d5494d6e799e6c367859a8"
 dependencies = [
+ "async-channel",
  "async-global-executor",
  "async-io",
  "async-mutex",
+ "async-process",
  "blocking",
- "crossbeam-utils",
+ "crossbeam-utils 0.8.1",
  "futures-channel",
  "futures-core",
  "futures-io",
@@ -280,8 +304,8 @@
  "log",
  "memchr",
  "num_cpus",
- "once_cell 1.4.1",
- "pin-project-lite",
+ "once_cell 1.5.2",
+ "pin-project-lite 0.2.0",
  "pin-utils",
  "slab",
  "wasm-bindgen-futures",
@@ -289,9 +313,9 @@
 
 [[package]]
 name = "async-task"
-version = "4.0.2"
+version = "4.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ab27c1aa62945039e44edaeee1dc23c74cc0c303dd5fe0fb462a184f1c3a518"
+checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0"
 
 [[package]]
 name = "async-tls"
@@ -299,7 +323,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "df097e3f506bec0e1a24f06bb3c962c228f36671de841ff579cb99f371772634"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "rustls",
  "webpki",
  "webpki-roots 0.19.0",
@@ -307,9 +331,9 @@
 
 [[package]]
 name = "async-trait"
-version = "0.1.41"
+version = "0.1.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b246867b8b3b6ae56035f1eb1ed557c1d8eae97f0d53696138a50fa0e3a3b8c0"
+checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -353,15 +377,15 @@
 
 [[package]]
 name = "backtrace"
-version = "0.3.53"
+version = "0.3.55"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "707b586e0e2f247cbde68cdd2c3ce69ea7b7be43e1c5b426e37c9319c4b9838e"
+checksum = "ef5140344c85b01f9bbb4d4b7288a8aa4b3287ccef913a14bcc78a1063623598"
 dependencies = [
  "addr2line",
  "cfg-if 1.0.0",
  "libc",
  "miniz_oxide",
- "object 0.21.1",
+ "object 0.22.0",
  "rustc-demangle",
 ]
 
@@ -384,6 +408,12 @@
 checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
 
 [[package]]
+name = "base64"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
+
+[[package]]
 name = "bincode"
 version = "1.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -456,15 +486,13 @@
 
 [[package]]
 name = "blake2"
-version = "0.9.0"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84ce5b6108f8e154604bd4eb76a2f726066c3464d5a552a4229262a18c9bb471"
+checksum = "10a5720225ef5daecf08657f23791354e1685a8c91a4c60c7f3d3b2892f978f4"
 dependencies = [
- "byte-tools",
- "byteorder 1.3.4",
  "crypto-mac 0.8.0",
  "digest 0.9.0",
- "opaque-debug 0.2.3",
+ "opaque-debug 0.3.0",
 ]
 
 [[package]]
@@ -479,23 +507,23 @@
 
 [[package]]
 name = "blake2b_simd"
-version = "0.5.10"
+version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a"
+checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587"
 dependencies = [
  "arrayref",
- "arrayvec 0.5.1",
+ "arrayvec 0.5.2",
  "constant_time_eq",
 ]
 
 [[package]]
 name = "blake2s_simd"
-version = "0.5.10"
+version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab9e07352b829279624ceb7c64adb4f585dacdb81d35cafae81139ccd617cf44"
+checksum = "9e461a7034e85b211a4acb57ee2e6730b32912b06c08cc242243c39fc21ae6a2"
 dependencies = [
  "arrayref",
- "arrayvec 0.5.1",
+ "arrayvec 0.5.2",
  "constant_time_eq",
 ]
 
@@ -556,7 +584,7 @@
  "atomic-waker",
  "fastrand",
  "futures-lite",
- "once_cell 1.4.1",
+ "once_cell 1.5.2",
 ]
 
 [[package]]
@@ -566,10 +594,16 @@
 checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb"
 
 [[package]]
+name = "bs58"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
+
+[[package]]
 name = "bstr"
-version = "0.2.13"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931"
+checksum = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf"
 dependencies = [
  "memchr",
 ]
@@ -635,9 +669,9 @@
 
 [[package]]
 name = "cc"
-version = "1.0.61"
+version = "1.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d"
+checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
 dependencies = [
  "jobserver",
 ]
@@ -669,7 +703,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "244fbce0d47e97e8ef2f63b81d5e05882cb518c68531eb33194990d7b7e85845"
 dependencies = [
- "stream-cipher 0.7.1",
+ "stream-cipher",
  "zeroize",
 ]
 
@@ -682,7 +716,7 @@
  "aead",
  "chacha20",
  "poly1305",
- "stream-cipher 0.7.1",
+ "stream-cipher",
  "zeroize",
 ]
 
@@ -730,15 +764,6 @@
 version = "0.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "cloudabi"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467"
 dependencies = [
  "bitflags",
 ]
@@ -754,9 +779,9 @@
 
 [[package]]
 name = "const-random"
-version = "0.1.11"
+version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02dc82c12dc2ee6e1ded861cf7d582b46f66f796d1b6c93fa28b911ead95da02"
+checksum = "f590d95d011aa80b063ffe3253422ed5aa462af4e9867d43ce8337562bac77c4"
 dependencies = [
  "const-random-macro",
  "proc-macro-hack",
@@ -764,15 +789,23 @@
 
 [[package]]
 name = "const-random-macro"
-version = "0.1.11"
+version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc757bbb9544aa296c2ae00c679e81f886b37e28e59097defe0cf524306f6685"
+checksum = "615f6e27d000a2bffbc7f2f6a8669179378fa27ee4d0a509e985dfc0a7defb40"
 dependencies = [
  "getrandom 0.2.0",
+ "lazy_static",
  "proc-macro-hack",
+ "tiny-keccak",
 ]
 
 [[package]]
+name = "const_fn"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826"
+
+[[package]]
 name = "constant_time_eq"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -801,6 +834,12 @@
 checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
 
 [[package]]
+name = "cpuid-bool"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba"
+
+[[package]]
 name = "cranelift-bforest"
 version = "0.66.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -824,7 +863,7 @@
  "log",
  "regalloc",
  "serde",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "target-lexicon",
  "thiserror",
 ]
@@ -862,7 +901,7 @@
 dependencies = [
  "cranelift-codegen",
  "log",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "target-lexicon",
 ]
 
@@ -894,21 +933,21 @@
 
 [[package]]
 name = "crc32fast"
-version = "1.2.0"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
+checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
 ]
 
 [[package]]
 name = "crossbeam-channel"
-version = "0.4.4"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87"
+checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
 dependencies = [
- "crossbeam-utils",
- "maybe-uninit",
+ "cfg-if 1.0.0",
+ "crossbeam-utils 0.8.1",
 ]
 
 [[package]]
@@ -917,12 +956,23 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
 dependencies = [
- "crossbeam-epoch",
- "crossbeam-utils",
+ "crossbeam-epoch 0.8.2",
+ "crossbeam-utils 0.7.2",
  "maybe-uninit",
 ]
 
 [[package]]
+name = "crossbeam-deque"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
+dependencies = [
+ "cfg-if 1.0.0",
+ "crossbeam-epoch 0.9.1",
+ "crossbeam-utils 0.8.1",
+]
+
+[[package]]
 name = "crossbeam-epoch"
 version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -930,10 +980,24 @@
 dependencies = [
  "autocfg 1.0.1",
  "cfg-if 0.1.10",
- "crossbeam-utils",
+ "crossbeam-utils 0.7.2",
  "lazy_static",
  "maybe-uninit",
- "memoffset",
+ "memoffset 0.5.6",
+ "scopeguard 1.1.0",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
+dependencies = [
+ "cfg-if 1.0.0",
+ "const_fn",
+ "crossbeam-utils 0.8.1",
+ "lazy_static",
+ "memoffset 0.6.1",
  "scopeguard 1.1.0",
 ]
 
@@ -944,7 +1008,7 @@
 checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570"
 dependencies = [
  "cfg-if 0.1.10",
- "crossbeam-utils",
+ "crossbeam-utils 0.7.2",
  "maybe-uninit",
 ]
 
@@ -960,6 +1024,17 @@
 ]
 
 [[package]]
+name = "crossbeam-utils"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
+dependencies = [
+ "autocfg 1.0.1",
+ "cfg-if 1.0.0",
+ "lazy_static",
+]
+
+[[package]]
 name = "crunchy"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -982,7 +1057,7 @@
 checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab"
 dependencies = [
  "generic-array 0.14.4",
- "subtle 2.3.0",
+ "subtle 2.4.0",
 ]
 
 [[package]]
@@ -1013,7 +1088,7 @@
  "byteorder 1.3.4",
  "digest 0.8.1",
  "rand_core 0.5.1",
- "subtle 2.3.0",
+ "subtle 2.4.0",
  "zeroize",
 ]
 
@@ -1026,15 +1101,15 @@
  "byteorder 1.3.4",
  "digest 0.9.0",
  "rand_core 0.5.1",
- "subtle 2.3.0",
+ "subtle 2.4.0",
  "zeroize",
 ]
 
 [[package]]
 name = "data-encoding"
-version = "2.3.0"
+version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4d0e2d24e5ee3b23a01de38eefdcd978907890701f08ffffd4cb457ca4ee8d6"
+checksum = "993a608597367c6377b258c25d7120740f00ed23a2252b729b1932dd7866f908"
 
 [[package]]
 name = "derive_more"
@@ -1119,9 +1194,9 @@
 
 [[package]]
 name = "dyn-clone"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c53dc3a653e0f64081026e4bf048d48fec9fce90c66e8326ca7292df0ff2d82"
+checksum = "d55796afa1b20c2945ca8eabfc421839f2b766619209f1ede813cf2484f31804"
 
 [[package]]
 name = "ed25519"
@@ -1142,7 +1217,7 @@
  "ed25519",
  "rand 0.7.3",
  "serde",
- "sha2 0.9.1",
+ "sha2 0.9.2",
  "zeroize",
 ]
 
@@ -1153,6 +1228,26 @@
 checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
 
 [[package]]
+name = "enumflags2"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83c8d82922337cd23a15f88b70d8e4ef5f11da38dd7cdb55e84dd5de99695da0"
+dependencies = [
+ "enumflags2_derive",
+]
+
+[[package]]
+name = "enumflags2_derive"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "env_logger"
 version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1182,9 +1277,9 @@
 
 [[package]]
 name = "errno"
-version = "0.2.6"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6eab5ee3df98a279d9b316b1af6ac95422127b1290317e6d18c1743c99418b01"
+checksum = "fa68f2fb9cae9d37c9b2b3584aba698a2e97f72d7aef7b9f7aa71d8b54ce46fe"
 dependencies = [
  "errno-dragonfly",
  "libc",
@@ -1213,7 +1308,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
 ]
 
 [[package]]
@@ -1285,7 +1380,7 @@
 checksum = "8feb87a63249689640ac9c011742c33139204e3c134293d3054022276869133b"
 dependencies = [
  "either",
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-timer 2.0.2",
  "log",
  "num-traits",
@@ -1313,11 +1408,11 @@
 
 [[package]]
 name = "flate2"
-version = "1.0.18"
+version = "1.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da80be589a72651dcda34d8b35bcdc9b7254ad06325611074d9cc0fbb19f60ee"
+checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "crc32fast",
  "libc",
  "libz-sys",
@@ -1325,6 +1420,22 @@
 ]
 
 [[package]]
+name = "flexi_logger"
+version = "0.15.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aaab3caedb4149800f91e8e4899f29cd9ddf3b569b04c365ca9334f92f7542bf"
+dependencies = [
+ "atty",
+ "chrono",
+ "glob",
+ "lazy_static",
+ "log",
+ "regex",
+ "thiserror",
+ "yansi",
+]
+
+[[package]]
 name = "fnv"
 version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1333,15 +1444,25 @@
 [[package]]
 name = "fork-tree"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
 ]
 
 [[package]]
+name = "form_urlencoded"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00"
+dependencies = [
+ "matches",
+ "percent-encoding 2.1.0",
+]
+
+[[package]]
 name = "frame-benchmarking"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -1359,7 +1480,7 @@
 [[package]]
 name = "frame-benchmarking-cli"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-benchmarking",
  "parity-scale-codec",
@@ -1377,7 +1498,7 @@
 [[package]]
 name = "frame-executive"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -1393,7 +1514,7 @@
 [[package]]
 name = "frame-metadata"
 version = "12.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
  "serde",
@@ -1404,18 +1525,18 @@
 [[package]]
 name = "frame-support"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "bitmask",
  "frame-metadata",
  "frame-support-procedural",
  "impl-trait-for-tuples",
  "log",
- "once_cell 1.4.1",
+ "once_cell 1.5.2",
  "parity-scale-codec",
  "paste",
  "serde",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "sp-arithmetic",
  "sp-core",
  "sp-inherents",
@@ -1429,7 +1550,7 @@
 [[package]]
 name = "frame-support-procedural"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-support-procedural-tools",
  "proc-macro2",
@@ -1440,7 +1561,7 @@
 [[package]]
 name = "frame-support-procedural-tools"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-support-procedural-tools-derive",
  "proc-macro-crate",
@@ -1452,7 +1573,7 @@
 [[package]]
 name = "frame-support-procedural-tools-derive"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1462,7 +1583,7 @@
 [[package]]
 name = "frame-system"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-support",
  "impl-trait-for-tuples",
@@ -1478,7 +1599,7 @@
 [[package]]
 name = "frame-system-benchmarking"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
@@ -1492,7 +1613,7 @@
 [[package]]
 name = "frame-system-rpc-runtime-api"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
  "sp-api",
@@ -1500,9 +1621,9 @@
 
 [[package]]
 name = "fs-swap"
-version = "0.2.4"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "921d332c89b3b61a826de38c61ee5b6e02c56806cade1b0e5d81bd71f57a71bb"
+checksum = "5839fda247e24ca4919c87c71dd5ca658f1f39e4f06829f80e3f15c3bafcfc2c"
 dependencies = [
  "lazy_static",
  "libc",
@@ -1540,9 +1661,9 @@
 
 [[package]]
 name = "futures"
-version = "0.3.6"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d8e3078b7b2a8a671cb7a3d17b4760e4181ea243227776ba83fd043b4ca034e"
+checksum = "9b3b0c040a1fe6529d30b3c5944b280c7f0dcb2930d2c3062bca967b602583d0"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -1555,9 +1676,9 @@
 
 [[package]]
 name = "futures-channel"
-version = "0.3.6"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a4d35f7401e948629c9c3d6638fb9bf94e0b2121e96c3b428cc4e631f3eb74"
+checksum = "4b7109687aa4e177ef6fe84553af6280ef2778bdb7783ba44c9dc3399110fe64"
 dependencies = [
  "futures-core",
  "futures-sink",
@@ -1574,9 +1695,9 @@
 
 [[package]]
 name = "futures-core"
-version = "0.3.6"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d674eaa0056896d5ada519900dbf97ead2e46a7b6621e8160d79e2f2e1e2784b"
+checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748"
 
 [[package]]
 name = "futures-core-preview"
@@ -1601,20 +1722,20 @@
 checksum = "fdcef58a173af8148b182684c9f2d5250875adbcaff7b5794073894f9d8634a9"
 dependencies = [
  "futures 0.1.30",
- "futures 0.3.6",
+ "futures 0.3.8",
  "lazy_static",
  "log",
  "parking_lot 0.9.0",
- "pin-project",
+ "pin-project 0.4.27",
  "serde",
  "serde_json",
 ]
 
 [[package]]
 name = "futures-executor"
-version = "0.3.6"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc709ca1da6f66143b8c9bec8e6260181869893714e9b5a490b169b0414144ab"
+checksum = "4caa2b2b68b880003057c1dd49f1ed937e38f22fcf6c212188a121f08cf40a65"
 dependencies = [
  "futures-core",
  "futures-task",
@@ -1624,30 +1745,30 @@
 
 [[package]]
 name = "futures-io"
-version = "0.3.6"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fc94b64bb39543b4e432f1790b6bf18e3ee3b74653c5449f63310e9a74b123c"
+checksum = "611834ce18aaa1bd13c4b374f5d653e1027cf99b6b502584ff8c9a64413b30bb"
 
 [[package]]
 name = "futures-lite"
-version = "1.11.1"
+version = "1.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "381a7ad57b1bad34693f63f6f377e1abded7a9c85c9d3eb6771e11c60aaadab9"
+checksum = "5e6c079abfac3ab269e2927ec048dabc89d009ebfdda6b8ee86624f30c689658"
 dependencies = [
  "fastrand",
  "futures-core",
  "futures-io",
  "memchr",
  "parking",
- "pin-project-lite",
+ "pin-project-lite 0.1.11",
  "waker-fn",
 ]
 
 [[package]]
 name = "futures-macro"
-version = "0.3.6"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f57ed14da4603b2554682e9f2ff3c65d7567b53188db96cb71538217fc64581b"
+checksum = "77408a692f1f97bcc61dc001d752e00643408fbc922e4d634c655df50d595556"
 dependencies = [
  "proc-macro-hack",
  "proc-macro2",
@@ -1657,17 +1778,17 @@
 
 [[package]]
 name = "futures-sink"
-version = "0.3.6"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d8764258ed64ebc5d9ed185cf86a95db5cac810269c5d20ececb32e0088abbd"
+checksum = "f878195a49cee50e006b02b93cf7e0a95a38ac7b776b4c4d9cc1207cd20fcb3d"
 
 [[package]]
 name = "futures-task"
-version = "0.3.6"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dd26820a9f3637f1302da8bceba3ff33adbe53464b54ca24d4e2d4f1db30f94"
+checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d"
 dependencies = [
- "once_cell 1.4.1",
+ "once_cell 1.5.2",
 ]
 
 [[package]]
@@ -1684,9 +1805,9 @@
 
 [[package]]
 name = "futures-util"
-version = "0.3.6"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a894a0acddba51a2d49a6f4263b1e64b8c579ece8af50fa86503d52cd1eea34"
+checksum = "d304cff4a7b99cfb7986f7d43fbe93d175e72e704a8860787cc95e9ffd85cbd2"
 dependencies = [
  "futures 0.1.30",
  "futures-channel",
@@ -1696,7 +1817,7 @@
  "futures-sink",
  "futures-task",
  "memchr",
- "pin-project",
+ "pin-project 1.0.2",
  "pin-utils",
  "proc-macro-hack",
  "proc-macro-nested",
@@ -1722,9 +1843,9 @@
 checksum = "ce54d63f8b0c75023ed920d46fd71d0cbbb830b0ee012726b5b4f506fb6dea5b"
 dependencies = [
  "bytes 0.5.6",
- "futures 0.3.6",
+ "futures 0.3.8",
  "memchr",
- "pin-project",
+ "pin-project 0.4.27",
 ]
 
 [[package]]
@@ -1734,6 +1855,19 @@
 checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
 
 [[package]]
+name = "generator"
+version = "0.6.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8cdc09201b2e8ca1b19290cf7e65de2246b8e91fb6874279722189c4de7b94dc"
+dependencies = [
+ "cc",
+ "libc",
+ "log",
+ "rustc_version",
+ "winapi 0.3.9",
+]
+
+[[package]]
 name = "generic-array"
 version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1818,9 +1952,9 @@
 
 [[package]]
 name = "gimli"
-version = "0.22.0"
+version = "0.23.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
+checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
 
 [[package]]
 name = "glob"
@@ -1830,9 +1964,9 @@
 
 [[package]]
 name = "globset"
-version = "0.4.5"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ad1da430bd7281dde2576f44c84cc3f0f7b475e7202cd503042dff01a8c8120"
+checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a"
 dependencies = [
  "aho-corasick",
  "bstr",
@@ -1874,21 +2008,22 @@
 
 [[package]]
 name = "h2"
-version = "0.2.6"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53"
+checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535"
 dependencies = [
  "bytes 0.5.6",
  "fnv",
  "futures-core",
  "futures-sink",
  "futures-util",
- "http 0.2.1",
+ "http 0.2.2",
  "indexmap",
  "slab",
- "tokio 0.2.22",
+ "tokio 0.2.24",
  "tokio-util",
  "tracing",
+ "tracing-futures",
 ]
 
 [[package]]
@@ -1941,6 +2076,9 @@
 version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
+dependencies = [
+ "ahash 0.4.7",
+]
 
 [[package]]
 name = "heck"
@@ -2012,9 +2150,9 @@
 
 [[package]]
 name = "http"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9"
+checksum = "84129d298a6d57d246960ff8eb831ca4af3f96d29e2e28848dae275408658e26"
 dependencies = [
  "bytes 0.5.6",
  "fnv",
@@ -2040,7 +2178,7 @@
 checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
 dependencies = [
  "bytes 0.5.6",
- "http 0.2.1",
+ "http 0.2.2",
 ]
 
 [[package]]
@@ -2096,23 +2234,23 @@
 
 [[package]]
 name = "hyper"
-version = "0.13.8"
+version = "0.13.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f3afcfae8af5ad0576a31e768415edb627824129e8e5a29b8bfccb2f234e835"
+checksum = "f6ad767baac13b44d4529fcf58ba2cd0995e36e7b435bc5b039de6f47e880dbf"
 dependencies = [
  "bytes 0.5.6",
  "futures-channel",
  "futures-core",
  "futures-util",
- "h2 0.2.6",
- "http 0.2.1",
+ "h2 0.2.7",
+ "http 0.2.2",
  "http-body 0.3.1",
  "httparse",
  "httpdate",
  "itoa",
- "pin-project",
+ "pin-project 1.0.2",
  "socket2",
- "tokio 0.2.22",
+ "tokio 0.2.24",
  "tower-service",
  "tracing",
  "want 0.3.0",
@@ -2127,11 +2265,11 @@
  "bytes 0.5.6",
  "ct-logs",
  "futures-util",
- "hyper 0.13.8",
+ "hyper 0.13.9",
  "log",
  "rustls",
  "rustls-native-certs",
- "tokio 0.2.22",
+ "tokio 0.2.24",
  "tokio-rustls",
  "webpki",
 ]
@@ -2189,9 +2327,9 @@
 
 [[package]]
 name = "indexmap"
-version = "1.6.0"
+version = "1.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
+checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b"
 dependencies = [
  "autocfg 1.0.1",
  "hashbrown 0.9.1",
@@ -2200,11 +2338,11 @@
 
 [[package]]
 name = "instant"
-version = "0.1.7"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66"
+checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
 ]
 
 [[package]]
@@ -2222,7 +2360,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "64fa110ec7b8f493f416eed552740d10e7030ad5f63b2308f82c9608ec2df275"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-timer 2.0.2",
 ]
 
@@ -2282,9 +2420,9 @@
 
 [[package]]
 name = "js-sys"
-version = "0.3.45"
+version = "0.3.46"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8"
+checksum = "cf3d7383929f7c9c7c2d0fa596f325832df98c3704f2c60553080f7127a58175"
 dependencies = [
  "wasm-bindgen",
 ]
@@ -2443,7 +2581,7 @@
 checksum = "0315ef2f688e33844400b31f11c263f2b3dc21d8b9355c6891c5f185fae43f9a"
 dependencies = [
  "parity-util-mem",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
 ]
 
 [[package]]
@@ -2472,7 +2610,7 @@
  "parking_lot 0.10.2",
  "regex",
  "rocksdb",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
 ]
 
 [[package]]
@@ -2495,9 +2633,9 @@
 
 [[package]]
 name = "libc"
-version = "0.2.79"
+version = "0.2.81"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
+checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
 
 [[package]]
 name = "libloading"
@@ -2523,7 +2661,7 @@
 dependencies = [
  "atomic",
  "bytes 0.5.6",
- "futures 0.3.6",
+ "futures 0.3.8",
  "lazy_static",
  "libp2p-core",
  "libp2p-core-derive",
@@ -2549,8 +2687,8 @@
  "multihash",
  "parity-multiaddr",
  "parking_lot 0.10.2",
- "pin-project",
- "smallvec 1.4.2",
+ "pin-project 0.4.27",
+ "smallvec 1.5.1",
  "wasm-timer",
 ]
 
@@ -2561,11 +2699,11 @@
 checksum = "52f13ba8c7df0768af2eb391696d562c7de88cc3a35122531aaa6a7d77754d25"
 dependencies = [
  "asn1_der",
- "bs58",
+ "bs58 0.3.1",
  "ed25519-dalek",
  "either",
  "fnv",
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-timer 3.0.2",
  "lazy_static",
  "libsecp256k1",
@@ -2574,14 +2712,14 @@
  "multistream-select",
  "parity-multiaddr",
  "parking_lot 0.10.2",
- "pin-project",
+ "pin-project 0.4.27",
  "prost",
  "prost-build",
  "rand 0.7.3",
  "ring",
  "rw-stream-sink",
  "sha2 0.8.2",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "thiserror",
  "unsigned-varint 0.4.0",
  "void",
@@ -2605,7 +2743,7 @@
 checksum = "74029ae187f35f4b8ddf26b9779a68b340045d708528a103917cdca49a296db5"
 dependencies = [
  "flate2",
- "futures 0.3.6",
+ "futures 0.3.8",
  "libp2p-core",
 ]
 
@@ -2615,7 +2753,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7cf319822e08dd65c8e060d2354e9f952895bbc433f5706c75ed010c152aee5e"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "libp2p-core",
  "log",
 ]
@@ -2628,13 +2766,13 @@
 dependencies = [
  "cuckoofilter",
  "fnv",
- "futures 0.3.6",
+ "futures 0.3.8",
  "libp2p-core",
  "libp2p-swarm",
  "prost",
  "prost-build",
  "rand 0.7.3",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
 ]
 
 [[package]]
@@ -2647,7 +2785,7 @@
  "byteorder 1.3.4",
  "bytes 0.5.6",
  "fnv",
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures_codec",
  "hex_fmt",
  "libp2p-core",
@@ -2658,7 +2796,7 @@
  "prost-build",
  "rand 0.7.3",
  "sha2 0.8.2",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "unsigned-varint 0.4.0",
  "wasm-timer",
 ]
@@ -2669,13 +2807,13 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "56396ee63aa9164eacf40c2c5d2bda8c4133c2f57e1b0425d51d3a4e362583b1"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "libp2p-core",
  "libp2p-swarm",
  "log",
  "prost",
  "prost-build",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "wasm-timer",
 ]
 
@@ -2685,11 +2823,11 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cc7fa9047f8b8f544278a35c2d9d45d3b2c1785f2d86d4e1629d6edf97be3955"
 dependencies = [
- "arrayvec 0.5.1",
+ "arrayvec 0.5.2",
  "bytes 0.5.6",
  "either",
  "fnv",
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures_codec",
  "libp2p-core",
  "libp2p-swarm",
@@ -2699,7 +2837,7 @@
  "prost-build",
  "rand 0.7.3",
  "sha2 0.8.2",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "uint",
  "unsigned-varint 0.4.0",
  "void",
@@ -2716,14 +2854,14 @@
  "data-encoding",
  "dns-parser",
  "either",
- "futures 0.3.6",
+ "futures 0.3.8",
  "lazy_static",
  "libp2p-core",
  "libp2p-swarm",
  "log",
  "net2",
  "rand 0.7.3",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "void",
  "wasm-timer",
 ]
@@ -2736,7 +2874,7 @@
 dependencies = [
  "bytes 0.5.6",
  "fnv",
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures_codec",
  "libp2p-core",
  "log",
@@ -2752,7 +2890,7 @@
 dependencies = [
  "bytes 0.5.6",
  "curve25519-dalek 2.1.0",
- "futures 0.3.6",
+ "futures 0.3.8",
  "lazy_static",
  "libp2p-core",
  "log",
@@ -2772,7 +2910,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ad063c21dfcea4518ac9e8bd4119d33a5b26c41e674f602f41f05617a368a5c8"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "libp2p-core",
  "libp2p-swarm",
  "log",
@@ -2788,7 +2926,7 @@
 checksum = "903a12e99c72dbebefea258de887982adeacc7025baa1ceb10b7fa9928f54791"
 dependencies = [
  "bytes 0.5.6",
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures_codec",
  "libp2p-core",
  "log",
@@ -2801,16 +2939,16 @@
 
 [[package]]
 name = "libp2p-pnet"
-version = "0.19.1"
+version = "0.19.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37d0db10e139d22d7af0b23ed7949449ec86262798aa0fd01595abdbcb02dc87"
+checksum = "96b3c2d5d26a9500e959a0e19743897239a6c4be78dadf99b70414301a70c006"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "log",
- "pin-project",
+ "pin-project 0.4.27",
  "rand 0.7.3",
  "salsa20",
- "sha3 0.8.2",
+ "sha3",
 ]
 
 [[package]]
@@ -2821,14 +2959,14 @@
 dependencies = [
  "async-trait",
  "bytes 0.5.6",
- "futures 0.3.6",
+ "futures 0.3.8",
  "libp2p-core",
  "libp2p-swarm",
  "log",
- "lru 0.6.0",
+ "lru 0.6.2",
  "minicbor",
  "rand 0.7.3",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "unsigned-varint 0.5.1",
  "wasm-timer",
 ]
@@ -2840,11 +2978,11 @@
 checksum = "7193e444210132237b81b755ec7fe53f1c4bd2f53cf719729b94c0c72eb6eaa1"
 dependencies = [
  "either",
- "futures 0.3.6",
+ "futures 0.3.8",
  "libp2p-core",
  "log",
  "rand 0.7.3",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "void",
  "wasm-timer",
 ]
@@ -2856,7 +2994,7 @@
 checksum = "44f42ec130d7a37a7e47bf4398026b7ad9185c08ed26972e2720f8b94112796f"
 dependencies = [
  "async-std",
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-timer 3.0.2",
  "get_if_addrs",
  "ipnet",
@@ -2872,7 +3010,7 @@
 checksum = "dea7acb0a034f70d7db94c300eba3f65c0f6298820105624088a9609c9974d77"
 dependencies = [
  "async-std",
- "futures 0.3.6",
+ "futures 0.3.8",
  "libp2p-core",
  "log",
 ]
@@ -2883,7 +3021,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "34c1faac6f92c21fbe155417957863ea822fba9e9fd5eb24c0912336a100e63f"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "js-sys",
  "libp2p-core",
  "parity-send-wrapper",
@@ -2899,14 +3037,14 @@
 dependencies = [
  "async-tls",
  "either",
- "futures 0.3.6",
+ "futures 0.3.8",
  "libp2p-core",
  "log",
  "quicksink",
  "rustls",
  "rw-stream-sink",
  "soketto",
- "url 2.1.1",
+ "url 2.2.0",
  "webpki",
  "webpki-roots 0.18.0",
 ]
@@ -2917,9 +3055,9 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "781d9b9f043dcdabc40640807125368596b849fd4d96cdca2dcf052fdf6f33fd"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "libp2p-core",
- "parking_lot 0.11.0",
+ "parking_lot 0.11.1",
  "thiserror",
  "yamux",
 ]
@@ -2948,7 +3086,7 @@
  "hmac-drbg",
  "rand 0.7.3",
  "sha2 0.8.2",
- "subtle 2.3.0",
+ "subtle 2.4.0",
  "typenum",
 ]
 
@@ -3009,9 +3147,9 @@
 
 [[package]]
 name = "lock_api"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c"
+checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
 dependencies = [
  "scopeguard 1.1.0",
 ]
@@ -3026,6 +3164,19 @@
 ]
 
 [[package]]
+name = "loom"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0e8460f2f2121162705187214720353c517b97bdfb3494c0b1e33d83ebe4bed"
+dependencies = [
+ "cfg-if 0.1.10",
+ "generator",
+ "scoped-tls",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
 name = "lru"
 version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3036,11 +3187,11 @@
 
 [[package]]
 name = "lru"
-version = "0.6.0"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "111b945ac72ec09eb7bc62a0fbdc3cc6e80555a7245f52a69d3921a75b53b153"
+checksum = "3abe07af102235a56ac9a6dd904aab1e05483e2e8afdfffec3598be55b1b7606"
 dependencies = [
- "hashbrown 0.8.2",
+ "hashbrown 0.9.1",
 ]
 
 [[package]]
@@ -3075,9 +3226,9 @@
 
 [[package]]
 name = "matrixmultiply"
-version = "0.2.3"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4f7ec66360130972f34830bfad9ef05c6610a43938a467bcc9ab9369ab3478f"
+checksum = "916806ba0031cd542105d916a97c8572e1fa6dd79c9c51e7eb43a09ec2dd84c1"
 dependencies = [
  "rawpointer",
 ]
@@ -3090,9 +3241,9 @@
 
 [[package]]
 name = "memchr"
-version = "2.3.3"
+version = "2.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
+checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
 
 [[package]]
 name = "memmap"
@@ -3114,6 +3265,15 @@
 ]
 
 [[package]]
+name = "memoffset"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
+dependencies = [
+ "autocfg 1.0.1",
+]
+
+[[package]]
 name = "memory-db"
 version = "0.24.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3174,9 +3334,9 @@
 
 [[package]]
 name = "mio"
-version = "0.6.22"
+version = "0.6.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
+checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4"
 dependencies = [
  "cfg-if 0.1.10",
  "fuchsia-zircon",
@@ -3185,7 +3345,7 @@
  "kernel32-sys",
  "libc",
  "log",
- "miow 0.2.1",
+ "miow 0.2.2",
  "net2",
  "slab",
  "winapi 0.2.8",
@@ -3211,7 +3371,7 @@
 dependencies = [
  "log",
  "mio",
- "miow 0.3.5",
+ "miow 0.3.6",
  "winapi 0.3.9",
 ]
 
@@ -3228,9 +3388,9 @@
 
 [[package]]
 name = "miow"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
+checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
 dependencies = [
  "kernel32-sys",
  "net2",
@@ -3240,9 +3400,9 @@
 
 [[package]]
 name = "miow"
-version = "0.3.5"
+version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e"
+checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897"
 dependencies = [
  "socket2",
  "winapi 0.3.9",
@@ -3263,9 +3423,9 @@
  "blake2b_simd",
  "blake2s_simd",
  "digest 0.9.0",
- "sha-1 0.9.1",
- "sha2 0.9.1",
- "sha3 0.9.1",
+ "sha-1 0.9.2",
+ "sha2 0.9.2",
+ "sha3",
  "unsigned-varint 0.5.1",
 ]
 
@@ -3277,16 +3437,16 @@
 
 [[package]]
 name = "multistream-select"
-version = "0.8.2"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9157e87afbc2ef0d84cc0345423d715f445edde00141c93721c162de35a05e5"
+checksum = "93faf2e41f9ee62fb01680ed48f3cc26652352327aa2e59869070358f6b7dd75"
 dependencies = [
  "bytes 0.5.6",
- "futures 0.3.6",
+ "futures 0.3.8",
  "log",
- "pin-project",
- "smallvec 1.4.2",
- "unsigned-varint 0.4.0",
+ "pin-project 1.0.2",
+ "smallvec 1.5.1",
+ "unsigned-varint 0.5.1",
 ]
 
 [[package]]
@@ -3327,9 +3487,9 @@
 
 [[package]]
 name = "net2"
-version = "0.2.35"
+version = "0.2.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853"
+checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae"
 dependencies = [
  "cfg-if 0.1.10",
  "libc",
@@ -3340,9 +3500,10 @@
 name = "nft"
 version = "2.0.0"
 dependencies = [
+ "flexi_logger",
  "frame-benchmarking",
  "frame-benchmarking-cli",
- "futures 0.3.6",
+ "futures 0.3.8",
  "jsonrpc-core",
  "log",
  "nft-runtime",
@@ -3361,6 +3522,8 @@
  "sc-rpc-api",
  "sc-service",
  "sc-transaction-pool",
+ "serde",
+ "serde_json",
  "sp-api",
  "sp-block-builder",
  "sp-blockchain",
@@ -3400,6 +3563,7 @@
  "pallet-transaction-payment",
  "pallet-transaction-payment-rpc-runtime-api",
  "pallet-treasury",
+ "pallet-vesting",
  "parity-scale-codec",
  "serde",
  "sp-api",
@@ -3474,9 +3638,9 @@
 
 [[package]]
 name = "num-integer"
-version = "0.1.43"
+version = "0.1.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
+checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
 dependencies = [
  "autocfg 1.0.1",
  "num-traits",
@@ -3496,9 +3660,9 @@
 
 [[package]]
 name = "num-traits"
-version = "0.2.12"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
 dependencies = [
  "autocfg 1.0.1",
  "libm",
@@ -3533,9 +3697,9 @@
 
 [[package]]
 name = "object"
-version = "0.21.1"
+version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37fd5004feb2ce328a52b0b3d01dbf4ffff72583493900ed15f22d4111c51693"
+checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
 
 [[package]]
 name = "once_cell"
@@ -3548,11 +3712,11 @@
 
 [[package]]
 name = "once_cell"
-version = "1.4.1"
+version = "1.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
+checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
 dependencies = [
- "parking_lot 0.11.0",
+ "parking_lot 0.11.1",
 ]
 
 [[package]]
@@ -3585,7 +3749,7 @@
 [[package]]
 name = "pallet-aura"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -3604,7 +3768,7 @@
 [[package]]
 name = "pallet-authorship"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -3619,7 +3783,7 @@
 [[package]]
 name = "pallet-balances"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
@@ -3633,7 +3797,7 @@
 [[package]]
 name = "pallet-contracts"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "bitflags",
  "frame-support",
@@ -3654,7 +3818,7 @@
 [[package]]
 name = "pallet-contracts-primitives"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
  "sp-runtime",
@@ -3664,7 +3828,7 @@
 [[package]]
 name = "pallet-contracts-rpc"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "jsonrpc-core",
  "jsonrpc-core-client",
@@ -3683,7 +3847,7 @@
 [[package]]
 name = "pallet-contracts-rpc-runtime-api"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "pallet-contracts-primitives",
  "parity-scale-codec",
@@ -3695,7 +3859,7 @@
 [[package]]
 name = "pallet-finality-tracker"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -3711,7 +3875,7 @@
 [[package]]
 name = "pallet-grandpa"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
@@ -3754,7 +3918,7 @@
 [[package]]
 name = "pallet-randomness-collective-flip"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -3767,7 +3931,7 @@
 [[package]]
 name = "pallet-session"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -3787,7 +3951,7 @@
 [[package]]
 name = "pallet-sudo"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -3801,7 +3965,7 @@
 [[package]]
 name = "pallet-timestamp"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
@@ -3819,14 +3983,14 @@
 [[package]]
 name = "pallet-transaction-payment"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-support",
  "frame-system",
  "pallet-transaction-payment-rpc-runtime-api",
  "parity-scale-codec",
  "serde",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -3836,7 +4000,7 @@
 [[package]]
 name = "pallet-transaction-payment-rpc"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "jsonrpc-core",
  "jsonrpc-core-client",
@@ -3854,7 +4018,7 @@
 [[package]]
 name = "pallet-transaction-payment-rpc-runtime-api"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-support",
  "parity-scale-codec",
@@ -3867,7 +4031,7 @@
 [[package]]
 name = "pallet-treasury"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-support",
  "frame-system",
@@ -3879,6 +4043,20 @@
 ]
 
 [[package]]
+name = "pallet-vesting"
+version = "2.0.0"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
+dependencies = [
+ "enumflags2",
+ "frame-support",
+ "frame-system",
+ "parity-scale-codec",
+ "serde",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
 name = "parity-db"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3894,20 +4072,20 @@
 
 [[package]]
 name = "parity-multiaddr"
-version = "0.9.2"
+version = "0.9.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2165a93382a93de55868dcbfa11e4a8f99676a9164eee6a2b4a9479ad319c257"
+checksum = "43244a26dc1ddd3097216bb12eaa6cf8a07b060c72718d9ebd60fd297d6401df"
 dependencies = [
  "arrayref",
- "bs58",
+ "bs58 0.4.0",
  "byteorder 1.3.4",
  "data-encoding",
  "multihash",
  "percent-encoding 2.1.0",
  "serde",
  "static_assertions",
- "unsigned-varint 0.4.0",
- "url 2.1.1",
+ "unsigned-varint 0.5.1",
+ "url 2.2.0",
 ]
 
 [[package]]
@@ -3916,7 +4094,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7c740e5fbcb6847058b40ac7e5574766c6388f585e184d769910fe0d3a2ca861"
 dependencies = [
- "arrayvec 0.5.1",
+ "arrayvec 0.5.2",
  "bitvec",
  "byte-slice-cast",
  "parity-scale-codec-derive",
@@ -3952,7 +4130,7 @@
  "libc",
  "log",
  "mio-named-pipes",
- "miow 0.3.5",
+ "miow 0.3.6",
  "rand 0.7.3",
  "tokio 0.1.22",
  "tokio-named-pipes",
@@ -3972,7 +4150,7 @@
  "parity-util-mem-derive",
  "parking_lot 0.10.2",
  "primitive-types",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "winapi 0.3.9",
 ]
 
@@ -4008,7 +4186,7 @@
  "rand 0.7.3",
  "sha-1 0.8.2",
  "slab",
- "url 2.1.1",
+ "url 2.2.0",
 ]
 
 [[package]]
@@ -4050,13 +4228,13 @@
 
 [[package]]
 name = "parking_lot"
-version = "0.11.0"
+version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733"
+checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
 dependencies = [
  "instant",
- "lock_api 0.4.1",
- "parking_lot_core 0.8.0",
+ "lock_api 0.4.2",
+ "parking_lot_core 0.8.1",
 ]
 
 [[package]]
@@ -4079,7 +4257,7 @@
 checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
 dependencies = [
  "cfg-if 0.1.10",
- "cloudabi 0.0.3",
+ "cloudabi",
  "libc",
  "redox_syscall",
  "rustc_version",
@@ -4094,25 +4272,24 @@
 checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3"
 dependencies = [
  "cfg-if 0.1.10",
- "cloudabi 0.0.3",
+ "cloudabi",
  "libc",
  "redox_syscall",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "winapi 0.3.9",
 ]
 
 [[package]]
 name = "parking_lot_core"
-version = "0.8.0"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
+checksum = "d7c6d9b8427445284a09c55be860a15855ab580a417ccad9da88f5a06787ced0"
 dependencies = [
- "cfg-if 0.1.10",
- "cloudabi 0.1.0",
+ "cfg-if 1.0.0",
  "instant",
  "libc",
  "redox_syscall",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "winapi 0.3.9",
 ]
 
@@ -4180,7 +4357,16 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15"
 dependencies = [
- "pin-project-internal",
+ "pin-project-internal 0.4.27",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ccc2237c2c489783abd8c4c80e5450fc0e98644555b1364da68cc29aa151ca7"
+dependencies = [
+ "pin-project-internal 1.0.2",
 ]
 
 [[package]]
@@ -4195,10 +4381,27 @@
 ]
 
 [[package]]
+name = "pin-project-internal"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8e8d2bf0b23038a4424865103a4df472855692821aab4e4f5c3312d461d9e5f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b"
+
+[[package]]
 name = "pin-project-lite"
-version = "0.1.10"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e555d9e657502182ac97b539fb3dae8b79cda19e3e4f8ffb5e8de4f18df93c95"
+checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c"
 
 [[package]]
 name = "pin-utils"
@@ -4220,9 +4423,9 @@
 
 [[package]]
 name = "polling"
-version = "2.0.1"
+version = "2.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab773feb154f12c49ffcfd66ab8bdcf9a1843f950db48b0d8be9d4393783b058"
+checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4"
 dependencies = [
  "cfg-if 0.1.10",
  "libc",
@@ -4233,34 +4436,35 @@
 
 [[package]]
 name = "poly1305"
-version = "0.6.1"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22ce46de8e53ee414ca4d02bfefac75d8c12fba948b76622a40b4be34dfce980"
+checksum = "4b7456bc1ad2d4cf82b3a016be4c2ac48daf11bf990c1603ebd447fe6f30fca8"
 dependencies = [
+ "cpuid-bool 0.2.0",
  "universal-hash",
 ]
 
 [[package]]
 name = "polyval"
-version = "0.4.1"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5884790f1ce3553ad55fec37b5aaac5882e0e845a2612df744d6c85c9bf046c"
+checksum = "b4fd92d8e0c06d08525d2e2643cc2b5c80c69ae8eb12c18272d501cd7079ccc0"
 dependencies = [
- "cfg-if 0.1.10",
+ "cpuid-bool 0.2.0",
  "universal-hash",
 ]
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.9"
+version = "0.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20"
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
 
 [[package]]
 name = "primitive-types"
-version = "0.7.2"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c55c21c64d0eaa4d7ed885d959ef2d62d9e488c27c0e02d9aa5ce6c877b7d5f8"
+checksum = "7dd39dcacf71411ba488570da7bbc89b717225e46478b30ba99b92db6b149809"
 dependencies = [
  "fixed-hash",
  "impl-codec",
@@ -4303,9 +4507,9 @@
 
 [[package]]
 name = "proc-macro-hack"
-version = "0.5.18"
+version = "0.5.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598"
+checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
 
 [[package]]
 name = "proc-macro-nested"
@@ -4331,7 +4535,7 @@
  "cfg-if 0.1.10",
  "fnv",
  "lazy_static",
- "parking_lot 0.11.0",
+ "parking_lot 0.11.1",
  "regex",
  "thiserror",
 ]
@@ -4412,7 +4616,7 @@
 dependencies = [
  "futures-core",
  "futures-sink",
- "pin-project-lite",
+ "pin-project-lite 0.1.11",
 ]
 
 [[package]]
@@ -4459,7 +4663,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9"
 dependencies = [
- "cloudabi 0.0.3",
+ "cloudabi",
  "fuchsia-cprng",
  "libc",
  "rand_core 0.3.1",
@@ -4587,7 +4791,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
 dependencies = [
- "cloudabi 0.0.3",
+ "cloudabi",
  "fuchsia-cprng",
  "libc",
  "rand_core 0.4.2",
@@ -4642,25 +4846,25 @@
 
 [[package]]
 name = "rayon"
-version = "1.4.1"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcf6960dc9a5b4ee8d3e4c5787b4a112a8818e0290a42ff664ad60692fdf2032"
+checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
 dependencies = [
  "autocfg 1.0.1",
- "crossbeam-deque",
+ "crossbeam-deque 0.8.0",
  "either",
  "rayon-core",
 ]
 
 [[package]]
 name = "rayon-core"
-version = "1.8.1"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8c4fec834fb6e6d2dd5eece3c7b432a52f0ba887cf40e595190c4107edc08bf"
+checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
 dependencies = [
  "crossbeam-channel",
- "crossbeam-deque",
- "crossbeam-utils",
+ "crossbeam-deque 0.8.0",
+ "crossbeam-utils 0.8.1",
  "lazy_static",
  "num_cpus",
 ]
@@ -4693,18 +4897,18 @@
 
 [[package]]
 name = "ref-cast"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "745c1787167ddae5569661d5ffb8b25ae5fedbf46717eaa92d652221cec72623"
+checksum = "e17626b2f4bcf35b84bf379072a66e28cfe5c3c6ae58b38e4914bb8891dabece"
 dependencies = [
  "ref-cast-impl",
 ]
 
 [[package]]
 name = "ref-cast-impl"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d21b475ab879ef0e315ad99067fa25778c3b0377f57f1b00207448dac1a3144"
+checksum = "0c523ccaed8ac4b0288948849a350b37d3035827413c458b6a40ddb614bb4f72"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4719,14 +4923,14 @@
 dependencies = [
  "log",
  "rustc-hash",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
 ]
 
 [[package]]
 name = "regex"
-version = "1.4.1"
+version = "1.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8963b85b8ce3074fecffde43b4b0dded83ce2f367dc8d363afc56679f3ee820b"
+checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -4746,9 +4950,9 @@
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.20"
+version = "0.6.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cab7a364d15cde1e505267766a2d3c4e22a843e1a601f0fa7564c0f82ced11c"
+checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
 
 [[package]]
 name = "region"
@@ -4779,13 +4983,13 @@
 
 [[package]]
 name = "ring"
-version = "0.16.15"
+version = "0.16.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "952cd6b98c85bbc30efa1ba5783b8abf12fec8b3287ffa52605b9432313e34e4"
+checksum = "024a1e66fea74c66c66624ee5622a7ff0e4b73a13b4f5c326ddb50c708944226"
 dependencies = [
  "cc",
  "libc",
- "once_cell 1.4.1",
+ "once_cell 1.5.2",
  "spin",
  "untrusted",
  "web-sys",
@@ -4814,21 +5018,21 @@
 
 [[package]]
 name = "rust-argon2"
-version = "0.8.2"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19"
+checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb"
 dependencies = [
- "base64 0.12.3",
+ "base64 0.13.0",
  "blake2b_simd",
  "constant_time_eq",
- "crossbeam-utils",
+ "crossbeam-utils 0.8.1",
 ]
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.17"
+version = "0.1.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2610b7f643d18c87dff3b489950269617e6601a51f1f05aa5daefee36f64f0b"
+checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
 
 [[package]]
 name = "rustc-hash"
@@ -4882,8 +5086,8 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020"
 dependencies = [
- "futures 0.3.6",
- "pin-project",
+ "futures 0.3.8",
+ "pin-project 0.4.27",
  "static_assertions",
 ]
 
@@ -4904,30 +5108,19 @@
 
 [[package]]
 name = "salsa20"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2324b0e8c3bb9a586a571fdb3136f70e7e2c748de00a78043f86e0cff91f91fe"
-dependencies = [
- "byteorder 1.3.4",
- "salsa20-core",
- "stream-cipher 0.3.2",
-]
-
-[[package]]
-name = "salsa20-core"
-version = "0.2.3"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fe6cc1b9f5a5867853ade63099de70f042f7679e408d1ffe52821c9248e6e69"
+checksum = "c7f47b10fa80f6969bbbd9c8e7cc998f082979d402a9e10579e2303a87955395"
 dependencies = [
- "stream-cipher 0.3.2",
+ "stream-cipher",
 ]
 
 [[package]]
 name = "sc-basic-authorship"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-timer 3.0.2",
  "log",
  "parity-scale-codec",
@@ -4949,7 +5142,7 @@
 [[package]]
 name = "sc-block-builder"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
  "sc-client-api",
@@ -4966,7 +5159,7 @@
 [[package]]
 name = "sc-chain-spec"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "impl-trait-for-tuples",
  "parity-scale-codec",
@@ -4983,7 +5176,7 @@
 [[package]]
 name = "sc-chain-spec-derive"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "proc-macro-crate",
  "proc-macro2",
@@ -4994,7 +5187,7 @@
 [[package]]
 name = "sc-cli"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "ansi_term 0.12.1",
  "atty",
@@ -5002,7 +5195,8 @@
  "chrono",
  "derive_more",
  "fdlimit",
- "futures 0.3.6",
+ "flexi_logger",
+ "futures 0.3.8",
  "hex",
  "lazy_static",
  "libp2p",
@@ -5034,7 +5228,7 @@
  "structopt",
  "substrate-prometheus-endpoint",
  "time",
- "tokio 0.2.22",
+ "tokio 0.2.24",
  "tracing",
  "tracing-log",
  "tracing-subscriber",
@@ -5043,11 +5237,11 @@
 [[package]]
 name = "sc-client-api"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
  "fnv",
- "futures 0.3.6",
+ "futures 0.3.8",
  "hash-db",
  "hex-literal",
  "kvdb",
@@ -5079,7 +5273,7 @@
 [[package]]
 name = "sc-client-db"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "blake2-rfc",
  "hash-db",
@@ -5109,7 +5303,7 @@
 [[package]]
 name = "sc-consensus"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "sc-client-api",
  "sp-blockchain",
@@ -5120,10 +5314,10 @@
 [[package]]
 name = "sc-consensus-aura"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-timer 3.0.2",
  "log",
  "parity-scale-codec",
@@ -5151,9 +5345,9 @@
 [[package]]
 name = "sc-consensus-slots"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-timer 3.0.2",
  "log",
  "parity-scale-codec",
@@ -5174,7 +5368,7 @@
 [[package]]
 name = "sc-executor"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
  "lazy_static",
@@ -5202,7 +5396,7 @@
 [[package]]
 name = "sc-executor-common"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
  "log",
@@ -5219,7 +5413,7 @@
 [[package]]
 name = "sc-executor-wasmi"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "log",
  "parity-scale-codec",
@@ -5234,7 +5428,7 @@
 [[package]]
 name = "sc-executor-wasmtime"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "log",
  "parity-scale-codec",
@@ -5252,17 +5446,17 @@
 [[package]]
 name = "sc-finality-grandpa"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
  "finality-grandpa",
  "fork-tree",
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-timer 3.0.2",
  "log",
  "parity-scale-codec",
  "parking_lot 0.10.2",
- "pin-project",
+ "pin-project 0.4.27",
  "rand 0.7.3",
  "sc-block-builder",
  "sc-client-api",
@@ -5289,10 +5483,10 @@
 [[package]]
 name = "sc-informant"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "ansi_term 0.12.1",
- "futures 0.3.6",
+ "futures 0.3.8",
  "log",
  "parity-util-mem",
  "sc-client-api",
@@ -5307,7 +5501,7 @@
 [[package]]
 name = "sc-keystore"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
  "hex",
@@ -5317,13 +5511,13 @@
  "serde_json",
  "sp-application-crypto",
  "sp-core",
- "subtle 2.3.0",
+ "subtle 2.4.0",
 ]
 
 [[package]]
 name = "sc-light"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "hash-db",
  "lazy_static",
@@ -5342,19 +5536,19 @@
 [[package]]
 name = "sc-network"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "async-std",
  "async-trait",
  "bitflags",
- "bs58",
+ "bs58 0.3.1",
  "bytes 0.5.6",
  "derive_more",
  "either",
  "erased-serde",
  "fnv",
  "fork-tree",
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-timer 3.0.2",
  "futures_codec",
  "hex",
@@ -5367,7 +5561,7 @@
  "nohash-hasher",
  "parity-scale-codec",
  "parking_lot 0.10.2",
- "pin-project",
+ "pin-project 0.4.27",
  "prost",
  "prost-build",
  "rand 0.7.3",
@@ -5396,9 +5590,9 @@
 [[package]]
 name = "sc-network-gossip"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-timer 3.0.2",
  "libp2p",
  "log",
@@ -5411,13 +5605,13 @@
 [[package]]
 name = "sc-offchain"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "bytes 0.5.6",
  "fnv",
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-timer 3.0.2",
- "hyper 0.13.8",
+ "hyper 0.13.9",
  "hyper-rustls",
  "log",
  "num_cpus",
@@ -5438,9 +5632,9 @@
 [[package]]
 name = "sc-peerset"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "libp2p",
  "log",
  "serde_json",
@@ -5451,7 +5645,7 @@
 [[package]]
 name = "sc-proposer-metrics"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "log",
  "substrate-prometheus-endpoint",
@@ -5460,9 +5654,9 @@
 [[package]]
 name = "sc-rpc"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "hash-db",
  "jsonrpc-core",
  "jsonrpc-pubsub",
@@ -5492,10 +5686,10 @@
 [[package]]
 name = "sc-rpc-api"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
- "futures 0.3.6",
+ "futures 0.3.8",
  "jsonrpc-core",
  "jsonrpc-core-client",
  "jsonrpc-derive",
@@ -5516,7 +5710,7 @@
 [[package]]
 name = "sc-rpc-server"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "futures 0.1.30",
  "jsonrpc-core",
@@ -5534,13 +5728,13 @@
 [[package]]
 name = "sc-service"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
  "directories",
  "exit-future",
  "futures 0.1.30",
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-timer 3.0.2",
  "hash-db",
  "jsonrpc-core",
@@ -5550,7 +5744,7 @@
  "parity-scale-codec",
  "parity-util-mem",
  "parking_lot 0.10.2",
- "pin-project",
+ "pin-project 0.4.27",
  "rand 0.7.3",
  "sc-block-builder",
  "sc-chain-spec",
@@ -5596,7 +5790,7 @@
 [[package]]
 name = "sc-state-db"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "log",
  "parity-scale-codec",
@@ -5610,14 +5804,14 @@
 [[package]]
 name = "sc-telemetry"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-timer 3.0.2",
  "libp2p",
  "log",
  "parking_lot 0.10.2",
- "pin-project",
+ "pin-project 0.4.27",
  "rand 0.7.3",
  "serde",
  "slog",
@@ -5631,7 +5825,7 @@
 [[package]]
 name = "sc-tracing"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "erased-serde",
  "log",
@@ -5650,10 +5844,10 @@
 [[package]]
 name = "sc-transaction-graph"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
- "futures 0.3.6",
+ "futures 0.3.8",
  "linked-hash-map",
  "log",
  "parity-util-mem",
@@ -5671,10 +5865,10 @@
 [[package]]
 name = "sc-transaction-pool"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-diagnose",
  "intervalier",
  "log",
@@ -5711,14 +5905,14 @@
 checksum = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862"
 dependencies = [
  "arrayref",
- "arrayvec 0.5.1",
+ "arrayvec 0.5.2",
  "curve25519-dalek 2.1.0",
  "getrandom 0.1.15",
  "merlin",
  "rand 0.7.3",
  "rand_core 0.5.1",
  "sha2 0.8.2",
- "subtle 2.3.0",
+ "subtle 2.4.0",
  "zeroize",
 ]
 
@@ -5751,9 +5945,9 @@
 
 [[package]]
 name = "scroll_derive"
-version = "0.10.3"
+version = "0.10.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6dfde5d1531034db129e95c76ac857e2baecea3443579d493d02224950b0fb6d"
+checksum = "b12bd20b94c7cdfda8c7ba9b92ad0d9a56e3fa018c25fca83b51aa664c9b4c0d"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5819,18 +6013,18 @@
 
 [[package]]
 name = "serde"
-version = "1.0.117"
+version = "1.0.118"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
+checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.117"
+version = "1.0.118"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
+checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5839,9 +6033,9 @@
 
 [[package]]
 name = "serde_json"
-version = "1.0.59"
+version = "1.0.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
+checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779"
 dependencies = [
  "itoa",
  "ryu",
@@ -5862,13 +6056,13 @@
 
 [[package]]
 name = "sha-1"
-version = "0.9.1"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "170a36ea86c864a3f16dd2687712dd6646f7019f301e57537c7f4dc9f5916770"
+checksum = "ce3cdf1b5e620a498ee6f2a171885ac7e22f0e12089ec4b3d22b84921792507c"
 dependencies = [
  "block-buffer 0.9.0",
- "cfg-if 0.1.10",
- "cpuid-bool",
+ "cfg-if 1.0.0",
+ "cpuid-bool 0.1.2",
  "digest 0.9.0",
  "opaque-debug 0.3.0",
 ]
@@ -5887,28 +6081,15 @@
 
 [[package]]
 name = "sha2"
-version = "0.9.1"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1"
+checksum = "6e7aab86fe2149bad8c507606bdb3f4ef5e7b2380eb92350f56122cca72a42a8"
 dependencies = [
  "block-buffer 0.9.0",
- "cfg-if 0.1.10",
- "cpuid-bool",
+ "cfg-if 1.0.0",
+ "cpuid-bool 0.1.2",
  "digest 0.9.0",
  "opaque-debug 0.3.0",
-]
-
-[[package]]
-name = "sha3"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf"
-dependencies = [
- "block-buffer 0.7.3",
- "byte-tools",
- "digest 0.8.1",
- "keccak",
- "opaque-debug 0.2.3",
 ]
 
 [[package]]
@@ -5925,11 +6106,12 @@
 
 [[package]]
 name = "sharded-slab"
-version = "0.0.9"
+version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06d5a3f5166fb5b42a5439f2eee8b9de149e235961e3eb21c5808fc3ea17ff3e"
+checksum = "7b4921be914e16899a80adefb821f8ddb7974e3f1250223575a44ed994882127"
 dependencies = [
  "lazy_static",
+ "loom",
 ]
 
 [[package]]
@@ -5939,12 +6121,21 @@
 checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
 
 [[package]]
+name = "signal-hook"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "604508c1418b99dfe1925ca9224829bb2a8a9a04dda655cc01fcad46f4ab05ed"
+dependencies = [
+ "libc",
+ "signal-hook-registry",
+]
+
+[[package]]
 name = "signal-hook-registry"
-version = "1.2.1"
+version = "1.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035"
+checksum = "ce32ea0c6c56d5eacaeb814fbed9960547021d3edd010ded1425f180536b20ab"
 dependencies = [
- "arc-swap",
  "libc",
 ]
 
@@ -5962,9 +6153,9 @@
 
 [[package]]
 name = "slog"
-version = "2.5.2"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cc9c640a4adbfbcc11ffb95efe5aa7af7309e002adab54b185507dbf2377b99"
+checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06"
 dependencies = [
  "erased-serde",
 ]
@@ -6015,9 +6206,9 @@
 
 [[package]]
 name = "smallvec"
-version = "1.4.2"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"
+checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75"
 
 [[package]]
 name = "snow"
@@ -6032,20 +6223,19 @@
  "rand_core 0.5.1",
  "ring",
  "rustc_version",
- "sha2 0.9.1",
- "subtle 2.3.0",
+ "sha2 0.9.2",
+ "subtle 2.4.0",
  "x25519-dalek 1.1.0",
 ]
 
 [[package]]
 name = "socket2"
-version = "0.3.15"
+version = "0.3.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44"
+checksum = "97e0e9fd577458a4f61fb91fcb559ea2afecc54c934119421f9f5d3d5b1a1057"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "libc",
- "redox_syscall",
  "winapi 0.3.9",
 ]
 
@@ -6058,17 +6248,17 @@
  "base64 0.12.3",
  "bytes 0.5.6",
  "flate2",
- "futures 0.3.6",
+ "futures 0.3.8",
  "httparse",
  "log",
  "rand 0.7.3",
- "sha-1 0.9.1",
+ "sha-1 0.9.2",
 ]
 
 [[package]]
 name = "sp-allocator"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
  "log",
@@ -6080,7 +6270,7 @@
 [[package]]
 name = "sp-api"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "hash-db",
  "parity-scale-codec",
@@ -6095,7 +6285,7 @@
 [[package]]
 name = "sp-api-proc-macro"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "blake2-rfc",
  "proc-macro-crate",
@@ -6107,7 +6297,7 @@
 [[package]]
 name = "sp-application-crypto"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
  "serde",
@@ -6119,7 +6309,7 @@
 [[package]]
 name = "sp-arithmetic"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "integer-sqrt",
  "num-traits",
@@ -6132,7 +6322,7 @@
 [[package]]
 name = "sp-authorship"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
  "sp-inherents",
@@ -6143,7 +6333,7 @@
 [[package]]
 name = "sp-block-builder"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
  "sp-api",
@@ -6155,7 +6345,7 @@
 [[package]]
 name = "sp-blockchain"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
  "log",
@@ -6172,7 +6362,7 @@
 [[package]]
 name = "sp-chain-spec"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "serde",
  "serde_json",
@@ -6181,10 +6371,10 @@
 [[package]]
 name = "sp-consensus"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-timer 3.0.2",
  "libp2p",
  "log",
@@ -6207,7 +6397,7 @@
 [[package]]
 name = "sp-consensus-aura"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
  "sp-api",
@@ -6221,7 +6411,7 @@
 [[package]]
 name = "sp-consensus-slots"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
  "sp-runtime",
@@ -6230,7 +6420,7 @@
 [[package]]
 name = "sp-core"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "base58",
  "blake2-rfc",
@@ -6238,7 +6428,7 @@
  "derive_more",
  "dyn-clonable",
  "ed25519-dalek",
- "futures 0.3.6",
+ "futures 0.3.8",
  "hash-db",
  "hash256-std-hasher",
  "hex",
@@ -6274,7 +6464,7 @@
 [[package]]
 name = "sp-database"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "kvdb",
  "parking_lot 0.10.2",
@@ -6283,7 +6473,7 @@
 [[package]]
 name = "sp-debug-derive"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -6293,7 +6483,7 @@
 [[package]]
 name = "sp-externalities"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "environmental",
  "parity-scale-codec",
@@ -6304,7 +6494,7 @@
 [[package]]
 name = "sp-finality-grandpa"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "finality-grandpa",
  "log",
@@ -6320,7 +6510,7 @@
 [[package]]
 name = "sp-finality-tracker"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
  "sp-inherents",
@@ -6330,7 +6520,7 @@
 [[package]]
 name = "sp-inherents"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
  "parity-scale-codec",
@@ -6342,9 +6532,9 @@
 [[package]]
 name = "sp-io"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "hash-db",
  "libsecp256k1",
  "log",
@@ -6365,7 +6555,7 @@
 [[package]]
 name = "sp-keyring"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "lazy_static",
  "sp-core",
@@ -6376,7 +6566,7 @@
 [[package]]
 name = "sp-offchain"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "sp-api",
  "sp-core",
@@ -6386,7 +6576,7 @@
 [[package]]
 name = "sp-panic-handler"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "backtrace",
  "log",
@@ -6395,7 +6585,7 @@
 [[package]]
 name = "sp-rpc"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "serde",
  "sp-core",
@@ -6404,7 +6594,7 @@
 [[package]]
 name = "sp-runtime"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "either",
  "hash256-std-hasher",
@@ -6426,7 +6616,7 @@
 [[package]]
 name = "sp-runtime-interface"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
  "primitive-types",
@@ -6442,7 +6632,7 @@
 [[package]]
 name = "sp-runtime-interface-proc-macro"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "Inflector",
  "proc-macro-crate",
@@ -6454,7 +6644,7 @@
 [[package]]
 name = "sp-sandbox"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
  "sp-core",
@@ -6467,7 +6657,7 @@
 [[package]]
 name = "sp-serializer"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "serde",
  "serde_json",
@@ -6476,7 +6666,7 @@
 [[package]]
 name = "sp-session"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
  "sp-api",
@@ -6489,7 +6679,7 @@
 [[package]]
 name = "sp-staking"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "parity-scale-codec",
  "sp-runtime",
@@ -6499,7 +6689,7 @@
 [[package]]
 name = "sp-state-machine"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "hash-db",
  "log",
@@ -6507,7 +6697,7 @@
  "parity-scale-codec",
  "parking_lot 0.10.2",
  "rand 0.7.3",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "sp-core",
  "sp-externalities",
  "sp-panic-handler",
@@ -6520,12 +6710,12 @@
 [[package]]
 name = "sp-std"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 
 [[package]]
 name = "sp-storage"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "impl-serde",
  "parity-scale-codec",
@@ -6538,7 +6728,7 @@
 [[package]]
 name = "sp-timestamp"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "impl-trait-for-tuples",
  "parity-scale-codec",
@@ -6552,7 +6742,7 @@
 [[package]]
 name = "sp-tracing"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "log",
  "parity-scale-codec",
@@ -6565,10 +6755,10 @@
 [[package]]
 name = "sp-transaction-pool"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "derive_more",
- "futures 0.3.6",
+ "futures 0.3.8",
  "log",
  "parity-scale-codec",
  "serde",
@@ -6580,7 +6770,7 @@
 [[package]]
 name = "sp-trie"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "hash-db",
  "memory-db",
@@ -6594,9 +6784,9 @@
 [[package]]
 name = "sp-utils"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "futures-core",
  "futures-timer 3.0.2",
  "lazy_static",
@@ -6606,7 +6796,7 @@
 [[package]]
 name = "sp-version"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "impl-serde",
  "parity-scale-codec",
@@ -6618,7 +6808,7 @@
 [[package]]
 name = "sp-wasm-interface"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "impl-trait-for-tuples",
  "parity-scale-codec",
@@ -6651,15 +6841,6 @@
 checksum = "10102ac8d55e35db2b3fafc26f81ba8647da2e15879ab686a67e6d19af2685e8"
 dependencies = [
  "rand 0.5.6",
-]
-
-[[package]]
-name = "stream-cipher"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8131256a5896cabcf5eb04f4d6dacbe1aefda854b0d9896e09cb58829ec5638c"
-dependencies = [
- "generic-array 0.12.3",
 ]
 
 [[package]]
@@ -6689,9 +6870,9 @@
 
 [[package]]
 name = "structopt"
-version = "0.3.20"
+version = "0.3.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "126d630294ec449fae0b16f964e35bf3c74f940da9dca17ee9b905f7b3112eb8"
+checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c"
 dependencies = [
  "clap",
  "lazy_static",
@@ -6700,9 +6881,9 @@
 
 [[package]]
 name = "structopt-derive"
-version = "0.4.13"
+version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65e51c492f9e23a220534971ff5afc14037289de430e3c83f9daf6a1b6ae91e8"
+checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90"
 dependencies = [
  "heck",
  "proc-macro-error",
@@ -6748,7 +6929,7 @@
 [[package]]
 name = "substrate-build-script-utils"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "platforms",
 ]
@@ -6756,10 +6937,10 @@
 [[package]]
 name = "substrate-frame-rpc-system"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "frame-system-rpc-runtime-api",
- "futures 0.3.6",
+ "futures 0.3.8",
  "jsonrpc-core",
  "jsonrpc-core-client",
  "jsonrpc-derive",
@@ -6779,15 +6960,15 @@
 [[package]]
 name = "substrate-prometheus-endpoint"
 version = "0.8.0"
-source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#a200cdb93c6af5763b9c7bf313fa708764ac88ca"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
 dependencies = [
  "async-std",
  "derive_more",
  "futures-util",
- "hyper 0.13.8",
+ "hyper 0.13.9",
  "log",
  "prometheus",
- "tokio 0.2.22",
+ "tokio 0.2.24",
 ]
 
 [[package]]
@@ -6804,15 +6985,15 @@
 
 [[package]]
 name = "subtle"
-version = "2.3.0"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd"
+checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
 
 [[package]]
 name = "syn"
-version = "1.0.44"
+version = "1.0.54"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e03e57e4fcbfe7749842d53e24ccb9aa12b7252dbe5e91d2acad31834c8b8fdd"
+checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -6859,9 +7040,9 @@
 
 [[package]]
 name = "termcolor"
-version = "1.1.0"
+version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
+checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
 dependencies = [
  "winapi-util",
 ]
@@ -6877,18 +7058,18 @@
 
 [[package]]
 name = "thiserror"
-version = "1.0.21"
+version = "1.0.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "318234ffa22e0920fe9a40d7b8369b5f649d490980cf7aadcf1eb91594869b42"
+checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.21"
+version = "1.0.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab"
+checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -6932,7 +7113,7 @@
 dependencies = [
  "failure",
  "hmac",
- "once_cell 1.4.1",
+ "once_cell 1.5.2",
  "pbkdf2",
  "rand 0.7.3",
  "rustc-hash",
@@ -6951,9 +7132,18 @@
 
 [[package]]
 name = "tinyvec"
-version = "0.3.4"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf8dbc19eb42fba10e8feaaec282fb50e2c14b2726d6301dbfeed0f73306a6f"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117"
+checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
 
 [[package]]
 name = "tokio"
@@ -6981,9 +7171,9 @@
 
 [[package]]
 name = "tokio"
-version = "0.2.22"
+version = "0.2.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd"
+checksum = "099837d3464c16a808060bb3f02263b412f6fafcb5d01c533d309985fbeebe48"
 dependencies = [
  "bytes 0.5.6",
  "fnv",
@@ -6995,7 +7185,7 @@
  "mio",
  "mio-uds",
  "num_cpus",
- "pin-project-lite",
+ "pin-project-lite 0.1.11",
  "signal-hook-registry",
  "slab",
  "winapi 0.3.9",
@@ -7039,7 +7229,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671"
 dependencies = [
- "crossbeam-utils",
+ "crossbeam-utils 0.7.2",
  "futures 0.1.30",
 ]
 
@@ -7095,7 +7285,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351"
 dependencies = [
- "crossbeam-utils",
+ "crossbeam-utils 0.7.2",
  "futures 0.1.30",
  "lazy_static",
  "log",
@@ -7116,7 +7306,7 @@
 dependencies = [
  "futures-core",
  "rustls",
- "tokio 0.2.22",
+ "tokio 0.2.24",
  "webpki",
 ]
 
@@ -7170,9 +7360,9 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89"
 dependencies = [
- "crossbeam-deque",
+ "crossbeam-deque 0.7.3",
  "crossbeam-queue",
- "crossbeam-utils",
+ "crossbeam-utils 0.7.2",
  "futures 0.1.30",
  "lazy_static",
  "log",
@@ -7187,7 +7377,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296"
 dependencies = [
- "crossbeam-utils",
+ "crossbeam-utils 0.7.2",
  "futures 0.1.30",
  "slab",
  "tokio-executor 0.1.10",
@@ -7236,8 +7426,8 @@
  "futures-core",
  "futures-sink",
  "log",
- "pin-project-lite",
- "tokio 0.2.22",
+ "pin-project-lite 0.1.11",
+ "tokio 0.2.24",
 ]
 
 [[package]]
@@ -7257,13 +7447,13 @@
 
 [[package]]
 name = "tracing"
-version = "0.1.21"
+version = "0.1.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27"
+checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "log",
- "pin-project-lite",
+ "pin-project-lite 0.2.0",
  "tracing-attributes",
  "tracing-core",
 ]
@@ -7289,6 +7479,16 @@
 ]
 
 [[package]]
+name = "tracing-futures"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c"
+dependencies = [
+ "pin-project 0.4.27",
+ "tracing",
+]
+
+[[package]]
 name = "tracing-log"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -7311,9 +7511,9 @@
 
 [[package]]
 name = "tracing-subscriber"
-version = "0.2.13"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ef0a5e15477aa303afbfac3a44cba9b6430fdaad52423b1e6c0dbbe28c3eedd"
+checksum = "a1fa8f0c8f4c594e4fc9debc1990deab13238077271ba84dd853d54902ee3401"
 dependencies = [
  "ansi_term 0.12.1",
  "chrono",
@@ -7323,7 +7523,7 @@
  "serde",
  "serde_json",
  "sharded-slab",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "thread_local",
  "tracing",
  "tracing-core",
@@ -7341,7 +7541,7 @@
  "hashbrown 0.8.2",
  "log",
  "rustc-hex",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
 ]
 
 [[package]]
@@ -7408,18 +7608,18 @@
 
 [[package]]
 name = "unicode-normalization"
-version = "0.1.13"
+version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977"
+checksum = "a13e63ab62dbe32aeee58d1c5408d35c36c392bba5d9d3142287219721afe606"
 dependencies = [
  "tinyvec",
 ]
 
 [[package]]
 name = "unicode-segmentation"
-version = "1.6.0"
+version = "1.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
+checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
 
 [[package]]
 name = "unicode-width"
@@ -7440,7 +7640,7 @@
 checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402"
 dependencies = [
  "generic-array 0.14.4",
- "subtle 2.3.0",
+ "subtle 2.4.0",
 ]
 
 [[package]]
@@ -7484,10 +7684,11 @@
 
 [[package]]
 name = "url"
-version = "2.1.1"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
+checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e"
 dependencies = [
+ "form_urlencoded",
  "idna 0.2.0",
  "matches",
  "percent-encoding 2.1.0",
@@ -7495,9 +7696,9 @@
 
 [[package]]
 name = "vcpkg"
-version = "0.2.10"
+version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c"
+checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
 
 [[package]]
 name = "vec-arena"
@@ -7564,19 +7765,19 @@
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.68"
+version = "0.2.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42"
+checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "wasm-bindgen-macro",
 ]
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.68"
+version = "0.2.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68"
+checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62"
 dependencies = [
  "bumpalo",
  "lazy_static",
@@ -7589,11 +7790,11 @@
 
 [[package]]
 name = "wasm-bindgen-futures"
-version = "0.4.18"
+version = "0.4.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da"
+checksum = "1fe9756085a84584ee9457a002b7cdfe0bfff169f45d2591d8be1345a6780e35"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "js-sys",
  "wasm-bindgen",
  "web-sys",
@@ -7601,9 +7802,9 @@
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.68"
+version = "0.2.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038"
+checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -7611,9 +7812,9 @@
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.68"
+version = "0.2.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe"
+checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -7624,9 +7825,9 @@
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.68"
+version = "0.2.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307"
+checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158"
 
 [[package]]
 name = "wasm-timer"
@@ -7634,9 +7835,9 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "js-sys",
- "parking_lot 0.11.0",
+ "parking_lot 0.11.1",
  "pin-utils",
  "wasm-bindgen",
  "wasm-bindgen-futures",
@@ -7692,7 +7893,7 @@
  "log",
  "region",
  "rustc-demangle",
- "smallvec 1.4.2",
+ "smallvec 1.5.1",
  "target-lexicon",
  "wasmparser 0.59.0",
  "wasmtime-environ",
@@ -7825,7 +8026,7 @@
  "lazy_static",
  "libc",
  "log",
- "memoffset",
+ "memoffset 0.5.6",
  "more-asserts",
  "region",
  "thiserror",
@@ -7835,27 +8036,27 @@
 
 [[package]]
 name = "wast"
-version = "26.0.0"
+version = "30.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d54b3678343bfdf1768c16308a4b53823b70f7bb148d3d38225123d4306ec731"
+checksum = "9b79907b22f740634810e882d8d1d9d0f9563095a8ab94e786e370242bff5cd2"
 dependencies = [
  "leb128",
 ]
 
 [[package]]
 name = "wat"
-version = "1.0.27"
+version = "1.0.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26b2dccbce4d0e14875091846e110a2369267b18ddd0d6423479b88dad914d71"
+checksum = "a8279a02835bf12e61ed2b3c3cbc6ecf9918762fd97e036917c11a09ec20ca44"
 dependencies = [
  "wast",
 ]
 
 [[package]]
 name = "web-sys"
-version = "0.3.45"
+version = "0.3.46"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d"
+checksum = "222b1ef9334f92a21d3fb53dc3fd80f30836959a90f9274a626d7e06315ba3c3"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
@@ -7863,9 +8064,9 @@
 
 [[package]]
 name = "webpki"
-version = "0.21.3"
+version = "0.21.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab146130f5f790d45f82aeeb09e55a256573373ec64409fc19a6fb82fb1032ae"
+checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea"
 dependencies = [
  "ring",
  "untrusted",
@@ -7891,9 +8092,9 @@
 
 [[package]]
 name = "wepoll-sys"
-version = "3.0.0"
+version = "3.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "142bc2cba3fe88be1a8fcb55c727fa4cd5b0cf2d7438722792e22f26f04bc1e0"
+checksum = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff"
 dependencies = [
  "cc",
 ]
@@ -7988,19 +8189,25 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9aeb8c4043cac71c3c299dff107171c220d179492350ea198e109a414981b83c"
 dependencies = [
- "futures 0.3.6",
+ "futures 0.3.8",
  "log",
  "nohash-hasher",
- "parking_lot 0.11.0",
+ "parking_lot 0.11.1",
  "rand 0.7.3",
  "static_assertions",
 ]
 
 [[package]]
+name = "yansi"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71"
+
+[[package]]
 name = "zeroize"
-version = "1.1.1"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f33972566adbd2d3588b0491eb94b98b43695c4ef897903470ede4f3f5a28a"
+checksum = "81a974bcdd357f0dca4d41677db03436324d45a4c9ed2d0b873a5a360ce41c36"
 dependencies = [
  "zeroize_derive",
 ]
@@ -8019,18 +8226,18 @@
 
 [[package]]
 name = "zstd"
-version = "0.5.3+zstd.1.4.5"
+version = "0.5.4+zstd.1.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01b32eaf771efa709e8308605bbf9319bf485dc1503179ec0469b611937c0cd8"
+checksum = "69996ebdb1ba8b1517f61387a883857818a66c8a295f487b1ffd8fd9d2c82910"
 dependencies = [
  "zstd-safe",
 ]
 
 [[package]]
 name = "zstd-safe"
-version = "2.0.5+zstd.1.4.5"
+version = "2.0.6+zstd.1.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cfb642e0d27f64729a639c52db457e0ae906e7bc6f5fe8f5c453230400f1055"
+checksum = "98aa931fb69ecee256d44589d19754e61851ae4769bf963b385119b1cc37a49e"
 dependencies = [
  "libc",
  "zstd-sys",
@@ -8038,9 +8245,9 @@
 
 [[package]]
 name = "zstd-sys"
-version = "1.4.17+zstd.1.4.5"
+version = "1.4.18+zstd.1.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b89249644df056b522696b1bb9e7c18c87e8ffa3e2f0dc3b0155875d6498f01b"
+checksum = "a1e6e8778706838f43f771d80d37787cb2fe06dafe89dd3aebaf6721b9eaec81"
 dependencies = [
  "cc",
  "glob",
modifiedLICENSEdiffbeforeafterboth
--- a/LICENSE
+++ b/LICENSE
@@ -1,24 +1,15 @@
-This is free and unencumbered software released into the public domain.
-
-Anyone is free to copy, modify, publish, use, compile, sell, or
-distribute this software, either in source code form or as a compiled
-binary, for any purpose, commercial or non-commercial, and by any
-means.
-
-In jurisdictions that recognize copyright laws, the author or authors
-of this software dedicate any and all copyright interest in the
-software to the public domain. We make this dedication for the benefit
-of the public at large and to the detriment of our heirs and
-successors. We intend this dedication to be an overt act of
-relinquishment in perpetuity of all present and future rights to this
-software under copyright law.
+USETECH PROFESSIONAL CONFIDENTIAL
+__________________
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
+ [2019] - [2020] UseTech Professional LTD. 
+ All Rights Reserved.
 
-For more information, please refer to <http://unlicense.org>
+NOTICE:  All information contained herein is, and remains
+the property of UseTech Professional LTD. and its suppliers,
+if any. The intellectual and technical concepts contained
+herein are proprietary to UseTech Professional LTD.
+and its suppliers and may be covered by U.S. and Foreign Patents,
+patents in process, and are protected by trade secret or copyright law.
+Dissemination of this information or reproduction of this material
+is strictly forbidden unless prior written permission is obtained
+from UseTech Professional LTD..
modifiedREADME.mddiffbeforeafterboth
--- a/README.md
+++ b/README.md
@@ -52,28 +52,27 @@
 
 2. Remove all installed toolchains with `rustup toolchain list` and `rustup toolchain uninstall <toolchain>`.
 
-3. Install Rust Toolchain 1.44.0:
+3. Install Toolchain and make it default:
 
 ```bash
-rustup install 1.44.0
+rustup toolchain install nightly-2020-10-01
+rustup default nightly-2020-10-01
 ```
 
-4. Make it default (actual toochain version may be different, so do a `rustup toolchain list` first)
+4. Add wasm target for default toolchain:
+
 ```bash
-rustup toolchain list
-rustup default 1.44.0-x86_64-unknown-linux-gnu
+rustup target add wasm32-unknown-unknown
 ```
 
-5. Install nightly toolchain and add wasm target for it:
-
+5. Build:
 ```bash
-rustup toolchain install nightly-2020-05-01
-rustup target add wasm32-unknown-unknown --toolchain nightly-2020-05-01-x86_64-unknown-linux-gnu
+cargo build
 ```
 
-6. Build:
+optionally, build in release:
 ```bash
-cargo build
+cargo build --release
 ```
 
 ## Run
@@ -134,4 +133,8 @@
 
 ## UI custom types
 
-Moved to [runtime_types.json](./runtime_types.json).
\ No newline at end of file
+Moved to [runtime_types.json](./runtime_types.json).
+
+## Running Integration Tests
+
+See [tests/README.md](./tests/README.md).
\ No newline at end of file
addeddoc/builders_walk_through.mddiffbeforeafterboth
--- /dev/null
+++ b/doc/builders_walk_through.md
@@ -0,0 +1,244 @@
+# Builders Program Walk-Through
+
+This document walks through current state of Uniquch Chain as of end of October 2020.
+
+## Unique Chain Source code
+
+Unique chain is a substrate based chain, which mainly consists of NFT pallet (developed by Unique Network) and Smart Contracts pallet.
+
+As of now, it is based off Substrate 2.0 release and supports Ink! 3.0 smart contracts.
+
+[Unique Chain](https://github.com/usetech-llc/nft_private)
+
+### Unique TestNet
+
+The TestNet public node is avaiable at wss://unique.usetech.com. It connects to the standard AppsUI (works best with our version of AppsUI, see below, but connection can be still tested with Polkadot.js.org):
+
+1. Open the [Apps UI](https://polkadot.js.org/apps/#)
+2. Click on the network icon in the top left corner
+3. Scroll down the list and input `wss://unique.usetech.com` under "custom endpoint"
+4. After connection is established, copy these [UI Custom Types](https://github.com/usetech-llc/nft_parachain#ui-custom-types) and paste them in [Developer Settings](https://polkadot.js.org/apps/#/settings/developer). Hit "Save" button.
+5. Now the NFT node is connected with AppsUI. 
+6. Go to [Chain State](https://polkadot.js.org/apps/#/chainstate) and verify that NFT pallet is visible and you can read information from it.
+7. For example, select nft -> collection, and enter collection ID 4 (for SubstraPunks) and click "+" button. You will see the collection properties such as UTF-16 encoded collection name and description, UTF-8 encoded token prefix, the size of custom data, etc.
+
+#### Getting some Unique Tokens
+
+1. Install Polkadot{.js} extension if you don't have it already installed. Here are the links for [Chrome](https://chrome.google.com/webstore/detail/polkadot%7Bjs%7D-extension/mopnmbcafieddcagagdcbnhejhlodfdd) and [Firefox](https://addons.mozilla.org/en-US/firefox/addon/polkadot-js-extension/) extensions.
+2. Create an address
+3. Use Unique Faucet Telegram bot: @UniqueFaucetBot
+
+### Smart Contracts Pallet
+
+1. Open [Contracts](https://polkadot.js.org/apps/#/contracts) tab. It only appears in the UI when Smart Contracts pallet is included in the runtime.
+2. Additionally, we can find an existing smart contract. Click on "Add an existing contract" link.
+3. Input this contract address: `5GdNqKMv4Sszq3SRd3TkXNa6a9ct4D3nXvtTWTFR7rTyccVJ`
+4. Input any contract name, for example `Claim Substrapunks`
+5. Download and drag-and-drop this [metadata.json](https://github.com/usetech-llc/substrapunks/releases/download/v1.0.2/metadata.json) file into contract ABI field.
+6. Click Save. The contract appears in the page. If the contract did not exist at that address, the UI would display an error message: "Unable to find deployed contract code at the specified address".
+
+### Integration Between Smart Contracts and NFT Pallet
+
+#### TestNet
+
+This is one of the most technically challenging parts. The pre-RC4 versions of Substrate did not function properly when we tried to use `ext_dispatch_call` to dispatch a runtime call to NFT pallet from Contracts pallet, and RC4 had the `ext_dispatch_call` already removed to "free space" for some friendlier way of interaction between pallets, that was not yet implemented. Thanks to Alexander Theißen who reverted the removal of `ext_dispatch_call` and created a special branch based on RC4 for us!
+
+The smart contract source code exists in this [repository folder](https://github.com/usetech-llc/nft_parachain/tree/master/smart_contract/ink-types-node-runtime), but the best way to test how the interaction between smart contracts and NFT pallet works is to see it in action using the [SubstraPunks Game Example](https://ipfs-gateway.usetech.com/ipns/QmaMtDqE9nhMX9RQLTpaCboqg7bqkb6Gi67iCKMe8NDpCE/) that uses smart contract to claim free characters. The complete demo of this game will come later, so please bare with us and let's put this item demonstration for a bit later.
+
+#### MainNet
+
+The Ink! 3.0 Chain Extensions will allow calling pallets from smart contracts with env() object in Ink!, as soon as they are ready. Our code is prewired for this and waiting for Chain Extensions to release.
+
+### Fungibility and Re-Fungibility support
+
+Fungible and Re-Fungible modes are fully implemented and ready for QA as of now. Fungible mode allows creation of ERC-20-like tokens, and Re-Fungible allows sharing NFT tokens between multiple addresses.
+
+#### Re-Fungibility
+
+Re-fungible feature is best demonstrated in action using our NFT wallet. First, you need to have some Unique and Re-Fungible tokens. [This section](#getting-some-unique-tokens) tells how to get them.
+
+1. Open the [NFT Wallet](https://uniqueapps.usetech.com/#/nft)
+2. Search for collection called "Artwork". Search can be done either by collection name or collection ID (which is 2).
+3. Click on "+ Add collection" in search results. The collection will appear under "My collections"
+4. Expand the "Artwork" collection and see that you own a token with a partial balance
+5. Transfer the token to some other address: Click "Transfer token" and enter address and the amount. Amount should be entered as decimal fraction. For example "0.01" to transfer 1/100th part of the token. 
+6. Observe that your balance decreased by the amount you entered.
+
+#### Fungibility
+
+Fungible tokens can be created manually by calling extrinsics:
+1. Open [Extrinsics page in UI](https://uniqueapps.usetech.com/#/extrinsics)
+2. Select nft - createCollection
+3. In the CollectionMode select Fungible, enter decimal points number and click "Submit Transaction"
+4. Switch to [Explorer](https://uniqueapps.usetech.com/#/explorer) and find the block where the transaction was mined.
+5. Find nft.Created Event, which will contain the ID of the Fungible token you just created
+6. In order to mint a token, use nft - createItem extrinsic. Enter the collection ID (that you found in the previous step) and submit transaction. One token will be minted. (We also support Batch minting for minting different amounts, etc).
+
+#### Re-fungibility The Hard Way
+
+Also, the Re-Fungible support can be demonstrated using the standard UI features without NFT wallet.
+
+1. Open [Chain State](https://uniqueapps.usetech.com/#/chainstate).
+2. Select "nft" - "reFungbleItemList"
+3. Enter parameters: 2 and 1, click "+" button
+4. Observe the following data structure returned:
+
+```
+{
+  Collection: 2,
+  Owner: [
+    {
+      owner: 5FNujvbtMyKoJC2zTrfGVaQek7jhfR1L558BMhogfFfD7veH,
+      fraction: 3,000
+    },
+    {
+      owner: 5D73wtH5pqN99auP4b6KQRQAbketaSj4StkBJxACPBUAUdiq,
+      fraction: 3,000
+    },
+    {
+      owner: 5FZeTmbZQZsJcyEevjGVK1HHkcKfWBYxWpbgEffQ2M1SqAnP,
+      fraction: 2,000
+    },
+    {
+      owner: 5EnzEXBuxFHdymceAAtstym8FETQqH4inx29XJSP6uHaCUiP,
+      fraction: 1,000
+    },
+    {
+      owner: 5GU6iHnc3qTMaufmKYzHUpDmVN2CgzA2JMcGFQLcKNDbE7c6,
+      fraction: 1,000
+    }
+  ],
+  Data: 
+}
+```
+
+The Owner field contains a list of owners with the fractions they own. The fractions are represented as fixed point decimals. The number of decimal points in this fraction is determined by collection properties. For example, in the Artwork collection this property is equal to 4. The owned fraction is then determined as `fraction` divided by 10^DecimalPoints, i.e. 10,000 in this case.
+
+5. Staying in Chain State, select "nft" - "colection"
+6. Input "2" and click "+"
+7. Observe the following structure returned. It tells that collection is ReFungible and DecimalPoints field is equal to 4.
+
+```
+{
+  Owner: 5FNujvbtMyKoJC2zTrfGVaQek7jhfR1L558BMhogfFfD7veH,
+  Mode: {
+    ReFungible: [
+      0,
+      4
+    ]
+  },
+  Access: 0,
+  DecimalPoints: 4,
+  Name: [
+...
+```
+
+### Off-Chain Schema to store token image URLs
+
+This feature is best demonstrated in action using our NFT wallet. First, you need to have some Unique and Re-Fungible tokens. [This section](#getting-some-unique-tokens) tells how to get them.
+
+1. Open the [NFT Wallet](https://uniqueapps.usetech.com/#/nft)
+2. Search for collection called "Artwork". Search can be done either by collection name or collection ID (which is 2).
+3. Expand "Artwork" collection
+4. Click on the image to zoom in. 
+5. Right-click on the image and select "Open Image in New Tab"
+6. Note the image URL:
+```
+https://ipfs-gateway.usetech.com/ipfs/QmUSv64cUmL2m44QYkUFWmH89qykC8VLPFwjhpeAScjejS/image1.jpg
+``` 
+7. Open [Chain State](https://uniqueapps.usetech.com/#/chainstate).
+8. Select "nft" - "colection"
+9. Input "2" and click "+"
+10. Scroll down:
+```
+  ],
+  TokenPrefix: ARTu0000,
+  CustomDataSize: 0,
+  OffchainSchema: https://ipfs-gateway.usetech.com/ipfs/QmUSv64cUmL2m44QYkUFWmH89qykC8VLPFwjhpeAScjejS/image{id}.jpg,
+  Sponsor: 5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM,
+  UnconfirmedSponsor: 5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM
+}
+```
+11. Observe the field called `OffchainSchema`. This field defines the URL schema that is used to contruct token URLs based on the token ID. In this particular example, the {id} template variable is replaced with token id 1, which results in the proper image URL.
+
+### New economic models
+
+This feature is best demonstrated when you own a SubstraPunk character. Please proceed with the demonstration, and then come back after you claim one.
+
+1. Create a new address in Polkadot{.js} extension. We need an address that has zero balance in Unique tokens. Let's call it "ZERO BALANCE" address.
+2. Open the [NFT Wallet](https://uniqueapps.usetech.com/#/nft)
+3. Search for collection called "SubstraPunks" (partial search also works, so you can just type "punk" and hit Enter)
+4. Add collection
+5. Expand substrapunks collection and transfer your PNK token to your "ZERO BALANCE" address.
+6. Now select your "ZERO BALANCE" address in the drop-down list and repeat searching and adding the collection for this address.
+7. Transfer token back to your main address. Observe that despite the zero balance, the transfer is successful.
+
+### White Lists and Public Mint Permission
+
+We did not complete these features in time by Hackusama deadline, but because they are important for security of the network, we completed them after the deadline anyway. They can be seen in branch [feature/white_list](https://github.com/usetech-llc/nft_parachain/tree/feature/white_list). Here are the permalinks to essential functions:
+
+[white_lists](https://github.com/usetech-llc/nft_parachain/blob/b7c59f0085ed2bc1922e937adf68ef4174a8ba36/pallets/nft/src/lib.rs#L659)
+
+[mint_permission](https://github.com/usetech-llc/nft_parachain/blob/b7c59f0085ed2bc1922e937adf68ef4174a8ba36/pallets/nft/src/lib.rs#L373)
+
+## NFT Wallet
+
+[Project Description](https://github.com/usetech-llc/apps/blob/master/README.md)
+
+All features of the NFT Wallet were already demonstrated previously:
+
+* Enables adding favorite collections
+* Shows tokens owned
+* Allows NFT and Re-Fungible transfers
+* Shows Re-Fungible Balances
+* Shows Token Images
+
+## Our version of AppsUI
+
+The UI was also mainly demonstrated. We only need to show some configuration that happens behind the scenes:
+
+### Loads appropriate custom API types
+1. Open the [NFT Wallet Developer Settings](https://uniqueapps.usetech.com/#/settings/developer)
+2. Observe that Custom UI types are already in place
+
+### Defaults to NFT TestNet
+
+1. Open the [NFT Wallet](https://uniqueapps.usetech.com/)
+2. Observe that Unique Network icon appears in the left top corner without a need to specify the network
+3. Click on Unique Network icon and see that `NFT Testnet` is in the network list
+
+## Unity API and SDK PoC
+
+[Project Description](https://github.com/usetech-llc/nft_unity/blob/master/README.md)
+
+In order to see Unity Asset in action, please follow the instructions in this README file:
+
+[Demonstration](https://github.com/usetech-llc/nft_unity/blob/master/src/DemoApplication/readme.md)
+
+## SubstraPunks Game and Marketplace
+
+[Project Description](https://github.com/usetech-llc/substrapunks/blob/master/README.md)
+
+First, you will need some Unique balance. [This section](#getting-some-unique-tokens) tells how to get the TestNet currency.
+
+This game initially was meant as a demonstration, but all Punks were quickly claimed, and we had to develop the marketplace to keep demonstrating capability of it. [Here](https://github.com/usetech-llc/nft_parachain/blob/master/doc/hackusama_walk_through.md#substrapunks-game) is the original description.
+
+Here is how one can test Marketplace:
+
+1. Open [Substrapunks Marketplace](https://ipfs-gateway.usetech.com/ipns/QmaMtDqE9nhMX9RQLTpaCboqg7bqkb6Gi67iCKMe8NDpCE/)
+2. Contact us in [Unique Telegram channel](https://t.me/Uniquechain), so we can place a test NFT for you buy on the marketplace.
+3. Refresh the marketplace page and click on the NFT to buy (the one we placed)
+4. Go through buying process
+5. Let us know to exchange KSM back for the NFT (if you would not like to keep the punk of course :) )
+
+### How Marketplace works
+
+Marketplace is a PoC and it consists a PoC bridge between Kusama and Unique and a Matcher smart contract.
+
+#### Kusama Bridge
+
+The bridge works mainly as an escrow that locks NFTs and KSM allowing users to trustlessly exchange their assets.
+
+#### Matcher Smart Contract
+
+The matcher smart contract allows placing punks on sale and buying. It operates assets that are locked in the bridge and releases them once the trade happens or the offer is cancelled.
modifiednode/Cargo.tomldiffbeforeafterboth
--- a/node/Cargo.toml
+++ b/node/Cargo.toml
@@ -58,6 +58,9 @@
 substrate-frame-rpc-system = {version = '2.0.0', git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi'}
 pallet-contracts-rpc = {version = '0.8.0', git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi'} 
 
+serde = { version = "1.0.102", features = ["derive"] }
+serde_json = "1.0.41"
+
 [features]
 default = []
 runtime-benchmarks = ['nft-runtime/runtime-benchmarks']
modifiednode/build.rsdiffbeforeafterboth
--- a/node/build.rs
+++ b/node/build.rs
@@ -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.
+//
+
 use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed};
 
 fn main() {
modifiednode/src/chain_spec.rsdiffbeforeafterboth
--- a/node/src/chain_spec.rs
+++ b/node/src/chain_spec.rs
@@ -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.
+//
+
 // use nft_runtime::{
 //     AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig,
 //     SystemConfig, WASM_BINARY,
@@ -9,6 +14,7 @@
 use sp_core::{sr25519, Pair, Public};
 use sp_finality_grandpa::AuthorityId as GrandpaId;
 use sp_runtime::traits::{IdentifyAccount, Verify};
+use serde_json::map::Map;
 
 // Note this is the URL for the telemetry server
 //const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
@@ -41,6 +47,11 @@
 pub fn development_config() -> Result<ChainSpec, String> {
 	let wasm_binary = WASM_BINARY.ok_or("Development wasm binary not available".to_string())?;
 
+	let mut properties = Map::new();
+	properties.insert("tokenSymbol".into(), "UniqueTest".into());
+	properties.insert("tokenDecimals".into(), 15.into());
+	properties.insert("ss58Format".into(), 42.into()); // Generic Substrate wildcard (SS58 checksum preimage)
+
 	Ok(ChainSpec::from_genesis(
 		// Name
 		"Development",
@@ -71,7 +82,7 @@
 		// Protocol ID
 		None,
 		// Properties
-		None,
+		Some(properties),
 		// Extensions
 		None,
 	))
@@ -132,6 +143,11 @@
     endowed_accounts: Vec<AccountId>,
     enable_println: bool,
 ) -> GenesisConfig {
+
+	let vested_accounts = vec![
+		get_account_id_from_seed::<sr25519::Public>("Bob"),
+	];
+
     GenesisConfig {
         system: Some(SystemConfig {
             code: wasm_binary.to_vec(),
@@ -154,7 +170,14 @@
                 .collect(),
 		}),
 		pallet_treasury: Some(Default::default()),
-        pallet_sudo: Some(SudoConfig { key: root_key }),
+		pallet_sudo: Some(SudoConfig { key: root_key }),
+		pallet_vesting: Some(VestingConfig {
+            vesting: vested_accounts
+                .iter()
+                .cloned()
+                .map(|k| (k, 1000, 100, 1 << 98))
+                .collect(),
+        }),
         pallet_nft: Some(NftConfig {
             collection: vec![(
                 1,
@@ -170,7 +193,7 @@
 					offchain_schema: vec![],
 					schema_version: SchemaVersion::default(),
                     sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),
-                    unconfirmed_sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),
+                    sponsor_confirmed: true,
                     const_on_chain_schema: vec![],
 					variable_on_chain_schema: vec![],
 					limits: CollectionLimits::default()
@@ -180,8 +203,8 @@
             fungible_item_id: vec![],
             refungible_item_id: vec![],
             chain_limit: ChainLimits {
-                collection_numbers_limit: 10,
-                account_token_ownership_limit: 10,
+                collection_numbers_limit: 100000,
+                account_token_ownership_limit: 1000000,
                 collections_admins_limit: 5,
                 custom_data_limit: 2048,
                 nft_sponsor_transfer_timeout: 15,
modifiednode/src/main.rsdiffbeforeafterboth
--- a/node/src/main.rs
+++ b/node/src/main.rs
@@ -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.
+//
+
 //! Substrate Node Template CLI library.
 #![warn(missing_docs)]
 
modifiednode/src/service.rsdiffbeforeafterboth
--- a/node/src/service.rs
+++ b/node/src/service.rs
@@ -1,5 +1,10 @@
 //! Service and ServiceFactory implementation. Specialized wrapper over substrate service.
 
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 use std::sync::Arc;
 use std::time::Duration;
 use sc_client_api::{ExecutorProvider, RemoteBackend};
modifiedpallets/nft/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/nft/src/benchmarking.rs
+++ b/pallets/nft/src/benchmarking.rs
@@ -355,4 +355,66 @@
             Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
 
         }: set_variable_meta_data(RawOrigin::Signed(caller.clone()), 2, 1, [1, 2, 3].to_vec())
+
+        set_schema_version {
+            let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+            let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+            let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+            let mode: CollectionMode = CollectionMode::NFT;
+            let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+            Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+        }: set_schema_version(RawOrigin::Signed(caller.clone()), 2, SchemaVersion::Unique)
+
+        set_chain_limits {
+            let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+            let limits = ChainLimits { 
+                collection_numbers_limit: 0,
+                account_token_ownership_limit: 0,
+                collections_admins_limit: 0,
+                custom_data_limit: 0,
+                nft_sponsor_transfer_timeout: 0,
+                fungible_sponsor_transfer_timeout: 0,
+                refungible_sponsor_transfer_timeout: 0
+            };
+        }: set_chain_limits(RawOrigin::Signed(caller.clone()), limits)
+
+        set_contract_sponsoring_rate_limit {
+            let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+            let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+            let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+            let mode: CollectionMode = CollectionMode::NFT;
+            let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+            Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+            let block_number: T::BlockNumber = 0.into();   
+        }: set_contract_sponsoring_rate_limit(RawOrigin::Signed(caller.clone()), caller.clone(), block_number)
+
+        set_collection_limits{
+            let col_name1: Vec<u16> = "Test1".encode_utf16().collect::<Vec<u16>>();
+            let col_desc1: Vec<u16> = "TestDescription1".encode_utf16().collect::<Vec<u16>>();
+            let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
+            let mode: CollectionMode = CollectionMode::NFT;
+            let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+            Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+     
+            let cl = CollectionLimits {
+                account_token_ownership_limit: 0,
+                sponsored_data_size: 0,
+                token_limit: 0,
+                sponsor_transfer_timeout: 0
+            };
+
+        }: set_collection_limits(RawOrigin::Signed(caller.clone()), 2, cl)
+
+        add_to_contract_white_list{
+            let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+        }: add_to_contract_white_list(RawOrigin::Signed(caller.clone()), caller.clone(), caller.clone())
+
+        remove_from_contract_white_list{
+            let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+            Nft::<T>::add_to_contract_white_list(RawOrigin::Signed(caller.clone()).into(), caller.clone(), caller.clone())?;
+        }: remove_from_contract_white_list(RawOrigin::Signed(caller.clone()), caller.clone(), caller.clone())
+
+        toggle_contract_white_list{
+            let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
+        }: toggle_contract_white_list(RawOrigin::Signed(caller.clone()), caller.clone(), true)
 }
\ No newline at end of file
modifiedpallets/nft/src/default_weights.rsdiffbeforeafterboth
--- a/pallets/nft/src/default_weights.rs
+++ b/pallets/nft/src/default_weights.rs
@@ -107,19 +107,44 @@
             .saturating_add(DbWeight::get().reads(2 as Weight))
             .saturating_add(DbWeight::get().writes(1 as Weight))
     }
-    // fn set_chain_limits() -> Weight {
-    //     (0 as Weight)
-    //         .saturating_add(DbWeight::get().reads(1 as Weight))
-    //         .saturating_add(DbWeight::get().writes(1 as Weight))
-    // }
     fn enable_contract_sponsoring() -> Weight {
         (13_000_000 as Weight)
             .saturating_add(DbWeight::get().reads(1 as Weight))
             .saturating_add(DbWeight::get().writes(1 as Weight))
     }
-    // fn set_contract_sponsoring_rate_limit() -> Weight {
-    //     (0 as Weight)
-    //         .saturating_add(DbWeight::get().reads(1 as Weight))
-    //         .saturating_add(DbWeight::get().writes(1 as Weight))
-    // }
+    fn set_schema_version() -> Weight {
+        (8_500_000 as Weight)
+            .saturating_add(DbWeight::get().reads(2 as Weight))
+            .saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn set_chain_limits() -> Weight {
+        (1_300_000 as Weight)
+            .saturating_add(DbWeight::get().reads(0 as Weight))
+            .saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn set_contract_sponsoring_rate_limit() -> Weight {
+        (3_500_000 as Weight)
+            .saturating_add(DbWeight::get().reads(0 as Weight))
+            .saturating_add(DbWeight::get().writes(2 as Weight))
+    }    
+    fn toggle_contract_white_list() -> Weight {
+        (3_000_000 as Weight)
+            .saturating_add(DbWeight::get().reads(0 as Weight))
+            .saturating_add(DbWeight::get().writes(2 as Weight))
+    }    
+    fn add_to_contract_white_list() -> Weight {
+        (3_000_000 as Weight)
+            .saturating_add(DbWeight::get().reads(0 as Weight))
+            .saturating_add(DbWeight::get().writes(2 as Weight))
+    }    
+    fn remove_from_contract_white_list() -> Weight {
+        (3_200_000 as Weight)
+            .saturating_add(DbWeight::get().reads(0 as Weight))
+            .saturating_add(DbWeight::get().writes(2 as Weight))
+    }
+    fn set_collection_limits() -> Weight {
+        (8_900_000 as Weight)
+            .saturating_add(DbWeight::get().reads(2 as Weight))
+            .saturating_add(DbWeight::get().writes(1 as Weight))
+    }
 }
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -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.
+//
+
 #![recursion_limit = "1024"]
 
 #![cfg_attr(not(feature = "std"), no_std)]
@@ -29,10 +34,10 @@
 use sp_runtime::sp_std::prelude::Vec;
 use sp_runtime::{
     traits::{
-        DispatchInfoOf, Dispatchable, PostDispatchInfoOf, Saturating, SignedExtension, Zero,
+        DispatchInfoOf, Dispatchable, PostDispatchInfoOf, Saturating, SaturatedConversion, SignedExtension, Zero,
     },
     transaction_validity::{
-        InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction,
+        TransactionPriority, InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction,
     },
     FixedPointOperand, FixedU128,
 };
@@ -131,7 +136,7 @@
     pub offchain_schema: Vec<u8>,
     pub schema_version: SchemaVersion,
     pub sponsor: AccountId, // Who pays fees. If set to default address, the fees are applied to the transaction sender
-    pub unconfirmed_sponsor: AccountId, // Sponsor address that has not yet confirmed sponsorship
+    pub sponsor_confirmed: bool, // False if sponsor address has not yet confirmed sponsorship. True otherwise.
     pub limits: CollectionLimits, // Collection private restrictions 
     pub variable_on_chain_schema: Vec<u8>, //
     pub const_on_chain_schema: Vec<u8>, //
@@ -140,7 +145,6 @@
 #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub struct NftItemType<AccountId> {
-    pub collection: CollectionId,
     pub owner: AccountId,
     pub const_data: Vec<u8>,
     pub variable_data: Vec<u8>,
@@ -148,45 +152,28 @@
 
 #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-pub struct FungibleItemType<AccountId> {
-    pub collection: CollectionId,
-    pub owner: AccountId,
+pub struct FungibleItemType {
     pub value: u128,
 }
 
 #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub struct ReFungibleItemType<AccountId> {
-    pub collection: CollectionId,
     pub owner: Vec<Ownership<AccountId>>,
     pub const_data: Vec<u8>,
     pub variable_data: Vec<u8>,
 }
 
-#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-pub struct ApprovePermissions<AccountId> {
-    pub approved: AccountId,
-    pub amount: u128,
-}
-
-#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-pub struct VestingItem<AccountId, Moment> {
-    pub sender: AccountId,
-    pub recipient: AccountId,
-    pub collection_id: CollectionId,
-    pub item_id: TokenId,
-    pub amount: u64,
-    pub vesting_date: Moment,
-}
-
-#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-pub struct BasketItem<AccountId, BlockNumber> {
-    pub address: AccountId,
-    pub start_block: BlockNumber,
-}
+// #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+// #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+// pub struct VestingItem<AccountId, Moment> {
+//     pub sender: AccountId,
+//     pub recipient: AccountId,
+//     pub collection_id: CollectionId,
+//     pub item_id: TokenId,
+//     pub amount: u64,
+//     pub vesting_date: Moment,
+// }
 
 #[derive(Encode, Decode, Debug, Clone, PartialEq)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
@@ -246,6 +233,13 @@
     fn set_variable_on_chain_schema() -> Weight;
     fn set_variable_meta_data() -> Weight;
     fn enable_contract_sponsoring() -> Weight;
+    fn set_schema_version() -> Weight;
+    fn set_chain_limits() -> Weight;
+    fn set_contract_sponsoring_rate_limit() -> Weight;
+    fn toggle_contract_white_list() -> Weight;
+    fn add_to_contract_white_list() -> Weight;
+    fn remove_from_contract_white_list() -> Weight;
+    fn set_collection_limits() -> Weight;
 }
 
 #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
@@ -258,6 +252,7 @@
 #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub struct CreateFungibleData {
+    pub value: u128,
 }
 
 #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
@@ -407,17 +402,17 @@
         // Basic collections
         pub Collection get(fn collection) config(): map hasher(identity) CollectionId => CollectionType<T::AccountId>;
         pub AdminList get(fn admin_list_collection): map hasher(identity) CollectionId => Vec<T::AccountId>;
-        pub WhiteList get(fn white_list): map hasher(identity) CollectionId => Vec<T::AccountId>;
+        pub WhiteList get(fn white_list): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => bool;
 
         /// Balance owner per collection map
         pub Balance get(fn balance_count): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => u128;
 
-        /// second parameter: item id + owner account id
-        pub ApprovedList get(fn approved): double_map hasher(identity) CollectionId, hasher(twox_64_concat) (TokenId, T::AccountId) => Vec<ApprovePermissions<T::AccountId>>;
+        /// second parameter: item id + owner account id + spender account id
+        pub Allowances get(fn approved): double_map hasher(identity) CollectionId, hasher(twox_64_concat) (TokenId, T::AccountId, T::AccountId) => u128;
 
         /// Item collections
         pub NftItemList get(fn nft_item_id) config(): double_map hasher(identity) CollectionId, hasher(identity) TokenId => NftItemType<T::AccountId>;
-        pub FungibleItemList get(fn fungible_item_id) config(): double_map hasher(identity) CollectionId, hasher(identity) TokenId => FungibleItemType<T::AccountId>;
+        pub FungibleItemList get(fn fungible_item_id) config(): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => FungibleItemType;
         pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(identity) CollectionId, hasher(identity) TokenId => ReFungibleItemType<T::AccountId>;
 
         /// Index list
@@ -425,7 +420,7 @@
 
         /// Tokens transfer baskets
         pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(identity) CollectionId, hasher(identity) TokenId => T::BlockNumber;
-        pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(identity) CollectionId, hasher(identity) TokenId => Vec<BasketItem<T::AccountId, T::BlockNumber>>;
+        pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(identity) CollectionId, hasher(twox_64_concat) T::AccountId => T::BlockNumber;
         pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(identity) CollectionId, hasher(identity) TokenId => T::BlockNumber;
 
         // Contract Sponsorship and Ownership
@@ -433,6 +428,8 @@
         pub ContractSelfSponsoring get(fn contract_self_sponsoring): map hasher(twox_64_concat) T::AccountId => bool;
         pub ContractSponsorBasket get(fn contract_sponsor_basket): map hasher(twox_64_concat) (T::AccountId, T::AccountId) => T::BlockNumber;
         pub ContractSponsoringRateLimit get(fn contract_sponsoring_rate_limit): map hasher(twox_64_concat) T::AccountId => T::BlockNumber;
+        pub ContractWhiteListEnabled get(fn contract_white_list_enabled): map hasher(twox_64_concat) T::AccountId => bool; 
+        pub ContractWhiteList get(fn contract_white_list): double_map hasher(twox_64_concat) T::AccountId, hasher(twox_64_concat) T::AccountId => bool; 
     }
     add_extra_genesis {
         build(|config: &GenesisConfig<T>| {
@@ -441,16 +438,16 @@
                 <Module<T>>::init_collection(_c);
             }
 
-            for (_num, _q, _i) in &config.nft_item_id {
-                <Module<T>>::init_nft_token(_i);
+            for (_num, _c, _i) in &config.nft_item_id {
+                <Module<T>>::init_nft_token(*_c, _i);
             }
 
-            for (_num, _q, _i) in &config.fungible_item_id {
-                <Module<T>>::init_fungible_token(_i);
+            for (collection_id, account_id, fungible_item) in &config.fungible_item_id {
+                <Module<T>>::init_fungible_token(*collection_id, account_id, fungible_item);
             }
 
-            for (_num, _q, _i) in &config.refungible_item_id {
-                <Module<T>>::init_refungible_token(_i);
+            for (_num, _c, _i) in &config.refungible_item_id {
+                <Module<T>>::init_refungible_token(*_c, _i);
             }
         })
     }
@@ -586,7 +583,7 @@
                 offchain_schema: Vec::new(),
                 schema_version: SchemaVersion::ImageURL,
                 sponsor: T::AccountId::default(),
-                unconfirmed_sponsor: T::AccountId::default(),
+                sponsor_confirmed: false,
                 variable_on_chain_schema: Vec::new(),
                 const_on_chain_schema: Vec::new(),
                 limits: CollectionLimits::default(),
@@ -617,12 +614,12 @@
             Self::check_owner_permissions(collection_id, sender)?;
 
             <AddressTokens<T>>::remove_prefix(collection_id);
-            <ApprovedList<T>>::remove_prefix(collection_id);
+            <Allowances<T>>::remove_prefix(collection_id);
             <Balance<T>>::remove_prefix(collection_id);
             <ItemListIndex>::remove(collection_id);
             <AdminList<T>>::remove(collection_id);
             <Collection<T>>::remove(collection_id);
-            <WhiteList<T>>::remove(collection_id);
+            <WhiteList<T>>::remove_prefix(collection_id);
 
             <NftItemList<T>>::remove_prefix(collection_id);
             <FungibleItemList<T>>::remove_prefix(collection_id);
@@ -663,20 +660,8 @@
             let sender = ensure_signed(origin)?;
             Self::check_owner_or_admin_permissions(collection_id, sender)?;
 
-            let mut white_list_collection: Vec<T::AccountId>;
-            if <WhiteList<T>>::contains_key(collection_id) {
-                white_list_collection = <WhiteList<T>>::get(collection_id);
-                if !white_list_collection.contains(&address.clone())
-                {
-                    white_list_collection.push(address.clone());
-                }
-            }
-            else {
-                white_list_collection = Vec::new();
-                white_list_collection.push(address.clone());
-            }
-
-            <WhiteList<T>>::insert(collection_id, white_list_collection);
+            <WhiteList<T>>::insert(collection_id, address, true);
+            
             Ok(())
         }
 
@@ -698,14 +683,7 @@
             let sender = ensure_signed(origin)?;
             Self::check_owner_or_admin_permissions(collection_id, sender)?;
 
-            if <WhiteList<T>>::contains_key(collection_id) {
-                let mut white_list_collection = <WhiteList<T>>::get(collection_id);
-                if white_list_collection.contains(&address.clone())
-                {
-                    white_list_collection.retain(|i| *i != address.clone());
-                    <WhiteList<T>>::insert(collection_id, white_list_collection);
-                }
-            }
+            <WhiteList<T>>::remove(collection_id, address);
 
             Ok(())
         }
@@ -864,7 +842,8 @@
             let mut target_collection = <Collection<T>>::get(collection_id);
             ensure!(sender == target_collection.owner, Error::<T>::NoPermission);
 
-            target_collection.unconfirmed_sponsor = new_sponsor;
+            target_collection.sponsor = new_sponsor;
+            target_collection.sponsor_confirmed = false;
             <Collection<T>>::insert(collection_id, target_collection);
 
             Ok(())
@@ -884,10 +863,9 @@
             ensure!(<Collection<T>>::contains_key(collection_id), Error::<T>::CollectionNotFound);
 
             let mut target_collection = <Collection<T>>::get(collection_id);
-            ensure!(sender == target_collection.unconfirmed_sponsor, Error::<T>::ConfirmUnsetSponsorFail);
+            ensure!(sender == target_collection.sponsor, Error::<T>::ConfirmUnsetSponsorFail);
 
-            target_collection.sponsor = target_collection.unconfirmed_sponsor;
-            target_collection.unconfirmed_sponsor = T::AccountId::default();
+            target_collection.sponsor_confirmed = true;
             <Collection<T>>::insert(collection_id, target_collection);
 
             Ok(())
@@ -912,6 +890,7 @@
             ensure!(sender == target_collection.owner, Error::<T>::NoPermission);
 
             target_collection.sponsor = T::AccountId::default();
+            target_collection.sponsor_confirmed = false;
             <Collection<T>>::insert(collection_id, target_collection);
 
             Ok(())
@@ -1012,7 +991,7 @@
         /// 
         /// * item_id: ID of NFT to burn.
         #[weight = T::WeightInfo::burn_item()]
-        pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId) -> DispatchResult {
+        pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResult {
 
             let sender = ensure_signed(origin)?;
             Self::collection_exists(collection_id)?;
@@ -1030,7 +1009,7 @@
             match target_collection.mode
             {
                 CollectionMode::NFT => Self::burn_nft_item(collection_id, item_id)?,
-                CollectionMode::Fungible(_)  => Self::burn_fungible_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.clone())?,
                 _ => ()
             };
@@ -1086,7 +1065,7 @@
             match target_collection.mode
             {
                 CollectionMode::NFT => Self::transfer_nft(collection_id, item_id, sender.clone(), recipient)?,
-                CollectionMode::Fungible(_)  => Self::transfer_fungible(collection_id, item_id, value, 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)?,
                 _ => ()
             };
@@ -1110,7 +1089,7 @@
         /// 
         /// * item_id: ID of the item.
         #[weight = T::WeightInfo::approve()]
-        pub fn approve(origin, approved: T::AccountId, collection_id: CollectionId, item_id: TokenId) -> DispatchResult {
+        pub fn approve(origin, spender: T::AccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResult {
 
             let sender = ensure_signed(origin)?;
 
@@ -1122,28 +1101,15 @@
 
             if target_collection.access == AccessMode::WhiteList {
                 Self::check_white_list(collection_id, &sender)?;
-                Self::check_white_list(collection_id, &approved)?;
+                Self::check_white_list(collection_id, &spender)?;
             }
 
-            // amount param stub
-            let amount = 100000000;
-
-            let list_exists = <ApprovedList<T>>::contains_key(collection_id, (item_id, sender.clone()));
-            if list_exists {
-
-                let mut list = <ApprovedList<T>>::get(collection_id, (item_id, sender.clone()));
-                let item_contains = list.iter().any(|i| i.approved == approved);
-
-                if !item_contains {
-                    list.push(ApprovePermissions { approved: approved.clone(), amount: amount });
-                    <ApprovedList<T>>::insert(collection_id, (item_id, sender.clone()), list);
-                }
-            } else {
-
-                let mut list = Vec::new();
-                list.push(ApprovePermissions { approved: approved.clone(), amount: amount });
-                <ApprovedList<T>>::insert(collection_id, (item_id, sender.clone()), list);
+            let allowance_exists = <Allowances<T>>::contains_key(collection_id, (item_id, &sender, &spender));
+            let mut allowance: u128 = amount;
+            if allowance_exists {
+                allowance += <Allowances<T>>::get(collection_id, (item_id, &sender, &spender));
             }
+            <Allowances<T>>::insert(collection_id, (item_id, sender.clone(), spender.clone()), allowance);
 
             Ok(())
         }
@@ -1173,15 +1139,12 @@
             let sender = ensure_signed(origin)?;
             let mut appoved_transfer = false;
 
-            // Check approve
-            if <ApprovedList<T>>::contains_key(collection_id, (item_id, from.clone())) {
-                let list_itm = <ApprovedList<T>>::get(collection_id, (item_id, from.clone()));
-                let opt_item = list_itm.iter().find(|i| i.approved == sender.clone());
-                if opt_item.is_some()
-                {
-                    appoved_transfer = true;
-                    ensure!(opt_item.unwrap().amount >= value, Error::<T>::TokenValueNotEnough);
-                }
+            // 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));
+                ensure!(approval >= value, Error::<T>::TokenValueNotEnough);
+                appoved_transfer = true;
             }
 
             let target_collection = <Collection<T>>::get(collection_id);
@@ -1191,23 +1154,25 @@
 
             // Transfer permissions check         
             ensure!(appoved_transfer || Self::is_owner_or_admin_permissions(collection_id, sender.clone()),
-            Error::<T>::NoPermission);
+                Error::<T>::NoPermission);
 
             if target_collection.access == AccessMode::WhiteList {
                 Self::check_white_list(collection_id, &sender)?;
                 Self::check_white_list(collection_id, &recipient)?;
             }
 
-            // remove approve
-            let approve_list: Vec<ApprovePermissions<T::AccountId>> = <ApprovedList<T>>::get(collection_id, (item_id, from.clone()))
-                .into_iter().filter(|i| i.approved != sender.clone()).collect();
-            <ApprovedList<T>>::insert(collection_id, (item_id, from.clone()), approve_list);
+            // Reduce approval by transferred amount or remove if remaining approval drops to 0
+            if approval - value > 0 {
+                <Allowances<T>>::insert(collection_id, (item_id, &from, &recipient), approval - value);
+            }
+            else {
+                <Allowances<T>>::remove(collection_id, (item_id, &from, &recipient));
+            }
 
-
             match target_collection.mode
             {
                 CollectionMode::NFT => Self::transfer_nft(collection_id, item_id, from, recipient)?,
-                CollectionMode::Fungible(_)  => Self::transfer_fungible(collection_id, item_id, value, from.clone(), recipient)?,
+                CollectionMode::Fungible(_)  => Self::transfer_fungible(collection_id, value, &from, &recipient)?,
                 CollectionMode::ReFungible(_)  => Self::transfer_refungible(collection_id, item_id, value, from.clone(), recipient)?,
                 _ => ()
             };
@@ -1288,7 +1253,7 @@
         /// * collection_id.
         /// 
         /// * schema: SchemaVersion: enum
-        #[weight = 0]
+        #[weight = T::WeightInfo::set_schema_version()]
         pub fn set_schema_version(
             origin,
             collection_id: CollectionId,
@@ -1388,12 +1353,15 @@
         }
 
         // Sudo permissions function
-        #[weight = 0]
+        #[weight = T::WeightInfo::set_chain_limits()]
         pub fn set_chain_limits(
             origin,
             limits: ChainLimits
         ) -> DispatchResult {
+
+            #[cfg(not(feature = "runtime-benchmarks"))]
             ensure_root(origin)?;
+
             <ChainLimit>::put(limits);
             Ok(())
         }
@@ -1421,12 +1389,7 @@
             #[cfg(feature = "runtime-benchmarks")]
             <ContractOwner<T>>::insert(contract_address.clone(), sender.clone());
 
-            let mut is_owner = false;
-            if <ContractOwner<T>>::contains_key(contract_address.clone()) {
-                let owner = <ContractOwner<T>>::get(&contract_address);
-                is_owner = sender == owner;
-            }
-            ensure!(is_owner, Error::<T>::NoPermission);
+            Self::ensure_contract_owned(sender, &contract_address)?;
 
             <ContractSelfSponsoring<T>>::insert(contract_address, enable);
             Ok(())
@@ -1449,25 +1412,104 @@
         /// -`contract_address`: Address of the contract to sponsor
         /// -`rate_limit`: Number of blocks to wait until the next sponsored transaction is allowed
         /// 
-        #[weight = 0]
+        #[weight = T::WeightInfo::set_contract_sponsoring_rate_limit()]
         pub fn set_contract_sponsoring_rate_limit(
             origin,
             contract_address: T::AccountId,
             rate_limit: T::BlockNumber
         ) -> DispatchResult {
             let sender = ensure_signed(origin)?;
-            let mut is_owner = false;
-            if <ContractOwner<T>>::contains_key(contract_address.clone()) {
-                let owner = <ContractOwner<T>>::get(&contract_address);
-                is_owner = sender == owner;
-            }
-            ensure!(is_owner, Error::<T>::NoPermission);
 
+            #[cfg(feature = "runtime-benchmarks")]
+            <ContractOwner<T>>::insert(contract_address.clone(), sender.clone());
+
+            Self::ensure_contract_owned(sender, &contract_address)?;
             <ContractSponsoringRateLimit<T>>::insert(contract_address, rate_limit);
             Ok(())
         }
 
-        #[weight = 0]
+        /// Enable the white list for a contract. Only addresses added to the white list with addToContractWhiteList will be able to call this smart contract.
+        /// 
+        /// # Permissions
+        /// 
+        /// * Address that deployed smart contract.
+        /// 
+        /// # Arguments
+        /// 
+        /// -`contract_address`: Address of the contract.
+        /// 
+        /// - `enable`: .  
+        #[weight = T::WeightInfo::toggle_contract_white_list()]
+        pub fn toggle_contract_white_list(
+            origin,
+            contract_address: T::AccountId,
+            enable: bool
+        ) -> DispatchResult {
+            let sender = ensure_signed(origin)?;
+
+            #[cfg(feature = "runtime-benchmarks")]
+            <ContractOwner<T>>::insert(contract_address.clone(), sender.clone());
+
+            Self::ensure_contract_owned(sender, &contract_address)?;
+            <ContractWhiteListEnabled<T>>::insert(contract_address, enable);
+            Ok(())
+        }
+        
+        /// Add an address to smart contract white list.
+        /// 
+        /// # Permissions
+        /// 
+        /// * Address that deployed smart contract.
+        /// 
+        /// # Arguments
+        /// 
+        /// -`contract_address`: Address of the contract.
+        ///
+        /// -`account_address`: Address to add.
+        #[weight = T::WeightInfo::add_to_contract_white_list()]
+        pub fn add_to_contract_white_list(
+            origin,
+            contract_address: T::AccountId,
+            account_address: T::AccountId
+        ) -> DispatchResult {
+            let sender = ensure_signed(origin)?;
+
+            #[cfg(feature = "runtime-benchmarks")]
+            <ContractOwner<T>>::insert(contract_address.clone(), sender.clone());
+            
+            Self::ensure_contract_owned(sender, &contract_address)?;      
+            <ContractWhiteList<T>>::insert(contract_address, account_address, true);
+            Ok(())
+        }
+
+        /// Remove an address from smart contract white list.
+        /// 
+        /// # Permissions
+        /// 
+        /// * Address that deployed smart contract.
+        /// 
+        /// # Arguments
+        /// 
+        /// -`contract_address`: Address of the contract.
+        ///
+        /// -`account_address`: Address to remove.
+        #[weight = T::WeightInfo::remove_from_contract_white_list()]
+        pub fn remove_from_contract_white_list(
+            origin,
+            contract_address: T::AccountId,
+            account_address: T::AccountId
+        ) -> DispatchResult {
+            let sender = ensure_signed(origin)?;
+
+            #[cfg(feature = "runtime-benchmarks")]
+            <ContractOwner<T>>::insert(contract_address.clone(), sender.clone());
+
+            Self::ensure_contract_owned(sender, &contract_address)?;
+            <ContractWhiteList<T>>::remove(contract_address, account_address);
+            Ok(())
+        }
+
+        #[weight = T::WeightInfo::set_collection_limits()]
         pub fn set_collection_limits(
             origin,
             collection_id: u32,
@@ -1564,22 +1606,15 @@
         {
             CreateItemData::NFT(data) => {
                 let item = NftItemType {
-                    collection: collection_id,
                     owner,
                     const_data: data.const_data,
                     variable_data: data.variable_data
                 };
 
-                Self::add_nft_item(item)?;
+                Self::add_nft_item(collection_id, item)?;
             },
-            CreateItemData::Fungible(_) => {
-                let item = FungibleItemType {
-                    collection: collection_id,
-                    owner,
-                    value: (10 as u128).pow(collection.decimal_points as u32)
-                };
-
-                Self::add_fungible_item(item)?;
+            CreateItemData::Fungible(data) => {
+                Self::add_fungible_item(collection_id, &owner, data.value)?;
             },
             CreateItemData::ReFungible(data) => {
                 let mut owner_list = Vec::new();
@@ -1587,13 +1622,12 @@
                 owner_list.push(Ownership {owner: owner.clone(), fraction: value});
 
                 let item = ReFungibleItemType {
-                    collection: collection_id,
                     owner: owner_list,
                     const_data: data.const_data,
                     variable_data: data.variable_data
                 };
 
-                Self::add_refungible_item(item)?;
+                Self::add_refungible_item(collection_id, item)?;
             }
         };
 
@@ -1603,33 +1637,31 @@
         Ok(())
     }
 
-    fn add_fungible_item(item: FungibleItemType<T::AccountId>) -> DispatchResult {
-        let current_index = <ItemListIndex>::get(item.collection)
-            .checked_add(1)
-            .ok_or(Error::<T>::NumOverflow)?;
-        let itemcopy = item.clone();
-        let owner = item.owner.clone();
+    fn add_fungible_item(collection_id: CollectionId, owner: &T::AccountId, value: u128) -> DispatchResult {
 
-        Self::add_token_index(item.collection, current_index, owner.clone())?;
+        // Does new owner already have an account?
+        let mut balance: u128 = 0;
+        if <FungibleItemList<T>>::contains_key(collection_id, owner) {
+            balance = <FungibleItemList<T>>::get(collection_id, owner).value;
+        } 
 
-        <ItemListIndex>::insert(item.collection, current_index);
-        <FungibleItemList<T>>::insert(item.collection, current_index, itemcopy);
+        // Mint 
+        let item = FungibleItemType {
+            value: balance + value
+        };
+        <FungibleItemList<T>>::insert(collection_id, (*owner).clone(), item);
 
-        // Add current block
-        let v: Vec<BasketItem<T::AccountId, T::BlockNumber>> = Vec::new();
-        <FungibleTransferBasket<T>>::insert(item.collection, current_index, v);
-        
         // Update balance
-        let new_balance = <Balance<T>>::get(item.collection, owner.clone())
-            .checked_add(item.value)
+        let new_balance = <Balance<T>>::get(collection_id, owner)
+            .checked_add(value)
             .ok_or(Error::<T>::NumOverflow)?;
-        <Balance<T>>::insert(item.collection, owner.clone(), new_balance);
+        <Balance<T>>::insert(collection_id, (*owner).clone(), new_balance);
 
         Ok(())
     }
 
-    fn add_refungible_item(item: ReFungibleItemType<T::AccountId>) -> DispatchResult {
-        let current_index = <ItemListIndex>::get(item.collection)
+    fn add_refungible_item(collection_id: CollectionId, item: ReFungibleItemType<T::AccountId>) -> DispatchResult {
+        let current_index = <ItemListIndex>::get(collection_id)
             .checked_add(1)
             .ok_or(Error::<T>::NumOverflow)?;
         let itemcopy = item.clone();
@@ -1637,40 +1669,31 @@
         let value = item.owner.first().unwrap().fraction;
         let owner = item.owner.first().unwrap().owner.clone();
 
-        Self::add_token_index(item.collection, current_index, owner.clone())?;
+        Self::add_token_index(collection_id, current_index, owner.clone())?;
 
-        <ItemListIndex>::insert(item.collection, current_index);
-        <ReFungibleItemList<T>>::insert(item.collection, current_index, itemcopy);
-
-        // Add current block
-        let block_number: T::BlockNumber = 0.into();
-        <ReFungibleTransferBasket<T>>::insert(item.collection, current_index, block_number);
+        <ItemListIndex>::insert(collection_id, current_index);
+        <ReFungibleItemList<T>>::insert(collection_id, current_index, itemcopy);
 
         // Update balance
-        let new_balance = <Balance<T>>::get(item.collection, owner.clone())
+        let new_balance = <Balance<T>>::get(collection_id, owner.clone())
             .checked_add(value)
             .ok_or(Error::<T>::NumOverflow)?;
-        <Balance<T>>::insert(item.collection, owner.clone(), new_balance);
+        <Balance<T>>::insert(collection_id, owner.clone(), new_balance);
 
         Ok(())
     }
 
-    fn add_nft_item(item: NftItemType<T::AccountId>) -> DispatchResult {
-        let current_index = <ItemListIndex>::get(item.collection)
+    fn add_nft_item(collection_id: CollectionId, item: NftItemType<T::AccountId>) -> DispatchResult {
+        let current_index = <ItemListIndex>::get(collection_id)
             .checked_add(1)
             .ok_or(Error::<T>::NumOverflow)?;
 
         let item_owner = item.owner.clone();
-        let collection_id = item.collection.clone();
         Self::add_token_index(collection_id, current_index, item.owner.clone())?;
 
         <ItemListIndex>::insert(collection_id, current_index);
         <NftItemList<T>>::insert(collection_id, current_index, item);
 
-        // Add current block
-        let block_number: T::BlockNumber = 0.into();
-        <NftTransferBasket<T>>::insert(collection_id, current_index, block_number);
-
         // Update balance
         let new_balance = <Balance<T>>::get(collection_id, item_owner.clone())
             .checked_add(1)
@@ -1697,9 +1720,6 @@
             .next()
             .unwrap();
         Self::remove_token_index(collection_id, item_id, owner.clone())?;
-
-        // remove approve list
-        <ApprovedList<T>>::remove(collection_id, (item_id, owner.clone()));
 
         // update balance
         let new_balance = <Balance<T>>::get(collection_id, item.owner.clone())
@@ -1719,9 +1739,6 @@
         );
         let item = <NftItemList<T>>::get(collection_id, item_id);
         Self::remove_token_index(collection_id, item_id, item.owner.clone())?;
-
-        // remove approve list
-        <ApprovedList<T>>::remove(collection_id, (item_id, item.owner.clone()));
 
         // update balance
         let new_balance = <Balance<T>>::get(collection_id, item.owner.clone())
@@ -1733,24 +1750,27 @@
         Ok(())
     }
 
-    fn burn_fungible_item(collection_id: CollectionId, item_id: TokenId) -> DispatchResult {
+    fn burn_fungible_item(owner: &T::AccountId, collection_id: CollectionId, value: u128) -> DispatchResult {
         ensure!(
-            <FungibleItemList<T>>::contains_key(collection_id, item_id),
+            <FungibleItemList<T>>::contains_key(collection_id, owner),
             Error::<T>::TokenNotFound
         );
-        let item = <FungibleItemList<T>>::get(collection_id, item_id);
-        Self::remove_token_index(collection_id, item_id, item.owner.clone())?;
-
-        // remove approve list
-        <ApprovedList<T>>::remove(collection_id, (item_id, item.owner.clone()));
+        let mut balance = <FungibleItemList<T>>::get(collection_id, owner);
+        ensure!(balance.value >= value, Error::<T>::TokenValueNotEnough);
 
         // update balance
-        let new_balance = <Balance<T>>::get(collection_id, item.owner.clone())
-            .checked_sub(item.value)
+        let new_balance = <Balance<T>>::get(collection_id, owner)
+            .checked_sub(value)
             .ok_or(Error::<T>::NumOverflow)?;
-        <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);
+        <Balance<T>>::insert(collection_id, (*owner).clone(), new_balance);
 
-        <FungibleItemList<T>>::remove(collection_id, item_id);
+        if balance.value - value > 0 {
+            balance.value -= value;
+            <FungibleItemList<T>>::insert(collection_id, (*owner).clone(), balance);
+        }
+        else {
+            <FungibleItemList<T>>::remove(collection_id, owner);
+        }
 
         Ok(())
     }
@@ -1811,7 +1831,7 @@
                 <NftItemList<T>>::get(collection_id, item_id).owner == subject
             }
             CollectionMode::Fungible(_) => {
-                <FungibleItemList<T>>::get(collection_id, item_id).owner == subject
+                <FungibleItemList<T>>::contains_key(collection_id, &subject)
             }
             CollectionMode::ReFungible(_) => {
                 <ReFungibleItemList<T>>::get(collection_id, item_id)
@@ -1825,95 +1845,38 @@
 
     fn check_white_list(collection_id: CollectionId, address: &T::AccountId) -> DispatchResult {
         let mes = Error::<T>::AddresNotInWhiteList;
-        ensure!(<WhiteList<T>>::contains_key(collection_id), mes);
-        let wl = <WhiteList<T>>::get(collection_id);
-        ensure!(wl.contains(address), mes);
+        ensure!(<WhiteList<T>>::contains_key(collection_id, address), mes);
 
         Ok(())
     }
 
     fn transfer_fungible(
         collection_id: CollectionId,
-        item_id: TokenId,
         value: u128,
-        owner: T::AccountId,
-        new_owner: T::AccountId,
+        owner: &T::AccountId,
+        recipient: &T::AccountId,
     ) -> DispatchResult {
         ensure!(
-            <FungibleItemList<T>>::contains_key(collection_id, item_id),
+            <FungibleItemList<T>>::contains_key(collection_id, owner),
             Error::<T>::TokenNotFound
         );
 
-        let full_item = <FungibleItemList<T>>::get(collection_id, item_id);
-        let amount = full_item.value;
+        let mut balance = <FungibleItemList<T>>::get(collection_id, owner);
+        ensure!(balance.value >= value, Error::<T>::TokenValueTooLow);
 
-        ensure!(amount >= value, Error::<T>::TokenValueTooLow);
+        // Send balance to recipient (updates balanceOf of recipient)
+        Self::add_fungible_item(collection_id, recipient, value)?;
 
-        // update balance
-        let balance_old_owner = <Balance<T>>::get(collection_id, owner.clone())
-            .checked_sub(value)
-            .ok_or(Error::<T>::NumOverflow)?;
-        <Balance<T>>::insert(collection_id, owner.clone(), balance_old_owner);
+        // update balanceOf of sender
+        <Balance<T>>::insert(collection_id, (*owner).clone(), balance.value - value);
 
-        let mut new_owner_account_id = 0;
-        let new_owner_items = <AddressTokens<T>>::get(collection_id, new_owner.clone());
-        if new_owner_items.len() > 0 {
-            new_owner_account_id = new_owner_items[0];
+        // Reduce or remove sender
+        if balance.value == value {
+            <FungibleItemList<T>>::remove(collection_id, owner);
         }
-
-        // transfer
-        if amount == value && new_owner_account_id == 0 {
-            // change owner
-            // new owner do not have account
-            let mut new_full_item = full_item.clone();
-            new_full_item.owner = new_owner.clone();
-            <FungibleItemList<T>>::insert(collection_id, item_id, new_full_item);
-
-            // update balance
-            let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.clone())
-                .checked_add(value)
-                .ok_or(Error::<T>::NumOverflow)?;
-            <Balance<T>>::insert(collection_id, new_owner.clone(), balance_new_owner);
-
-            // update index collection
-            Self::move_token_index(collection_id, item_id, owner.clone(), new_owner.clone())?;
-        } else {
-            let mut new_full_item = full_item.clone();
-            new_full_item.value -= value;
-
-            // separate amount
-            if new_owner_account_id > 0 {
-                // new owner has account
-                let mut item = <FungibleItemList<T>>::get(collection_id, new_owner_account_id);
-                item.value += value;
-
-                // update balance
-                let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.clone())
-                    .checked_add(value)
-                    .ok_or(Error::<T>::NumOverflow)?;
-                <Balance<T>>::insert(collection_id, new_owner.clone(), balance_new_owner);
-
-                <FungibleItemList<T>>::insert(collection_id, new_owner_account_id, item);
-            } else {
-                // new owner do not have account
-                let item = FungibleItemType {
-                    collection: collection_id,
-                    owner: new_owner.clone(),
-                    value
-                };
-
-                Self::add_fungible_item(item)?;
-            }
-
-            if amount == value {
-                Self::remove_token_index(collection_id, item_id, full_item.owner.clone())?;
-
-                // remove approve list
-                <ApprovedList<T>>::remove(collection_id, (item_id, full_item.owner.clone()));
-                <FungibleItemList<T>>::remove(collection_id, item_id);
-            }
-
-            <FungibleItemList<T>>::insert(collection_id, item_id, new_full_item);
+        else {
+            balance.value -= value;
+            <FungibleItemList<T>>::insert(collection_id, (*owner).clone(), balance);
         }
 
         Ok(())
@@ -1948,10 +1911,10 @@
             .ok_or(Error::<T>::NumOverflow)?;
         <Balance<T>>::insert(collection_id, item.owner.clone(), balance_old_owner);
 
-        let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.clone())
+        let balancenew_owner = <Balance<T>>::get(collection_id, new_owner.clone())
             .checked_add(value)
             .ok_or(Error::<T>::NumOverflow)?;
-        <Balance<T>>::insert(collection_id, new_owner.clone(), balance_new_owner);
+        <Balance<T>>::insert(collection_id, new_owner.clone(), balancenew_owner);
 
         let old_owner = item.owner.clone();
         let new_owner_has_account = full_item.owner.iter().any(|i| i.owner == new_owner);
@@ -2028,10 +1991,10 @@
             .ok_or(Error::<T>::NumOverflow)?;
         <Balance<T>>::insert(collection_id, item.owner.clone(), balance_old_owner);
 
-        let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.clone())
+        let balancenew_owner = <Balance<T>>::get(collection_id, new_owner.clone())
             .checked_add(1)
             .ok_or(Error::<T>::NumOverflow)?;
-        <Balance<T>>::insert(collection_id, new_owner.clone(), balance_new_owner);
+        <Balance<T>>::insert(collection_id, new_owner.clone(), balancenew_owner);
 
         // change owner
         let old_owner = item.owner.clone();
@@ -2041,8 +2004,6 @@
         // update index collection
         Self::move_token_index(collection_id, item_id, old_owner.clone(), new_owner.clone())?;
 
-        // reset approved list
-        <ApprovedList<T>>::remove(collection_id, (item_id, old_owner));
         Ok(())
     }
     
@@ -2054,7 +2015,6 @@
         match mode {
             CollectionMode::NFT => ensure!(<NftItemList<T>>::contains_key(collection_id, item_id), Error::<T>::TokenNotFound),
             CollectionMode::ReFungible(_) => ensure!(<ReFungibleItemList<T>>::contains_key(collection_id, item_id), Error::<T>::TokenNotFound),
-            CollectionMode::Fungible(_) => ensure!(<FungibleItemList<T>>::contains_key(collection_id, item_id), Error::<T>::TokenNotFound),
             _ => ()
         };
         
@@ -2116,13 +2076,12 @@
         CreatedCollectionCount::put(next_id);
     }
 
-    fn init_nft_token(item: &NftItemType<T::AccountId>) {
-        let current_index = <ItemListIndex>::get(item.collection)
+    fn init_nft_token(collection_id: CollectionId, item: &NftItemType<T::AccountId>) {
+        let current_index = <ItemListIndex>::get(collection_id)
             .checked_add(1)
             .unwrap();
 
         let item_owner = item.owner.clone();
-        let collection_id = item.collection.clone();
         Self::add_token_index(collection_id, current_index, item.owner.clone()).unwrap();
 
         <ItemListIndex>::insert(collection_id, current_index);
@@ -2134,40 +2093,39 @@
         <Balance<T>>::insert(collection_id, item_owner.clone(), new_balance);
     }
 
-    fn init_fungible_token(item: &FungibleItemType<T::AccountId>) {
-        let current_index = <ItemListIndex>::get(item.collection)
+    fn init_fungible_token(collection_id: CollectionId, owner: &T::AccountId, item: &FungibleItemType) {
+        let current_index = <ItemListIndex>::get(collection_id)
             .checked_add(1)
             .unwrap();
-        let owner = item.owner.clone();
 
-        Self::add_token_index(item.collection, current_index, owner.clone()).unwrap();
+        Self::add_token_index(collection_id, current_index, (*owner).clone()).unwrap();
 
-        <ItemListIndex>::insert(item.collection, current_index);
+        <ItemListIndex>::insert(collection_id, current_index);
 
         // Update balance
-        let new_balance = <Balance<T>>::get(item.collection, owner.clone())
+        let new_balance = <Balance<T>>::get(collection_id, owner)
             .checked_add(item.value)
             .unwrap();
-        <Balance<T>>::insert(item.collection, owner.clone(), new_balance);
+        <Balance<T>>::insert(collection_id, (*owner).clone(), new_balance);
     }
 
-    fn init_refungible_token(item: &ReFungibleItemType<T::AccountId>) {
-        let current_index = <ItemListIndex>::get(item.collection)
+    fn init_refungible_token(collection_id: CollectionId, item: &ReFungibleItemType<T::AccountId>) {
+        let current_index = <ItemListIndex>::get(collection_id)
             .checked_add(1)
             .unwrap();
 
         let value = item.owner.first().unwrap().fraction;
         let owner = item.owner.first().unwrap().owner.clone();
 
-        Self::add_token_index(item.collection, current_index, owner.clone()).unwrap();
+        Self::add_token_index(collection_id, current_index, owner.clone()).unwrap();
 
-        <ItemListIndex>::insert(item.collection, current_index);
+        <ItemListIndex>::insert(collection_id, current_index);
 
         // Update balance
-        let new_balance = <Balance<T>>::get(item.collection, owner.clone())
+        let new_balance = <Balance<T>>::get(collection_id, owner.clone())
             .checked_add(value)
             .unwrap();
-        <Balance<T>>::insert(item.collection, owner.clone(), new_balance);
+        <Balance<T>>::insert(collection_id, owner.clone(), new_balance);
     }
 
     fn add_token_index(collection_id: CollectionId, item_index: TokenId, owner: T::AccountId) -> DispatchResult {
@@ -2245,6 +2203,17 @@
 
         Ok(())
     }
+    
+    fn ensure_contract_owned(account: T::AccountId, contract: &T::AccountId) -> DispatchResult {
+        if <ContractOwner<T>>::contains_key(contract.clone()) {
+            let owner = <ContractOwner<T>>::get(contract);
+            ensure!(account == owner, Error::<T>::NoPermission);
+        } else {
+            fail!(Error::<T>::NoPermission);
+        }
+
+        Ok(())
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -2302,6 +2271,13 @@
         <transaction_payment::Module<T>>::compute_fee(len as u32, info, tip)
     }
 
+	fn get_priority(len: usize, info: &DispatchInfoOf<T::Call>, final_fee: BalanceOf<T>) -> TransactionPriority {
+		let weight_saturation = T::MaximumBlockWeight::get() / info.weight.max(1);
+		let len_saturation = T::MaximumBlockLength::get() as u64 / (len as u64).max(1);
+		let coefficient: BalanceOf<T> = weight_saturation.min(len_saturation).saturated_into::<BalanceOf<T>>();
+		final_fee.saturating_mul(coefficient).saturated_into::<TransactionPriority>()
+	}
+
     fn withdraw_fee(
         &self,
         who: &T::AccountId,
@@ -2320,99 +2296,111 @@
         // };
         let fee = Self::traditional_fee(len, info, tip);
 
+        // Only mess with balances if fee is not zero.
+        if fee.is_zero() {
+            return Ok((fee, None));
+        }
+
         // Determine who is paying transaction fee based on ecnomic model
         // Parse call to extract collection ID and access collection sponsor
         let mut sponsor: T::AccountId = match IsSubType::<Call<T>>::is_sub_type(call) {
             Some(Call::create_item(collection_id, _owner, _properties)) => {
 
                 // check free create limit
-                if <Collection<T>>::get(collection_id).limits.sponsored_data_size >= (_properties.len() as u32)
+                if (<Collection<T>>::get(collection_id).limits.sponsored_data_size >= (_properties.len() as u32)) &&
+                   (<Collection<T>>::get(collection_id).sponsor_confirmed)
                 {
                     <Collection<T>>::get(collection_id).sponsor
                 } else {
                     T::AccountId::default()
                 }
             }
-            Some(Call::transfer(_new_owner, collection_id, _item_id, _value)) => {
+            Some(Call::transfer(_new_owner, collection_id, item_id, _value)) => {
                 
-                let _collection_limits = <Collection<T>>::get(collection_id).limits;
-                let _collection_mode = <Collection<T>>::get(collection_id).mode;
+                let mut sponsor_transfer = false;
+                if <Collection<T>>::get(collection_id).sponsor_confirmed {
 
-                // sponsor timeout
-                let sponsor_transfer = match _collection_mode {
-                    CollectionMode::NFT => {
+                    let collection_limits = <Collection<T>>::get(collection_id).limits;
+                    let collection_mode = <Collection<T>>::get(collection_id).mode;
+    
+                    // sponsor timeout
+                    let block_number = <system::Module<T>>::block_number() as T::BlockNumber;
+                    sponsor_transfer = match collection_mode {
+                        CollectionMode::NFT => {
+    
+                            // get correct limit
+                            let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
+                                collection_limits.sponsor_transfer_timeout
+                            } else {
+                                ChainLimit::get().nft_sponsor_transfer_timeout
+                            };
+    
+                            let mut sponsored = true;
+                            if <NftTransferBasket<T>>::contains_key(collection_id, item_id) {
+                                let last_tx_block = <NftTransferBasket<T>>::get(collection_id, item_id);
+                                let limit_time = last_tx_block + limit.into();
+                                if block_number <= limit_time {
+                                    sponsored = false;
+                                }
+                            }
+                            if sponsored {
+                                <NftTransferBasket<T>>::insert(collection_id, item_id, block_number);
+                            }
 
-                        // get correct limit
-                        let limit: u32 = if _collection_limits.sponsor_transfer_timeout > 0 {
-                            _collection_limits.sponsor_transfer_timeout
-                        } else {
-                            ChainLimit::get().nft_sponsor_transfer_timeout
-                        };
-
-                        let basket = <NftTransferBasket<T>>::get(collection_id, _item_id);
-                        let block_number = <system::Module<T>>::block_number() as T::BlockNumber;
-                        let limit_time = basket + limit.into();
-                        if block_number >= limit_time {
-                            <NftTransferBasket<T>>::insert(collection_id, _item_id, block_number);
-                            true
+                            sponsored
                         }
-                        else {
-                            false
-                        }
-                    }
-                    CollectionMode::Fungible(_) => {
-
-                        // get correct limit
-                        let limit: u32 = if _collection_limits.sponsor_transfer_timeout > 0 {
-                            _collection_limits.sponsor_transfer_timeout
-                        } else {
-                            ChainLimit::get().fungible_sponsor_transfer_timeout
-                        };
-
-                        let mut basket = <FungibleTransferBasket<T>>::get(collection_id, _item_id);
-                        let block_number = <system::Module<T>>::block_number() as T::BlockNumber;
-                        if basket.iter().any(|i| i.address == _new_owner.clone())
-                        {
-                            let item = basket.iter_mut().find(|i| i.address == _new_owner.clone()).unwrap().clone();
-                            let limit_time = item.start_block + limit.into();
-                            if block_number >= limit_time {
-                                basket.retain(|x| x.address == item.address);
-                                basket.push(BasketItem { start_block: block_number, address: _new_owner.clone() });
-                                <FungibleTransferBasket<T>>::insert(collection_id, _item_id, basket);
-                                true
+                        CollectionMode::Fungible(_) => {
+    
+                            // get correct limit
+                            let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
+                                collection_limits.sponsor_transfer_timeout
+                            } else {
+                                ChainLimit::get().fungible_sponsor_transfer_timeout
+                            };
+    
+                            let block_number = <system::Module<T>>::block_number() as T::BlockNumber;
+                            let mut sponsored = true;
+                            if <FungibleTransferBasket<T>>::contains_key(collection_id, who) {
+                                let last_tx_block = <FungibleTransferBasket<T>>::get(collection_id, who);
+                                let limit_time = last_tx_block + limit.into();
+                                if block_number <= limit_time {
+                                    sponsored = false;
+                                }
                             }
-                            else {
-                                false
+                            if sponsored {
+                                <FungibleTransferBasket<T>>::insert(collection_id, who, block_number);
                             }
+
+                            sponsored
                         }
-                        else {
-                            basket.push(BasketItem { start_block: block_number, address: _new_owner.clone()});
-                            true
-                        }
-                    }
-                    CollectionMode::ReFungible(_) => {
-
-                        // get correct limit
-                        let limit: u32 = if _collection_limits.sponsor_transfer_timeout > 0 {
-                            _collection_limits.sponsor_transfer_timeout
-                        } else {
-                            ChainLimit::get().refungible_sponsor_transfer_timeout
-                        };
+                        CollectionMode::ReFungible(_) => {
+    
+                            // get correct limit
+                            let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
+                                collection_limits.sponsor_transfer_timeout
+                            } else {
+                                ChainLimit::get().refungible_sponsor_transfer_timeout
+                            };
+    
+                            let mut sponsored = true;
+                            if <ReFungibleTransferBasket<T>>::contains_key(collection_id, item_id) {
+                                let last_tx_block = <ReFungibleTransferBasket<T>>::get(collection_id, item_id);
+                                let limit_time = last_tx_block + limit.into();
+                                if block_number <= limit_time {
+                                    sponsored = false;
+                                }
+                            }
+                            if sponsored {
+                                <ReFungibleTransferBasket<T>>::insert(collection_id, item_id, block_number);
+                            }
 
-                        let basket = <ReFungibleTransferBasket<T>>::get(collection_id, _item_id);
-                        let block_number = <system::Module<T>>::block_number() as T::BlockNumber;
-                        let limit_time = basket + limit.into();
-                        if block_number >= limit_time {
-                            <ReFungibleTransferBasket<T>>::insert(collection_id, _item_id, block_number);
-                            true
-                        } else {
-                            false
+                            sponsored
                         }
-                    }
-                    _ => {
-                        false
-                    },
-                };
+                        _ => {
+                            false
+                        },
+                    };
+                }
 
                 if !sponsor_transfer {
                     T::AccountId::default()
@@ -2445,6 +2433,16 @@
 
                 let called_contract: T::AccountId = T::Lookup::lookup((*dest).clone()).unwrap_or(T::AccountId::default());
 
+                let owned_contract = <ContractOwner<T>>::contains_key(called_contract.clone())
+                  && <ContractOwner<T>>::get(called_contract.clone()) == *who;
+                let white_list_enabled = <ContractWhiteListEnabled<T>>::contains_key(called_contract.clone()) && <ContractWhiteListEnabled<T>>::get(called_contract.clone());
+                  
+                if !owned_contract && white_list_enabled {
+                    if !<ContractWhiteList<T>>::contains_key(called_contract.clone(), who) {
+                        return Err(InvalidTransaction::Call.into());
+                    }
+                }
+
                 let mut sponsor_transfer = false;
                 if <ContractSponsoringRateLimit<T>>::contains_key(called_contract.clone()) {
                     let last_tx_block = <ContractSponsorBasket<T>>::get((&called_contract, &who));
@@ -2481,11 +2479,6 @@
             who_pays_fee = who.clone();
         }
 
-        // Only mess with balances if fee is not zero.
-        if fee.is_zero() {
-            return Ok((fee, None));
-        }
-
         match <T as transaction_payment::Trait>::Currency::withdraw(
             &who_pays_fee,
             fee,
@@ -2525,12 +2518,16 @@
 
     fn validate(
         &self,
-        _who: &Self::AccountId,
-        _call: &Self::Call,
-        _info: &DispatchInfoOf<Self::Call>,
-        _len: usize,
+        who: &Self::AccountId,
+        call: &Self::Call,
+        info: &DispatchInfoOf<Self::Call>,
+        len: usize,
     ) -> TransactionValidity {
-        Ok(ValidTransaction::default())
+		let (fee, _) = self.withdraw_fee(who, call, info, len)?;
+		Ok(ValidTransaction {
+			priority: Self::get_priority(len, info, fee),
+			..Default::default()
+		})
     }
 
     fn pre_dispatch(
modifiedpallets/nft/src/tests.rsdiffbeforeafterboth
before · pallets/nft/src/tests.rs
1// Tests to be written here2use super::*;3use crate::mock::*;4use crate::{AccessMode, ApprovePermissions, 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        }));24}2526fn default_nft_data() -> CreateNftData {27    CreateNftData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] }28}2930fn default_fungible_data () -> CreateFungibleData {31    CreateFungibleData { }32}3334fn default_re_fungible_data () -> CreateReFungibleData {35    CreateReFungibleData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] }36}3738fn create_test_collection_for_owner(mode: &CollectionMode, owner: u64, id: CollectionId) -> CollectionId {39    let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();40    let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();41    let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();4243    let origin1 = Origin::signed(owner);44    assert_ok!(TemplateModule::create_collection(45            origin1.clone(),46            col_name1.clone(),47            col_desc1.clone(),48            token_prefix1.clone(),49            mode.clone()50        ));5152    let saved_col_name: Vec<u16> = "Test1\0\0".encode_utf16().collect::<Vec<u16>>();53    let saved_description: Vec<u16> = "TestDescription1\0\0".encode_utf16().collect::<Vec<u16>>();54    let saved_prefix: Vec<u8> = b"token_prefix1\0\0".to_vec();55    assert_eq!(TemplateModule::collection(id).owner, owner);56    assert_eq!(TemplateModule::collection(id).name, saved_col_name);57    assert_eq!(TemplateModule::collection(id).mode, *mode);58    assert_eq!(TemplateModule::collection(id).description, saved_description);59    assert_eq!(TemplateModule::collection(id).token_prefix, saved_prefix);60    id61}6263fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {64    create_test_collection_for_owner(&mode, 1, id)65}6667fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {68    let origin1 = Origin::signed(1);69    assert_ok!(TemplateModule::create_item(70            origin1.clone(),71            collection_id,72            1,73            data.clone()74        ));7576}7778// Use cases tests region79// #region8081#[test]82fn set_version_schema() {83    new_test_ext().execute_with(|| {84        default_limits();85        let origin1 = Origin::signed(1);86        let collection_id = create_test_collection(&CollectionMode::NFT, 1);87        88        assert_ok!(TemplateModule::set_schema_version(origin1, collection_id, SchemaVersion::Unique));89        assert_eq!(TemplateModule::collection(collection_id).schema_version, SchemaVersion::Unique);90    });91}9293#[test]94fn create_fungible_collection_fails_with_large_decimal_numbers() {95    new_test_ext().execute_with(|| {96        default_limits();9798        let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();99        let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();100        let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();101102        let origin1 = Origin::signed(1);103        assert_noop!(TemplateModule::create_collection(104            origin1,105            col_name1,106            col_desc1,107            token_prefix1,108            CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1)109        ), Error::<Test>::CollectionDecimalPointLimitExceeded);110    });    111}112113#[test]114fn create_re_fungible_collection_fails_with_large_decimal_numbers() {115    new_test_ext().execute_with(|| {116        default_limits();117118        let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();119        let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();120        let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();121122        let origin1 = Origin::signed(1);123        assert_noop!(TemplateModule::create_collection(124            origin1,125            col_name1,126            col_desc1,127            token_prefix1,128            CollectionMode::ReFungible(MAX_DECIMAL_POINTS + 1)129        ), Error::<Test>::CollectionDecimalPointLimitExceeded);130    });131}132133#[test]134fn create_nft_item() {135    new_test_ext().execute_with(|| {136        default_limits();137        let collection_id = create_test_collection(&CollectionMode::NFT, 1);138        139        let data = default_nft_data();140        create_test_item(collection_id, &data.clone().into());141        assert_eq!(TemplateModule::nft_item_id(collection_id, 1).const_data, data.const_data);142        assert_eq!(TemplateModule::nft_item_id(collection_id, 1).variable_data, data.variable_data);143    });144}145146// Use cases tests region147// #region148#[test]149fn create_nft_multiple_items() {150    new_test_ext().execute_with(|| {151        default_limits();152        153        create_test_collection(&CollectionMode::NFT, 1);154155        let origin1 = Origin::signed(1);156157        let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];158159        assert_ok!(TemplateModule::create_multiple_items(160            origin1.clone(),161            1,162            1,163            items_data.clone().into_iter().map(|d| { d.into() }).collect()164        ));165        for (index, data) in items_data.iter().enumerate() {166            assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as TokenId).const_data.to_vec(), data.const_data);167            assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as TokenId).variable_data.to_vec(), data.variable_data);168        }169    });170}171172#[test]173fn create_refungible_item() {174    new_test_ext().execute_with(|| {175        default_limits();176        let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);177178        let data = default_re_fungible_data();179        create_test_item(collection_id, &data.clone().into());180        assert_eq!(181            TemplateModule::refungible_item_id(collection_id, 1).const_data,182            data.const_data183        );184        assert_eq!(185            TemplateModule::refungible_item_id(collection_id, 1).variable_data,186            data.variable_data187        );188        assert_eq!(189            TemplateModule::refungible_item_id(collection_id, 1).owner[0],190            Ownership {191                owner: 1,192                fraction: 1000193            }194        );195    });196}197198#[test]199fn create_multiple_refungible_items() {200    new_test_ext().execute_with(|| {201        default_limits();202        203        create_test_collection(&CollectionMode::ReFungible(3), 1);204205        let origin1 = Origin::signed(1);206207        let items_data = vec![default_re_fungible_data(), default_re_fungible_data(), default_re_fungible_data()];208209        assert_ok!(TemplateModule::create_multiple_items(210            origin1.clone(),211            1,212            1,213            items_data.clone().into_iter().map(|d| { d.into() }).collect()214        ));215        for (index, data) in items_data.iter().enumerate() {216217            let item = TemplateModule::refungible_item_id(1, (index + 1) as TokenId);218            assert_eq!(item.const_data.to_vec(), data.const_data);219            assert_eq!(item.variable_data.to_vec(), data.variable_data);220            assert_eq!(221                item.owner[0],222                Ownership {223                    owner: 1,224                    fraction: 1000225                }226            );227        }228    });229}230231#[test]232fn create_fungible_item() {233    new_test_ext().execute_with(|| {234        default_limits();235        236        let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);237238        let data = default_fungible_data();239        create_test_item(collection_id, &data.into());240241        assert_eq!(TemplateModule::fungible_item_id(collection_id, 1).owner, 1);242    });243}244245#[test]246fn create_multiple_fungible_items() {247    new_test_ext().execute_with(|| {248        default_limits();249250        create_test_collection(&CollectionMode::Fungible(3), 1);251252        let origin1 = Origin::signed(1);253254        let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];255256        assert_ok!(TemplateModule::create_multiple_items(257            origin1.clone(),258            1,259            1,260            items_data.clone().into_iter().map(|d| { d.into() }).collect()261        ));262        263        for (index, _) in items_data.iter().enumerate() {264            assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as TokenId).owner, 1);265        }266        assert_eq!(TemplateModule::balance_count(1, 1), 3000);267        assert_eq!(TemplateModule::address_tokens(1, 1), [1, 2, 3]);268    });269}270271#[test]272fn transfer_fungible_item() {273    new_test_ext().execute_with(|| {274        default_limits();275        276        let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);277278        let origin1 = Origin::signed(1);279        let origin2 = Origin::signed(2);280281        let data = default_fungible_data();282        create_test_item(collection_id, &data.into());283284        assert_eq!(TemplateModule::fungible_item_id(1, 1).owner, 1);285        assert_eq!(TemplateModule::balance_count(1, 1), 1000);286        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);287288        // change owner scenario289        assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1000));290        assert_eq!(TemplateModule::fungible_item_id(1, 1).owner, 2);291        assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 1000);292        assert_eq!(TemplateModule::balance_count(1, 1), 0);293        assert_eq!(TemplateModule::balance_count(1, 2), 1000);294        // assert_eq!(TemplateModule::address_tokens(1, 1), []);295        assert_eq!(TemplateModule::address_tokens(1, 2), [1]);296297        // split item scenario298        assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 500));299        assert_eq!(TemplateModule::fungible_item_id(1, 1).owner, 2);300        assert_eq!(TemplateModule::fungible_item_id(1, 2).owner, 3);301        assert_eq!(TemplateModule::balance_count(1, 2), 500);302        assert_eq!(TemplateModule::balance_count(1, 3), 500);303        assert_eq!(TemplateModule::address_tokens(1, 2), [1]);304        assert_eq!(TemplateModule::address_tokens(1, 3), [2]);305306        // split item and new owner has account scenario307        assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 200));308        assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 300);309        assert_eq!(TemplateModule::fungible_item_id(1, 2).value, 700);310        assert_eq!(TemplateModule::balance_count(1, 2), 300);311        assert_eq!(TemplateModule::balance_count(1, 3), 700);312        assert_eq!(TemplateModule::address_tokens(1, 2), [1]);313        assert_eq!(TemplateModule::address_tokens(1, 3), [2]);314    });315}316317#[test]318fn transfer_refungible_item() {319    new_test_ext().execute_with(|| {320        default_limits();321        322        let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);323324        let data = default_re_fungible_data();325        create_test_item(collection_id, &data.clone().into());326327        let origin1 = Origin::signed(1);328        let origin2 = Origin::signed(2);329        assert_eq!(330            TemplateModule::refungible_item_id(collection_id, 1).const_data,331            data.const_data332        );333        assert_eq!(334            TemplateModule::refungible_item_id(collection_id, 1).variable_data,335            data.variable_data336        );337        assert_eq!(338            TemplateModule::refungible_item_id(collection_id, 1).owner[0],339            Ownership {340                owner: 1,341                fraction: 1000342            }343        );344        assert_eq!(TemplateModule::balance_count(1, 1), 1000);345        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);346347        // change owner scenario348        assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1000));349        assert_eq!(350            TemplateModule::refungible_item_id(1, 1).owner[0],351            Ownership {352                owner: 2,353                fraction: 1000354            }355        );356        assert_eq!(TemplateModule::balance_count(1, 1), 0);357        assert_eq!(TemplateModule::balance_count(1, 2), 1000);358        // assert_eq!(TemplateModule::address_tokens(1, 1), []);359        assert_eq!(TemplateModule::address_tokens(1, 2), [1]);360361        // split item scenario362        assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 500));363        assert_eq!(364            TemplateModule::refungible_item_id(1, 1).owner[0],365            Ownership {366                owner: 2,367                fraction: 500368            }369        );370        assert_eq!(371            TemplateModule::refungible_item_id(1, 1).owner[1],372            Ownership {373                owner: 3,374                fraction: 500375            }376        );377        assert_eq!(TemplateModule::balance_count(1, 2), 500);378        assert_eq!(TemplateModule::balance_count(1, 3), 500);379        assert_eq!(TemplateModule::address_tokens(1, 2), [1]);380        assert_eq!(TemplateModule::address_tokens(1, 3), [1]);381382        // split item and new owner has account scenario383        assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 200));384        assert_eq!(385            TemplateModule::refungible_item_id(1, 1).owner[0],386            Ownership {387                owner: 2,388                fraction: 300389            }390        );391        assert_eq!(392            TemplateModule::refungible_item_id(1, 1).owner[1],393            Ownership {394                owner: 3,395                fraction: 700396            }397        );398        assert_eq!(TemplateModule::balance_count(1, 2), 300);399        assert_eq!(TemplateModule::balance_count(1, 3), 700);400        assert_eq!(TemplateModule::address_tokens(1, 2), [1]);401        assert_eq!(TemplateModule::address_tokens(1, 3), [1]);402    });403}404405#[test]406fn transfer_nft_item() {407    new_test_ext().execute_with(|| {408        default_limits();409        410        let collection_id = create_test_collection(&CollectionMode::NFT, 1);411412        let data = default_nft_data();413        create_test_item(collection_id, &data.into());414        assert_eq!(TemplateModule::balance_count(1, 1), 1);415        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);416417        let origin1 = Origin::signed(1);418        // default scenario419        assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1000));420        assert_eq!(TemplateModule::nft_item_id(1, 1).owner, 2);421        assert_eq!(TemplateModule::balance_count(1, 1), 0);422        assert_eq!(TemplateModule::balance_count(1, 2), 1);423        // assert_eq!(TemplateModule::address_tokens(1, 1), []);424        assert_eq!(TemplateModule::address_tokens(1, 2), [1]);425    });426}427428#[test]429fn nft_approve_and_transfer_from() {430    new_test_ext().execute_with(|| {431        default_limits();432        433        let collection_id = create_test_collection(&CollectionMode::NFT, 1);434435        let data = default_nft_data();436        create_test_item(collection_id, &data.into());437438        let origin1 = Origin::signed(1);439        let origin2 = Origin::signed(2);440441        assert_eq!(TemplateModule::balance_count(1, 1), 1);442        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);443444        // neg transfer445        assert_noop!(TemplateModule::transfer_from(446            origin2.clone(),447            1,448            2,449            1,450            1,451            1), Error::<Test>::NoPermission);452453        // do approve454        assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));455        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);456        assert_eq!(457            TemplateModule::approved(1, (1, 1))[0],458            ApprovePermissions {459                approved: 2,460                amount: 100000000461            }462        );463464        assert_ok!(TemplateModule::transfer_from(465            origin2.clone(),466            1,467            2,468            1,469            1,470            1471        ));472        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 0);473    });474}475476#[test]477fn nft_approve_and_transfer_from_white_list() {478    new_test_ext().execute_with(|| {479        default_limits();480        481        let collection_id = create_test_collection(&CollectionMode::NFT, 1);482483        let origin1 = Origin::signed(1);484        let origin2 = Origin::signed(2);485486        let data = default_nft_data();487        create_test_item(collection_id, &data.clone().into());488489        assert_eq!(TemplateModule::nft_item_id(1, 1).const_data, data.const_data);490        assert_eq!(TemplateModule::balance_count(1, 1), 1);491        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);492493        assert_ok!(TemplateModule::set_mint_permission(494            origin1.clone(),495            1,496            true497        ));498        assert_ok!(TemplateModule::set_public_access_mode(499            origin1.clone(),500            1,501            AccessMode::WhiteList502        ));503        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));504        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));505        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));506507        // do approve508        assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));509        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);510        assert_ok!(TemplateModule::approve(origin1.clone(), 3, 1, 1));511        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 2);512        assert_eq!(513            TemplateModule::approved(1, (1, 1))[0],514            ApprovePermissions {515                approved: 2,516                amount: 100000000517            }518        );519520        assert_ok!(TemplateModule::transfer_from(521            origin2.clone(),522            1,523            3,524            1,525            1,526            1527        ));528        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 0);529    });530}531532#[test]533fn refungible_approve_and_transfer_from() {534    new_test_ext().execute_with(|| {535        default_limits();536        537        let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);538        539        let origin1 = Origin::signed(1);540        let origin2 = Origin::signed(2);541542        let data = default_re_fungible_data();543        create_test_item(collection_id, &data.into());544545        assert_eq!(TemplateModule::balance_count(1, 1), 1000);546        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);547548        assert_ok!(TemplateModule::set_mint_permission(549            origin1.clone(),550            1,551            true552        ));553        assert_ok!(TemplateModule::set_public_access_mode(554            origin1.clone(),555            1,556            AccessMode::WhiteList557        ));558        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));559        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));560        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));561562        // do approve563        assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));564        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);565        assert_ok!(TemplateModule::approve(origin1.clone(), 3, 1, 1));566        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 2);567        assert_eq!(568            TemplateModule::approved(1, (1, 1))[0],569            ApprovePermissions {570                approved: 2,571                amount: 100000000572            }573        );574575        assert_ok!(TemplateModule::transfer_from(576            origin2.clone(),577            1,578            3,579            1,580            1,581            100582        ));583        assert_eq!(TemplateModule::balance_count(1, 1), 900);584        assert_eq!(TemplateModule::balance_count(1, 3), 100);585        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);586        assert_eq!(TemplateModule::address_tokens(1, 3), [1]);587588        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);589        assert_eq!(590            TemplateModule::approved(1, (1, 1))[0],591            ApprovePermissions {592                approved: 3,593                amount: 100000000594            }595        );596    });597}598599#[test]600fn fungible_approve_and_transfer_from() {601    new_test_ext().execute_with(|| {602        default_limits();603        604        let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);605        606        let data = default_fungible_data();607        create_test_item(collection_id, &data.into());608609        let origin1 = Origin::signed(1);610        let origin2 = Origin::signed(2);611612        assert_eq!(TemplateModule::balance_count(1, 1), 1000);613        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);614615        assert_ok!(TemplateModule::set_mint_permission(616            origin1.clone(),617            1,618            true619        ));620        assert_ok!(TemplateModule::set_public_access_mode(621            origin1.clone(),622            1,623            AccessMode::WhiteList624        ));625        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));626        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));627        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));628629        // do approve630        assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));631        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);632        assert_ok!(TemplateModule::approve(origin1.clone(), 3, 1, 1));633        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 2);634        assert_eq!(635            TemplateModule::approved(1, (1, 1))[0],636            ApprovePermissions {637                approved: 2,638                amount: 100000000639            }640        );641642        assert_ok!(TemplateModule::transfer_from(643            origin2.clone(),644            1,645            3,646            1,647            1,648            100649        ));650        assert_eq!(TemplateModule::balance_count(1, 1), 900);651        assert_eq!(TemplateModule::balance_count(1, 3), 100);652        assert_eq!(TemplateModule::address_tokens(1, 1), [1]);653        assert_eq!(TemplateModule::address_tokens(1, 3), [2]);654655        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);656        assert_eq!(657            TemplateModule::approved(1, (1, 1))[0],658            ApprovePermissions {659                approved: 3,660                amount: 100000000661            }662        );663664        assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));665        assert_ok!(TemplateModule::transfer_from(666            origin2.clone(),667            1,668            3,669            1,670            1,671            900672        ));673        assert_eq!(TemplateModule::balance_count(1, 1), 0);674        assert_eq!(TemplateModule::balance_count(1, 3), 1000);675        // assert_eq!(TemplateModule::address_tokens(1, 1), []);676        assert_eq!(TemplateModule::address_tokens(1, 3), [2]);677678        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 0);679    });680}681682#[test]683fn change_collection_owner() {684    new_test_ext().execute_with(|| {685        default_limits();686        687        let collection_id = create_test_collection(&CollectionMode::NFT, 1);688        689        let origin1 = Origin::signed(1);690        assert_ok!(TemplateModule::change_collection_owner(691            origin1.clone(),692            collection_id,693            2694        ));695        assert_eq!(TemplateModule::collection(collection_id).owner, 2);696    });697}698699#[test]700fn destroy_collection() {701    new_test_ext().execute_with(|| {702        default_limits();703        704        let collection_id = create_test_collection(&CollectionMode::NFT, 1);705        706        let origin1 = Origin::signed(1);707        assert_ok!(TemplateModule::destroy_collection(origin1.clone(), collection_id));708    });709}710711#[test]712fn burn_nft_item() {713    new_test_ext().execute_with(|| {714        default_limits();715        716        let collection_id = create_test_collection(&CollectionMode::NFT, 1);717718        let origin1 = Origin::signed(1);719        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));720        721        let data = default_nft_data();722        create_test_item(collection_id, &data.into());723724        // check balance (collection with id = 1, user id = 1)725        assert_eq!(TemplateModule::balance_count(1, 1), 1);726727        // burn item728        assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1));729        assert_noop!(730            TemplateModule::burn_item(origin1.clone(), 1, 1),731            Error::<Test>::TokenNotFound732        );733734        assert_eq!(TemplateModule::balance_count(1, 1), 0);735    });736}737738#[test]739fn burn_fungible_item() {740    new_test_ext().execute_with(|| {741        default_limits();742        743        let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);744        745        let origin1 = Origin::signed(1);746        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));747        748        let data = default_fungible_data();749        create_test_item(collection_id, &data.into());750751        // check balance (collection with id = 1, user id = 1)752        assert_eq!(TemplateModule::balance_count(1, 1), 1000);753754        // burn item755        assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1));756        assert_noop!(757            TemplateModule::burn_item(origin1.clone(), 1, 1),758            Error::<Test>::TokenNotFound759        );760761        assert_eq!(TemplateModule::balance_count(1, 1), 0);762    });763}764765#[test]766fn burn_refungible_item() {767    new_test_ext().execute_with(|| {768        default_limits();769        770        let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);771        let origin1 = Origin::signed(1);772773        assert_ok!(TemplateModule::set_mint_permission(774            origin1.clone(),775            collection_id,776            true777        ));778        assert_ok!(TemplateModule::set_public_access_mode(779            origin1.clone(),780            collection_id,781            AccessMode::WhiteList782        ));783        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));784785        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));786        787        let data = default_re_fungible_data();788        create_test_item(collection_id, &data.into());789790        // check balance (collection with id = 1, user id = 2)791        assert_eq!(TemplateModule::balance_count(1, 1), 1000);792793        // burn item794        assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1));795        assert_noop!(796            TemplateModule::burn_item(origin1.clone(), 1, 1),797            Error::<Test>::TokenNotFound798        );799800        assert_eq!(TemplateModule::balance_count(1, 1), 0);801    });802}803804#[test]805fn add_collection_admin() {806    new_test_ext().execute_with(|| {807        default_limits();808        809        let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);810        create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);811        create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);812        813        let origin1 = Origin::signed(1);814815        // collection admin816        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 2));817        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 3));818819        assert_eq!(TemplateModule::admin_list_collection(collection1_id).contains(&2), true);820        assert_eq!(TemplateModule::admin_list_collection(collection1_id).contains(&3), true);821    });822}823824#[test]825fn remove_collection_admin() {826    new_test_ext().execute_with(|| {827        default_limits();828        829        let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);830        create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);831        create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);832833        let origin1 = Origin::signed(1);834        let origin2 = Origin::signed(2);835836        // collection admin837        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 2));838        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 3));839840        assert_eq!(TemplateModule::admin_list_collection(1).contains(&2), true);841        assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), true);842843        // remove admin844        assert_ok!(TemplateModule::remove_collection_admin(845            origin2.clone(),846            1,847            3848        ));849        assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), false);850    });851}852853#[test]854fn balance_of() {855    new_test_ext().execute_with(|| {856        default_limits();857        858        let nft_collection_id = create_test_collection(&CollectionMode::NFT, 1);859        let fungible_collection_id = create_test_collection(&CollectionMode::Fungible(3), 2);860        let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible(3), 3);861        862        // check balance before863        assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 0);864        assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 0);865        assert_eq!(TemplateModule::balance_count(re_fungible_collection_id, 1), 0);866867        let nft_data = default_nft_data();868        create_test_item(nft_collection_id, &nft_data.into());869        870        let fungible_data = default_fungible_data();871        create_test_item(fungible_collection_id, &fungible_data.into());872        873        let re_fungible_data = default_re_fungible_data();874        create_test_item(re_fungible_collection_id, &re_fungible_data.into());875876        // check balance (collection with id = 1, user id = 1)877        assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 1);878        assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 1000);879        assert_eq!(TemplateModule::balance_count(re_fungible_collection_id, 1), 1000);880        assert_eq!(TemplateModule::nft_item_id(nft_collection_id, 1).owner, 1);881        assert_eq!(TemplateModule::fungible_item_id(fungible_collection_id, 1).owner, 1);882        assert_eq!(TemplateModule::refungible_item_id(re_fungible_collection_id, 1).owner[0].owner, 1);883    });884}885886#[test]887fn approve() {888    new_test_ext().execute_with(|| {889        default_limits();890        891        let collection_id = create_test_collection(&CollectionMode::NFT, 1);892        893        let data = default_nft_data();894        create_test_item(collection_id, &data.into());895896        let origin1 = Origin::signed(1);897        898        // approve899        assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));900        assert_eq!(TemplateModule::approved(1, (1, 1))[0].approved, 2);901    });902}903904#[test]905fn transfer_from() {906    new_test_ext().execute_with(|| {907        default_limits();908        909        let collection_id = create_test_collection(&CollectionMode::NFT, 1);910        let origin1 = Origin::signed(1);911        let origin2 = Origin::signed(2);912913        let data = default_nft_data();914        create_test_item(collection_id, &data.into());915916        // approve917        assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));918        assert_eq!(TemplateModule::approved(1, (1, 1))[0].approved, 2);919920        assert_ok!(TemplateModule::set_mint_permission(921            origin1.clone(),922            1,923            true924        ));925        assert_ok!(TemplateModule::set_public_access_mode(926            origin1.clone(),927            1,928            AccessMode::WhiteList929        ));930        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));931        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));932        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));933934        assert_ok!(TemplateModule::transfer_from(935            origin2.clone(),936            1,937            2,938            1,939            1,940            1941        ));942943        // after transfer944        assert_eq!(TemplateModule::balance_count(1, 1), 0);945        assert_eq!(TemplateModule::balance_count(1, 2), 1);946    });947}948949// #endregion950951// Coverage tests region952// #region953954#[test]955fn owner_can_add_address_to_white_list() {956    new_test_ext().execute_with(|| {957        default_limits();958        959        let collection_id = create_test_collection(&CollectionMode::NFT, 1);960961        let origin1 = Origin::signed(1);962        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));963        assert_eq!(TemplateModule::white_list(collection_id)[0], 2);964    });965}966967#[test]968fn admin_can_add_address_to_white_list() {969    new_test_ext().execute_with(|| {970        default_limits();971        972        let collection_id = create_test_collection(&CollectionMode::NFT, 1);973        let origin1 = Origin::signed(1);974        let origin2 = Origin::signed(2);975976        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));977        assert_ok!(TemplateModule::add_to_white_list(origin2.clone(), collection_id, 3));978        assert_eq!(TemplateModule::white_list(collection_id)[0], 3);979    });980}981982#[test]983fn nonprivileged_user_cannot_add_address_to_white_list() {984    new_test_ext().execute_with(|| {985        default_limits();986        987        let collection_id = create_test_collection(&CollectionMode::NFT, 1);988989        let origin2 = Origin::signed(2);990        assert_noop!(991            TemplateModule::add_to_white_list(origin2.clone(), collection_id, 3),992            Error::<Test>::NoPermission993        );994    });995}996997#[test]998fn nobody_can_add_address_to_white_list_of_nonexisting_collection() {999    new_test_ext().execute_with(|| {1000        default_limits();10011002        let origin1 = Origin::signed(1);10031004        assert_noop!(1005            TemplateModule::add_to_white_list(origin1.clone(), 1, 2),1006            Error::<Test>::CollectionNotFound1007        );1008    });1009}10101011#[test]1012fn nobody_can_add_address_to_white_list_of_deleted_collection() {1013    new_test_ext().execute_with(|| {1014        default_limits();1015        1016        let collection_id = create_test_collection(&CollectionMode::NFT, 1);10171018        let origin1 = Origin::signed(1);1019        assert_ok!(TemplateModule::destroy_collection(origin1.clone(), collection_id));1020        assert_noop!(1021            TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2),1022            Error::<Test>::CollectionNotFound1023        );1024    });1025}10261027// If address is already added to white list, nothing happens1028#[test]1029fn address_is_already_added_to_white_list() {1030    new_test_ext().execute_with(|| {1031        default_limits();1032        1033        let collection_id = create_test_collection(&CollectionMode::NFT, 1);1034        let origin1 = Origin::signed(1);1035        1036        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1037        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1038        assert_eq!(TemplateModule::white_list(collection_id)[0], 2);1039        assert_eq!(TemplateModule::white_list(collection_id).len(), 1);1040    });1041}10421043#[test]1044fn owner_can_remove_address_from_white_list() {1045    new_test_ext().execute_with(|| {1046        default_limits();1047        1048        let collection_id = create_test_collection(&CollectionMode::NFT, 1);10491050        let origin1 = Origin::signed(1);1051        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1052        assert_ok!(TemplateModule::remove_from_white_list(1053            origin1.clone(),1054            collection_id,1055            21056        ));1057        assert_eq!(TemplateModule::white_list(collection_id).len(), 0);1058    });1059}10601061#[test]1062fn admin_can_remove_address_from_white_list() {1063    new_test_ext().execute_with(|| {1064        default_limits();1065        1066        let collection_id = create_test_collection(&CollectionMode::NFT, 1);1067        let origin1 = Origin::signed(1);1068        let origin2 = Origin::signed(2);10691070        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));10711072        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 3));1073        assert_ok!(TemplateModule::remove_from_white_list(1074            origin2.clone(),1075            collection_id,1076            31077        ));1078        assert_eq!(TemplateModule::white_list(collection_id).len(), 0);1079    });1080}10811082#[test]1083fn nonprivileged_user_cannot_remove_address_from_white_list() {1084    new_test_ext().execute_with(|| {1085        default_limits();1086        1087        let collection_id = create_test_collection(&CollectionMode::NFT, 1);1088        let origin1 = Origin::signed(1);1089        let origin2 = Origin::signed(2);10901091        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1092        assert_noop!(1093            TemplateModule::remove_from_white_list(origin2.clone(), collection_id, 2),1094            Error::<Test>::NoPermission1095        );1096        assert_eq!(TemplateModule::white_list(collection_id)[0], 2);1097    });1098}10991100#[test]1101fn nobody_can_remove_address_from_white_list_of_nonexisting_collection() {1102    new_test_ext().execute_with(|| {1103        default_limits();1104        let origin1 = Origin::signed(1);11051106        assert_noop!(1107            TemplateModule::remove_from_white_list(origin1.clone(), 1, 2),1108            Error::<Test>::CollectionNotFound1109        );1110    });1111}11121113#[test]1114fn nobody_can_remove_address_from_white_list_of_deleted_collection() {1115    new_test_ext().execute_with(|| {1116        default_limits();1117        1118        let collection_id = create_test_collection(&CollectionMode::NFT, 1);1119        let origin1 = Origin::signed(1);1120        let origin2 = Origin::signed(2);11211122        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1123        assert_ok!(TemplateModule::destroy_collection(origin1.clone(), collection_id));1124        assert_noop!(1125            TemplateModule::remove_from_white_list(origin2.clone(), collection_id, 2),1126            Error::<Test>::CollectionNotFound1127        );1128        assert_eq!(TemplateModule::white_list(collection_id).len(), 0);1129    });1130}11311132// If address is already removed from white list, nothing happens1133#[test]1134fn address_is_already_removed_from_white_list() {1135    new_test_ext().execute_with(|| {1136        default_limits();1137        1138        let collection_id = create_test_collection(&CollectionMode::NFT, 1);1139        let origin1 = Origin::signed(1);11401141        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1142        assert_ok!(TemplateModule::remove_from_white_list(1143            origin1.clone(),1144            collection_id,1145            21146        ));1147        assert_ok!(TemplateModule::remove_from_white_list(1148            origin1.clone(),1149            collection_id,1150            21151        ));1152        assert_eq!(TemplateModule::white_list(collection_id).len(), 0);1153    });1154}11551156// If Public Access mode is set to WhiteList, tokens can’t be transferred from a non-whitelisted address with transfer or transferFrom (2 tests)1157#[test]1158fn white_list_test_1() {1159    new_test_ext().execute_with(|| {1160        default_limits();1161        1162        let collection_id = create_test_collection(&CollectionMode::NFT, 1);11631164        let origin1 = Origin::signed(1);1165        1166        let data = default_nft_data();1167        create_test_item(collection_id, &data.into());11681169        assert_ok!(TemplateModule::set_public_access_mode(1170            origin1.clone(),1171            collection_id,1172            AccessMode::WhiteList1173        ));1174        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));11751176        assert_noop!(1177            TemplateModule::transfer(origin1.clone(), 3, 1, 1, 1),1178            Error::<Test>::AddresNotInWhiteList1179        );1180    });1181}11821183#[test]1184fn white_list_test_2() {1185    new_test_ext().execute_with(|| {1186        default_limits();1187        1188        let collection_id = create_test_collection(&CollectionMode::NFT, 1);1189        let origin1 = Origin::signed(1);1190        1191        let data = default_nft_data();1192        create_test_item(collection_id, &data.into());11931194        assert_ok!(TemplateModule::set_public_access_mode(1195            origin1.clone(),1196            collection_id,1197            AccessMode::WhiteList1198        ));1199        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));1200        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));12011202        // do approve1203        assert_ok!(TemplateModule::approve(origin1.clone(), 1, 1, 1));1204        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);12051206        assert_ok!(TemplateModule::remove_from_white_list(1207            origin1.clone(),1208            1,1209            11210        ));12111212        assert_noop!(1213            TemplateModule::transfer_from(origin1.clone(), 1, 3, 1, 1, 1),1214            Error::<Test>::AddresNotInWhiteList1215        );1216    });1217}12181219// If Public Access mode is set to WhiteList, tokens can’t be transferred to a non-whitelisted address with transfer or transferFrom (2 tests)1220#[test]1221fn white_list_test_3() {1222    new_test_ext().execute_with(|| {1223        default_limits();1224        1225        let collection_id = create_test_collection(&CollectionMode::NFT, 1);12261227        let origin1 = Origin::signed(1);1228        1229        let data = default_nft_data();1230        create_test_item(collection_id, &data.into());12311232        assert_ok!(TemplateModule::set_public_access_mode(1233            origin1.clone(),1234            collection_id,1235            AccessMode::WhiteList1236        ));1237        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));12381239        assert_noop!(1240            TemplateModule::transfer(origin1.clone(), 3, 1, 1, 1),1241            Error::<Test>::AddresNotInWhiteList1242        );1243    });1244}12451246#[test]1247fn white_list_test_4() {1248    new_test_ext().execute_with(|| {1249        default_limits();1250        1251        let collection_id = create_test_collection(&CollectionMode::NFT, 1);12521253        let origin1 = Origin::signed(1);12541255        let data = default_nft_data();1256        create_test_item(collection_id, &data.into());12571258        assert_ok!(TemplateModule::set_public_access_mode(1259            origin1.clone(),1260            collection_id,1261            AccessMode::WhiteList1262        ));1263        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 1));1264        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));12651266        // do approve1267        assert_ok!(TemplateModule::approve(origin1.clone(), 1, 1, 1));1268        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);12691270        assert_ok!(TemplateModule::remove_from_white_list(1271            origin1.clone(),1272            collection_id,1273            21274        ));12751276        assert_noop!(1277            TemplateModule::transfer_from(origin1.clone(), 1, 3, 1, 1, 1),1278            Error::<Test>::AddresNotInWhiteList1279        );1280    });1281}12821283// 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)1284#[test]1285fn white_list_test_5() {1286    new_test_ext().execute_with(|| {1287        default_limits();1288        1289        let collection_id = create_test_collection(&CollectionMode::NFT, 1);12901291        let origin1 = Origin::signed(1);12921293        let data = default_nft_data();1294        create_test_item(collection_id, &data.into());12951296        assert_ok!(TemplateModule::set_public_access_mode(1297            origin1.clone(),1298            collection_id,1299            AccessMode::WhiteList1300        ));1301        assert_noop!(1302            TemplateModule::burn_item(origin1.clone(), 1, 1),1303            Error::<Test>::AddresNotInWhiteList1304        );1305    });1306}13071308// If Public Access mode is set to WhiteList, oken transfers can’t be Approved by a non-whitelisted address (see Approve method).1309#[test]1310fn white_list_test_6() {1311    new_test_ext().execute_with(|| {1312        default_limits();1313        1314        let collection_id = create_test_collection(&CollectionMode::NFT, 1);13151316        let origin1 = Origin::signed(1);1317        assert_ok!(TemplateModule::set_public_access_mode(1318            origin1.clone(),1319            collection_id,1320            AccessMode::WhiteList1321        ));13221323        // do approve1324        assert_noop!(1325            TemplateModule::approve(origin1.clone(), 1, 1, 1),1326            Error::<Test>::AddresNotInWhiteList1327        );1328    });1329}13301331// If Public Access mode is set to WhiteList, tokens can be transferred from a whitelisted address with transfer or transferFrom (2 tests) and1332//          tokens can be transferred from a whitelisted address with transfer or transferFrom (2 tests)1333#[test]1334fn white_list_test_7() {1335    new_test_ext().execute_with(|| {1336        default_limits();1337        1338        let collection_id = create_test_collection(&CollectionMode::NFT, 1);13391340        let data = default_nft_data();1341        create_test_item(collection_id, &data.into());1342        1343        let origin1 = Origin::signed(1);13441345        assert_ok!(TemplateModule::set_public_access_mode(1346            origin1.clone(),1347            collection_id,1348            AccessMode::WhiteList1349        ));1350        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 1));1351        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));13521353        assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1));1354    });1355}13561357#[test]1358fn white_list_test_8() {1359    new_test_ext().execute_with(|| {1360        default_limits();1361        1362        let collection_id = create_test_collection(&CollectionMode::NFT, 1);13631364        let data = default_nft_data();1365        create_test_item(collection_id, &data.into());1366        1367        let origin1 = Origin::signed(1);13681369        assert_ok!(TemplateModule::set_public_access_mode(1370            origin1.clone(),1371            collection_id,1372            AccessMode::WhiteList1373        ));1374        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 1));1375        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));13761377        // do approve1378        assert_ok!(TemplateModule::approve(origin1.clone(), 1, 1, 1));1379        assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);13801381        assert_ok!(TemplateModule::transfer_from(1382            origin1.clone(),1383            1,1384            2,1385            1,1386            1,1387            11388        ));1389    });1390}13911392// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens can be created by owner.1393#[test]1394fn white_list_test_9() {1395    new_test_ext().execute_with(|| {1396        default_limits();1397        1398        let collection_id = create_test_collection(&CollectionMode::NFT, 1);1399        let origin1 = Origin::signed(1);14001401        assert_ok!(TemplateModule::set_public_access_mode(1402            origin1.clone(),1403            collection_id,1404            AccessMode::WhiteList1405        ));1406        assert_ok!(TemplateModule::set_mint_permission(1407            origin1.clone(),1408            collection_id,1409            false1410        ));14111412        let data = default_nft_data();1413        create_test_item(collection_id, &data.into());1414    });1415}14161417// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens can be created by admin.1418#[test]1419fn white_list_test_10() {1420    new_test_ext().execute_with(|| {1421        default_limits();1422        1423        let collection_id = create_test_collection(&CollectionMode::NFT, 1);14241425        let origin1 = Origin::signed(1);1426        let origin2 = Origin::signed(2);14271428        assert_ok!(TemplateModule::set_public_access_mode(1429            origin1.clone(),1430            collection_id,1431            AccessMode::WhiteList1432        ));1433        assert_ok!(TemplateModule::set_mint_permission(1434            origin1.clone(),1435            collection_id,1436            false1437        ));14381439        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));14401441        assert_ok!(TemplateModule::create_item(1442            origin2.clone(),1443            collection_id,1444            2,1445            default_nft_data().into()1446        ));1447    });1448}14491450// 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.1451#[test]1452fn white_list_test_11() {1453    new_test_ext().execute_with(|| {1454        default_limits();1455        1456        let collection_id = create_test_collection(&CollectionMode::NFT, 1);14571458        let origin1 = Origin::signed(1);1459        let origin2 = Origin::signed(2);14601461        assert_ok!(TemplateModule::set_public_access_mode(1462            origin1.clone(),1463            collection_id,1464            AccessMode::WhiteList1465        ));1466        assert_ok!(TemplateModule::set_mint_permission(1467            origin1.clone(),1468            collection_id,1469            false1470        ));1471        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));14721473        assert_noop!(1474            TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1475            Error::<Test>::PublicMintingNotAllowed1476        );1477    });1478}14791480// 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.1481#[test]1482fn white_list_test_12() {1483    new_test_ext().execute_with(|| {1484        default_limits();1485        1486        let collection_id = create_test_collection(&CollectionMode::NFT, 1);14871488        let origin1 = Origin::signed(1);1489        let origin2 = Origin::signed(2);14901491        assert_ok!(TemplateModule::set_public_access_mode(1492            origin1.clone(),1493            collection_id,1494            AccessMode::WhiteList1495        ));1496        assert_ok!(TemplateModule::set_mint_permission(1497            origin1.clone(),1498            collection_id,1499            false1500        ));15011502        assert_noop!(1503            TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1504            Error::<Test>::PublicMintingNotAllowed1505        );1506    });1507}15081509// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens can be created by owner.1510#[test]1511fn white_list_test_13() {1512    new_test_ext().execute_with(|| {1513        default_limits();1514        1515        let collection_id = create_test_collection(&CollectionMode::NFT, 1);15161517        let origin1 = Origin::signed(1);15181519        assert_ok!(TemplateModule::set_public_access_mode(1520            origin1.clone(),1521            collection_id,1522            AccessMode::WhiteList1523        ));1524        assert_ok!(TemplateModule::set_mint_permission(1525            origin1.clone(),1526            collection_id,1527            true1528        ));15291530        let data = default_nft_data();1531        create_test_item(collection_id, &data.into());1532    });1533}15341535// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens can be created by admin.1536#[test]1537fn white_list_test_14() {1538    new_test_ext().execute_with(|| {1539        default_limits();1540        1541        let collection_id = create_test_collection(&CollectionMode::NFT, 1);15421543        let origin1 = Origin::signed(1);1544        let origin2 = Origin::signed(2);15451546        assert_ok!(TemplateModule::set_public_access_mode(1547            origin1.clone(),1548            collection_id,1549            AccessMode::WhiteList1550        ));1551        assert_ok!(TemplateModule::set_mint_permission(1552            origin1.clone(),1553            collection_id,1554            true1555        ));15561557        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));15581559        assert_ok!(TemplateModule::create_item(1560            origin2.clone(),1561            1,1562            2,1563            default_nft_data().into()1564        ));1565    });1566}15671568// 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.1569#[test]1570fn white_list_test_15() {1571    new_test_ext().execute_with(|| {1572        default_limits();1573        1574        let collection_id = create_test_collection(&CollectionMode::NFT, 1);15751576        let origin1 = Origin::signed(1);1577        let origin2 = Origin::signed(2);15781579        assert_ok!(TemplateModule::set_public_access_mode(1580            origin1.clone(),1581            collection_id,1582            AccessMode::WhiteList1583        ));1584        assert_ok!(TemplateModule::set_mint_permission(1585            origin1.clone(),1586            collection_id,1587            true1588        ));15891590        assert_noop!(1591            TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1592            Error::<Test>::AddresNotInWhiteList1593        );1594    });1595}15961597// 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.1598#[test]1599fn white_list_test_16() {1600    new_test_ext().execute_with(|| {1601        default_limits();1602        1603        let collection_id = create_test_collection(&CollectionMode::NFT, 1);16041605        let origin1 = Origin::signed(1);1606        let origin2 = Origin::signed(2);16071608        assert_ok!(TemplateModule::set_public_access_mode(1609            origin1.clone(),1610            collection_id,1611            AccessMode::WhiteList1612        ));1613        assert_ok!(TemplateModule::set_mint_permission(1614            origin1.clone(),1615            collection_id,1616            true1617        ));1618        assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));16191620        assert_ok!(TemplateModule::create_item(1621            origin2.clone(),1622            1,1623            2,1624            default_nft_data().into()1625        ));1626    });1627}16281629// Total number of collections. Positive test1630#[test]1631fn total_number_collections_bound() {1632    new_test_ext().execute_with(|| {1633        default_limits();1634        1635        create_test_collection(&CollectionMode::NFT, 1);1636    });1637}16381639// Total number of collections. Negotive test1640#[test]1641fn total_number_collections_bound_neg() {1642    new_test_ext().execute_with(|| {1643        default_limits();16441645        let origin1 = Origin::signed(1);16461647        for i in 0..default_collection_numbers_limit() {1648            create_test_collection(&CollectionMode::NFT, i + 1);1649        }16501651        let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();1652        let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();1653        let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();16541655        // 11-th collection in chain. Expects error1656        assert_noop!(TemplateModule::create_collection(1657            origin1.clone(),1658            col_name1.clone(),1659            col_desc1.clone(),1660            token_prefix1.clone(),1661            CollectionMode::NFT1662        ), Error::<Test>::TotalCollectionsLimitExceeded);1663    });1664}16651666// Owned tokens by a single address. Positive test1667#[test]1668fn owned_tokens_bound() {1669    new_test_ext().execute_with(|| {1670        default_limits();1671        1672        let collection_id = create_test_collection(&CollectionMode::NFT, 1);16731674        let data = default_nft_data();1675        create_test_item(collection_id, &data.clone().into());1676        create_test_item(collection_id, &data.into());1677    });1678}16791680// Owned tokens by a single address. Negotive test1681#[test]1682fn owned_tokens_bound_neg() {1683    new_test_ext().execute_with(|| {1684        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1685            collection_numbers_limit: 10,1686            account_token_ownership_limit: 1,1687            collections_admins_limit: 5,1688            custom_data_limit: 2048,1689            nft_sponsor_transfer_timeout: 15,1690            fungible_sponsor_transfer_timeout: 15,1691            refungible_sponsor_transfer_timeout: 15,          1692        }));1693        1694        let collection_id = create_test_collection(&CollectionMode::NFT, 1);16951696        let origin1 = Origin::signed(1);1697        let data = default_nft_data();1698        create_test_item(collection_id, &data.clone().into());16991700        assert_noop!(TemplateModule::create_item(1701            origin1.clone(),1702            1,1703            1,1704            data.into()1705        ),  Error::<Test>::AddressOwnershipLimitExceeded);1706    });1707}17081709// Number of collection admins. Positive test1710#[test]1711fn collection_admins_bound() {1712    new_test_ext().execute_with(|| {1713        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1714            collection_numbers_limit: 10,1715            account_token_ownership_limit: 10,1716            collections_admins_limit: 2,1717            custom_data_limit: 2048,1718            nft_sponsor_transfer_timeout: 15,1719            fungible_sponsor_transfer_timeout: 15,1720            refungible_sponsor_transfer_timeout: 15,          1721        }));1722        1723        let collection_id = create_test_collection(&CollectionMode::NFT, 1);17241725        let origin1 = Origin::signed(1);1726        1727        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));1728        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 3));1729    });1730}17311732// Number of collection admins. Negotive test1733#[test]1734fn collection_admins_bound_neg() {1735    new_test_ext().execute_with(|| {1736        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1737            collection_numbers_limit: 10,1738            account_token_ownership_limit: 1,1739            collections_admins_limit: 1,1740            custom_data_limit: 2048,1741            nft_sponsor_transfer_timeout: 15,1742            fungible_sponsor_transfer_timeout: 15,1743            refungible_sponsor_transfer_timeout: 15,          1744        }));1745        1746        let collection_id = create_test_collection(&CollectionMode::NFT, 1);17471748        let origin1 = Origin::signed(1);17491750        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));1751        assert_noop!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 3), Error::<Test>::CollectionAdminsLimitExceeded);1752    });1753}17541755// NFT custom data size. Negative test const_data.1756#[test]1757fn custom_data_size_nft_const_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        }));1768        1769        let collection_id = create_test_collection(&CollectionMode::NFT, 1);17701771        let origin1 = Origin::signed(1);1772        let too_big_const_data = CreateItemData::NFT(CreateNftData{1773            const_data: vec![1, 2, 3, 4],1774            variable_data: vec![]1775        });17761777        assert_noop!(TemplateModule::create_item(1778            origin1.clone(),1779            collection_id,1780            1,1781            too_big_const_data1782        ), Error::<Test>::TokenConstDataLimitExceeded);1783    });1784}17851786// NFT custom data size. Negative test variable_data.1787#[test]1788fn custom_data_size_nft_variable_data_bound_neg() {1789    new_test_ext().execute_with(|| {1790        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1791            collection_numbers_limit: 10,1792            account_token_ownership_limit: 10,1793            collections_admins_limit: 5,1794            custom_data_limit: 2,1795            nft_sponsor_transfer_timeout: 15,1796            fungible_sponsor_transfer_timeout: 15,1797            refungible_sponsor_transfer_timeout: 15,          1798        }));17991800        let collection_id = create_test_collection(&CollectionMode::NFT, 1);18011802        let origin1 = Origin::signed(1);1803        let too_big_const_data = CreateItemData::NFT(CreateNftData{1804            const_data: vec![],1805            variable_data: vec![1, 2, 3, 4]1806        });18071808        assert_noop!(TemplateModule::create_item(1809            origin1.clone(),1810            collection_id,1811            1,1812            too_big_const_data1813        ), Error::<Test>::TokenVariableDataLimitExceeded);1814    });1815}18161817// Re fungible custom data size. Negative test const_data.1818#[test]1819fn custom_data_size_re_fungible_const_data_bound_neg() {1820    new_test_ext().execute_with(|| {1821        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1822            collection_numbers_limit: 10,1823            account_token_ownership_limit: 10,1824            collections_admins_limit: 5,1825            custom_data_limit: 2,1826            nft_sponsor_transfer_timeout: 15,1827            fungible_sponsor_transfer_timeout: 15,1828            refungible_sponsor_transfer_timeout: 15,          1829        }));18301831        let collection_id = create_test_collection(&CollectionMode::NFT, 1);18321833        let origin1 = Origin::signed(1);1834        let too_big_const_data = CreateItemData::NFT(CreateNftData{1835            const_data: vec![1, 2, 3, 4],1836            variable_data: vec![]1837        });18381839        assert_noop!(TemplateModule::create_item(1840            origin1.clone(),1841            collection_id,1842            1,1843            too_big_const_data1844        ), Error::<Test>::TokenConstDataLimitExceeded);1845    });1846}18471848// Re fungible custom data size. Negative test variable_data.1849#[test]1850fn custom_data_size_re_fungible_variable_data_bound_neg() {1851    new_test_ext().execute_with(|| {1852        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1853            collection_numbers_limit: 10,1854            account_token_ownership_limit: 10,1855            collections_admins_limit: 5,1856            custom_data_limit: 2,1857            nft_sponsor_transfer_timeout: 15,1858            fungible_sponsor_transfer_timeout: 15,1859            refungible_sponsor_transfer_timeout: 15,          1860        }));18611862        let collection_id = create_test_collection(&CollectionMode::NFT, 1);18631864        let origin1 = Origin::signed(1);1865        let too_big_const_data = CreateItemData::NFT(CreateNftData{1866            const_data: vec![],1867            variable_data: vec![1, 2, 3, 4]1868        });18691870        assert_noop!(TemplateModule::create_item(1871            origin1.clone(),1872            collection_id,1873            1,1874            too_big_const_data1875        ), Error::<Test>::TokenVariableDataLimitExceeded);1876    });1877}1878// #endregion18791880#[test]1881fn set_const_on_chain_schema() {1882    new_test_ext().execute_with(|| {1883        default_limits();18841885        let collection_id = create_test_collection(&CollectionMode::NFT, 1);18861887        let origin1 = Origin::signed(1);1888        assert_ok!(TemplateModule::set_const_on_chain_schema(origin1, collection_id, b"test const on chain schema".to_vec()));18891890        assert_eq!(TemplateModule::collection(collection_id).const_on_chain_schema, b"test const on chain schema".to_vec());1891        assert_eq!(TemplateModule::collection(collection_id).variable_on_chain_schema, b"".to_vec());1892    });1893}18941895#[test]1896fn set_variable_on_chain_schema() {1897    new_test_ext().execute_with(|| {1898        default_limits();1899        1900        let collection_id = create_test_collection(&CollectionMode::NFT, 1);19011902        let origin1 = Origin::signed(1);1903        assert_ok!(TemplateModule::set_variable_on_chain_schema(origin1, collection_id, b"test variable on chain schema".to_vec()));19041905        assert_eq!(TemplateModule::collection(collection_id).const_on_chain_schema, b"".to_vec());1906        assert_eq!(TemplateModule::collection(collection_id).variable_on_chain_schema, b"test variable on chain schema".to_vec());1907    });1908}19091910#[test]1911fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {1912    new_test_ext().execute_with(|| {1913        default_limits();19141915        let collection_id = create_test_collection(&CollectionMode::NFT, 1);19161917        let origin1 = Origin::signed(1);1918        1919        let data = default_nft_data();1920        create_test_item(1, &data.into());1921        1922        let variable_data = b"test set_variable_meta_data method.".to_vec();1923        assert_ok!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data.clone()));19241925        assert_eq!(TemplateModule::nft_item_id(collection_id, 1).variable_data, variable_data);1926    });1927}19281929#[test]1930fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {1931    new_test_ext().execute_with(|| {1932        default_limits();19331934        let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);19351936        let origin1 = Origin::signed(1);19371938        let data = default_re_fungible_data();1939        create_test_item(1, &data.into());19401941        let variable_data = b"test set_variable_meta_data method.".to_vec();1942        assert_ok!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data.clone()));19431944        assert_eq!(TemplateModule::refungible_item_id(collection_id, 1).variable_data, variable_data);1945    });1946}194719481949#[test]1950fn set_variable_meta_data_on_fungible_token_fails() {1951    new_test_ext().execute_with(|| {1952        default_limits();19531954        let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);19551956        let origin1 = Origin::signed(1);19571958        let data = default_fungible_data();1959        create_test_item(1, &data.into());19601961        let variable_data = b"test set_variable_meta_data method.".to_vec();1962        assert_noop!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data.clone()), Error::<Test>::CantStoreMetadataInFungibleTokens);1963    });1964}19651966#[test]1967fn set_variable_meta_data_on_nft_token_fails_for_big_data() {1968    new_test_ext().execute_with(|| {1969        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1970            collection_numbers_limit: default_collection_numbers_limit(),1971            account_token_ownership_limit: 10,1972            collections_admins_limit: 5,1973            custom_data_limit: 10,1974            nft_sponsor_transfer_timeout: 15,1975            fungible_sponsor_transfer_timeout: 15,1976            refungible_sponsor_transfer_timeout: 15,          1977        }));19781979        let collection_id = create_test_collection(&CollectionMode::NFT, 1);19801981        let origin1 = Origin::signed(1);19821983        let data = default_nft_data();1984        create_test_item(1, &data.into());19851986        let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();1987        assert_noop!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data), Error::<Test>::TokenVariableDataLimitExceeded);1988    });1989}19901991#[test]1992fn set_variable_meta_data_on_re_fungible_token_fails_for_big_data() {1993    new_test_ext().execute_with(|| {1994        assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1995            collection_numbers_limit: default_collection_numbers_limit(),1996            account_token_ownership_limit: 10,1997            collections_admins_limit: 5,1998            custom_data_limit: 10,1999            nft_sponsor_transfer_timeout: 15,2000            fungible_sponsor_transfer_timeout: 15,2001            refungible_sponsor_transfer_timeout: 15,          2002        }));200320042005        let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1);20062007        let origin1 = Origin::signed(1);20082009        let data = default_re_fungible_data();2010        create_test_item(1, &data.into());20112012        let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();2013        assert_noop!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data), Error::<Test>::TokenVariableDataLimitExceeded);2014    });2015}
modifiedruntime/Cargo.tomldiffbeforeafterboth
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -45,6 +45,8 @@
 pallet-timestamp = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
 pallet-transaction-payment = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
 pallet-transaction-payment-rpc-runtime-api = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
+pallet-treasury = { version = "2.0.0", default-features = false, git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
+pallet-vesting = { version = "2.0.0", default-features = false, git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
 sp-api = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
 sp-block-builder = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
 sp-consensus-aura = { default-features = false, version = '0.8.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
@@ -56,8 +58,6 @@
 sp-std = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
 sp-transaction-pool = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
 sp-version = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
-
-pallet-treasury = { version = "2.0.0", default-features = false, git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
 
 [features]
 default = ['std']
@@ -90,6 +90,9 @@
     'pallet-timestamp/std',
     'pallet-transaction-payment/std',
     'pallet-transaction-payment-rpc-runtime-api/std',
+    'pallet-treasury/std',
+    'pallet-vesting/std',
+
     'pallet-nft/std',
     'sp-api/std',
     'sp-block-builder/std',
@@ -103,5 +106,4 @@
     'sp-transaction-pool/std',
     'sp-version/std',
 
-    'pallet-treasury/std',
 ]
modifiedruntime/src/lib.rsdiffbeforeafterboth
--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -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.
+//
+
 //! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.
 
 #![cfg_attr(not(feature = "std"), no_std)]
@@ -17,7 +22,7 @@
 use sp_runtime::{
     create_runtime_str, generic, impl_opaque_keys,
     traits::{
-        Convert, BlakeTwo256, Block as BlockT, IdentifyAccount, 
+        Convert, ConvertInto, BlakeTwo256, Block as BlockT, IdentifyAccount, 
         IdentityLookup, NumberFor, Saturating, Verify,
     },
     transaction_validity::{TransactionSource, TransactionValidity},
@@ -315,7 +320,7 @@
 	type Balance = Balance;
 	/// The ubiquitous event type.
 	type Event = Event;
-	type DustRemoval = ();
+	type DustRemoval = Treasury;
 	type ExistentialDeposit = ExistentialDeposit;
 	type AccountStore = System;
 	type WeightInfo = ();
@@ -357,7 +362,7 @@
 
 impl pallet_transaction_payment::Trait for Runtime {
     type Currency = pallet_balances::Module<Runtime>;
-    type OnTransactionPayment = ();
+    type OnTransactionPayment = Treasury;
     type TransactionByteFee = TransactionByteFee;
     type WeightToFee = IdentityFee<Balance>;
     type FeeMultiplierUpdate =  ();
@@ -412,6 +417,18 @@
     type Call = Call;
 }
 
+parameter_types! {
+	pub const MinVestedTransfer: Balance = 100 * DOLLARS;
+}
+
+impl pallet_vesting::Trait for Runtime {
+	type Event = Event;
+	type Currency = Balances;
+	type BlockNumberToBalance = ConvertInto;
+	type MinVestedTransfer = MinVestedTransfer;
+	type WeightInfo = ();
+}
+
 /// Used for the module nft in `./nft.rs`
 impl pallet_nft::Trait for Runtime {
     type Event = Event;
@@ -435,6 +452,7 @@
         Sudo: pallet_sudo::{Module, Call, Config<T>, Storage, Event<T>},
         Nft: pallet_nft::{Module, Call, Config<T>, Storage, Event<T>},
         Treasury: pallet_treasury::{Module, Call, Storage, Config, Event<T>},
+        Vesting: pallet_vesting::{Module, Call, Config<T>, Storage, Event<T>},
     }
 );
 
modifiedruntime/src/nft_weights.rsdiffbeforeafterboth
--- a/runtime/src/nft_weights.rs
+++ b/runtime/src/nft_weights.rs
@@ -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.
+//
+
 use frame_support::weights::{Weight, constants::RocksDbWeight as DbWeight};
 
 pub struct WeightInfo;
@@ -108,19 +113,44 @@
             .saturating_add(DbWeight::get().reads(2 as Weight))
             .saturating_add(DbWeight::get().writes(1 as Weight))
     }
-    // fn set_chain_limits() -> Weight {
-    //     (0 as Weight)
-    //         .saturating_add(DbWeight::get().reads(1 as Weight))
-    //         .saturating_add(DbWeight::get().writes(1 as Weight))
-    // }
     fn enable_contract_sponsoring() -> Weight {
         (13_000_000 as Weight)
             .saturating_add(DbWeight::get().reads(1 as Weight))
             .saturating_add(DbWeight::get().writes(1 as Weight))
     }
-    // fn set_contract_sponsoring_rate_limit() -> Weight {
-    //     (0 as Weight)
-    //         .saturating_add(DbWeight::get().reads(1 as Weight))
-    //         .saturating_add(DbWeight::get().writes(1 as Weight))
-    // }
+    fn set_schema_version() -> Weight {
+        (8_500_000 as Weight)
+            .saturating_add(DbWeight::get().reads(2 as Weight))
+            .saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn set_chain_limits() -> Weight {
+        (1_300_000 as Weight)
+            .saturating_add(DbWeight::get().reads(0 as Weight))
+            .saturating_add(DbWeight::get().writes(1 as Weight))
+    }
+    fn set_contract_sponsoring_rate_limit() -> Weight {
+        (3_500_000 as Weight)
+            .saturating_add(DbWeight::get().reads(0 as Weight))
+            .saturating_add(DbWeight::get().writes(2 as Weight))
+    }    
+    fn toggle_contract_white_list() -> Weight {
+        (3_000_000 as Weight)
+            .saturating_add(DbWeight::get().reads(0 as Weight))
+            .saturating_add(DbWeight::get().writes(2 as Weight))
+    }    
+    fn add_to_contract_white_list() -> Weight {
+        (3_000_000 as Weight)
+            .saturating_add(DbWeight::get().reads(0 as Weight))
+            .saturating_add(DbWeight::get().writes(2 as Weight))
+    }    
+    fn remove_from_contract_white_list() -> Weight {
+        (3_200_000 as Weight)
+            .saturating_add(DbWeight::get().reads(0 as Weight))
+            .saturating_add(DbWeight::get().writes(2 as Weight))
+    }
+    fn set_collection_limits() -> Weight {
+        (8_900_000 as Weight)
+            .saturating_add(DbWeight::get().reads(2 as Weight))
+            .saturating_add(DbWeight::get().writes(1 as Weight))
+    }
 }
modifiedruntime_types.jsondiffbeforeafterboth
--- a/runtime_types.json
+++ b/runtime_types.json
@@ -42,18 +42,14 @@
       "Fraction": "u128"
     },
     "FungibleItemType": {
-      "Collection": "CollectionId",
-      "Owner": "AccountId",
       "Value": "u128"
     },
     "NftItemType": {
-      "Collection": "CollectionId",
       "Owner": "AccountId",
       "ConstData": "Vec<u8>",
       "VariableData": "Vec<u8>"
     },
     "ReFungibleItemType": {
-      "Collection": "CollectionId",
       "Owner": "Vec<Ownership<AccountId>>",
       "ConstData": "Vec<u8>",
       "VariableData": "Vec<u8>"
@@ -70,14 +66,10 @@
       "OffchainSchema": "Vec<u8>",
       "SchemaVersion": "SchemaVersion",
       "Sponsor": "AccountId",
-      "UnconfirmedSponsor": "AccountId",
+      "SponsorConfirmed": "bool",
       "Limits": "CollectionLimits",
       "VariableOnChainSchema": "Vec<u8>",
       "ConstOnChainSchema": "Vec<u8>"
-    },
-    "ApprovePermissions": {
-      "Approved": "AccountId",
-      "Amount": "u128"
     },
     "RawData": "Vec<u8>",
     "Address": "AccountId",
@@ -87,7 +79,9 @@
       "const_data": "Vec<u8>",
       "variable_data": "Vec<u8>" 
     },
-    "CreateFungibleData": {},
+    "CreateFungibleData": {
+      "value": "u128"
+    },
     "CreateReFungibleData": {
       "const_data": "Vec<u8>",
       "variable_data": "Vec<u8>" 
@@ -107,10 +101,6 @@
     },
     "CollectionId": "u32",
     "TokenId": "u32",
-    "BasketItem": {
-      "Address": "AccountId",
-      "start_block": "BlockNumber"
-    },
     "ChainLimits": {
       "collection_numbers_limit": "u32",
       "account_token_ownership_limit": "u32",
deletedtests/READMEdiffbeforeafterboth
--- a/tests/README
+++ /dev/null
@@ -1,12 +0,0 @@
-# Tests
-
-## How to run
-
-1. Run `npm install`.
-2. Setup a test node. You can do it using `docker-compose up -d` in parent directory.
-3. Configure tests with env variables or by editing [configuration file](src/config.ts).
-4. Run `npm run test`.
-
-## Don't run on the same node twice
-
-Some tests fail when ran on the same blockchain node twice. Either always use a new node or purge the existing one with `nft purge-chain --dev`. There is also [a script](../purge-running-node.sh) to purge and restart a node, started with docker-compose.
addedtests/README.mddiffbeforeafterboth
--- /dev/null
+++ b/tests/README.md
@@ -0,0 +1,9 @@
+# Tests
+
+## How to run
+
+1. Run `npm 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`.
+
addedtests/loadtester-src/.gitignorediffbeforeafterboth
--- /dev/null
+++ b/tests/loadtester-src/.gitignore
@@ -0,0 +1,9 @@
+# Ignore build artifacts from the local tests sub-crate.
+/target/
+
+# Ignore backup files creates by cargo fmt.
+**/*.rs.bk
+
+# Remove Cargo.lock when creating an executable, leave it for libraries
+# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
+Cargo.lock
\ No newline at end of file
addedtests/loadtester-src/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/tests/loadtester-src/Cargo.toml
@@ -0,0 +1,36 @@
+[package]
+name = "loadtester"
+version = "0.1.0"
+authors = ["[your_name] <[your_email]>"]
+edition = "2018"
+
+[dependencies]
+ink_primitives = { version = "3.0.0-rc2", default-features = false }
+ink_metadata = { version = "3.0.0-rc2", default-features = false, features = ["derive"], optional = true }
+ink_env = { version = "3.0.0-rc2", default-features = false }
+ink_storage = { version = "3.0.0-rc2", default-features = false }
+ink_lang = { version = "3.0.0-rc2", default-features = false }
+ink_prelude = { version = "3.0.0-rc2", default-features = false }
+
+scale = { package = "parity-scale-codec", version = "1.3", default-features = false, features = ["derive"] }
+scale-info = { version = "0.4.1", default-features = false, features = ["derive"], optional = true }
+
+[lib]
+name = "loadtester"
+path = "lib.rs"
+crate-type = [
+	# Used for normal contract Wasm blobs.
+	"cdylib",
+]
+
+[features]
+default = ["std"]
+std = [
+    "ink_metadata/std",
+    "ink_env/std",
+    "ink_storage/std",
+    "ink_primitives/std",
+    "scale/std",
+    "scale-info/std",
+]
+ink-as-dependency = []
addedtests/loadtester-src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/tests/loadtester-src/lib.rs
@@ -0,0 +1,53 @@
+#![cfg_attr(not(feature = "std"), no_std)]
+
+use ink_lang as ink;
+
+#[ink::contract]
+mod loadtester {
+    use ink_storage::collections::Vec as InkVec;
+
+    #[ink(storage)]
+    pub struct LoadTester {
+        vector: InkVec<u64>,
+    }
+
+    impl LoadTester {
+        #[ink(constructor)]
+        pub fn new() -> Self {
+            Self {
+                vector: InkVec::new(),
+            }
+        }
+
+        #[ink(message)]
+        pub fn bloat(&mut self, count: u64){
+            for i in 1..count+1 {
+                self.vector.push(i);
+            }
+        }
+
+        #[ink(message)]
+        pub fn get(&self) -> u128 {
+            let mut sum: u128 = 0;
+            for num in self.vector.iter() {
+                sum += *num as u128;
+            }
+            sum
+        }
+    }
+
+    #[cfg(test)]
+    mod tests {
+       
+        use super::*;
+
+        #[test]
+        fn it_works() {
+            let mut lt = LoadTester::new();
+            lt.bloat(4);
+            assert_eq!(lt.get(), [1,2,3,4]);
+            lt.bloat(3);
+            assert_eq!(lt.get(), [1,2,3,4,1,2,3]);
+        }
+    }
+}
modifiedtests/package-lock.jsondiffbeforeafterboth
--- a/tests/package-lock.json
+++ b/tests/package-lock.json
@@ -13,13 +13,12 @@
         "@polkadot/api-contract": "^2.3.1",
         "@polkadot/types": "^2.3.1",
         "@polkadot/util": "^3.4.1",
-        "@types/bn.js": "^4.11.6",
+        "bignumber.js": "^9.0.0",
         "chai-as-promised": "^7.1.1"
       },
       "devDependencies": {
         "@polkadot/dev": "^0.52.11",
         "@polkadot/ts": "^0.3.41",
-        "@types/bn.js": "^4.11.6",
         "@types/chai": "^4.2.12",
         "@types/chai-as-promised": "^7.1.3",
         "@types/mocha": "^8.0.3",
@@ -7114,6 +7113,14 @@
         "node": "*"
       }
     },
+    "node_modules/bignumber.js": {
+      "version": "9.0.1",
+      "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz",
+      "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==",
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/binary-extensions": {
       "version": "1.13.1",
       "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
@@ -34960,6 +34967,11 @@
       "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
       "dev": true
     },
+    "bignumber.js": {
+      "version": "9.0.1",
+      "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz",
+      "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA=="
+    },
     "binary-extensions": {
       "version": "1.13.1",
       "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
modifiedtests/package.jsondiffbeforeafterboth
--- a/tests/package.json
+++ b/tests/package.json
@@ -6,7 +6,6 @@
   "devDependencies": {
     "@polkadot/dev": "^0.52.11",
     "@polkadot/ts": "^0.3.41",
-    "@types/bn.js": "^4.11.6",
     "@types/chai": "^4.2.12",
     "@types/chai-as-promised": "^7.1.3",
     "@types/mocha": "^8.0.3",
@@ -17,7 +16,8 @@
     "typescript": "^3.9.7"
   },
   "scripts": {
-    "test": "mocha --timeout 9999999 -r ts-node/register ./**/*.test.ts"
+    "test": "mocha --timeout 9999999 -r ts-node/register ./**/*.test.ts",
+    "load": "mocha --timeout 9999999 -r ts-node/register ./**/*.load.ts"
   },
   "author": "",
   "license": "Apache 2.0",
@@ -27,7 +27,7 @@
     "@polkadot/api-contract": "^2.3.1",
     "@polkadot/types": "^2.3.1",
     "@polkadot/util": "^3.4.1",
-    "@types/bn.js": "^4.11.6",
+    "bignumber.js": "^9.0.0",
     "chai-as-promised": "^7.1.1"
   },
   "standard": {
modifiedtests/src/accounts.tsdiffbeforeafterboth
--- a/tests/src/accounts.ts
+++ b/tests/src/accounts.ts
@@ -1,2 +1,9 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 export const bobsPublicKey = '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty';
 export const alicesPublicKey = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY';
+export const ferdiesPublicKey = '5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL';
+export const nullPublicKey = '5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM';
\ No newline at end of file
modifiedtests/src/blocks-production.test.tsdiffbeforeafterboth
--- a/tests/src/blocks-production.test.ts
+++ b/tests/src/blocks-production.test.ts
@@ -1,8 +1,13 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 import usingApi from "./substrate/substrate-api";
 import promisifySubstrate from "./substrate/promisify-substrate";
 import { expect } from "chai";
 
-describe('Blocks Production', () => {
+describe('Blocks Production smoke test', () => {
   it('Node produces new blocks', async () => {
     await usingApi(async api => {
       const blocksPromise = promisifySubstrate(api, () => {
modifiedtests/src/config.tsdiffbeforeafterboth
--- a/tests/src/config.ts
+++ b/tests/src/config.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 process from 'process';
 
 const config = {
addedtests/src/confirmSponsorship.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/confirmSponsorship.test.ts
@@ -0,0 +1,350 @@
+//
+// 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, 
+  setCollectionSponsorExpectSuccess, 
+  destroyCollectionExpectSuccess, 
+  setCollectionSponsorExpectFailure,
+  confirmSponsorshipExpectSuccess,
+  confirmSponsorshipExpectFailure,
+  createItemExpectSuccess,
+  findUnusedAddress,
+  getGenericResult,
+  enableWhiteListExpectSuccess,
+  enablePublicMintingExpectSuccess,
+  addToWhiteListExpectSuccess,
+} from "./util/helpers";
+import { Keyring } from "@polkadot/api";
+import { IKeyringPair } from "@polkadot/types/types";
+import type { AccountId } from '@polkadot/types/interfaces';
+import { BigNumber } from 'bignumber.js';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+let alice: IKeyringPair;
+let bob: IKeyringPair;
+let charlie: IKeyringPair;
+
+describe('integration test: ext. confirmSponsorship():', () => {
+
+  before(async () => {
+    await usingApi(async (api) => {
+      const keyring = new Keyring({ type: 'sr25519' });
+      alice = keyring.addFromUri(`//Alice`);
+      bob = keyring.addFromUri(`//Bob`);
+      charlie = keyring.addFromUri(`//Charlie`);
+    });
+  });
+
+  it('Confirm collection sponsorship', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+  });
+  it('Add sponsor to a collection after the same sponsor was already added and confirmed', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+  });
+  it('Add new sponsor to a collection after another sponsor was already added and confirmed', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+    await setCollectionSponsorExpectSuccess(collectionId, charlie.address);
+  });
+
+  it('NFT: Transfer fees are paid by the sponsor after confirmation', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+
+    await usingApi(async (api) => {
+      const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+      // Find unused address
+      const zeroBalance = await findUnusedAddress(api);
+
+      // Mint token for unused address
+      const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', zeroBalance.address);
+
+      // Transfer this tokens from unused address to Alice
+      const zeroToAlice = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 0);
+      const events = await submitTransactionAsync(zeroBalance, zeroToAlice);
+      const result = getGenericResult(events);
+
+      const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+      expect(result.success).to.be.true;
+      expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;
+    });
+
+  });
+
+  it('Fungible: Transfer fees are paid by the sponsor after confirmation', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'Fungible');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+
+    await usingApi(async (api) => {
+      const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+      // Find unused address
+      const zeroBalance = await findUnusedAddress(api);
+
+      // Mint token for unused address
+      const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);
+
+      // Transfer this tokens from unused address to Alice
+      const zeroToAlice = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 1);
+      const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);
+      const result1 = getGenericResult(events1);
+
+      const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+      expect(result1.success).to.be.true;
+      expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;
+    });
+  });
+
+  it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'ReFungible');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+
+    await usingApi(async (api) => {
+      const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+      // Find unused address
+      const zeroBalance = await findUnusedAddress(api);
+
+      // Mint token for unused address
+      const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', zeroBalance.address);
+
+      // Transfer this tokens from unused address to Alice
+      const zeroToAlice = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 1);
+      const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);
+      const result1 = getGenericResult(events1);
+
+      const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+      expect(result1.success).to.be.true;
+      expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;
+    });
+  });
+
+  it('CreateItem fees are paid by the sponsor after confirmation', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+
+    // Enable collection white list 
+    await enableWhiteListExpectSuccess(alice, collectionId);
+
+    // Enable public minting
+    await enablePublicMintingExpectSuccess(alice, collectionId);
+
+    // Create Item 
+    await usingApi(async (api) => {
+      const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+      // Find unused address
+      const zeroBalance = await findUnusedAddress(api);
+
+      // Add zeroBalance address to white list
+      await addToWhiteListExpectSuccess(alice, collectionId, zeroBalance.address);
+
+      // Mint token using unused address as signer
+      const tokenId = await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);
+
+      const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+      expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;
+    });
+  });
+
+  it('NFT: Sponsoring is rate limited', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+
+    await usingApi(async (api) => {
+      // Find unused address
+      const zeroBalance = await findUnusedAddress(api);
+
+      // Mint token for alice
+      const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);
+
+      // Transfer this token from Alice to unused address and back
+      // Alice to Zero gets sponsored
+      const aliceToZero = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 0);
+      const events1 = await submitTransactionAsync(alice, aliceToZero);
+      const result1 = getGenericResult(events1);
+
+      // Second transfer should fail
+      const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+      const zeroToAlice = api.tx.nft.transfer(alice.address, collectionId, itemId, 0);
+      const badTransaction = async function () { 
+        console.log = function () {};
+        console.error = function () {};
+        await submitTransactionAsync(zeroBalance, zeroToAlice);
+        delete console.log;
+        delete console.error;
+      };
+      await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees");
+      const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+      // Try again after Zero gets some balance - now it should succeed
+      const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);
+      await submitTransactionAsync(alice, balancetx);
+      const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);
+      const result2 = getGenericResult(events2);
+
+      expect(result1.success).to.be.true;
+      expect(result2.success).to.be.true;
+      expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;
+    });
+  });
+
+  it('Fungible: Sponsoring is rate limited', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'Fungible');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+
+    await usingApi(async (api) => {
+      // Find unused address
+      const zeroBalance = await findUnusedAddress(api);
+
+      // Mint token for unused address
+      const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);
+
+      // Transfer this tokens in parts from unused address to Alice
+      const zeroToAlice = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 1);
+      const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);
+      const result1 = getGenericResult(events1);
+
+      const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+      const badTransaction = async function () { 
+        console.log = function () {};
+        console.error = function () {};
+        await submitTransactionAsync(zeroBalance, zeroToAlice);
+        delete console.log;
+        delete console.error;
+      };
+
+      const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+      // Try again after Zero gets some balance - now it should succeed
+      const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);
+      await submitTransactionAsync(alice, balancetx);
+      const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);
+      const result2 = getGenericResult(events2);
+
+      expect(result1.success).to.be.true;
+      expect(result2.success).to.be.true;
+      expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;
+    });
+  });
+
+  it('ReFungible: Sponsoring is rate limited', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'ReFungible');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+
+    await usingApi(async (api) => {
+      // Find unused address
+      const zeroBalance = await findUnusedAddress(api);
+
+      // Mint token for alice
+      const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', alice.address);
+
+      // Transfer this token from Alice to unused address and back
+      // Alice to Zero gets sponsored
+      const aliceToZero = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 1);
+      const events1 = await submitTransactionAsync(alice, aliceToZero);
+      const result1 = getGenericResult(events1);
+
+      // Second transfer should fail
+      const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+      const zeroToAlice = api.tx.nft.transfer(alice.address, collectionId, itemId, 1);
+      const badTransaction = async function () { 
+        console.log = function () {};
+        console.error = function () {};
+        await submitTransactionAsync(zeroBalance, zeroToAlice);
+        delete console.log;
+        delete console.error;
+      };
+      await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees");
+      const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+      // Try again after Zero gets some balance - now it should succeed
+      const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);
+      await submitTransactionAsync(alice, balancetx);
+      const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);
+      const result2 = getGenericResult(events2);
+
+      expect(result1.success).to.be.true;
+      expect(result2.success).to.be.true;
+      expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;
+    });
+  });
+
+});
+
+describe('(!negative test!) integration test: ext. removeCollectionSponsor():', () => {
+  before(async () => {
+    await usingApi(async (api) => {
+      const keyring = new Keyring({ type: 'sr25519' });
+      alice = keyring.addFromUri(`//Alice`);
+      bob = keyring.addFromUri(`//Bob`);
+      charlie = keyring.addFromUri(`//Charlie`);
+    });
+  });
+
+  it('(!negative test!) Confirm sponsorship for a collection that never existed', async () => {
+    // Find the collection that never existed
+    const collectionId = 0;
+    await usingApi(async (api) => {
+      const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;
+    });
+
+    await confirmSponsorshipExpectFailure(collectionId, '//Bob');
+  });
+
+  it('(!negative test!) Confirm sponsorship using a non-sponsor address', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+
+    await usingApi(async (api) => {
+      const transfer = api.tx.balances.transfer(charlie.address, 1e15);
+      await submitTransactionAsync(alice, transfer);
+    });
+
+    await confirmSponsorshipExpectFailure(collectionId, '//Charlie');
+  });
+
+  it('(!negative test!) Confirm sponsorship using owner address', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await confirmSponsorshipExpectFailure(collectionId, '//Alice');
+  });
+
+  it('(!negative test!) Confirm sponsorship without sponsor being set with setCollectionSponsor', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await confirmSponsorshipExpectFailure(collectionId, '//Bob');
+  });
+    
+  it('(!negative test!) Confirm sponsorship in a collection that was destroyed', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await destroyCollectionExpectSuccess(collectionId);
+    await confirmSponsorshipExpectFailure(collectionId, '//Bob');
+  });
+});
modifiedtests/src/connection.test.tsdiffbeforeafterboth
--- a/tests/src/connection.test.ts
+++ b/tests/src/connection.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 usingApi from "./substrate/substrate-api";
 import { WsProvider } from '@polkadot/api';
 import * as chai from 'chai';
@@ -7,7 +12,7 @@
 
 const expect = chai.expect;
 
-describe('Connection', () => {
+describe('Connection smoke test', () => {
   it('Connection can be established', async () => {
     await usingApi(async api => {
       const health = await api.rpc.system.health();
@@ -16,11 +21,17 @@
   });
 
   it('Cannot connect to 255.255.255.255', async () => {
+    console.log = function () {};
+    console.error = function () {};
+
     const neverConnectProvider = new WsProvider('ws://255.255.255.255:9944');
     await expect((async () => {
       await usingApi(async api => {
         const health = await api.rpc.system.health();
       }, { provider: neverConnectProvider });
     })()).to.be.eventually.rejected;
+
+    delete console.log;
+    delete console.error;
   });
 });
\ No newline at end of file
modifiedtests/src/contracts.test.tsdiffbeforeafterboth
--- a/tests/src/contracts.test.ts
+++ b/tests/src/contracts.test.ts
@@ -1,17 +1,25 @@
-import { expect } from "chai";
-import usingApi from "./substrate/substrate-api";
+import chai from "chai";
+import chaiAsPromised from 'chai-as-promised';
+import usingApi, { submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api";
 import fs from "fs";
-import { Abi, BlueprintPromise, CodePromise, ContractPromise } from "@polkadot/api-contract";
+import { Abi, BlueprintPromise as Blueprint, CodePromise, ContractPromise as Contract } from "@polkadot/api-contract";
 import { IKeyringPair } from "@polkadot/types/types";
-import { Keyring } from "@polkadot/api";
+import { ApiPromise, Keyring } from "@polkadot/api";
 import { ApiTypes, SubmittableExtrinsic } from "@polkadot/api/types";
+import privateKey from "./substrate/privateKey";
 
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+import { BigNumber } from 'bignumber.js';
+import { findUnusedAddress } from './util/helpers'
+
 const value = 0;
 const gasLimit = 3000n * 1000000n;
+const endowment = `1000000000000000`;
 const marketContractAddress = '5CYN9j3YvRkqxewoxeSvRbhAym4465C57uMmX5j4yz99L5H6';
 
-function deployBlueprint(alice: IKeyringPair, code: CodePromise): Promise<BlueprintPromise> {
-  return new Promise<BlueprintPromise>(async (resolve, reject) => {
+function deployBlueprint(alice: IKeyringPair, code: CodePromise): Promise<Blueprint> {
+  return new Promise<Blueprint>(async (resolve, reject) => {
     const unsub = await code
       .createBlueprint()
       .signAndSend(alice, (result) => {
@@ -24,7 +32,7 @@
   });
 }
 
-function deployContract(alice: IKeyringPair, blueprint: BlueprintPromise) : Promise<any> {
+function deployContract(alice: IKeyringPair, blueprint: Blueprint) : Promise<any> {
   return new Promise<any>(async (resolve, reject) => {
     const endowment = 1000000000000000n;
     const initValue = true;
@@ -40,57 +48,127 @@
   });
 }
 
-function runTransaction(privateKey: IKeyringPair, extrinsic: SubmittableExtrinsic<ApiTypes>) {
-  return new Promise<void>(async (resolve, reject) => {
-    extrinsic.signAndSend(privateKey, async result => {
-        if(!result.isInBlock) {
-          return;
-        }
+async function prepareDeployer(api: ApiPromise) {
+  // Find unused address
+  const deployer = await findUnusedAddress(api);
 
-        if(result.findRecord('system', 'ExtrinsicSuccess')) {
-          resolve();
-        }
-        else {
-          reject('Failed to flip value.');
-        }
-      })
-  });
+  // Transfer balance to it
+  const keyring = new Keyring({ type: 'sr25519' });
+  const alice = keyring.addFromUri(`//Alice`);
+  let amount = new BigNumber(endowment);
+  amount = amount.plus(1e15);
+  const tx = api.tx.balances.transfer(deployer.address, amount.toFixed());
+  await submitTransactionAsync(alice, tx);
+
+  return deployer;
 }
 
+async function deployFlipper(api: ApiPromise): Promise<[Contract, IKeyringPair]> {
+  const metadata = JSON.parse(fs.readFileSync('./src/flipper/metadata.json').toString('utf-8'));
+  const abi = new Abi(metadata);
+
+  const deployer = await prepareDeployer(api);
+
+  const wasm = fs.readFileSync('./src/flipper/flipper.wasm');
+
+  const code = new CodePromise(api, abi, wasm);
+
+  const blueprint = await deployBlueprint(deployer, code);
+  const contract = (await deployContract(deployer, blueprint))['contract'] as Contract;
+
+  const initialGetResponse = await getFlipValue(contract, deployer);
+  expect(initialGetResponse).to.be.true;
+
+  return [contract, deployer];
+}
+
+async function getFlipValue(contract: Contract, deployer: IKeyringPair) {
+  const result = await contract.query.get(deployer.address, value, gasLimit);
+
+  if(!result.result.isSuccess) {
+    throw `Failed to get flipper value`;
+  }
+  return (result.result.asSuccess.data[0] == 0x00) ? false : true;
+}
+
 describe('Contracts', () => {
   it(`Can deploy smart contract Flipper, instantiate it and call it's get and flip messages.`, async () => {
     await usingApi(async api => {
-      const keyring = new Keyring({ type: 'sr25519' });
-      const alice = keyring.addFromUri("//Alice");
-      
-      const wasm = fs.readFileSync('./src/flipper/flipper.wasm');
-      
-      const metadata = JSON.parse(fs.readFileSync('./src/flipper/metadata.json').toString('utf-8'));
-      const abi = new Abi(metadata);
+      const [contract, deployer] = await deployFlipper(api);
+      const initialGetResponse = await getFlipValue(contract, deployer);
 
-      const code = new CodePromise(api, abi, wasm);
+      const bob = privateKey("//Bob");
+      const flip = contract.exec('flip', value, gasLimit);
+      await submitTransactionAsync(bob, flip);
 
-      const blueprint = await deployBlueprint(alice, code);
-      const contract = (await deployContract(alice, blueprint))['contract'];
+      const afterFlipGetResponse = await getFlipValue(contract, deployer);
+      expect(afterFlipGetResponse).not.to.be.eq(initialGetResponse, 'Flipping should change value.');
+    });
+  });
 
-      const getFlipValue = async () => {
-        const result = await contract.query.get(alice.address, value, gasLimit);
+  it(`Whitelisted account can call contract.`, async () => {
+    await usingApi(async api => {
+      const bob = privateKey("//Bob");
 
-        if(!result.result.isSuccess) {
-          throw `Failed to get flipper value`;
-        }
-        return (result.result.asSuccess.data[0] == 0x00) ? false : true;
-      }
+      const [contract, deployer] = await deployFlipper(api);
+      const consoleError = console.error;
+      console.error = (...data: any[]) => {
+      };
 
-      const initialGetResponse = await getFlipValue();
-      expect(initialGetResponse).to.be.true;
+      let expectedFlipValue = await getFlipValue(contract, deployer);
 
       const flip = contract.exec('flip', value, gasLimit);
-      await runTransaction(alice, flip);
+      await submitTransactionAsync(bob, flip);
+      expectedFlipValue = !expectedFlipValue;
+      const afterFlip = await getFlipValue(contract,deployer);
+      expect(afterFlip).to.be.eq(expectedFlipValue, `Anyone can call new contract.`);
 
-      const afterFlipGetResponse = await getFlipValue();
+      const deployerCanFlip = async () => {
+        expectedFlipValue = !expectedFlipValue;
+        const deployerFlip = contract.exec('flip', value, gasLimit);
+        await submitTransactionAsync(deployer, deployerFlip);
+        const aliceFlip1Response = await getFlipValue(contract, deployer);
+        expect(aliceFlip1Response).to.be.eq(expectedFlipValue, `Deployer always can flip.`);
+      };
+      await deployerCanFlip();
 
-      expect(afterFlipGetResponse).to.be.false;
+      const enableWhiteListTx = api.tx.nft.toggleContractWhiteList(contract.address, true);
+      const enableResult = await submitTransactionAsync(deployer, enableWhiteListTx);
+      const flipWithEnabledWhiteList = contract.exec('flip', value, gasLimit);
+      await expect(submitTransactionExpectFailAsync(bob, flipWithEnabledWhiteList)).to.be.rejected;
+      const flipValueAfterEnableWhiteList = await getFlipValue(contract, deployer);
+      expect(flipValueAfterEnableWhiteList).to.be.eq(expectedFlipValue, `Enabling whitelist doesn't make it possible to call contract for everyone.`);
+
+      await deployerCanFlip();
+
+      const addBobToWhiteListTx = api.tx.nft.addToContractWhiteList(contract.address, bob.address);
+      const addBobResult = await submitTransactionAsync(deployer, addBobToWhiteListTx);
+      const flipWithWhitelistedBob = contract.exec('flip', value, gasLimit);
+      await submitTransactionAsync(bob, flipWithWhitelistedBob);
+      expectedFlipValue = !expectedFlipValue;
+      const flipAfterWhiteListed = await getFlipValue(contract,deployer);
+      expect(flipAfterWhiteListed).to.be.eq(expectedFlipValue, `Bob was whitelisted, now he can flip.`);
+
+      await deployerCanFlip();
+
+      const removeBobFromWhiteListTx = api.tx.nft.removeFromContractWhiteList(contract.address, bob.address);
+      const removeBobResult = await submitTransactionAsync(deployer, removeBobFromWhiteListTx);
+      const bobRemoved = contract.exec('flip', value, gasLimit);
+      await expect(submitTransactionExpectFailAsync(bob, bobRemoved)).to.be.rejected;
+      const afterBobRemoved = await getFlipValue(contract, deployer);
+      expect(afterBobRemoved).to.be.eq(expectedFlipValue, `Bob can't call contract, now when he is removeed from white list.`);
+
+      await deployerCanFlip();
+
+      const disableWhiteListTx = api.tx.nft.toggleContractWhiteList(contract.address, false);
+      const disableWhiteListResult = await submitTransactionAsync(deployer, disableWhiteListTx);
+      const whiteListDisabledFlip = contract.exec('flip', value, gasLimit);
+      await submitTransactionAsync(bob, whiteListDisabledFlip);
+      expectedFlipValue = !expectedFlipValue;
+      const afterWhiteListDisabled = await getFlipValue(contract,deployer);
+      expect(afterWhiteListDisabled).to.be.eq(expectedFlipValue, `Anyone can call contract with disabled whitelist.`);
+
+      console.error = consoleError;
     });
   });
 
@@ -123,7 +201,7 @@
       // const bob = new GenericAccountId(api.registry, bobsPublicKey);
 
       // const transfer = contractInstance.exec('balance_transfer', 0, 1000000000000n, [bob, new u128(api.registry, 1000000)]);
-      // await runTransaction(alicesPrivateKey, transfer);
+      // await submitTransactionAsync(alicesPrivateKey, transfer);
 
       // const [alicesBalanceAfter, bobsBalanceAfter] = await getBalance(api, [alicesPublicKey, bobsPublicKey]);
 
addedtests/src/createCollection.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/createCollection.test.ts
@@ -0,0 +1,72 @@
+//
+// 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, createCollectionExpectFailure } from "./util/helpers";
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+describe('integration test: ext. createCollection():', () => {
+  it('Create new NFT collection', async () => {
+    await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+  });
+  it('Create new NFT collection whith collection_name of maximum length (64 bytes)', async () => {
+    await createCollectionExpectSuccess(
+      'ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCD',
+      '1', '1', 'NFT');
+  });
+  it('Create new NFT collection whith collection_description of maximum length (256 bytes)', async () => {
+    await createCollectionExpectSuccess(
+      'A', 
+      'ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJabcdef',
+      '1', 'NFT');
+  });
+  it('Create new NFT collection whith token_prefix of maximum length (16 bytes)', async () => {
+    await createCollectionExpectSuccess(
+      '1', 
+      '1',
+      'ABCDEFGHIJABCDEF', 'NFT');
+  });
+  it('Create new Fungible collection', async () => {
+    await createCollectionExpectSuccess('1', '1', '1', 'Fungible');
+  });
+  it('Create new ReFungible collection', async () => {
+    await createCollectionExpectSuccess('1', '1', '1', 'ReFungible');
+  });
+});
+
+describe('(!negative test!) integration test: ext. createCollection():', () => {
+  it('(!negative test!) create new NFT collection whith incorrect data (mode)', async () => {
+    await usingApi(async (api) => {
+      const AcollectionCount = parseInt((await api.query.nft.collectionCount()).toString());
+
+      const badTransaction = async function () { 
+        await createCollectionExpectSuccess('1', '1', '1', 'BadMode');
+      };
+      expect(badTransaction()).to.be.rejected;
+
+      const BcollectionCount = parseInt((await api.query.nft.collectionCount()).toString());
+      expect(BcollectionCount).to.be.equal(AcollectionCount, 'Error: Incorrect collection created.');
+    });
+  });
+  it('(!negative test!) create new NFT collection whith incorrect data (collection_name)', async () => {
+    await createCollectionExpectFailure(
+      'ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDE', 
+      '1', '1', 'NFT');
+  });
+  it('(!negative test!) create new NFT collection whith incorrect data (collection_description)', async () => {
+    await createCollectionExpectFailure('1',
+      'ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJabcdefg',
+      '1', 'NFT');
+  });
+  it('(!negative test!) create new NFT collection whith incorrect data (token_prefix)', async () => {
+    await createCollectionExpectFailure('1', '1', 
+    'ABCDEFGHIJABCDEFG',
+    'NFT');
+  });
+});
addedtests/src/createItem.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/createItem.test.ts
@@ -0,0 +1,34 @@
+import { default as usingApi } from './substrate/substrate-api';
+import { Keyring } from "@polkadot/api";
+import { IKeyringPair } from "@polkadot/types/types";
+import { 
+  createCollectionExpectSuccess, 
+  createItemExpectSuccess
+} from './util/helpers';
+
+let alice: IKeyringPair;
+
+describe('integration test: ext. createItem():', () => {
+  before(async () => {
+    await usingApi(async (api) => {
+      const keyring = new Keyring({ type: 'sr25519' });
+      alice = keyring.addFromUri(`//Alice`);
+    });
+  });
+
+  it('Create new item in NFT collection', async () => {
+    const createMode = 'NFT';
+    const newCollectionID = await createCollectionExpectSuccess('0', '0', '0', createMode);
+    await createItemExpectSuccess(alice, newCollectionID, createMode);
+  });
+  it('Create new item in Fungible collection', async () => {
+    const createMode = 'Fungible';
+    const newCollectionID = await createCollectionExpectSuccess('0', '0', '0', createMode);
+    await createItemExpectSuccess(alice, newCollectionID, createMode);
+  });
+  it('Create new item in ReFungible collection', async () => {
+    const createMode = 'ReFungible';
+    const newCollectionID = await createCollectionExpectSuccess('0', '0', '0', createMode);
+    await createItemExpectSuccess(alice, newCollectionID, createMode);
+  });
+});
addedtests/src/createMultipleItems.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/createMultipleItems.test.ts
@@ -0,0 +1,69 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+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';
+
+const idCollection = 12;
+
+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!'); }
+    });
+  });
+  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('(!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!'); }
+    });
+  });
+});
addedtests/src/creditFeesToTreasury.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/creditFeesToTreasury.test.ts
@@ -0,0 +1,112 @@
+//
+// 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 { alicesPublicKey, bobsPublicKey } from "./accounts";
+import privateKey from "./substrate/privateKey";
+import { BigNumber } from 'bignumber.js';
+import { createCollectionExpectSuccess, getGenericResult } from './util/helpers';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+const Treasury = "5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z";
+const saneMinimumFee = 0.0001;
+const saneMaximumFee = 0.01;
+
+describe('integration test: Fees must be credited to Treasury:', () => {
+  it('Total issuance does not change', async () => {
+    await usingApi(async (api) => {
+      const totalBefore = new BigNumber((await api.query.balances.totalIssuance()).toString());
+
+      const alicePrivateKey = privateKey('//Alice');
+      const amount = new BigNumber(1);
+      const transfer = api.tx.balances.transfer(bobsPublicKey, amount.toFixed());
+
+      const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer));
+
+      const totalAfter = new BigNumber((await api.query.balances.totalIssuance()).toString());
+
+      expect(result.success).to.be.true;
+      expect(totalAfter.toFixed()).to.be.equal(totalBefore.toFixed());
+    });
+  });
+
+  it('Sender balance decreased by fee+sent amount, Treasury balance increased by fee', async () => {
+    await usingApi(async (api) => {
+      const alicePrivateKey = privateKey('//Alice');
+      const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+      const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
+
+      const amount = new BigNumber(1);
+      const transfer = api.tx.balances.transfer(bobsPublicKey, amount.toFixed());
+      const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer));
+
+      const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+      const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
+      const fee = aliceBalanceBefore.minus(aliceBalanceAfter).minus(amount);
+      const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);
+
+      expect(result.success).to.be.true;
+      expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed());
+    });
+  });
+
+  it('Treasury balance increased by failed tx fee', async () => {
+    await usingApi(async (api) => {
+      const bobPrivateKey = privateKey('//Bob');
+      const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+      const bobBalanceBefore = new BigNumber((await api.query.system.account(bobsPublicKey)).data.free.toString());
+
+      const badTx = api.tx.balances.setBalance(alicesPublicKey, 0, 0);
+      const result = getGenericResult(await submitTransactionAsync(bobPrivateKey, badTx));
+
+      const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+      const bobBalanceAfter = new BigNumber((await api.query.system.account(bobsPublicKey)).data.free.toString());
+      const fee = bobBalanceBefore.minus(bobBalanceAfter);
+      const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);
+
+      expect(result.success).to.be.false;
+      expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed());
+    });
+  });
+
+  it('NFT Transactions also send fees to Treasury', async () => {
+    await usingApi(async (api) => {
+      const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+      const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
+
+      await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+
+      const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+      const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
+      const fee = aliceBalanceBefore.minus(aliceBalanceAfter);
+      const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);
+
+      expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed());
+    });
+  });
+
+  it('Fees are sane', async () => {
+    await usingApi(async (api) => {
+      const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+      const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
+
+      await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+
+      const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+      const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
+      const fee = aliceBalanceBefore.minus(aliceBalanceAfter);
+      const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);
+
+      expect(fee.dividedBy(1e15).toNumber()).to.be.lessThan(0.01);
+      expect(fee.dividedBy(1e15).toNumber()).to.be.greaterThan(0.0001);
+    });
+  });
+
+});
+
addedtests/src/destroyCollection.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/destroyCollection.test.ts
@@ -0,0 +1,44 @@
+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';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+describe('integration test: ext. destroyCollection():', () => {
+  it('NFT collection can be destroyed', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await destroyCollectionExpectSuccess(collectionId);
+  });
+  it('Fungible collection can be destroyed', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'Fungible');
+    await destroyCollectionExpectSuccess(collectionId);
+  });
+  it('ReFungible collection can be destroyed', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'ReFungible');
+    await destroyCollectionExpectSuccess(collectionId);
+  });
+});
+
+describe('(!negative test!) integration test: ext. destroyCollection():', () => {
+  it('(!negative test!) Destroy a collection that never existed', async () => {
+    await usingApi(async (api) => {
+      // Find the collection that never existed
+      const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;
+      await destroyCollectionExpectFailure(collectionId);
+    });
+  });
+  it('(!negative test!) Destroy a collection that has already been destroyed', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await destroyCollectionExpectSuccess(collectionId);
+    await destroyCollectionExpectFailure(collectionId);
+  });
+  it('(!negative test!) Destroy a collection using non-owner account', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await destroyCollectionExpectFailure(collectionId, '//Bob');
+    await destroyCollectionExpectSuccess(collectionId, '//Alice');
+  });
+});
addedtests/src/load_test_sc/loadtester.wasmdiffbeforeafterboth

binary blob — no preview

addedtests/src/load_test_sc/metadata.jsondiffbeforeafterboth
--- /dev/null
+++ b/tests/src/load_test_sc/metadata.json
@@ -0,0 +1,125 @@
+{
+  "metadataVersion": "0.1.0",
+  "source": {
+    "hash": "0x168cc3cba9657ad3950fb506e568751f99b90fb097685107f6101675662a8303",
+    "language": "ink! 3.0.0-rc2",
+    "compiler": "rustc 1.49.0-nightly"
+  },
+  "contract": {
+    "name": "loadtester",
+    "version": "0.1.0",
+    "authors": [
+      "[your_name] <[your_email]>"
+    ]
+  },
+  "spec": {
+    "constructors": [
+      {
+        "args": [],
+        "docs": [],
+        "name": [
+          "new"
+        ],
+        "selector": "0xd183512b"
+      }
+    ],
+    "docs": [],
+    "events": [],
+    "messages": [
+      {
+        "args": [
+          {
+            "name": "count",
+            "type": {
+              "displayName": [
+                "u64"
+              ],
+              "type": 2
+            }
+          }
+        ],
+        "docs": [],
+        "mutates": true,
+        "name": [
+          "bloat"
+        ],
+        "payable": false,
+        "returnType": null,
+        "selector": "0x49891c2a"
+      },
+      {
+        "args": [],
+        "docs": [],
+        "mutates": false,
+        "name": [
+          "get"
+        ],
+        "payable": false,
+        "returnType": {
+          "displayName": [
+            "u128"
+          ],
+          "type": 3
+        },
+        "selector": "0x1e5ca456"
+      }
+    ]
+  },
+  "storage": {
+    "struct": {
+      "fields": [
+        {
+          "layout": {
+            "struct": {
+              "fields": [
+                {
+                  "layout": {
+                    "cell": {
+                      "key": "0x0000000000000000000000000000000000000000000000000000000000000000",
+                      "ty": 1
+                    }
+                  },
+                  "name": "len"
+                },
+                {
+                  "layout": {
+                    "array": {
+                      "cellsPerElem": 1,
+                      "layout": {
+                        "cell": {
+                          "key": "0x0000000001000000000000000000000000000000000000000000000000000000",
+                          "ty": 2
+                        }
+                      },
+                      "len": 4294967295,
+                      "offset": "0x0100000000000000000000000000000000000000000000000000000000000000"
+                    }
+                  },
+                  "name": "elems"
+                }
+              ]
+            }
+          },
+          "name": "vector"
+        }
+      ]
+    }
+  },
+  "types": [
+    {
+      "def": {
+        "primitive": "u32"
+      }
+    },
+    {
+      "def": {
+        "primitive": "u64"
+      }
+    },
+    {
+      "def": {
+        "primitive": "u128"
+      }
+    }
+  ]
+}
\ No newline at end of file
modifiedtests/src/pallet-presence.test.tsdiffbeforeafterboth
--- a/tests/src/pallet-presence.test.ts
+++ b/tests/src/pallet-presence.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 { ApiPromise } from "@polkadot/api";
 import { expect } from "chai";
 import usingApi from "./substrate/substrate-api";
@@ -6,20 +11,34 @@
   return api.runtimeMetadata.asLatest.modules.map(m => m.name.toString().toLowerCase());
 }
 
-describe('Pallet presence.', () => {
-  it('NFT pallet is present.', async () => {
+// Pallets that must always be present
+const requiredPallets = [
+  'nft', 'balances', 'contracts', 'randomnesscollectiveflip', 'system', 'timestamp', 'transactionpayment', 'treasury', 'vesting'
+];
+
+// Pallets that depend on consensus and governance configuration
+const consensusPallets = [
+  'sudo', 'grandpa', 'aura'
+];
+
+describe('Pallet presence', () => {
+  it('Required pallets are present', async () => {
     await usingApi(async api => {
-      expect(getModuleNames(api)).to.include('nft');
+      for (let i=0; i<requiredPallets.length; i++) {
+        expect(getModuleNames(api)).to.include(requiredPallets[i]);
+      }
     });
   });
-  it('Balances pallet is present.', async () => {
+  it('Governance and consensus pallets are present', async () => {
     await usingApi(async api => {
-      expect(getModuleNames(api)).to.include('balances');
+      for (let i=0; i<consensusPallets.length; i++) {
+        expect(getModuleNames(api)).to.include(consensusPallets[i]);
+      }
     });
   });
-  it('Contracts pallet is present.', async () => {
+  it('No extra pallets are included', async () => {
     await usingApi(async api => {
-      expect(getModuleNames(api)).to.include('contracts');
+      expect(getModuleNames(api).length).to.be.equal(requiredPallets.length + consensusPallets.length);
     });
   });
 });
addedtests/src/removeCollectionSponsor.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/removeCollectionSponsor.test.ts
@@ -0,0 +1,141 @@
+//
+// 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, 
+  setCollectionSponsorExpectSuccess, 
+  destroyCollectionExpectSuccess, 
+  setCollectionSponsorExpectFailure,
+  confirmSponsorshipExpectSuccess,
+  confirmSponsorshipExpectFailure,
+  createItemExpectSuccess,
+  findUnusedAddress,
+  getGenericResult,
+  enableWhiteListExpectSuccess,
+  enablePublicMintingExpectSuccess,
+  addToWhiteListExpectSuccess,
+  removeCollectionSponsorExpectSuccess,
+  removeCollectionSponsorExpectFailure,
+} from "./util/helpers";
+import { Keyring } from "@polkadot/api";
+import { IKeyringPair } from "@polkadot/types/types";
+import type { AccountId } from '@polkadot/types/interfaces';
+import { BigNumber } from 'bignumber.js';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+let alice: IKeyringPair;
+let bob: IKeyringPair;
+let charlie: IKeyringPair;
+
+describe('integration test: ext. removeCollectionSponsor():', () => {
+
+  before(async () => {
+    await usingApi(async (api) => {
+      const keyring = new Keyring({ type: 'sr25519' });
+      alice = keyring.addFromUri(`//Alice`);
+      bob = keyring.addFromUri(`//Bob`);
+      charlie = keyring.addFromUri(`//Charlie`);
+    });
+  });
+
+  it('Remove NFT collection sponsor stops sponsorship', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+    await removeCollectionSponsorExpectSuccess(collectionId);
+
+    await usingApi(async (api) => {
+      // Find unused address
+      const zeroBalance = await findUnusedAddress(api);
+
+      // Mint token for unused address
+      const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', zeroBalance.address);
+
+      // Transfer this tokens from unused address to Alice - should fail
+      const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+      const zeroToAlice = api.tx.nft.transfer(alice.address, collectionId, itemId, 0);
+      const badTransaction = async function () { 
+        console.log = function () {};
+        console.error = function () {};
+        await submitTransactionAsync(zeroBalance, zeroToAlice);
+        delete console.log;
+        delete console.error;
+      };
+      await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees");
+      const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());
+
+      expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;
+    });
+  });
+
+  it('Remove a sponsor after it was already removed', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+    await removeCollectionSponsorExpectSuccess(collectionId);
+    await removeCollectionSponsorExpectSuccess(collectionId);
+  });
+
+  it('Remove sponsor in a collection that never had the sponsor set', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await removeCollectionSponsorExpectSuccess(collectionId);
+  });
+
+  it('Remove sponsor for a collection that had the sponsor set, but not confirmed', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await removeCollectionSponsorExpectSuccess(collectionId);
+  });
+
+});
+
+describe('(!negative test!) integration test: ext. removeCollectionSponsor():', () => {
+  before(async () => {
+    await usingApi(async (api) => {
+      const keyring = new Keyring({ type: 'sr25519' });
+      alice = keyring.addFromUri(`//Alice`);
+      bob = keyring.addFromUri(`//Bob`);
+      charlie = keyring.addFromUri(`//Charlie`);
+    });
+  });
+
+  it('(!negative test!) Remove sponsor for a collection that never existed', async () => {
+    // Find the collection that never existed
+    const collectionId = 0;
+    await usingApi(async (api) => {
+      const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;
+    });
+
+    await removeCollectionSponsorExpectFailure(collectionId);
+  });
+
+  it('(!negative test!) Remove sponsor in a destroyed collection', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await destroyCollectionExpectSuccess(collectionId);
+    await removeCollectionSponsorExpectFailure(collectionId);
+  });
+
+  it('Set - remove - confirm: fails', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await removeCollectionSponsorExpectSuccess(collectionId);
+    await confirmSponsorshipExpectFailure(collectionId, '//Bob');
+  });
+
+  it('Set - confirm - remove - confirm: Sponsor cannot come back', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+    await removeCollectionSponsorExpectSuccess(collectionId);
+    await confirmSponsorshipExpectFailure(collectionId, '//Bob');
+  });
+
+});
addedtests/src/rpc.load.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/rpc.load.ts
@@ -0,0 +1,145 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { expect, assert } from "chai";
+import usingApi, { submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api";
+import { IKeyringPair } from "@polkadot/types/types";
+import { Abi, BlueprintPromise as Blueprint, CodePromise, ContractPromise as Contract } from "@polkadot/api-contract";
+import { ApiPromise, Keyring } from "@polkadot/api";
+import { ApiTypes, SubmittableExtrinsic } from "@polkadot/api/types";
+import { BigNumber } from 'bignumber.js';
+import { findUnusedAddress } from './util/helpers'
+import fs from "fs";
+import privateKey from "./substrate/privateKey";
+
+const value = 0;
+const gasLimit = 500000n * 1000000n;
+const endowment = `1000000000000000`;
+
+
+function deployBlueprint(alice: IKeyringPair, code: CodePromise): Promise<Blueprint> {
+  return new Promise<Blueprint>(async (resolve, reject) => {
+    const unsub = await code
+      .createBlueprint()
+      .signAndSend(alice, (result) => {
+        if (result.status.isInBlock || result.status.isFinalized) {
+          // here we have an additional field in the result, containing the blueprint
+          resolve(result.blueprint);
+          unsub();
+        }
+      })
+  });
+}
+
+function deployContract(alice: IKeyringPair, blueprint: Blueprint) : Promise<any> {
+  return new Promise<any>(async (resolve, reject) => {
+    const unsub = await blueprint.tx
+    .new(endowment, gasLimit)
+    .signAndSend(alice, (result) => {
+      if (result.status.isInBlock || result.status.isFinalized) {
+        unsub();
+        resolve(result);
+      }
+    });    
+  });
+}
+
+async function prepareDeployer(api: ApiPromise) {
+  // Find unused address
+  const deployer = await findUnusedAddress(api);
+
+  // Transfer balance to it
+  const keyring = new Keyring({ type: 'sr25519' });
+  const alice = keyring.addFromUri(`//Alice`);
+  let amount = new BigNumber(endowment);
+  amount = amount.plus(1e15);
+  const tx = api.tx.balances.transfer(deployer.address, amount.toFixed());
+  await submitTransactionAsync(alice, tx);
+
+  return deployer;
+}
+
+async function deployLoadTester(api: ApiPromise): Promise<[Contract, IKeyringPair]> {
+  const metadata = JSON.parse(fs.readFileSync('./src/load_test_sc/metadata.json').toString('utf-8'));
+  const abi = new Abi(metadata);
+
+  const deployer = await prepareDeployer(api);
+
+  const wasm = fs.readFileSync('./src/load_test_sc/loadtester.wasm');
+
+  const code = new CodePromise(api, abi, wasm);
+
+  const blueprint = await deployBlueprint(deployer, code);
+  const contract = (await deployContract(deployer, blueprint))['contract'] as Contract;
+
+  return [contract, deployer];
+}
+
+async function getScData(contract: Contract, deployer: IKeyringPair) {
+  const result = await contract.query.get(deployer.address, value, gasLimit);
+
+  if(!result.result.isSuccess) {
+    throw `Failed to get value`;
+  }
+  return result.result.asSuccess.data;
+}
+
+
+describe('RPC Tests', () => {
+  it('Simple RPC Load Test', async () => {
+    await usingApi(async api => {
+      let count = 0;
+      let hrTime = process.hrtime();
+      let microsec1 = hrTime[0] * 1000000 + hrTime[1] / 1000;
+      let rate = 0;
+      const checkPoint = 1000;
+      while (true) {
+        await api.rpc.system.chain();
+        count++;
+        process.stdout.write(`RPC reads: ${count} times at rate ${rate} r/s            \r`);
+    
+        if (count % checkPoint == 0) {
+          hrTime = process.hrtime();
+          let microsec2 = hrTime[0] * 1000000 + hrTime[1] / 1000;
+          rate = 1000000*checkPoint/(microsec2 - microsec1);
+          microsec1 = microsec2;
+        }
+      }
+    });
+  });
+
+  it.only('Smart Contract RPC Load Test', async () => {
+    await usingApi(async api => {
+
+      // Deploy smart contract
+      const [contract, deployer] = await deployLoadTester(api);
+
+      // Fill smart contract up with data
+      const bob = privateKey("//Bob");
+      const tx = contract.tx.bloat(value, gasLimit, 200);
+      await submitTransactionAsync(bob, tx);
+
+      // Run load test
+      let count = 0;
+      let hrTime = process.hrtime();
+      let microsec1 = hrTime[0] * 1000000 + hrTime[1] / 1000;
+      let rate = 0;
+      const checkPoint = 10;
+      while (true) {
+        await getScData(contract, deployer);
+        count++;
+        process.stdout.write(`SC reads: ${count} times at rate ${rate} r/s            \r`);
+    
+        if (count % checkPoint == 0) {
+          hrTime = process.hrtime();
+          let microsec2 = hrTime[0] * 1000000 + hrTime[1] / 1000;
+          rate = 1000000*checkPoint/(microsec2 - microsec1);
+          microsec1 = microsec2;
+        }
+      }
+    });
+  });
+
+});
addedtests/src/setCollectionSponsor.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/setCollectionSponsor.test.ts
@@ -0,0 +1,82 @@
+//
+// 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, 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;
+
+let bob: IKeyringPair;
+
+describe('integration test: ext. setCollectionSponsor():', () => {
+
+  before(async () => {
+    await usingApi(async (api) => {
+      const keyring = new Keyring({ type: 'sr25519' });
+      bob = keyring.addFromUri(`//Bob`);
+    });
+  });
+
+  it('Set NFT collection sponsor', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+  });
+  it('Set Fungible collection sponsor', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'Fungible');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+  });
+  it('Set ReFungible collection sponsor', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'ReFungible');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+  });
+
+  it('Set the same sponsor repeatedly', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+  });
+  it('Replace collection sponsor', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+
+    const keyring = new Keyring({ type: 'sr25519' });
+    const charlie = keyring.addFromUri(`//Charlie`);
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await setCollectionSponsorExpectSuccess(collectionId, charlie.address);
+  });
+});
+
+describe('(!negative test!) integration test: ext. setCollectionSponsor():', () => {
+  before(async () => {
+    await usingApi(async (api) => {
+      const keyring = new Keyring({ type: 'sr25519' });
+      bob = keyring.addFromUri(`//Bob`);
+    });
+  });
+
+  it('(!negative test!) Add sponsor with a non-owner', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await setCollectionSponsorExpectFailure(collectionId, bob.address, '//Bob');
+  });
+  it('(!negative test!) Add sponsor to a collection that never existed', async () => {
+    // Find the collection that never existed
+    const collectionId = 0;
+    await usingApi(async (api) => {
+      const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;
+    });
+
+    await setCollectionSponsorExpectFailure(collectionId, bob.address);
+  });
+  it('(!negative test!) Add sponsor to a collection that was destroyed', async () => {
+    const collectionId = await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+    await destroyCollectionExpectSuccess(collectionId);
+    await setCollectionSponsorExpectFailure(collectionId, bob.address);
+  });
+});
modifiedtests/src/substrate/get-balance.tsdiffbeforeafterboth
--- a/tests/src/substrate/get-balance.ts
+++ b/tests/src/substrate/get-balance.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 { ApiPromise } from "@polkadot/api";
 import promisifySubstrate from "./promisify-substrate";
 import {AccountInfo} from "@polkadot/types/interfaces/system";
modifiedtests/src/substrate/privateKey.tsdiffbeforeafterboth
--- a/tests/src/substrate/privateKey.ts
+++ b/tests/src/substrate/privateKey.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 { Keyring } from "@polkadot/api";
 import { IKeyringPair } from "@polkadot/types/types";
 
modifiedtests/src/substrate/promisify-substrate.tsdiffbeforeafterboth
--- a/tests/src/substrate/promisify-substrate.ts
+++ b/tests/src/substrate/promisify-substrate.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 ApiPromise from "@polkadot/api/promise/Api";
 
 type PromiseType<T> = T extends PromiseLike<infer TInner> ? TInner : T;
modifiedtests/src/substrate/substrate-api.tsdiffbeforeafterboth
--- a/tests/src/substrate/substrate-api.ts
+++ b/tests/src/substrate/substrate-api.ts
@@ -1,7 +1,15 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
 import { WsProvider, ApiPromise } from "@polkadot/api";
+import type { AccountId, Address, ApplyExtrinsicResult, DispatchError, DispatchInfo, EventRecord, Extrinsic, ExtrinsicStatus, Hash, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
+import { IKeyringPair } from "@polkadot/types/types";
+
 import config from "../config";
 import promisifySubstrate from "./promisify-substrate";
-import { ApiOptions } from "@polkadot/api/types";
+import { ApiOptions, SubmittableExtrinsic, ApiTypes } from "@polkadot/api/types";
 import rtt from "../../../runtime_types.json";
 
 function defaultApiOptions(): ApiOptions {
@@ -23,4 +31,50 @@
   } finally {
     await api.disconnect();
   }
+}
+
+export function submitTransactionAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {
+  return new Promise(async function(resolve, reject) {
+    try {
+      await transaction.signAndSend(sender, ({ events = [], status }) => {
+        if (status.isReady) {
+          // nothing to do
+          // console.log(`Current tx status is Ready`);
+        } else if (status.isBroadcast) {
+          // nothing to do
+          // console.log(`Current tx status is Broadcast`);
+        } else if (status.isInBlock || status.isFinalized) {
+          resolve(events);
+        } else {
+          console.log(`Something went wrong with transaction. Status: ${status}`);
+          reject("Transaction failed");
+        }
+      });
+    } catch (e) {
+      console.log("Error: ", e);
+      reject(e);
+    }
+  });
+}
+
+export function submitTransactionExpectFailAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {
+  return new Promise(async function(resolve, reject) {
+    try {
+      await transaction.signAndSend(sender, ({ events = [], status }) => {
+        if (status.isReady) {
+          // nothing to do
+          // console.log(`Current tx status is Ready`);
+        } else if (status.isBroadcast) {
+          // nothing to do
+          // console.log(`Current tx status is Broadcast`);
+        } else if (status.isInBlock || status.isFinalized) {
+          resolve(events);
+        } else {
+          reject("Transaction failed");
+        }
+      });
+    } catch (e) {
+      reject(e);
+    }
+  });
 }
\ No newline at end of file
modifiedtests/src/substrate/wait-new-blocks.tsdiffbeforeafterboth
--- a/tests/src/substrate/wait-new-blocks.ts
+++ b/tests/src/substrate/wait-new-blocks.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 { ApiPromise } from "@polkadot/api";
 
 export default function waitNewBlocks(api: ApiPromise, blocksCount: number = 1): Promise<void> {
modifiedtests/src/transfer.test.tsdiffbeforeafterboth
--- a/tests/src/transfer.test.ts
+++ b/tests/src/transfer.test.ts
@@ -1,10 +1,15 @@
-import { expect } from "chai";
-import usingApi from "./substrate/substrate-api";
-import promisifySubstrate from "./substrate/promisify-substrate";
-import waitNewBlocks from "./substrate/wait-new-blocks";
-import { alicesPublicKey, bobsPublicKey } from "./accounts";
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { expect, assert } from "chai";
+import { default as usingApi, submitTransactionAsync } from "./substrate/substrate-api";
+import { alicesPublicKey, bobsPublicKey, ferdiesPublicKey } from "./accounts";
 import privateKey from "./substrate/privateKey";
 import getBalance from "./substrate/get-balance";
+import { BigNumber } from 'bignumber.js';
+import { findUnusedAddress } from './util/helpers'
 
 describe('Transfer', () => {
   it('Balance transfers', async () => {
@@ -14,15 +19,31 @@
       const alicePrivateKey = privateKey('//Alice');
       
       const transfer = api.tx.balances.transfer(bobsPublicKey, 1n);
-      
-      await promisifySubstrate(api, () => transfer.signAndSend(alicePrivateKey))();
+      const result = await submitTransactionAsync(alicePrivateKey, transfer);
 
-      await waitNewBlocks(api);
-  
       const [alicesBalanceAfter, bobsBalanceAfter] = await getBalance(api, [alicesPublicKey, bobsPublicKey]);
 
       expect(alicesBalanceAfter < alicesBalanceBefore).to.be.true;
       expect(bobsBalanceAfter > bobsBalanceBefore).to.be.true;
     });
   });
+
+  it('Inability to pay fees error message is correct', async () => {
+    await usingApi(async api => {
+      // Find unused address
+      const pk = await findUnusedAddress(api);
+
+      console.log = function () {};
+      console.error = function () {};
+  
+      const badTransfer = api.tx.balances.transfer(bobsPublicKey, 1n);
+      const badTransaction = async function () { 
+        const result = await submitTransactionAsync(pk, badTransfer);
+      };
+      await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees");
+
+      delete console.log;
+      delete console.error;
+    });
+  });
 });
addedtests/src/util/helpers.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/util/helpers.ts
@@ -0,0 +1,398 @@
+//
+// 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 type { AccountId, EventRecord } from '@polkadot/types/interfaces';
+import { ApiPromise, Keyring } from "@polkadot/api";
+import { default as usingApi, submitTransactionAsync } from "../substrate/substrate-api";
+import privateKey from '../substrate/privateKey';
+import { alicesPublicKey, nullPublicKey } from "../accounts";
+import { strToUTF16, utf16ToStr, hexToStr } from '../util/util';
+import { IKeyringPair } from "@polkadot/types/types";
+import { BigNumber } from 'bignumber.js';
+import { Struct, Enum } from '@polkadot/types/codec';
+import { u128 } from '@polkadot/types/primitive';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+type GenericResult = {
+  success: boolean,
+};
+
+type CreateCollectionResult = {
+  success: boolean,
+  collectionId: number
+};
+
+type CreateItemResult = {
+  success: boolean,
+  collectionId: number,
+  itemId: number
+};
+
+export function getGenericResult(events: EventRecord[]): GenericResult {
+  let result: GenericResult = {
+    success: false
+  }
+  events.forEach(({ phase, event: { data, method, section } }) => {
+    // console.log(`    ${phase}: ${section}.${method}:: ${data}`);
+    if (method == 'ExtrinsicSuccess') {
+      result.success = true;
+    }
+  });
+  return result;
+}
+
+function getCreateCollectionResult(events: EventRecord[]): CreateCollectionResult {
+  let success = false;
+  let collectionId: number = 0;
+  events.forEach(({ phase, event: { data, method, section } }) => {
+    // console.log(`    ${phase}: ${section}.${method}:: ${data}`);
+    if (method == 'ExtrinsicSuccess') {
+      success = true;
+    } else if ((section == 'nft') && (method == 'Created')) {
+      collectionId = parseInt(data[0].toString());
+    }
+  });
+  let result: CreateCollectionResult = {
+    success,
+    collectionId
+  }
+  return result;
+}
+
+function getCreateItemResult(events: EventRecord[]): CreateItemResult {
+  let success = false;
+  let collectionId: number = 0;
+  let itemId: number = 0;
+  events.forEach(({ phase, event: { data, method, section } }) => {
+    // console.log(`    ${phase}: ${section}.${method}:: ${data}`);
+    if (method == 'ExtrinsicSuccess') {
+      success = true;
+    } else if ((section == 'nft') && (method == 'ItemCreated')) {
+      collectionId = parseInt(data[0].toString());
+      itemId = parseInt(data[1].toString());
+    }
+  });
+  let result: CreateItemResult = {
+    success,
+    collectionId,
+    itemId
+  }
+  return result;
+}
+
+export async function createCollectionExpectSuccess(name: string, description: string, tokenPrefix: string, mode: string): Promise<number> {
+  let collectionId: number = 0;
+  await usingApi(async (api) => {
+    // Get number of collections before the transaction
+    const AcollectionCount = parseInt((await api.query.nft.createdCollectionCount()).toString());
+
+    // Run the CreateCollection transaction
+    const alicePrivateKey = privateKey('//Alice');
+    const tx = api.tx.nft.createCollection(strToUTF16(name), strToUTF16(description), strToUTF16(tokenPrefix), mode);
+    const events = await submitTransactionAsync(alicePrivateKey, tx);
+    const result = getCreateCollectionResult(events);
+
+    // Get number of collections after the transaction
+    const BcollectionCount = parseInt((await api.query.nft.createdCollectionCount()).toString());
+
+    // Get the collection 
+    const collection: any = (await api.query.nft.collection(result.collectionId)).toJSON();
+
+    // What to expect
+    expect(result.success).to.be.true;
+    expect(result.collectionId).to.be.equal(BcollectionCount);
+    expect(collection).to.be.not.null;
+    expect(BcollectionCount).to.be.equal(AcollectionCount+1, 'Error: NFT collection NOT created.');
+    expect(collection.Owner).to.be.equal(alicesPublicKey);
+    expect(utf16ToStr(collection.Name)).to.be.equal(name);
+    expect(utf16ToStr(collection.Description)).to.be.equal(description);
+    expect(hexToStr(collection.TokenPrefix)).to.be.equal(tokenPrefix);
+
+    collectionId = result.collectionId;
+  });
+
+  return collectionId;
+}
+  
+export async function createCollectionExpectFailure(name: string, description: string, tokenPrefix: string, mode: string) {
+  await usingApi(async (api) => {
+    // Get number of collections before the transaction
+    const AcollectionCount = parseInt((await api.query.nft.createdCollectionCount()).toString());
+
+    // Run the CreateCollection transaction
+    const alicePrivateKey = privateKey('//Alice');
+    const tx = api.tx.nft.createCollection(name, description, tokenPrefix, mode);
+    const events = await submitTransactionAsync(alicePrivateKey, tx);
+    const result = getCreateCollectionResult(events);
+
+    // Get number of collections after the transaction
+    const BcollectionCount = parseInt((await api.query.nft.createdCollectionCount()).toString());
+
+    // What to expect
+    expect(result.success).to.be.false;
+    expect(BcollectionCount).to.be.equal(AcollectionCount, 'Error: Collection with incorrect data created.');
+  });
+}
+  
+export async function findUnusedAddress(api: ApiPromise): Promise<IKeyringPair> {
+  let bal = new BigNumber(0);
+  let unused;
+  do {
+    const randomSeed = 'seed' +  Math.floor(Math.random() * Math.floor(10000));
+    const keyring = new Keyring({ type: 'sr25519' });
+    unused = keyring.addFromUri(`//${randomSeed}`);
+    bal = new BigNumber((await api.query.system.account(unused.address)).data.free.toString());
+  } while (bal.toFixed() != '0');
+  return unused; 
+}
+
+function getDestroyResult(events: EventRecord[]): boolean {
+  let success: boolean = false;
+  events.forEach(({ phase, event: { data, method, section } }) => {
+    // console.log(`    ${phase}: ${section}.${method}:: ${data}`);
+    if (method == 'ExtrinsicSuccess') {
+      success = true;
+    }
+  });
+  return success;
+}
+
+export async function destroyCollectionExpectFailure(collectionId: number, senderSeed: string = '//Alice') {
+  await usingApi(async (api) => {
+    // Run the DestroyCollection transaction
+    const alicePrivateKey = privateKey(senderSeed);
+    const tx = api.tx.nft.destroyCollection(collectionId);
+    const events = await submitTransactionAsync(alicePrivateKey, tx);
+    const result = getDestroyResult(events);
+
+    // What to expect
+    expect(result).to.be.false;
+  });
+}
+
+export async function destroyCollectionExpectSuccess(collectionId: number, senderSeed: string = '//Alice') {
+  await usingApi(async (api) => {
+    // Run the DestroyCollection transaction
+    const alicePrivateKey = privateKey(senderSeed);
+    const tx = api.tx.nft.destroyCollection(collectionId);
+    const events = await submitTransactionAsync(alicePrivateKey, tx);
+    const result = getDestroyResult(events);
+
+    // Get the collection 
+    const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
+
+    // What to expect
+    expect(result).to.be.true;
+    expect(collection).to.be.not.null;
+    expect(collection.Owner).to.be.equal(nullPublicKey);
+  });
+}
+
+export async function setCollectionSponsorExpectSuccess(collectionId: number, sponsor: string) {
+  await usingApi(async (api) => {
+
+    // Run the transaction
+    const alicePrivateKey = privateKey('//Alice');
+    const tx = api.tx.nft.setCollectionSponsor(collectionId, sponsor);
+    const events = await submitTransactionAsync(alicePrivateKey, tx);
+    const result = getGenericResult(events);
+
+    // Get the collection 
+    const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
+
+    // What to expect
+    expect(result.success).to.be.true;
+    expect(collection.Sponsor.toString()).to.be.equal(sponsor.toString());
+    expect(collection.SponsorConfirmed).to.be.false;
+  });
+}
+
+export async function removeCollectionSponsorExpectSuccess(collectionId: number) {
+  await usingApi(async (api) => {
+
+    // Run the transaction
+    const alicePrivateKey = privateKey('//Alice');
+    const tx = api.tx.nft.removeCollectionSponsor(collectionId);
+    const events = await submitTransactionAsync(alicePrivateKey, tx);
+    const result = getGenericResult(events);
+
+    // Get the collection 
+    const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
+
+    // What to expect
+    expect(result.success).to.be.true;
+    expect(collection.Sponsor).to.be.equal(nullPublicKey);
+    expect(collection.SponsorConfirmed).to.be.false;
+  });
+}
+
+export async function removeCollectionSponsorExpectFailure(collectionId: number) {
+  await usingApi(async (api) => {
+
+    // Run the transaction
+    const alicePrivateKey = privateKey('//Alice');
+    const tx = api.tx.nft.removeCollectionSponsor(collectionId);
+    const events = await submitTransactionAsync(alicePrivateKey, tx);
+    const result = getGenericResult(events);
+
+    // What to expect
+    expect(result.success).to.be.false;
+  });
+}
+
+export async function setCollectionSponsorExpectFailure(collectionId: number, sponsor: string, senderSeed: string = '//Alice') {
+  await usingApi(async (api) => {
+
+    // Run the transaction
+    const alicePrivateKey = privateKey(senderSeed);
+    const tx = api.tx.nft.setCollectionSponsor(collectionId, sponsor);
+    const events = await submitTransactionAsync(alicePrivateKey, tx);
+    const result = getGenericResult(events);
+
+    // What to expect
+    expect(result.success).to.be.false;
+  });
+}
+
+export async function confirmSponsorshipExpectSuccess(collectionId: number, senderSeed: string = '//Alice') {
+  await usingApi(async (api) => {
+
+    // Run the transaction
+    const sender = privateKey(senderSeed);
+    const tx = api.tx.nft.confirmSponsorship(collectionId);
+    const events = await submitTransactionAsync(sender, tx);
+    const result = getGenericResult(events);
+
+    // Get the collection 
+    const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
+
+    // What to expect
+    expect(result.success).to.be.true;
+    expect(collection.Sponsor).to.be.equal(sender.address);
+    expect(collection.SponsorConfirmed).to.be.true;
+  });
+}
+
+export async function confirmSponsorshipExpectFailure(collectionId: number, senderSeed: string = '//Alice') {
+  await usingApi(async (api) => {
+
+    // Run the transaction
+    const sender = privateKey(senderSeed);
+    const tx = api.tx.nft.confirmSponsorship(collectionId);
+    const events = await submitTransactionAsync(sender, tx);
+    const result = getGenericResult(events);
+
+    // What to expect
+    expect(result.success).to.be.false;
+  });
+}
+
+export interface CreateFungibleData extends Struct {
+  readonly value: u128;
+};
+
+export interface CreateReFungibleData extends Struct {};
+export interface CreateNftData extends Struct {};
+
+export interface CreateItemData extends Enum {
+  NFT: CreateNftData,
+  Fungible: CreateFungibleData,
+  ReFungible: CreateReFungibleData
+};
+
+export async function createItemExpectSuccess(sender: IKeyringPair, collectionId: number, createMode: string, owner: string = '') {
+  let newItemId: number = 0;
+  await usingApi(async (api) => {
+    const AItemCount = parseInt((await api.query.nft.itemListIndex(collectionId)).toString());
+    const Aitem: any = (await api.query.nft.fungibleItemList(collectionId, owner)).toJSON();    
+    const AItemBalance = new BigNumber(Aitem.Value);
+
+    if (owner === '') owner = sender.address;
+
+    let tx;
+    if (createMode == 'Fungible') {
+      let createData = {fungible: {value: 10}};
+      tx = api.tx.nft.createItem(collectionId, owner, createData);
+    }
+    else {
+      tx = api.tx.nft.createItem(collectionId, owner, createMode);
+    }
+    const events = await submitTransactionAsync(sender, tx);
+    const result = getCreateItemResult(events);
+
+    const BItemCount = parseInt((await api.query.nft.itemListIndex(collectionId)).toString());
+    const Bitem: any = (await api.query.nft.fungibleItemList(collectionId, owner)).toJSON();    
+    const BItemBalance = new BigNumber(Bitem.Value);
+
+    // What to expect
+    expect(result.success).to.be.true;
+    if (createMode == 'Fungible') {
+      expect(BItemBalance.minus(AItemBalance).toNumber()).to.be.equal(10);
+    }
+    else {
+      expect(BItemCount).to.be.equal(AItemCount+1);
+    }
+    expect(collectionId).to.be.equal(result.collectionId);
+    expect(BItemCount).to.be.equal(result.itemId);
+    newItemId = result.itemId;
+  });
+  return newItemId;
+}
+
+export async function enableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) {
+  await usingApi(async (api) => {
+
+    // Run the transaction
+    const tx = api.tx.nft.setPublicAccessMode(collectionId, 'WhiteList');
+    const events = await submitTransactionAsync(sender, tx);
+    const result = getGenericResult(events);
+
+    // Get the collection 
+    const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
+
+    // What to expect
+    expect(result.success).to.be.true;
+    expect(collection.Access).to.be.equal('WhiteList');
+  });
+}
+
+export async function enablePublicMintingExpectSuccess(sender: IKeyringPair, collectionId: number) {
+  await usingApi(async (api) => {
+
+    // Run the transaction
+    const tx = api.tx.nft.setMintPermission(collectionId, true);
+    const events = await submitTransactionAsync(sender, tx);
+    const result = getGenericResult(events);
+
+    // Get the collection 
+    const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
+
+    // What to expect
+    expect(result.success).to.be.true;
+    expect(collection.MintMode).to.be.equal(true);
+  });
+}
+
+export async function addToWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number, address: string) {
+  await usingApi(async (api) => {
+
+    // Run the transaction
+    const tx = api.tx.nft.addToWhiteList(collectionId, address);
+    const events = await submitTransactionAsync(sender, tx);
+    const result = getGenericResult(events);
+
+    // Get the collection 
+    const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
+
+    // What to expect
+    expect(result.success).to.be.true;
+    expect(collection.MintMode).to.be.equal(true);
+  });
+}
+
addedtests/src/util/util.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/util/util.ts
@@ -0,0 +1,35 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+export function strToUTF16(str: string): any {
+  let buf: number[] = [];
+  for (let i=0, strLen=str.length; i < strLen; i++) {
+    buf.push(str.charCodeAt(i));
+  }
+  return buf;
+}
+
+export function utf16ToStr(buf: number[]): string {
+  let str: string = "";
+  for (let i=0, strLen=buf.length; i < strLen; i++) {
+    if (buf[i] != 0) str += String.fromCharCode(buf[i]);
+    else break;
+  }
+  return str;
+}
+
+export function hexToStr(buf: string): string {
+  let str: string = "";
+  let hexStart = buf.indexOf("0x");
+  if (hexStart < 0) hexStart = 0;
+  else hexStart = 2;  
+  for (let i=hexStart, strLen=buf.length; i < strLen; i+=2) {
+    let ch = buf[i] + buf[i+1];
+    let num = parseInt(ch, 16);
+    if (num != 0) str += String.fromCharCode(num);
+    else break;
+  }
+  return str;
+}