git.delta.rocks / unique-network / refs/commits / 8057bddf39cb

difftreelog

Merge remote-tracking branch 'origin/develop' into feature/CORE-37

str-mv2021-08-31parents: #fee4139 #c1ca9e8.patch.diff
in: master

144 files changed

modified.devcontainer/Dockerfilediffbeforeafterboth
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -13,8 +13,8 @@
     [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \
     nvm install v16.2.0 && \
     npm install -g yarn && \
-    rustup toolchain install nightly-2021-05-30 && \
-    rustup default nightly-2021-05-30 && \
+    rustup toolchain install nightly-2021-05-20 && \
+    rustup default nightly-2021-05-20 && \
     rustup target add wasm32-unknown-unknown && \
     rustup component add rustfmt clippy && \
     cargo install cargo-expand cargo-edit cargo-contract
modified.devcontainer/devcontainer.jsondiffbeforeafterboth
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -1,9 +1,8 @@
 {
 	"name": "Rust",
-	"build": {
-		"dockerfile": "Dockerfile"
-	},
-	"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
+    "dockerComposeFile": "./docker-compose.yml",
+    "service": "nft_private",
+    "workspaceFolder": "/workspaces/nft_private",
 	"settings": { 
 		"terminal.integrated.shell.linux": "/bin/bash",
 		"lldb.executable": "/usr/bin/lldb",
@@ -13,7 +12,8 @@
 	},
 	"extensions": [
 		"matklad.rust-analyzer",
-		"dbaeumer.vscode-eslint"
+		"dbaeumer.vscode-eslint",
+		"tamasfe.even-better-toml"
 	],
 	"remoteUser": "vscode"
 }
added.devcontainer/docker-compose.ymldiffbeforeafterboth
--- /dev/null
+++ b/.devcontainer/docker-compose.yml
@@ -0,0 +1,23 @@
+version: '3'
+services:
+  nft_private:
+    build: 
+        context: .
+    environment:
+      - JAEGER_AGENT_HOST=jaeger
+      - JAEGER_AGENT_PORT=6831
+    volumes:
+      - ..:/workspaces/nft_private:cached
+      - ../../polkadot:/workspaces/polkadot:cached
+      - ../../polkadot-launch:/workspaces/polkadot-launch:cached
+      #- ../../frontier:/workspaces/frontier
+    cap_add:
+      - SYS_PTRACE
+    security_opt:
+      - seccomp:unconfined
+    command: /bin/sh -c "while sleep 1000; do :; done"
+  jaeger:
+    image: jaegertracing/all-in-one:latest
+    ports:
+      - "6831:6831/udp"
+      - "16686:16686"
\ No newline at end of file
modified.github/workflows/node_build_test.ymldiffbeforeafterboth
--- a/.github/workflows/node_build_test.yml
+++ b/.github/workflows/node_build_test.yml
@@ -31,11 +31,11 @@
           username: ${{ secrets.SERVER_USERNAME }}
           key: ${{ secrets.KEY }}
           port: ${{ secrets.SERVER_PORT }}
-          command_timeout: 240m
+          command_timeout: 300m
           script: |
             eval $(ssh-agent -s)
-            ssh-add /home/polkadot/.ssh/git_hub
-            git clone git@github.com:usetech-llc/nft_private.git
+            ssh-add /home/devops/.ssh/git_hub
+            git clone git@github.com:UniqueNetwork/nft_private.git
             cd nft_private
             git checkout develop
             # git pull --all
added.maintain/frame-weight-template.hbsdiffbeforeafterboth
--- /dev/null
+++ b/.maintain/frame-weight-template.hbs
@@ -0,0 +1,95 @@
+// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs
+
+//! Autogenerated weights for {{pallet}}
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION {{version}}
+//! DATE: {{date}}, STEPS: `{{cmd.steps}}`, REPEAT: {{cmd.repeat}}, LOW RANGE: `{{cmd.lowest_range_values}}`, HIGH RANGE: `{{cmd.highest_range_values}}`
+//! EXECUTION: {{cmd.execution}}, WASM-EXECUTION: {{cmd.wasm_execution}}, CHAIN: {{cmd.chain}}, DB CACHE: {{cmd.db_cache}}
+
+// Executed Command:
+{{#each args as |arg|~}}
+// {{arg}}
+{{/each}}
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use sp_std::marker::PhantomData;
+
+/// Weight functions needed for {{pallet}}.
+pub trait WeightInfo {
+	{{~#each benchmarks as |benchmark|}}
+	fn {{benchmark.name~}}
+	(
+		{{~#each benchmark.components as |c| ~}}
+		{{c.name}}: u32, {{/each~}}
+	) -> Weight;
+	{{~/each}}
+}
+
+/// Weights for {{pallet}} using the Substrate node and recommended hardware.
+pub struct SubstrateWeight<T>(PhantomData<T>);
+impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
+	{{~#each benchmarks as |benchmark|}}
+	{{~#each benchmark.comments as |comment|}}
+	// {{comment}}
+	{{~/each}}
+	fn {{benchmark.name~}}
+	(
+		{{~#each benchmark.components as |c| ~}}
+		{{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}}
+	) -> Weight {
+		({{underscore benchmark.base_weight}} as Weight)
+			{{~#each benchmark.component_weight as |cw|}}
+			// Standard Error: {{underscore cw.error}}
+			.saturating_add(({{underscore cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight))
+			{{~/each}}
+			{{~#if (ne benchmark.base_reads "0")}}
+			.saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}} as Weight))
+			{{~/if}}
+			{{~#each benchmark.component_reads as |cr|}}
+			.saturating_add(T::DbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as Weight)))
+			{{~/each}}
+			{{~#if (ne benchmark.base_writes "0")}}
+			.saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}} as Weight))
+			{{~/if}}
+			{{~#each benchmark.component_writes as |cw|}}
+			.saturating_add(T::DbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight)))
+			{{~/each}}
+	}
+	{{~/each}}
+}
+
+// For backwards compatibility and tests
+impl WeightInfo for () {
+	{{~#each benchmarks as |benchmark|}}
+	{{~#each benchmark.comments as |comment|}}
+	// {{comment}}
+	{{~/each}}
+	fn {{benchmark.name~}}
+	(
+		{{~#each benchmark.components as |c| ~}}
+		{{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}}
+	) -> Weight {
+		({{underscore benchmark.base_weight}} as Weight)
+			{{~#each benchmark.component_weight as |cw|}}
+			// Standard Error: {{underscore cw.error}}
+			.saturating_add(({{underscore cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight))
+			{{~/each}}
+			{{~#if (ne benchmark.base_reads "0")}}
+			.saturating_add(RocksDbWeight::get().reads({{benchmark.base_reads}} as Weight))
+			{{~/if}}
+			{{~#each benchmark.component_reads as |cr|}}
+			.saturating_add(RocksDbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as Weight)))
+			{{~/each}}
+			{{~#if (ne benchmark.base_writes "0")}}
+			.saturating_add(RocksDbWeight::get().writes({{benchmark.base_writes}} as Weight))
+			{{~/if}}
+			{{~#each benchmark.component_writes as |cw|}}
+			.saturating_add(RocksDbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight)))
+			{{~/each}}
+	}
+	{{~/each}}
+}
\ No newline at end of file
added.maintain/scripts/compile_stub.shdiffbeforeafterboth
--- /dev/null
+++ b/.maintain/scripts/compile_stub.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -eu
+
+dir=$PWD
+
+tmp=$(mktemp -d)
+cd $tmp
+cp $dir/$INPUT input.sol
+solcjs --optimize --bin input.sol
+
+mv input_sol_$(basename $OUTPUT .raw).bin out.bin
+xxd -r -p out.bin out.raw
+
+mv out.raw $dir/$OUTPUT
\ No newline at end of file
added.maintain/scripts/generate_api.shdiffbeforeafterboth
--- /dev/null
+++ b/.maintain/scripts/generate_api.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+set -eu
+
+tmp=$(mktemp)
+cargo test --package $PACKAGE -- $NAME --exact --nocapture --ignored | tee $tmp
+raw=$(mktemp --suffix .sol)
+sed -n '/=== SNIP START ===/, /=== SNIP END ===/{ /=== SNIP START ===/! { /=== SNIP END ===/! p } }' $tmp > $raw
+formatted=$(mktemp)
+prettier --use-tabs $raw > $formatted
+solhint --fix $formatted
+
+mv $formatted $OUTPUT
\ No newline at end of file
modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -18,7 +18,16 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e7a2e47a1fbe209ee101dd6d61285226744c6c8d3c21c8dc878ba6cb9f467f3a"
 dependencies = [
- "gimli",
+ "gimli 0.24.0",
+]
+
+[[package]]
+name = "addr2line"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
+dependencies = [
+ "gimli 0.25.0",
 ]
 
 [[package]]
@@ -57,7 +66,7 @@
  "aes",
  "block-cipher",
  "ghash",
- "subtle 2.4.0",
+ "subtle 2.4.1",
 ]
 
 [[package]]
@@ -88,6 +97,17 @@
 checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
 
 [[package]]
+name = "ahash"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98"
+dependencies = [
+ "getrandom 0.2.3",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
 name = "aho-corasick"
 version = "0.7.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -122,18 +142,9 @@
 
 [[package]]
 name = "anyhow"
-version = "1.0.41"
+version = "1.0.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61"
-
-[[package]]
-name = "approx"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278"
-dependencies = [
- "num-traits",
-]
+checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486"
 
 [[package]]
 name = "approx"
@@ -236,12 +247,11 @@
 
 [[package]]
 name = "async-io"
-version = "1.4.1"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bbfd5cf2794b1e908ea8457e6c45f8f8f1f6ec5f74617bf4662623f47503c3b"
+checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b"
 dependencies = [
  "concurrent-queue",
- "fastrand",
  "futures-lite",
  "libc",
  "log",
@@ -312,7 +322,7 @@
  "memchr",
  "num_cpus",
  "once_cell",
- "pin-project-lite 0.2.6",
+ "pin-project-lite 0.2.7",
  "pin-utils",
  "slab",
  "wasm-bindgen-futures",
@@ -359,7 +369,7 @@
  "futures-sink",
  "futures-util",
  "memchr",
- "pin-project-lite 0.2.6",
+ "pin-project-lite 0.2.7",
 ]
 
 [[package]]
@@ -372,7 +382,7 @@
  "futures-sink",
  "futures-util",
  "memchr",
- "pin-project-lite 0.2.6",
+ "pin-project-lite 0.2.7",
 ]
 
 [[package]]
@@ -409,16 +419,16 @@
 
 [[package]]
 name = "backtrace"
-version = "0.3.60"
+version = "0.3.61"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7815ea54e4d821e791162e078acbebfd6d8c8939cd559c9335dceb1c8ca7282"
+checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01"
 dependencies = [
- "addr2line",
+ "addr2line 0.16.0",
  "cc",
  "cfg-if 1.0.0",
  "libc",
  "miniz_oxide",
- "object 0.25.3",
+ "object 0.26.0",
  "rustc-demangle",
 ]
 
@@ -448,9 +458,9 @@
 
 [[package]]
 name = "beef"
-version = "0.5.0"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6736e2428df2ca2848d846c43e88745121a6654696e349ce0054a420815a7409"
+checksum = "bed554bd50246729a1ec158d08aa3235d1b69d94ad120ebe187e28894787e736"
 dependencies = [
  "serde",
 ]
@@ -458,13 +468,13 @@
 [[package]]
 name = "beefy-gadget"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=polkadot-v0.9.7#299dd5fd3fabd99c3c919f1312001283ddc5b365"
+source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=polkadot-v0.9.8#55ae3329847e0bbde51c9d45991d99f444777555"
 dependencies = [
  "beefy-primitives",
- "futures 0.3.15",
+ "futures 0.3.16",
  "hex",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "sc-client-api",
  "sc-keystore",
@@ -486,17 +496,17 @@
 [[package]]
 name = "beefy-gadget-rpc"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=polkadot-v0.9.7#299dd5fd3fabd99c3c919f1312001283ddc5b365"
+source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=polkadot-v0.9.8#55ae3329847e0bbde51c9d45991d99f444777555"
 dependencies = [
  "beefy-gadget",
  "beefy-primitives",
- "futures 0.3.15",
+ "futures 0.3.16",
  "jsonrpc-core 15.1.0",
  "jsonrpc-core-client 15.1.0",
  "jsonrpc-derive 15.1.0",
  "jsonrpc-pubsub 15.1.0",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sc-rpc",
  "serde",
  "serde_json",
@@ -507,9 +517,9 @@
 [[package]]
 name = "beefy-primitives"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=polkadot-v0.9.7#299dd5fd3fabd99c3c919f1312001283ddc5b365"
+source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=polkadot-v0.9.8#55ae3329847e0bbde51c9d45991d99f444777555"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-api",
  "sp-application-crypto",
  "sp-core",
@@ -528,9 +538,9 @@
 
 [[package]]
 name = "bindgen"
-version = "0.57.0"
+version = "0.59.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd4865004a46a0aafb2a0a5eb19d3c9fc46ee5f063a6cfc605c69ac9ecf5263d"
+checksum = "453c49e5950bb0eb63bb3df640e31618846c89d5b7faa54040d76e98e0134375"
 dependencies = [
  "bitflags",
  "cexpr",
@@ -553,12 +563,14 @@
 
 [[package]]
 name = "bitvec"
-version = "0.17.4"
+version = "0.19.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c"
+checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321"
 dependencies = [
- "either",
- "radium 0.3.0",
+ "funty",
+ "radium 0.5.3",
+ "tap",
+ "wyz",
 ]
 
 [[package]]
@@ -692,6 +704,117 @@
 ]
 
 [[package]]
+name = "bp-header-chain"
+version = "0.1.0"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
+dependencies = [
+ "finality-grandpa",
+ "frame-support",
+ "parity-scale-codec",
+ "serde",
+ "sp-core",
+ "sp-finality-grandpa",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
+name = "bp-messages"
+version = "0.1.0"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
+dependencies = [
+ "bitvec 0.20.4",
+ "bp-runtime",
+ "frame-support",
+ "frame-system",
+ "impl-trait-for-tuples",
+ "parity-scale-codec",
+ "serde",
+ "sp-std",
+]
+
+[[package]]
+name = "bp-polkadot-core"
+version = "0.1.0"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
+dependencies = [
+ "bp-messages",
+ "bp-runtime",
+ "frame-support",
+ "frame-system",
+ "parity-scale-codec",
+ "sp-api",
+ "sp-core",
+ "sp-runtime",
+ "sp-std",
+ "sp-version",
+]
+
+[[package]]
+name = "bp-rococo"
+version = "0.1.0"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
+dependencies = [
+ "bp-messages",
+ "bp-polkadot-core",
+ "bp-runtime",
+ "frame-support",
+ "parity-scale-codec",
+ "smallvec 1.6.1",
+ "sp-api",
+ "sp-runtime",
+ "sp-std",
+ "sp-version",
+]
+
+[[package]]
+name = "bp-runtime"
+version = "0.1.0"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
+dependencies = [
+ "frame-support",
+ "hash-db",
+ "num-traits",
+ "parity-scale-codec",
+ "sp-core",
+ "sp-io",
+ "sp-runtime",
+ "sp-state-machine",
+ "sp-std",
+ "sp-trie",
+]
+
+[[package]]
+name = "bp-test-utils"
+version = "0.1.0"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
+dependencies = [
+ "bp-header-chain",
+ "ed25519-dalek",
+ "finality-grandpa",
+ "parity-scale-codec",
+ "sp-application-crypto",
+ "sp-finality-grandpa",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
+name = "bp-wococo"
+version = "0.1.0"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
+dependencies = [
+ "bp-messages",
+ "bp-polkadot-core",
+ "bp-rococo",
+ "bp-runtime",
+ "parity-scale-codec",
+ "sp-api",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
 name = "bs58"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -720,12 +843,6 @@
 version = "3.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631"
-
-[[package]]
-name = "byte-slice-cast"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3"
 
 [[package]]
 name = "byte-slice-cast"
@@ -775,6 +892,15 @@
 checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
 
 [[package]]
+name = "camino"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4648c6d00a709aa069a236adcaae4f605a6241c72bf5bee79331a4b625921a9"
+dependencies = [
+ "serde",
+]
+
+[[package]]
 name = "cargo-platform"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -797,19 +923,33 @@
 ]
 
 [[package]]
+name = "cargo_metadata"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "081e3f0755c1f380c2d010481b6fa2e02973586d5f2b24eebb7a2a1d98b143d8"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "semver 0.11.0",
+ "semver-parser 0.10.2",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
 name = "cc"
-version = "1.0.68"
+version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
+checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
 dependencies = [
  "jobserver",
 ]
 
 [[package]]
 name = "cexpr"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
+checksum = "db507a7679252d2276ed0dd8113c6875ec56d3089f9225b2b42c30cc1f8e5c89"
 dependencies = [
  "nom",
 ]
@@ -987,19 +1127,18 @@
 
 [[package]]
 name = "cpp_demangle"
-version = "0.3.2"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44919ecaf6f99e8e737bc239408931c9a01e9a6c74814fee8242dd2506b65390"
+checksum = "8ea47428dc9d2237f3c6bc134472edfd63ebba0af932e783506dcfd66f10d18a"
 dependencies = [
  "cfg-if 1.0.0",
- "glob",
 ]
 
 [[package]]
 name = "cpufeatures"
-version = "0.1.4"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8"
+checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef"
 dependencies = [
  "libc",
 ]
@@ -1029,7 +1168,7 @@
  "cranelift-codegen-meta",
  "cranelift-codegen-shared",
  "cranelift-entity",
- "gimli",
+ "gimli 0.24.0",
  "log",
  "regalloc",
  "serde",
@@ -1228,7 +1367,7 @@
 checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab"
 dependencies = [
  "generic-array 0.14.4",
- "subtle 2.4.0",
+ "subtle 2.4.1",
 ]
 
 [[package]]
@@ -1264,7 +1403,7 @@
 [[package]]
 name = "cumulus-client-cli"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "sc-cli",
  "sc-service",
@@ -1274,13 +1413,13 @@
 [[package]]
 name = "cumulus-client-collator"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "cumulus-client-consensus-common",
  "cumulus-client-network",
  "cumulus-primitives-core",
- "futures 0.3.15",
- "parity-scale-codec 2.1.3",
+ "futures 0.3.16",
+ "parity-scale-codec",
  "parking_lot 0.10.2",
  "polkadot-node-primitives",
  "polkadot-node-subsystem",
@@ -1298,13 +1437,13 @@
 [[package]]
 name = "cumulus-client-consensus-aura"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "async-trait",
  "cumulus-client-consensus-common",
  "cumulus-primitives-core",
- "futures 0.3.15",
- "parity-scale-codec 2.1.3",
+ "futures 0.3.16",
+ "parity-scale-codec",
  "parking_lot 0.10.2",
  "polkadot-client",
  "sc-client-api",
@@ -1328,12 +1467,12 @@
 [[package]]
 name = "cumulus-client-consensus-common"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "async-trait",
  "dyn-clone",
- "futures 0.3.15",
- "parity-scale-codec 2.1.3",
+ "futures 0.3.16",
+ "parity-scale-codec",
  "polkadot-primitives",
  "polkadot-runtime",
  "sc-client-api",
@@ -1352,12 +1491,12 @@
 [[package]]
 name = "cumulus-client-network"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "derive_more",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.10.2",
  "polkadot-client",
  "polkadot-node-primitives",
@@ -1376,12 +1515,12 @@
 [[package]]
 name = "cumulus-client-pov-recovery"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "cumulus-primitives-core",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-node-primitives",
  "polkadot-node-subsystem",
  "polkadot-overseer",
@@ -1399,13 +1538,13 @@
 [[package]]
 name = "cumulus-client-service"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "cumulus-client-collator",
  "cumulus-client-consensus-common",
  "cumulus-client-pov-recovery",
  "cumulus-primitives-core",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.10.2",
  "polkadot-overseer",
  "polkadot-primitives",
@@ -1427,13 +1566,13 @@
 [[package]]
 name = "cumulus-pallet-aura-ext"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "frame-executive",
  "frame-support",
  "frame-system",
  "pallet-aura",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-application-crypto",
  "sp-consensus-aura",
@@ -1444,13 +1583,13 @@
 [[package]]
 name = "cumulus-pallet-dmp-queue"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "cumulus-primitives-core",
  "frame-support",
  "frame-system",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "rand 0.8.4",
  "rand_chacha 0.3.1",
  "sp-io",
@@ -1463,7 +1602,7 @@
 [[package]]
 name = "cumulus-pallet-parachain-system"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "cumulus-pallet-parachain-system-proc-macro",
  "cumulus-primitives-core",
@@ -1473,7 +1612,7 @@
  "frame-system",
  "log",
  "pallet-balances",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-parachain",
  "serde",
  "sp-core",
@@ -1491,7 +1630,7 @@
 [[package]]
 name = "cumulus-pallet-parachain-system-proc-macro"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "proc-macro-crate 1.0.0",
  "proc-macro2",
@@ -1502,12 +1641,12 @@
 [[package]]
 name = "cumulus-pallet-xcm"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "cumulus-primitives-core",
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-io",
  "sp-runtime",
@@ -1518,13 +1657,13 @@
 [[package]]
 name = "cumulus-pallet-xcmp-queue"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "cumulus-primitives-core",
  "frame-support",
  "frame-system",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "rand 0.8.4",
  "rand_chacha 0.3.1",
  "sp-runtime",
@@ -1536,11 +1675,11 @@
 [[package]]
 name = "cumulus-primitives-core"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "frame-support",
- "impl-trait-for-tuples 0.2.1",
- "parity-scale-codec 2.1.3",
+ "impl-trait-for-tuples",
+ "parity-scale-codec",
  "polkadot-core-primitives",
  "polkadot-parachain",
  "polkadot-primitives",
@@ -1554,11 +1693,12 @@
 [[package]]
 name = "cumulus-primitives-parachain-inherent"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "async-trait",
  "cumulus-primitives-core",
- "parity-scale-codec 2.1.3",
+ "cumulus-test-relay-sproof-builder",
+ "parity-scale-codec",
  "polkadot-client",
  "sc-client-api",
  "sp-api",
@@ -1574,7 +1714,7 @@
 [[package]]
 name = "cumulus-primitives-timestamp"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "cumulus-primitives-core",
  "sp-inherents",
@@ -1585,12 +1725,12 @@
 [[package]]
 name = "cumulus-primitives-utility"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "cumulus-primitives-core",
  "frame-support",
- "impl-trait-for-tuples 0.2.1",
- "parity-scale-codec 2.1.3",
+ "impl-trait-for-tuples",
+ "parity-scale-codec",
  "polkadot-core-primitives",
  "polkadot-parachain",
  "polkadot-primitives",
@@ -1601,15 +1741,28 @@
 ]
 
 [[package]]
+name = "cumulus-test-relay-sproof-builder"
+version = "0.1.0"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
+dependencies = [
+ "cumulus-primitives-core",
+ "parity-scale-codec",
+ "polkadot-primitives",
+ "sp-runtime",
+ "sp-state-machine",
+ "sp-std",
+]
+
+[[package]]
 name = "curve25519-dalek"
-version = "2.1.2"
+version = "2.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "434e1720189a637d44fe464f4df1e6eb900b4835255b14354497c78af37d9bb8"
+checksum = "4a9b85542f99a2dfa2a1b8e192662741c9859a846b296bef1c92ef9b58b5a216"
 dependencies = [
  "byteorder",
  "digest 0.8.1",
  "rand_core 0.5.1",
- "subtle 2.4.0",
+ "subtle 2.4.1",
  "zeroize",
 ]
 
@@ -1622,7 +1775,7 @@
  "byteorder",
  "digest 0.9.0",
  "rand_core 0.5.1",
- "subtle 2.4.0",
+ "subtle 2.4.1",
  "zeroize",
 ]
 
@@ -1700,13 +1853,14 @@
 
 [[package]]
 name = "derive_more"
-version = "0.99.14"
+version = "0.99.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cc7b9cef1e351660e5443924e4f43ab25fbbed3e9a5f052df3677deb4d6b320"
+checksum = "40eebddd2156ce1bb37b20bbe5151340a31828b1f2d22ba4141f3531710e38df"
 dependencies = [
  "convert_case",
  "proc-macro2",
  "quote",
+ "rustc_version 0.3.3",
  "syn",
 ]
 
@@ -1814,9 +1968,9 @@
 
 [[package]]
 name = "ed25519"
-version = "1.1.1"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d0860415b12243916284c67a9be413e044ee6668247b99ba26d94b2bc06c8f6"
+checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc"
 dependencies = [
  "signature",
 ]
@@ -1918,9 +2072,9 @@
 
 [[package]]
 name = "erased-serde"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5b36e6f2295f393f44894c6031f67df4d185b984cd54d08f768ce678007efcd"
+checksum = "3de9ad4541d99dc22b59134e7ff8dc3d6c988c89ecd7324bf10a8362b07a2afa"
 dependencies = [
  "serde",
 ]
@@ -1944,19 +2098,6 @@
 dependencies = [
  "gcc",
  "libc",
-]
-
-[[package]]
-name = "ethbloom"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71a6567e6fd35589fea0c63b94b4cf2e55573e413901bdbe60ab15cf0e25e5df"
-dependencies = [
- "crunchy",
- "fixed-hash 0.6.1",
- "impl-rlp 0.2.1",
- "impl-serde",
- "tiny-keccak",
 ]
 
 [[package]]
@@ -1966,9 +2107,9 @@
 checksum = "779864b9c7f7ead1f092972c3257496c6a84b46dba2ce131dd8a282cb2cc5972"
 dependencies = [
  "crunchy",
- "fixed-hash 0.7.0",
- "impl-codec 0.5.0",
- "impl-rlp 0.3.0",
+ "fixed-hash",
+ "impl-codec",
+ "impl-rlp",
  "impl-serde",
  "tiny-keccak",
 ]
@@ -1979,12 +2120,12 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "567ce064a8232c16e2b2c2173a936b91fbe35c2f2c5278871f5a1a31688b42e9"
 dependencies = [
- "ethereum-types 0.11.0",
+ "ethereum-types",
  "funty",
  "hash-db",
  "hash256-std-hasher",
- "parity-scale-codec 2.1.3",
- "rlp 0.5.0",
+ "parity-scale-codec",
+ "rlp",
  "rlp-derive",
  "serde",
  "sha3 0.9.1",
@@ -1992,48 +2133,18 @@
 ]
 
 [[package]]
-name = "ethereum-tx-sign"
-version = "3.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdcbb5f48282fa71ba2864818a442d0ee0ca04ebc9ef9eb1837c48298c3b8cbf"
-dependencies = [
- "ethereum-types 0.9.2",
- "num-traits",
- "rlp 0.4.6",
- "secp256k1",
- "serde",
- "serde_derive",
- "serde_json",
- "tiny-keccak",
-]
-
-[[package]]
 name = "ethereum-types"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "473aecff686bd8e7b9db0165cbbb53562376b39bf35b427f0c60446a9e1634b0"
-dependencies = [
- "ethbloom 0.9.2",
- "fixed-hash 0.6.1",
- "impl-rlp 0.2.1",
- "impl-serde",
- "primitive-types 0.7.3",
- "uint 0.8.5",
-]
-
-[[package]]
-name = "ethereum-types"
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f64b5df66a228d85e4b17e5d6c6aa43b0310898ffe8a85988c4c032357aaabfd"
 dependencies = [
- "ethbloom 0.11.0",
- "fixed-hash 0.7.0",
- "impl-codec 0.5.0",
- "impl-rlp 0.3.0",
+ "ethbloom",
+ "fixed-hash",
+ "impl-codec",
+ "impl-rlp",
  "impl-serde",
- "primitive-types 0.9.0",
- "uint 0.9.0",
+ "primitive-types",
+ "uint",
 ]
 
 [[package]]
@@ -2045,7 +2156,7 @@
 [[package]]
 name = "evm"
 version = "0.27.0"
-source = "git+https://github.com/usetech-llc/evm.git?branch=precompile-output-parachain#e13990a627375f327ca7da3c85d9bdfa0a9e903b"
+source = "git+https://github.com/uniquenetwork/evm.git?branch=precompile-output-parachain#e13990a627375f327ca7da3c85d9bdfa0a9e903b"
 dependencies = [
  "environmental",
  "ethereum",
@@ -2053,9 +2164,9 @@
  "evm-gasometer",
  "evm-runtime",
  "log",
- "parity-scale-codec 2.1.3",
- "primitive-types 0.9.0",
- "rlp 0.5.0",
+ "parity-scale-codec",
+ "primitive-types",
+ "rlp",
  "serde",
  "sha3 0.8.2",
 ]
@@ -2066,9 +2177,11 @@
 dependencies = [
  "ethereum",
  "evm-coder-macros",
+ "evm-core",
  "hex",
  "hex-literal",
- "primitive-types 0.9.0",
+ "impl-trait-for-tuples",
+ "primitive-types",
 ]
 
 [[package]]
@@ -2087,33 +2200,33 @@
 [[package]]
 name = "evm-core"
 version = "0.27.1"
-source = "git+https://github.com/usetech-llc/evm.git?branch=precompile-output-parachain#e13990a627375f327ca7da3c85d9bdfa0a9e903b"
+source = "git+https://github.com/uniquenetwork/evm.git?branch=precompile-output-parachain#e13990a627375f327ca7da3c85d9bdfa0a9e903b"
 dependencies = [
  "funty",
- "parity-scale-codec 2.1.3",
- "primitive-types 0.9.0",
+ "parity-scale-codec",
+ "primitive-types",
  "serde",
 ]
 
 [[package]]
 name = "evm-gasometer"
 version = "0.27.0"
-source = "git+https://github.com/usetech-llc/evm.git?branch=precompile-output-parachain#e13990a627375f327ca7da3c85d9bdfa0a9e903b"
+source = "git+https://github.com/uniquenetwork/evm.git?branch=precompile-output-parachain#e13990a627375f327ca7da3c85d9bdfa0a9e903b"
 dependencies = [
  "environmental",
  "evm-core",
  "evm-runtime",
- "primitive-types 0.9.0",
+ "primitive-types",
 ]
 
 [[package]]
 name = "evm-runtime"
 version = "0.27.0"
-source = "git+https://github.com/usetech-llc/evm.git?branch=precompile-output-parachain#e13990a627375f327ca7da3c85d9bdfa0a9e903b"
+source = "git+https://github.com/uniquenetwork/evm.git?branch=precompile-output-parachain#e13990a627375f327ca7da3c85d9bdfa0a9e903b"
 dependencies = [
  "environmental",
  "evm-core",
- "primitive-types 0.9.0",
+ "primitive-types",
  "sha3 0.8.2",
 ]
 
@@ -2123,7 +2236,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
 ]
 
 [[package]]
@@ -2162,9 +2275,9 @@
 
 [[package]]
 name = "fastrand"
-version = "1.4.1"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77b705829d1e87f762c2df6da140b26af5839e1033aa84aa5f56bb688e4e1bdb"
+checksum = "b394ed3d285a429378d3b384b9eb1285267e7df4b166df24b7a6939a04dc392e"
 dependencies = [
  "instant",
 ]
@@ -2172,16 +2285,16 @@
 [[package]]
 name = "fc-consensus"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/frontier.git?branch=injected-transactions-parachain#c1388c13be6d59b9a70e1277f1295977090adb63"
+source = "git+https://github.com/uniquenetwork/frontier.git?branch=injected-transactions-parachain#1e2a0537db656af0b300493b4f8eda72c22e9421"
 dependencies = [
  "async-trait",
  "derive_more",
  "fc-db",
  "fp-consensus",
  "fp-rpc",
- "futures 0.3.15",
+ "futures 0.3.16",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sc-client-api",
  "sp-api",
  "sp-block-builder",
@@ -2197,11 +2310,11 @@
 [[package]]
 name = "fc-db"
 version = "1.0.0"
-source = "git+https://github.com/usetech-llc/frontier.git?branch=injected-transactions-parachain#c1388c13be6d59b9a70e1277f1295977090adb63"
+source = "git+https://github.com/uniquenetwork/frontier.git?branch=injected-transactions-parachain#1e2a0537db656af0b300493b4f8eda72c22e9421"
 dependencies = [
  "kvdb",
  "kvdb-rocksdb",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "sp-core",
  "sp-database",
@@ -2211,13 +2324,13 @@
 [[package]]
 name = "fc-mapping-sync"
 version = "2.0.0-dev"
-source = "git+https://github.com/usetech-llc/frontier.git?branch=injected-transactions-parachain#c1388c13be6d59b9a70e1277f1295977090adb63"
+source = "git+https://github.com/uniquenetwork/frontier.git?branch=injected-transactions-parachain#1e2a0537db656af0b300493b4f8eda72c22e9421"
 dependencies = [
  "fc-consensus",
  "fc-db",
  "fp-consensus",
  "fp-rpc",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "log",
  "sc-client-api",
@@ -2229,10 +2342,10 @@
 [[package]]
 name = "fc-rpc"
 version = "2.0.0-dev"
-source = "git+https://github.com/usetech-llc/frontier.git?branch=injected-transactions-parachain#c1388c13be6d59b9a70e1277f1295977090adb63"
+source = "git+https://github.com/uniquenetwork/frontier.git?branch=injected-transactions-parachain#1e2a0537db656af0b300493b4f8eda72c22e9421"
 dependencies = [
  "ethereum",
- "ethereum-types 0.11.0",
+ "ethereum-types",
  "evm",
  "fc-consensus",
  "fc-db",
@@ -2241,7 +2354,7 @@
  "fp-evm",
  "fp-rpc",
  "fp-storage",
- "futures 0.3.15",
+ "futures 0.3.16",
  "jsonrpc-core 15.1.0",
  "jsonrpc-core-client 14.2.0",
  "jsonrpc-derive 14.2.2",
@@ -2250,9 +2363,9 @@
  "log",
  "pallet-ethereum",
  "pallet-evm",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "rand 0.7.3",
- "rlp 0.5.0",
+ "rlp",
  "rustc-hex",
  "sc-client-api",
  "sc-network",
@@ -2270,9 +2383,9 @@
 [[package]]
 name = "fc-rpc-core"
 version = "1.1.0-dev"
-source = "git+https://github.com/usetech-llc/frontier.git?branch=injected-transactions-parachain#c1388c13be6d59b9a70e1277f1295977090adb63"
+source = "git+https://github.com/uniquenetwork/frontier.git?branch=injected-transactions-parachain#1e2a0537db656af0b300493b4f8eda72c22e9421"
 dependencies = [
- "ethereum-types 0.11.0",
+ "ethereum-types",
  "jsonrpc-core 15.1.0",
  "jsonrpc-core-client 14.2.0",
  "jsonrpc-derive 14.2.2",
@@ -2308,28 +2421,16 @@
 checksum = "74a1bfdcc776e63e49f741c7ce6116fa1b887e8ac2e3ccb14dd4aa113e54feb9"
 dependencies = [
  "either",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "log",
  "num-traits",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
 ]
 
 [[package]]
 name = "fixed-hash"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11498d382790b7a8f2fd211780bec78619bba81cdad3a283997c0c41f836759c"
-dependencies = [
- "byteorder",
- "rand 0.7.3",
- "rustc-hex",
- "static_assertions",
-]
-
-[[package]]
-name = "fixed-hash"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c"
@@ -2384,9 +2485,9 @@
 [[package]]
 name = "fork-tree"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
 ]
 
 [[package]]
@@ -2402,11 +2503,11 @@
 [[package]]
 name = "fp-consensus"
 version = "1.0.0"
-source = "git+https://github.com/usetech-llc/frontier.git?branch=injected-transactions-parachain#c1388c13be6d59b9a70e1277f1295977090adb63"
+source = "git+https://github.com/uniquenetwork/frontier.git?branch=injected-transactions-parachain#1e2a0537db656af0b300493b4f8eda72c22e9421"
 dependencies = [
  "ethereum",
- "parity-scale-codec 2.1.3",
- "rlp 0.5.0",
+ "parity-scale-codec",
+ "rlp",
  "sha3 0.8.2",
  "sp-core",
  "sp-runtime",
@@ -2416,11 +2517,11 @@
 [[package]]
 name = "fp-evm"
 version = "2.0.0"
-source = "git+https://github.com/usetech-llc/frontier.git?branch=injected-transactions-parachain#c1388c13be6d59b9a70e1277f1295977090adb63"
+source = "git+https://github.com/uniquenetwork/frontier.git?branch=injected-transactions-parachain#1e2a0537db656af0b300493b4f8eda72c22e9421"
 dependencies = [
  "evm",
- "impl-trait-for-tuples 0.1.3",
- "parity-scale-codec 2.1.3",
+ "impl-trait-for-tuples",
+ "parity-scale-codec",
  "serde",
  "sp-core",
  "sp-std",
@@ -2429,12 +2530,12 @@
 [[package]]
 name = "fp-rpc"
 version = "2.1.0"
-source = "git+https://github.com/usetech-llc/frontier.git?branch=injected-transactions-parachain#c1388c13be6d59b9a70e1277f1295977090adb63"
+source = "git+https://github.com/uniquenetwork/frontier.git?branch=injected-transactions-parachain#1e2a0537db656af0b300493b4f8eda72c22e9421"
 dependencies = [
  "ethereum",
- "ethereum-types 0.11.0",
+ "ethereum-types",
  "fp-evm",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-api",
  "sp-core",
  "sp-io",
@@ -2445,18 +2546,18 @@
 [[package]]
 name = "fp-storage"
 version = "1.0.1"
-source = "git+https://github.com/usetech-llc/frontier.git?branch=injected-transactions-parachain#c1388c13be6d59b9a70e1277f1295977090adb63"
+source = "git+https://github.com/uniquenetwork/frontier.git?branch=injected-transactions-parachain#1e2a0537db656af0b300493b4f8eda72c22e9421"
 
 [[package]]
 name = "frame-benchmarking"
 version = "3.1.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
  "frame-system",
  "linregress",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "paste",
  "sp-api",
  "sp-io",
@@ -2469,13 +2570,13 @@
 [[package]]
 name = "frame-benchmarking-cli"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "Inflector",
  "chrono",
  "frame-benchmarking",
  "handlebars",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sc-cli",
  "sc-client-db",
  "sc-executor",
@@ -2492,11 +2593,11 @@
 [[package]]
 name = "frame-election-provider-support"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-arithmetic",
  "sp-npos-elections",
  "sp-std",
@@ -2505,11 +2606,11 @@
 [[package]]
 name = "frame-executive"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -2520,9 +2621,9 @@
 [[package]]
 name = "frame-metadata"
 version = "13.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-core",
  "sp-std",
@@ -2531,16 +2632,16 @@
 [[package]]
 name = "frame-support"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "bitflags",
  "frame-metadata",
  "frame-support-procedural",
- "impl-trait-for-tuples 0.2.1",
+ "impl-trait-for-tuples",
  "log",
  "max-encoded-len",
  "once_cell",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "paste",
  "serde",
  "smallvec 1.6.1",
@@ -2558,7 +2659,7 @@
 [[package]]
 name = "frame-support-procedural"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "Inflector",
  "frame-support-procedural-tools",
@@ -2570,7 +2671,7 @@
 [[package]]
 name = "frame-support-procedural-tools"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support-procedural-tools-derive",
  "proc-macro-crate 1.0.0",
@@ -2582,7 +2683,7 @@
 [[package]]
 name = "frame-support-procedural-tools-derive"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2592,12 +2693,12 @@
 [[package]]
 name = "frame-system"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
- "impl-trait-for-tuples 0.2.1",
+ "impl-trait-for-tuples",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-core",
  "sp-io",
@@ -2609,12 +2710,12 @@
 [[package]]
 name = "frame-system-benchmarking"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-core",
  "sp-runtime",
  "sp-std",
@@ -2623,19 +2724,19 @@
 [[package]]
 name = "frame-system-rpc-runtime-api"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-api",
 ]
 
 [[package]]
 name = "frame-try-runtime"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-api",
  "sp-runtime",
  "sp-std",
@@ -2705,9 +2806,9 @@
 
 [[package]]
 name = "futures"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27"
+checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -2720,9 +2821,9 @@
 
 [[package]]
 name = "futures-channel"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2"
+checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9"
 dependencies = [
  "futures-core",
  "futures-sink",
@@ -2730,9 +2831,9 @@
 
 [[package]]
 name = "futures-core"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1"
+checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99"
 
 [[package]]
 name = "futures-cpupool"
@@ -2746,9 +2847,9 @@
 
 [[package]]
 name = "futures-executor"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79"
+checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c"
 dependencies = [
  "futures-core",
  "futures-task",
@@ -2758,9 +2859,9 @@
 
 [[package]]
 name = "futures-io"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1"
+checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582"
 
 [[package]]
 name = "futures-lite"
@@ -2773,15 +2874,15 @@
  "futures-io",
  "memchr",
  "parking",
- "pin-project-lite 0.2.6",
+ "pin-project-lite 0.2.7",
  "waker-fn",
 ]
 
 [[package]]
 name = "futures-macro"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121"
+checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57"
 dependencies = [
  "autocfg",
  "proc-macro-hack",
@@ -2803,15 +2904,15 @@
 
 [[package]]
 name = "futures-sink"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282"
+checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53"
 
 [[package]]
 name = "futures-task"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae"
+checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2"
 
 [[package]]
 name = "futures-timer"
@@ -2827,9 +2928,9 @@
 
 [[package]]
 name = "futures-util"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967"
+checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78"
 dependencies = [
  "autocfg",
  "futures 0.1.31",
@@ -2840,7 +2941,7 @@
  "futures-sink",
  "futures-task",
  "memchr",
- "pin-project-lite 0.2.6",
+ "pin-project-lite 0.2.7",
  "pin-utils",
  "proc-macro-hack",
  "proc-macro-nested",
@@ -2916,6 +3017,12 @@
 ]
 
 [[package]]
+name = "gimli"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
+
+[[package]]
 name = "glob"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2923,9 +3030,9 @@
 
 [[package]]
 name = "globset"
-version = "0.4.7"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0fc1b9fa0e64ffb1aa5b95daa0f0f167734fd528b7c02eabc581d9d843649b1"
+checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd"
 dependencies = [
  "aho-corasick",
  "bstr",
@@ -3020,7 +3127,16 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
 dependencies = [
- "ahash",
+ "ahash 0.4.7",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+dependencies = [
+ "ahash 0.7.4",
 ]
 
 [[package]]
@@ -3034,9 +3150,9 @@
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.18"
+version = "0.1.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
 dependencies = [
  "libc",
 ]
@@ -3049,9 +3165,9 @@
 
 [[package]]
 name = "hex-literal"
-version = "0.3.1"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5af1f635ef1bc545d78392b136bfe1c9809e029023c84a3638a864a10b8819c8"
+checksum = "21e4590e13640f19f249fe3e4eca5113bc4289f2497710378190e7f4bd96f45b"
 
 [[package]]
 name = "hex_fmt"
@@ -3164,7 +3280,7 @@
 dependencies = [
  "bytes 1.0.1",
  "http 0.2.4",
- "pin-project-lite 0.2.6",
+ "pin-project-lite 0.2.7",
 ]
 
 [[package]]
@@ -3217,7 +3333,7 @@
  "itoa",
  "log",
  "net2",
- "rustc_version",
+ "rustc_version 0.2.3",
  "time",
  "tokio 0.1.22",
  "tokio-buf",
@@ -3246,7 +3362,7 @@
  "httparse",
  "httpdate 0.3.2",
  "itoa",
- "pin-project 1.0.7",
+ "pin-project 1.0.8",
  "socket2 0.3.19",
  "tokio 0.2.25",
  "tower-service",
@@ -3256,9 +3372,9 @@
 
 [[package]]
 name = "hyper"
-version = "0.14.10"
+version = "0.14.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7728a72c4c7d72665fde02204bcbd93b247721025b222ef78606f14513e0fd03"
+checksum = "0b61cf2d1aebcf6e6352c97b81dc2244ca29194be1b276f5d8ad5c6330fffb11"
 dependencies = [
  "bytes 1.0.1",
  "futures-channel",
@@ -3269,8 +3385,8 @@
  "httparse",
  "httpdate 1.0.1",
  "itoa",
- "pin-project-lite 0.2.6",
- "tokio 1.8.1",
+ "pin-project-lite 0.2.7",
+ "tokio 1.9.0",
  "tower-service",
  "tracing",
  "want 0.3.0",
@@ -3350,7 +3466,7 @@
 checksum = "ae8ab7f67bad3240049cb24fb9cb0b4c2c6af4c245840917fbbdededeee91179"
 dependencies = [
  "async-io",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-lite",
  "if-addrs",
  "ipnet",
@@ -3361,29 +3477,11 @@
 
 [[package]]
 name = "impl-codec"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1be51a921b067b0eaca2fad532d9400041561aa922221cc65f95a85641c6bf53"
-dependencies = [
- "parity-scale-codec 1.3.7",
-]
-
-[[package]]
-name = "impl-codec"
-version = "0.5.0"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df170efa359aebdd5cb7fe78edcc67107748e4737bdca8a8fb40d15ea7a877ed"
+checksum = "161ebdfec3c8e3b52bf61c4f3550a1eea4f9579d10dc1b936f3171ebdcd6c443"
 dependencies = [
- "parity-scale-codec 2.1.3",
-]
-
-[[package]]
-name = "impl-rlp"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f7a72f11830b52333f36e3b09a288333888bf54380fd0ac0790a3c31ab0f3c5"
-dependencies = [
- "rlp 0.4.6",
+ "parity-scale-codec",
 ]
 
 [[package]]
@@ -3392,7 +3490,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808"
 dependencies = [
- "rlp 0.5.0",
+ "rlp",
 ]
 
 [[package]]
@@ -3402,17 +3500,6 @@
 checksum = "b47ca4d2b6931707a55fce5cf66aff80e2178c8b63bbb4ecb5695cbc870ddf6f"
 dependencies = [
  "serde",
-]
-
-[[package]]
-name = "impl-trait-for-tuples"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ef5550a42e3740a0e71f909d4c861056a284060af885ae7aa6242820f920d9d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
 ]
 
 [[package]]
@@ -3428,20 +3515,20 @@
 
 [[package]]
 name = "indexmap"
-version = "1.6.2"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
+checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
 dependencies = [
  "autocfg",
- "hashbrown",
+ "hashbrown 0.11.2",
  "serde",
 ]
 
 [[package]]
 name = "instant"
-version = "0.1.9"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
+checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d"
 dependencies = [
  "cfg-if 1.0.0",
 ]
@@ -3467,7 +3554,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "64fa110ec7b8f493f416eed552740d10e7030ad5f63b2308f82c9608ec2df275"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 2.0.2",
 ]
 
@@ -3754,7 +3841,7 @@
  "beef",
  "futures-channel",
  "futures-util",
- "hyper 0.14.10",
+ "hyper 0.14.11",
  "log",
  "serde",
  "serde_json",
@@ -3770,10 +3857,10 @@
 dependencies = [
  "async-trait",
  "fnv",
- "futures 0.3.15",
+ "futures 0.3.16",
  "jsonrpsee-types",
  "log",
- "pin-project 1.0.7",
+ "pin-project 1.0.8",
  "rustls 0.19.1",
  "rustls-native-certs 0.5.0",
  "serde",
@@ -3803,6 +3890,91 @@
 ]
 
 [[package]]
+name = "kusama-runtime"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
+dependencies = [
+ "beefy-primitives",
+ "bitvec 0.20.4",
+ "frame-benchmarking",
+ "frame-election-provider-support",
+ "frame-executive",
+ "frame-support",
+ "frame-system",
+ "frame-system-benchmarking",
+ "frame-system-rpc-runtime-api",
+ "frame-try-runtime",
+ "hex-literal",
+ "log",
+ "max-encoded-len",
+ "pallet-authority-discovery",
+ "pallet-authorship",
+ "pallet-babe",
+ "pallet-balances",
+ "pallet-bounties",
+ "pallet-collective",
+ "pallet-democracy",
+ "pallet-election-provider-multi-phase",
+ "pallet-elections-phragmen",
+ "pallet-gilt",
+ "pallet-grandpa",
+ "pallet-identity",
+ "pallet-im-online",
+ "pallet-indices",
+ "pallet-membership",
+ "pallet-mmr-primitives",
+ "pallet-multisig",
+ "pallet-nicks",
+ "pallet-offences",
+ "pallet-offences-benchmarking",
+ "pallet-proxy",
+ "pallet-recovery",
+ "pallet-scheduler 3.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8)",
+ "pallet-session",
+ "pallet-session-benchmarking",
+ "pallet-society",
+ "pallet-staking",
+ "pallet-staking-reward-fn",
+ "pallet-timestamp",
+ "pallet-tips",
+ "pallet-transaction-payment",
+ "pallet-transaction-payment-rpc-runtime-api",
+ "pallet-treasury",
+ "pallet-utility",
+ "pallet-vesting",
+ "pallet-xcm",
+ "parity-scale-codec",
+ "polkadot-primitives",
+ "polkadot-runtime-common",
+ "polkadot-runtime-parachains",
+ "rustc-hex",
+ "serde",
+ "serde_derive",
+ "smallvec 1.6.1",
+ "sp-api",
+ "sp-arithmetic",
+ "sp-authority-discovery",
+ "sp-block-builder",
+ "sp-consensus-babe",
+ "sp-core",
+ "sp-inherents",
+ "sp-io",
+ "sp-npos-elections",
+ "sp-offchain",
+ "sp-runtime",
+ "sp-session",
+ "sp-staking",
+ "sp-std",
+ "sp-transaction-pool",
+ "sp-version",
+ "static_assertions",
+ "substrate-wasm-builder 4.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8)",
+ "xcm",
+ "xcm-builder",
+ "xcm-executor",
+]
+
+[[package]]
 name = "kv-log-macro"
 version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3870,9 +4042,9 @@
 
 [[package]]
 name = "libc"
-version = "0.2.97"
+version = "0.2.98"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
+checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
 
 [[package]]
 name = "libloading"
@@ -3908,7 +4080,7 @@
 dependencies = [
  "atomic",
  "bytes 1.0.1",
- "futures 0.3.15",
+ "futures 0.3.16",
  "lazy_static",
  "libp2p-core",
  "libp2p-deflate",
@@ -3934,7 +4106,7 @@
  "libp2p-yamux",
  "parity-multiaddr",
  "parking_lot 0.11.1",
- "pin-project 1.0.7",
+ "pin-project 1.0.8",
  "smallvec 1.6.1",
  "wasm-timer",
 ]
@@ -3950,7 +4122,7 @@
  "ed25519-dalek",
  "either",
  "fnv",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "lazy_static",
  "libsecp256k1 0.3.5",
@@ -3959,7 +4131,7 @@
  "multistream-select",
  "parity-multiaddr",
  "parking_lot 0.11.1",
- "pin-project 1.0.7",
+ "pin-project 1.0.8",
  "prost",
  "prost-build",
  "rand 0.7.3",
@@ -3980,7 +4152,7 @@
 checksum = "a2181a641cd15f9b6ba71b1335800f309012a0a97a29ffaabbbf40e9d3d58f08"
 dependencies = [
  "flate2",
- "futures 0.3.15",
+ "futures 0.3.16",
  "libp2p-core",
 ]
 
@@ -3991,7 +4163,7 @@
 checksum = "62e63dab8b5ff35e0c101a3e51e843ba782c07bbb1682f5fd827622e0d02b98b"
 dependencies = [
  "async-std-resolver",
- "futures 0.3.15",
+ "futures 0.3.16",
  "libp2p-core",
  "log",
  "smallvec 1.6.1",
@@ -4006,7 +4178,7 @@
 dependencies = [
  "cuckoofilter",
  "fnv",
- "futures 0.3.15",
+ "futures 0.3.16",
  "libp2p-core",
  "libp2p-swarm",
  "log",
@@ -4027,7 +4199,7 @@
  "byteorder",
  "bytes 1.0.1",
  "fnv",
- "futures 0.3.15",
+ "futures 0.3.16",
  "hex_fmt",
  "libp2p-core",
  "libp2p-swarm",
@@ -4048,7 +4220,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5f668f00efd9883e8b7bcc582eaf0164615792608f886f6577da18bcbeea0a46"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "libp2p-core",
  "libp2p-swarm",
  "log",
@@ -4069,7 +4241,7 @@
  "bytes 1.0.1",
  "either",
  "fnv",
- "futures 0.3.15",
+ "futures 0.3.16",
  "libp2p-core",
  "libp2p-swarm",
  "log",
@@ -4078,7 +4250,7 @@
  "rand 0.7.3",
  "sha2 0.9.5",
  "smallvec 1.6.1",
- "uint 0.9.0",
+ "uint",
  "unsigned-varint 0.7.0",
  "void",
  "wasm-timer",
@@ -4093,7 +4265,7 @@
  "async-io",
  "data-encoding",
  "dns-parser",
- "futures 0.3.15",
+ "futures 0.3.16",
  "if-watch",
  "lazy_static",
  "libp2p-core",
@@ -4113,7 +4285,7 @@
 dependencies = [
  "asynchronous-codec 0.6.0",
  "bytes 1.0.1",
- "futures 0.3.15",
+ "futures 0.3.16",
  "libp2p-core",
  "log",
  "nohash-hasher",
@@ -4131,7 +4303,7 @@
 dependencies = [
  "bytes 1.0.1",
  "curve25519-dalek 3.1.0",
- "futures 0.3.15",
+ "futures 0.3.16",
  "lazy_static",
  "libp2p-core",
  "log",
@@ -4151,7 +4323,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bf4bfaffac63bf3c7ec11ed9d8879d455966ddea7e78ee14737f0b6dce0d1cd1"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "libp2p-core",
  "libp2p-swarm",
  "log",
@@ -4168,7 +4340,7 @@
 dependencies = [
  "asynchronous-codec 0.6.0",
  "bytes 1.0.1",
- "futures 0.3.15",
+ "futures 0.3.16",
  "libp2p-core",
  "log",
  "prost",
@@ -4183,9 +4355,9 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6ce3374f3b28162db9d3442c9347c4f14cb01e8290052615c7d341d40eae0599"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "log",
- "pin-project 1.0.7",
+ "pin-project 1.0.8",
  "rand 0.7.3",
  "salsa20",
  "sha3 0.9.1",
@@ -4199,12 +4371,12 @@
 dependencies = [
  "asynchronous-codec 0.6.0",
  "bytes 1.0.1",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "libp2p-core",
  "libp2p-swarm",
  "log",
- "pin-project 1.0.7",
+ "pin-project 1.0.8",
  "prost",
  "prost-build",
  "rand 0.7.3",
@@ -4222,7 +4394,7 @@
 dependencies = [
  "async-trait",
  "bytes 1.0.1",
- "futures 0.3.15",
+ "futures 0.3.16",
  "libp2p-core",
  "libp2p-swarm",
  "log",
@@ -4241,7 +4413,7 @@
 checksum = "1e04d8e1eef675029ec728ba14e8d0da7975d84b6679b699b4ae91a1de9c3a92"
 dependencies = [
  "either",
- "futures 0.3.15",
+ "futures 0.3.16",
  "libp2p-core",
  "log",
  "rand 0.7.3",
@@ -4267,7 +4439,7 @@
 checksum = "2b1a27d21c477951799e99d5c105d78868258502ce092988040a808d5a19bbd9"
 dependencies = [
  "async-io",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "if-watch",
  "ipnet",
@@ -4284,7 +4456,7 @@
 checksum = "ffd6564bb3b7ff203661ccbb69003c2b551e34cef974f2d6c6a28306a12170b5"
 dependencies = [
  "async-std",
- "futures 0.3.15",
+ "futures 0.3.16",
  "libp2p-core",
  "log",
 ]
@@ -4295,7 +4467,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e2d413e4cf9b8e5dfbcd2a60d3dc5a3391308bdb463684093d4f67137b7113de"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "js-sys",
  "libp2p-core",
  "parity-send-wrapper",
@@ -4310,7 +4482,7 @@
 checksum = "cace60995ef6f637e4752cccbb2590f6bc358e8741a0d066307636c69a4b3a74"
 dependencies = [
  "either",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-rustls",
  "libp2p-core",
  "log",
@@ -4327,7 +4499,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f35da42cfc6d5cb0dcf3ad6881bc68d146cdf38f98655e09e33fbba4d13eabc4"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "libp2p-core",
  "parking_lot 0.11.1",
  "thiserror",
@@ -4336,9 +4508,9 @@
 
 [[package]]
 name = "librocksdb-sys"
-version = "6.17.3"
+version = "6.20.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5da125e1c0f22c7cae785982115523a0738728498547f415c9054cb17c7e89f9"
+checksum = "c309a9d2470844aceb9a4a098cf5286154d20596868b75a6b36357d2bb9ca25d"
 dependencies = [
  "bindgen",
  "cc",
@@ -4358,7 +4530,7 @@
  "hmac-drbg 0.2.0",
  "rand 0.7.3",
  "sha2 0.8.2",
- "subtle 2.4.0",
+ "subtle 2.4.1",
  "typenum",
 ]
 
@@ -4383,29 +4555,29 @@
 
 [[package]]
 name = "libsecp256k1-core"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ee11012b293ea30093c129173cac4335513064094619f4639a25b310fd33c11"
+checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80"
 dependencies = [
  "crunchy",
  "digest 0.9.0",
- "subtle 2.4.0",
+ "subtle 2.4.1",
 ]
 
 [[package]]
 name = "libsecp256k1-gen-ecmult"
-version = "0.2.0"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32239626ffbb6a095b83b37a02ceb3672b2443a87a000a884fc3c4d16925c9c0"
+checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3"
 dependencies = [
  "libsecp256k1-core",
 ]
 
 [[package]]
 name = "libsecp256k1-gen-genmult"
-version = "0.2.0"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76acb433e21d10f5f9892b1962c2856c58c7f39a9e4bd68ac82b9436a0ffd5b9"
+checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d"
 dependencies = [
  "libsecp256k1-core",
 ]
@@ -4438,11 +4610,11 @@
 
 [[package]]
 name = "linregress"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1ff7f341d23e1275eec0656a9a07225fcc86216c4322392868adffe59023d1a"
+checksum = "1e6e407dadb4ca4b31bc69c27aff00e7ca4534fdcee855159b039a7cebb5f395"
 dependencies = [
- "nalgebra 0.27.1",
+ "nalgebra",
  "statrs",
 ]
 
@@ -4480,7 +4652,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1f374d42cdfc1d7dbf3d3dec28afab2eb97ffbf43a3234d795b5986dbf4b90ba"
 dependencies = [
- "hashbrown",
+ "hashbrown 0.9.1",
 ]
 
 [[package]]
@@ -4540,18 +4712,18 @@
 [[package]]
 name = "max-encoded-len"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "impl-trait-for-tuples 0.2.1",
+ "impl-trait-for-tuples",
  "max-encoded-len-derive",
- "parity-scale-codec 2.1.3",
- "primitive-types 0.9.0",
+ "parity-scale-codec",
+ "primitive-types",
 ]
 
 [[package]]
 name = "max-encoded-len-derive"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "proc-macro-crate 1.0.0",
  "proc-macro2",
@@ -4605,7 +4777,7 @@
 checksum = "814bbecfc0451fc314eeea34f05bbcd5b98a7ad7af37faee088b86a1e633f1d4"
 dependencies = [
  "hash-db",
- "hashbrown",
+ "hashbrown 0.9.1",
  "parity-util-mem",
 ]
 
@@ -4639,10 +4811,10 @@
 [[package]]
 name = "metered-channel"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "derive_more",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
 ]
 
@@ -4652,7 +4824,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c023c3f16109e7f33aa451f773fd61070e265b4977d0b6e344a51049296dd7df"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "rand 0.7.3",
  "thrift",
 ]
@@ -4668,9 +4840,9 @@
 
 [[package]]
 name = "minicbor-derive"
-version = "0.6.3"
+version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f2b9e8883d58e34b18facd16c4564a77ea50fce028ad3d0ee6753440e37acc8"
+checksum = "54999f917cd092b13904737e26631aa2b2b88d625db68e4bab461dcd8006c788"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4823,43 +4995,28 @@
 checksum = "7d91ec0a2440aaff5f78ec35631a7027d50386c6163aa975f7caa0d5da4b6ff8"
 dependencies = [
  "bytes 1.0.1",
- "futures 0.3.15",
+ "futures 0.3.16",
  "log",
- "pin-project 1.0.7",
+ "pin-project 1.0.8",
  "smallvec 1.6.1",
  "unsigned-varint 0.7.0",
 ]
 
 [[package]]
 name = "nalgebra"
-version = "0.26.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "476d1d59fe02fe54c86356e91650cd892f392782a1cb9fc524ec84f7aa9e1d06"
-dependencies = [
- "approx 0.4.0",
- "matrixmultiply",
- "num-complex 0.3.1",
- "num-rational 0.3.2",
- "num-traits",
- "rand 0.8.4",
- "rand_distr",
- "simba 0.4.0",
- "typenum",
-]
-
-[[package]]
-name = "nalgebra"
 version = "0.27.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "462fffe4002f4f2e1f6a9dcf12cc1a6fc0e15989014efc02a941d3e0f5dc2120"
 dependencies = [
- "approx 0.5.0",
+ "approx",
  "matrixmultiply",
  "nalgebra-macros",
- "num-complex 0.4.0",
+ "num-complex",
  "num-rational 0.4.0",
  "num-traits",
- "simba 0.5.1",
+ "rand 0.8.4",
+ "rand_distr",
+ "simba",
  "typenum",
 ]
 
@@ -4915,7 +5072,7 @@
  "fp-rpc",
  "frame-benchmarking",
  "frame-benchmarking-cli",
- "futures 0.3.15",
+ "futures 0.3.16",
  "jsonrpc-core 15.1.0",
  "jsonrpc-pubsub 15.1.0",
  "log",
@@ -4924,7 +5081,7 @@
  "nft-runtime",
  "pallet-ethereum",
  "pallet-transaction-payment-rpc",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.10.2",
  "polkadot-cli",
  "polkadot-parachain",
@@ -4974,12 +5131,15 @@
 name = "nft-data-structs"
 version = "0.9.0"
 dependencies = [
+ "derivative",
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "max-encoded-len",
+ "parity-scale-codec",
  "serde",
  "sp-core",
  "sp-runtime",
+ "sp-std",
 ]
 
 [[package]]
@@ -4991,7 +5151,7 @@
  "fc-rpc",
  "fc-rpc-core",
  "fp-rpc",
- "futures 0.3.15",
+ "futures 0.3.16",
  "jsonrpc-core 15.1.0",
  "jsonrpc-pubsub 15.1.0",
  "nft-runtime",
@@ -5038,6 +5198,7 @@
  "cumulus-primitives-core",
  "cumulus-primitives-timestamp",
  "cumulus-primitives-utility",
+ "derivative",
  "fp-rpc",
  "frame-benchmarking",
  "frame-executive",
@@ -5046,11 +5207,16 @@
  "frame-system-benchmarking",
  "frame-system-rpc-runtime-api",
  "hex-literal",
+ "max-encoded-len",
  "nft-data-structs",
  "pallet-aura",
  "pallet-balances",
  "pallet-ethereum",
  "pallet-evm",
+ "pallet-evm-coder-substrate",
+ "pallet-evm-contract-helpers",
+ "pallet-evm-migration",
+ "pallet-evm-transaction-payment",
  "pallet-inflation",
  "pallet-nft",
  "pallet-nft-charge-transaction",
@@ -5065,7 +5231,7 @@
  "pallet-vesting",
  "pallet-xcm",
  "parachain-info",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-parachain",
  "serde",
  "smallvec 1.6.1",
@@ -5082,7 +5248,7 @@
  "sp-std",
  "sp-transaction-pool",
  "sp-version",
- "substrate-wasm-builder 4.0.0",
+ "substrate-wasm-builder 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "xcm",
  "xcm-builder",
  "xcm-executor",
@@ -5102,10 +5268,12 @@
 
 [[package]]
 name = "nom"
-version = "5.1.2"
+version = "6.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
+checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2"
 dependencies = [
+ "bitvec 0.19.5",
+ "funty",
  "memchr",
  "version_check",
 ]
@@ -5118,15 +5286,6 @@
 dependencies = [
  "autocfg",
  "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-complex"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
-dependencies = [
  "num-traits",
 ]
 
@@ -5163,17 +5322,6 @@
 
 [[package]]
 name = "num-rational"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
-dependencies = [
- "autocfg",
- "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-rational"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a"
@@ -5215,9 +5363,9 @@
 
 [[package]]
 name = "object"
-version = "0.25.3"
+version = "0.26.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7"
+checksum = "c55827317fb4c08822499848a14237d2874d6f139828893017237e7ab93eb386"
 dependencies = [
  "memchr",
 ]
@@ -5270,13 +5418,13 @@
 [[package]]
 name = "pallet-aura"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
  "frame-system",
  "pallet-session",
  "pallet-timestamp",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-application-crypto",
  "sp-consensus-aura",
  "sp-runtime",
@@ -5286,12 +5434,12 @@
 [[package]]
 name = "pallet-authority-discovery"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
  "frame-system",
  "pallet-session",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-application-crypto",
  "sp-authority-discovery",
  "sp-runtime",
@@ -5301,12 +5449,12 @@
 [[package]]
 name = "pallet-authorship"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
  "frame-system",
- "impl-trait-for-tuples 0.2.1",
- "parity-scale-codec 2.1.3",
+ "impl-trait-for-tuples",
+ "parity-scale-codec",
  "sp-authorship",
  "sp-runtime",
  "sp-std",
@@ -5315,7 +5463,7 @@
 [[package]]
 name = "pallet-babe"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
@@ -5324,7 +5472,7 @@
  "pallet-authorship",
  "pallet-session",
  "pallet-timestamp",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-application-crypto",
  "sp-consensus-babe",
  "sp-consensus-vrf",
@@ -5338,14 +5486,14 @@
 [[package]]
 name = "pallet-balances"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
  "frame-system",
  "log",
  "max-encoded-len",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-runtime",
  "sp-std",
 ]
@@ -5353,13 +5501,13 @@
 [[package]]
 name = "pallet-beefy"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=polkadot-v0.9.7#299dd5fd3fabd99c3c919f1312001283ddc5b365"
+source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=polkadot-v0.9.8#55ae3329847e0bbde51c9d45991d99f444777555"
 dependencies = [
  "beefy-primitives",
  "frame-support",
  "frame-system",
  "pallet-session",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-runtime",
  "sp-std",
@@ -5368,25 +5516,48 @@
 [[package]]
 name = "pallet-bounties"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
  "pallet-treasury",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-runtime",
  "sp-std",
 ]
 
 [[package]]
+name = "pallet-bridge-grandpa"
+version = "0.1.0"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
+dependencies = [
+ "bp-header-chain",
+ "bp-runtime",
+ "bp-test-utils",
+ "finality-grandpa",
+ "frame-support",
+ "frame-system",
+ "log",
+ "num-traits",
+ "parity-scale-codec",
+ "serde",
+ "sp-finality-grandpa",
+ "sp-runtime",
+ "sp-std",
+ "sp-trie",
+]
+
+[[package]]
 name = "pallet-collective"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5400,7 +5571,7 @@
  "frame-support",
  "frame-system",
  "pallet-contracts",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-runtime",
  "sp-std",
  "up-sponsorship",
@@ -5409,7 +5580,7 @@
 [[package]]
 name = "pallet-contracts"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "bitflags",
  "frame-support",
@@ -5417,7 +5588,7 @@
  "log",
  "pallet-contracts-primitives",
  "pallet-contracts-proc-macro",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "pwasm-utils",
  "serde",
  "smallvec 1.6.1",
@@ -5432,10 +5603,10 @@
 [[package]]
 name = "pallet-contracts-primitives"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "bitflags",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-core",
  "sp-runtime",
@@ -5445,7 +5616,7 @@
 [[package]]
 name = "pallet-contracts-proc-macro"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5455,12 +5626,12 @@
 [[package]]
 name = "pallet-democracy"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-io",
  "sp-runtime",
@@ -5470,13 +5641,15 @@
 [[package]]
 name = "pallet-election-provider-multi-phase"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
+ "frame-benchmarking",
  "frame-election-provider-support",
  "frame-support",
  "frame-system",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
+ "rand 0.7.3",
  "sp-arithmetic",
  "sp-core",
  "sp-io",
@@ -5489,12 +5662,13 @@
 [[package]]
 name = "pallet-elections-phragmen"
 version = "4.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-core",
  "sp-io",
  "sp-npos-elections",
@@ -5505,10 +5679,10 @@
 [[package]]
 name = "pallet-ethereum"
 version = "3.0.0-dev"
-source = "git+https://github.com/usetech-llc/frontier.git?branch=injected-transactions-parachain#c1388c13be6d59b9a70e1277f1295977090adb63"
+source = "git+https://github.com/uniquenetwork/frontier.git?branch=injected-transactions-parachain#1e2a0537db656af0b300493b4f8eda72c22e9421"
 dependencies = [
  "ethereum",
- "ethereum-types 0.11.0",
+ "ethereum-types",
  "evm",
  "fp-consensus",
  "fp-evm",
@@ -5520,8 +5694,8 @@
  "pallet-balances",
  "pallet-evm",
  "pallet-timestamp",
- "parity-scale-codec 2.1.3",
- "rlp 0.5.0",
+ "parity-scale-codec",
+ "rlp",
  "rustc-hex",
  "serde",
  "sha3 0.8.2",
@@ -5533,21 +5707,23 @@
 [[package]]
 name = "pallet-evm"
 version = "5.0.0-dev"
-source = "git+https://github.com/usetech-llc/frontier.git?branch=injected-transactions-parachain#c1388c13be6d59b9a70e1277f1295977090adb63"
+source = "git+https://github.com/uniquenetwork/frontier.git?branch=injected-transactions-parachain#1e2a0537db656af0b300493b4f8eda72c22e9421"
 dependencies = [
  "evm",
  "evm-gasometer",
  "evm-runtime",
  "fp-evm",
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
- "impl-trait-for-tuples 0.2.1",
+ "hex",
+ "impl-trait-for-tuples",
  "log",
  "pallet-balances",
  "pallet-timestamp",
- "parity-scale-codec 2.1.3",
- "primitive-types 0.9.0",
- "rlp 0.5.0",
+ "parity-scale-codec",
+ "primitive-types",
+ "rlp",
  "serde",
  "sha3 0.8.2",
  "sp-core",
@@ -5557,9 +5733,88 @@
 ]
 
 [[package]]
+name = "pallet-evm-coder-substrate"
+version = "0.1.0"
+dependencies = [
+ "ethereum",
+ "evm-coder",
+ "frame-support",
+ "frame-system",
+ "pallet-ethereum",
+ "pallet-evm",
+ "parity-scale-codec",
+ "sp-core",
+ "sp-std",
+]
+
+[[package]]
+name = "pallet-evm-contract-helpers"
+version = "0.1.0"
+dependencies = [
+ "evm-coder",
+ "frame-support",
+ "frame-system",
+ "log",
+ "pallet-evm",
+ "pallet-evm-coder-substrate",
+ "parity-scale-codec",
+ "sp-core",
+ "sp-runtime",
+ "sp-std",
+ "up-sponsorship",
+]
+
+[[package]]
+name = "pallet-evm-migration"
+version = "0.1.0"
+dependencies = [
+ "fp-evm",
+ "frame-benchmarking",
+ "frame-support",
+ "frame-system",
+ "pallet-evm",
+ "parity-scale-codec",
+ "sp-core",
+ "sp-io",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
+name = "pallet-evm-transaction-payment"
+version = "0.1.0"
+dependencies = [
+ "fp-evm",
+ "frame-support",
+ "frame-system",
+ "pallet-ethereum",
+ "pallet-evm",
+ "parity-scale-codec",
+ "sp-core",
+ "sp-io",
+ "sp-runtime",
+ "sp-std",
+ "up-sponsorship",
+]
+
+[[package]]
+name = "pallet-gilt"
+version = "3.0.0"
+source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
+dependencies = [
+ "frame-benchmarking",
+ "frame-support",
+ "frame-system",
+ "parity-scale-codec",
+ "sp-arithmetic",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
 name = "pallet-grandpa"
 version = "3.1.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
@@ -5567,7 +5822,7 @@
  "log",
  "pallet-authorship",
  "pallet-session",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-application-crypto",
  "sp-core",
  "sp-finality-grandpa",
@@ -5581,13 +5836,13 @@
 [[package]]
 name = "pallet-identity"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "enumflags2",
  "frame-benchmarking",
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-io",
  "sp-runtime",
  "sp-std",
@@ -5596,13 +5851,14 @@
 [[package]]
 name = "pallet-im-online"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
  "log",
  "pallet-authorship",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-application-crypto",
  "sp-core",
  "sp-io",
@@ -5614,11 +5870,12 @@
 [[package]]
 name = "pallet-indices"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-core",
  "sp-io",
  "sp-keyring",
@@ -5636,7 +5893,7 @@
  "pallet-balances",
  "pallet-randomness-collective-flip",
  "pallet-timestamp",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-core",
  "sp-io",
@@ -5647,13 +5904,13 @@
 [[package]]
 name = "pallet-membership"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
  "frame-system",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-io",
  "sp-runtime",
  "sp-std",
@@ -5662,14 +5919,14 @@
 [[package]]
 name = "pallet-mmr"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "ckb-merkle-mountain-range",
  "frame-benchmarking",
  "frame-support",
  "frame-system",
  "pallet-mmr-primitives",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5679,12 +5936,12 @@
 [[package]]
 name = "pallet-mmr-primitives"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
  "frame-system",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-api",
  "sp-core",
@@ -5695,13 +5952,13 @@
 [[package]]
 name = "pallet-mmr-rpc"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "jsonrpc-core 15.1.0",
  "jsonrpc-core-client 15.1.0",
  "jsonrpc-derive 15.1.0",
  "pallet-mmr-primitives",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-api",
  "sp-blockchain",
@@ -5713,11 +5970,12 @@
 [[package]]
 name = "pallet-multisig"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5729,7 +5987,6 @@
 version = "3.0.0"
 dependencies = [
  "ethereum",
- "ethereum-tx-sign",
  "evm-coder",
  "fp-evm",
  "frame-benchmarking",
@@ -5740,12 +5997,13 @@
  "pallet-balances",
  "pallet-ethereum",
  "pallet-evm",
+ "pallet-evm-coder-substrate",
  "pallet-randomness-collective-flip",
  "pallet-timestamp",
  "pallet-transaction-payment",
- "parity-scale-codec 2.1.3",
- "primitive-types 0.9.0",
- "rlp 0.5.0",
+ "parity-scale-codec",
+ "primitive-types",
+ "rlp",
  "serde",
  "sp-api",
  "sp-core",
@@ -5765,7 +6023,7 @@
  "pallet-balances",
  "pallet-nft-transaction-payment",
  "pallet-transaction-payment",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-core",
  "sp-io",
@@ -5781,7 +6039,7 @@
  "frame-support",
  "frame-system",
  "pallet-transaction-payment",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-core",
  "sp-io",
@@ -5793,11 +6051,11 @@
 [[package]]
 name = "pallet-nicks"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-io",
  "sp-runtime",
  "sp-std",
@@ -5806,13 +6064,13 @@
 [[package]]
 name = "pallet-offences"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
  "frame-system",
  "log",
  "pallet-balances",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-runtime",
  "sp-staking",
@@ -5820,14 +6078,37 @@
 ]
 
 [[package]]
+name = "pallet-offences-benchmarking"
+version = "3.0.0"
+source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
+dependencies = [
+ "frame-benchmarking",
+ "frame-election-provider-support",
+ "frame-support",
+ "frame-system",
+ "pallet-babe",
+ "pallet-balances",
+ "pallet-grandpa",
+ "pallet-im-online",
+ "pallet-offences",
+ "pallet-session",
+ "pallet-staking",
+ "parity-scale-codec",
+ "sp-runtime",
+ "sp-staking",
+ "sp-std",
+]
+
+[[package]]
 name = "pallet-proxy"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
  "max-encoded-len",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5837,26 +6118,40 @@
 [[package]]
 name = "pallet-randomness-collective-flip"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "safe-mix",
  "sp-runtime",
  "sp-std",
 ]
 
 [[package]]
+name = "pallet-recovery"
+version = "3.0.0"
+source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
+dependencies = [
+ "enumflags2",
+ "frame-support",
+ "frame-system",
+ "parity-scale-codec",
+ "sp-io",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
 name = "pallet-scheduler"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
  "frame-system",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-io",
  "sp-runtime",
  "sp-std",
@@ -5870,7 +6165,7 @@
  "frame-support",
  "frame-system",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-core",
  "sp-io",
@@ -5883,14 +6178,14 @@
 [[package]]
 name = "pallet-session"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
  "frame-system",
- "impl-trait-for-tuples 0.2.1",
+ "impl-trait-for-tuples",
  "log",
  "pallet-timestamp",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -5901,18 +6196,49 @@
 ]
 
 [[package]]
+name = "pallet-session-benchmarking"
+version = "3.0.0"
+source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
+dependencies = [
+ "frame-benchmarking",
+ "frame-support",
+ "frame-system",
+ "pallet-session",
+ "pallet-staking",
+ "rand 0.7.3",
+ "sp-runtime",
+ "sp-session",
+ "sp-std",
+]
+
+[[package]]
+name = "pallet-society"
+version = "3.0.0"
+source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
+dependencies = [
+ "frame-support",
+ "frame-system",
+ "parity-scale-codec",
+ "rand_chacha 0.2.2",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
 name = "pallet-staking"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
+ "frame-benchmarking",
  "frame-election-provider-support",
  "frame-support",
  "frame-system",
  "log",
  "pallet-authorship",
  "pallet-session",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "paste",
+ "rand_chacha 0.2.2",
  "serde",
  "sp-application-crypto",
  "sp-io",
@@ -5925,7 +6251,7 @@
 [[package]]
 name = "pallet-staking-reward-curve"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "proc-macro-crate 1.0.0",
  "proc-macro2",
@@ -5934,13 +6260,22 @@
 ]
 
 [[package]]
+name = "pallet-staking-reward-fn"
+version = "3.0.0"
+source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
+dependencies = [
+ "log",
+ "sp-arithmetic",
+]
+
+[[package]]
 name = "pallet-sudo"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-io",
  "sp-runtime",
  "sp-std",
@@ -5949,14 +6284,14 @@
 [[package]]
 name = "pallet-timestamp"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
  "frame-system",
- "impl-trait-for-tuples 0.2.1",
+ "impl-trait-for-tuples",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-inherents",
  "sp-io",
  "sp-runtime",
@@ -5967,12 +6302,13 @@
 [[package]]
 name = "pallet-tips"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
  "pallet-treasury",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-runtime",
  "sp-std",
@@ -5981,11 +6317,11 @@
 [[package]]
 name = "pallet-transaction-payment"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "smallvec 1.6.1",
  "sp-core",
@@ -5997,13 +6333,13 @@
 [[package]]
 name = "pallet-transaction-payment-rpc"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "jsonrpc-core 15.1.0",
  "jsonrpc-core-client 15.1.0",
  "jsonrpc-derive 15.1.0",
  "pallet-transaction-payment-rpc-runtime-api",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-api",
  "sp-blockchain",
  "sp-core",
@@ -6014,10 +6350,10 @@
 [[package]]
 name = "pallet-transaction-payment-rpc-runtime-api"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "pallet-transaction-payment",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-api",
  "sp-runtime",
 ]
@@ -6025,13 +6361,14 @@
 [[package]]
 name = "pallet-treasury"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
- "impl-trait-for-tuples 0.2.1",
+ "impl-trait-for-tuples",
  "pallet-balances",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-runtime",
  "sp-std",
@@ -6040,11 +6377,12 @@
 [[package]]
 name = "pallet-utility"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -6054,12 +6392,13 @@
 [[package]]
 name = "pallet-vesting"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "enumflags2",
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-runtime",
  "sp-std",
 ]
@@ -6067,11 +6406,12 @@
 [[package]]
 name = "pallet-xcm"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
+ "serde",
  "sp-runtime",
  "sp-std",
  "xcm",
@@ -6081,12 +6421,12 @@
 [[package]]
 name = "parachain-info"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.7#c5c3abf7eb9d4fdfb588d6560efaa8dca66a8dbc"
+source = "git+https://github.com/paritytech/cumulus.git?branch=polkadot-v0.9.8#ed6ba5dfb2c112c29505e856e8971da3420ce6d0"
 dependencies = [
  "cumulus-primitives-core",
  "frame-support",
  "frame-system",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
 ]
 
@@ -6127,34 +6467,23 @@
 
 [[package]]
 name = "parity-scale-codec"
-version = "1.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4b26b16c7687c3075982af47719e481815df30bc544f7a6690763a25ca16e9d"
-dependencies = [
- "arrayvec 0.5.2",
- "bitvec 0.17.4",
- "byte-slice-cast 0.3.5",
- "serde",
-]
-
-[[package]]
-name = "parity-scale-codec"
-version = "2.1.3"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b310f220c335f9df1b3d2e9fbe3890bbfeef5030dad771620f48c5c229877cd3"
+checksum = "8975095a2a03bbbdc70a74ab11a4f76a6d0b84680d87c68d722531b0ac28e8a9"
 dependencies = [
  "arrayvec 0.7.1",
  "bitvec 0.20.4",
- "byte-slice-cast 1.0.0",
+ "byte-slice-cast",
+ "impl-trait-for-tuples",
  "parity-scale-codec-derive",
  "serde",
 ]
 
 [[package]]
 name = "parity-scale-codec-derive"
-version = "2.1.3"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81038e13ca2c32587201d544ea2e6b6c47120f1e4eae04478f9f60b6bcb89145"
+checksum = "40dbbfef7f0a1143c5b06e0d76a6278e25dac0bc1af4be51a0fbb73f07e7ad09"
 dependencies = [
  "proc-macro-crate 1.0.0",
  "proc-macro2",
@@ -6194,13 +6523,13 @@
 checksum = "664a8c6b8e62d8f9f2f937e391982eb433ab285b4cd9545b342441e04a906e42"
 dependencies = [
  "cfg-if 1.0.0",
- "ethereum-types 0.11.0",
- "hashbrown",
- "impl-trait-for-tuples 0.2.1",
+ "ethereum-types",
+ "hashbrown 0.9.1",
+ "impl-trait-for-tuples",
  "lru",
  "parity-util-mem-derive",
  "parking_lot 0.11.1",
- "primitive-types 0.9.0",
+ "primitive-types",
  "smallvec 1.6.1",
  "winapi 0.3.9",
 ]
@@ -6233,9 +6562,9 @@
 
 [[package]]
 name = "parity-ws"
-version = "0.10.0"
+version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e02a625dd75084c2a7024f07c575b61b782f729d18702dabb3cdbf31911dc61"
+checksum = "322d72dfe461b8b9e367d057ceace105379d64d5b03907d23c481ccf3fbf8aa4"
 dependencies = [
  "byteorder",
  "bytes 0.4.12",
@@ -6263,7 +6592,7 @@
 dependencies = [
  "lock_api 0.3.4",
  "parking_lot_core 0.6.2",
- "rustc_version",
+ "rustc_version 0.2.3",
 ]
 
 [[package]]
@@ -6297,7 +6626,7 @@
  "cloudabi",
  "libc",
  "redox_syscall 0.1.57",
- "rustc_version",
+ "rustc_version 0.2.3",
  "smallvec 0.6.14",
  "winapi 0.3.9",
 ]
@@ -6443,11 +6772,11 @@
 
 [[package]]
 name = "pin-project"
-version = "1.0.7"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4"
+checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08"
 dependencies = [
- "pin-project-internal 1.0.7",
+ "pin-project-internal 1.0.8",
 ]
 
 [[package]]
@@ -6463,9 +6792,9 @@
 
 [[package]]
 name = "pin-project-internal"
-version = "1.0.7"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f"
+checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -6480,9 +6809,9 @@
 
 [[package]]
 name = "pin-project-lite"
-version = "0.2.6"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905"
+checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
 
 [[package]]
 name = "pin-utils"
@@ -6505,9 +6834,9 @@
 [[package]]
 name = "polkadot-approval-distribution"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "polkadot-node-network-protocol",
  "polkadot-node-primitives",
  "polkadot-node-subsystem",
@@ -6519,9 +6848,9 @@
 [[package]]
 name = "polkadot-availability-bitfield-distribution"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "polkadot-node-network-protocol",
  "polkadot-node-subsystem",
  "polkadot-node-subsystem-util",
@@ -6532,11 +6861,11 @@
 [[package]]
 name = "polkadot-availability-distribution"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "lru",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-erasure-coding",
  "polkadot-node-core-runtime-api",
  "polkadot-node-network-protocol",
@@ -6555,11 +6884,11 @@
 [[package]]
 name = "polkadot-availability-recovery"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "lru",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-erasure-coding",
  "polkadot-node-network-protocol",
  "polkadot-node-primitives",
@@ -6573,11 +6902,11 @@
 
 [[package]]
 name = "polkadot-cli"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "frame-benchmarking-cli",
- "futures 0.3.15",
+ "futures 0.3.16",
  "log",
  "polkadot-node-core-pvf",
  "polkadot-service",
@@ -6593,8 +6922,8 @@
 
 [[package]]
 name = "polkadot-client"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "beefy-primitives",
  "frame-benchmarking",
@@ -6623,10 +6952,10 @@
 [[package]]
 name = "polkadot-collator-protocol"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "always-assert",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "polkadot-node-network-protocol",
  "polkadot-node-primitives",
@@ -6642,10 +6971,10 @@
 
 [[package]]
 name = "polkadot-core-primitives"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parity-util-mem",
  "sp-core",
  "sp-runtime",
@@ -6654,10 +6983,10 @@
 
 [[package]]
 name = "polkadot-erasure-coding"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-node-primitives",
  "polkadot-primitives",
  "reed-solomon-novelpoly",
@@ -6669,14 +6998,17 @@
 [[package]]
 name = "polkadot-gossip-support"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "polkadot-node-network-protocol",
  "polkadot-node-subsystem",
  "polkadot-node-subsystem-util",
  "polkadot-primitives",
+ "rand 0.8.4",
+ "rand_chacha 0.3.1",
  "sp-application-crypto",
+ "sp-core",
  "sp-keystore",
  "tracing",
 ]
@@ -6684,11 +7016,11 @@
 [[package]]
 name = "polkadot-network-bridge"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "async-trait",
- "futures 0.3.15",
- "parity-scale-codec 2.1.3",
+ "futures 0.3.16",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "polkadot-node-network-protocol",
  "polkadot-node-subsystem",
@@ -6704,10 +7036,10 @@
 [[package]]
 name = "polkadot-node-collation-generation"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
- "futures 0.3.15",
- "parity-scale-codec 2.1.3",
+ "futures 0.3.16",
+ "parity-scale-codec",
  "polkadot-erasure-coding",
  "polkadot-node-primitives",
  "polkadot-node-subsystem",
@@ -6722,15 +7054,16 @@
 [[package]]
 name = "polkadot-node-core-approval-voting"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "bitvec 0.20.4",
  "derive_more",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "kvdb",
+ "lru",
  "merlin",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-node-jaeger",
  "polkadot-node-primitives",
  "polkadot-node-subsystem",
@@ -6751,13 +7084,13 @@
 [[package]]
 name = "polkadot-node-core-av-store"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "bitvec 0.20.4",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "kvdb",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-erasure-coding",
  "polkadot-node-primitives",
  "polkadot-node-subsystem",
@@ -6771,10 +7104,10 @@
 [[package]]
 name = "polkadot-node-core-backing"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "bitvec 0.20.4",
- "futures 0.3.15",
+ "futures 0.3.16",
  "polkadot-erasure-coding",
  "polkadot-node-primitives",
  "polkadot-node-subsystem",
@@ -6789,9 +7122,9 @@
 [[package]]
 name = "polkadot-node-core-bitfield-signing"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "polkadot-node-subsystem",
  "polkadot-node-subsystem-util",
  "polkadot-primitives",
@@ -6804,11 +7137,11 @@
 [[package]]
 name = "polkadot-node-core-candidate-validation"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "async-trait",
- "futures 0.3.15",
- "parity-scale-codec 2.1.3",
+ "futures 0.3.16",
+ "parity-scale-codec",
  "polkadot-node-core-pvf",
  "polkadot-node-primitives",
  "polkadot-node-subsystem",
@@ -6822,12 +7155,14 @@
 [[package]]
 name = "polkadot-node-core-chain-api"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "polkadot-node-subsystem",
  "polkadot-node-subsystem-util",
  "polkadot-primitives",
+ "sc-client-api",
+ "sc-consensus-babe",
  "sp-blockchain",
  "tracing",
 ]
@@ -6835,10 +7170,10 @@
 [[package]]
 name = "polkadot-node-core-parachains-inherent"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "async-trait",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "polkadot-node-subsystem",
  "polkadot-overseer",
@@ -6853,10 +7188,10 @@
 [[package]]
 name = "polkadot-node-core-provisioner"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "bitvec 0.20.4",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "polkadot-node-subsystem",
  "polkadot-node-subsystem-util",
@@ -6868,17 +7203,17 @@
 [[package]]
 name = "polkadot-node-core-pvf"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "always-assert",
  "assert_matches",
  "async-process",
  "async-std",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "libc",
- "parity-scale-codec 2.1.3",
- "pin-project 1.0.7",
+ "parity-scale-codec",
+ "pin-project 1.0.8",
  "polkadot-core-primitives",
  "polkadot-parachain",
  "rand 0.8.4",
@@ -6889,6 +7224,7 @@
  "sp-core",
  "sp-externalities",
  "sp-io",
+ "sp-maybe-compressed-blob",
  "sp-wasm-interface",
  "tracing",
 ]
@@ -6896,9 +7232,9 @@
 [[package]]
 name = "polkadot-node-core-runtime-api"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "memory-lru",
  "parity-util-mem",
  "polkadot-node-subsystem",
@@ -6914,13 +7250,13 @@
 [[package]]
 name = "polkadot-node-jaeger"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "async-std",
  "lazy_static",
  "log",
  "mick-jaeger",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "polkadot-node-primitives",
  "polkadot-primitives",
@@ -6932,10 +7268,10 @@
 [[package]]
 name = "polkadot-node-network-protocol"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
- "futures 0.3.15",
- "parity-scale-codec 2.1.3",
+ "futures 0.3.16",
+ "parity-scale-codec",
  "polkadot-node-jaeger",
  "polkadot-node-primitives",
  "polkadot-primitives",
@@ -6947,10 +7283,10 @@
 [[package]]
 name = "polkadot-node-primitives"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
- "futures 0.3.15",
- "parity-scale-codec 2.1.3",
+ "futures 0.3.16",
+ "parity-scale-codec",
  "polkadot-parachain",
  "polkadot-primitives",
  "polkadot-statement-table",
@@ -6970,19 +7306,19 @@
 [[package]]
 name = "polkadot-node-subsystem"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "async-std",
  "async-trait",
  "derive_more",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "lazy_static",
  "log",
  "mick-jaeger",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
- "pin-project 1.0.7",
+ "pin-project 1.0.8",
  "polkadot-node-jaeger",
  "polkadot-node-network-protocol",
  "polkadot-node-primitives",
@@ -7000,15 +7336,16 @@
 [[package]]
 name = "polkadot-node-subsystem-util"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "async-trait",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
+ "itertools 0.10.1",
  "lru",
  "metered-channel",
- "parity-scale-codec 2.1.3",
- "pin-project 1.0.7",
+ "parity-scale-codec",
+ "pin-project 1.0.8",
  "polkadot-node-jaeger",
  "polkadot-node-network-protocol",
  "polkadot-node-primitives",
@@ -7019,7 +7356,6 @@
  "sp-application-crypto",
  "sp-core",
  "sp-keystore",
- "streamunordered",
  "substrate-prometheus-endpoint",
  "thiserror",
  "tracing",
@@ -7028,10 +7364,10 @@
 [[package]]
 name = "polkadot-overseer"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "async-trait",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "lru",
  "polkadot-node-primitives",
@@ -7046,11 +7382,11 @@
 
 [[package]]
 name = "polkadot-parachain"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "derive_more",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parity-util-mem",
  "polkadot-core-primitives",
  "serde",
@@ -7061,13 +7397,13 @@
 
 [[package]]
 name = "polkadot-primitives"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "bitvec 0.20.4",
  "frame-system",
  "hex-literal",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parity-util-mem",
  "polkadot-core-primitives",
  "polkadot-parachain",
@@ -7092,7 +7428,7 @@
 [[package]]
 name = "polkadot-procmacro-overseer-subsystems-gen"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "assert_matches",
  "proc-macro2",
@@ -7103,7 +7439,7 @@
 [[package]]
 name = "polkadot-procmacro-subsystem-dispatch-gen"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "assert_matches",
  "proc-macro2",
@@ -7113,15 +7449,15 @@
 
 [[package]]
 name = "polkadot-rpc"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "beefy-gadget",
  "beefy-gadget-rpc",
  "jsonrpc-core 15.1.0",
  "pallet-mmr-rpc",
  "pallet-transaction-payment-rpc",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-primitives",
  "sc-chain-spec",
  "sc-client-api",
@@ -7146,17 +7482,20 @@
 
 [[package]]
 name = "polkadot-runtime"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "beefy-primitives",
  "bitvec 0.20.4",
+ "frame-benchmarking",
  "frame-election-provider-support",
  "frame-executive",
  "frame-support",
  "frame-system",
+ "frame-system-benchmarking",
  "frame-system-rpc-runtime-api",
  "frame-try-runtime",
+ "hex-literal",
  "log",
  "max-encoded-len",
  "pallet-authority-discovery",
@@ -7177,10 +7516,11 @@
  "pallet-multisig",
  "pallet-nicks",
  "pallet-offences",
+ "pallet-offences-benchmarking",
  "pallet-proxy",
- "pallet-randomness-collective-flip",
- "pallet-scheduler 3.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7)",
+ "pallet-scheduler 3.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8)",
  "pallet-session",
+ "pallet-session-benchmarking",
  "pallet-staking",
  "pallet-staking-reward-curve",
  "pallet-timestamp",
@@ -7190,7 +7530,7 @@
  "pallet-treasury",
  "pallet-utility",
  "pallet-vesting",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-primitives",
  "polkadot-runtime-common",
  "rustc-hex",
@@ -7213,24 +7553,27 @@
  "sp-transaction-pool",
  "sp-version",
  "static_assertions",
- "substrate-wasm-builder 3.0.0",
+ "substrate-wasm-builder 4.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8)",
 ]
 
 [[package]]
 name = "polkadot-runtime-common"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "beefy-primitives",
  "bitvec 0.20.4",
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
- "impl-trait-for-tuples 0.2.1",
+ "impl-trait-for-tuples",
  "libsecp256k1 0.3.5",
  "log",
  "pallet-authorship",
+ "pallet-babe",
  "pallet-balances",
  "pallet-beefy",
+ "pallet-election-provider-multi-phase",
  "pallet-mmr",
  "pallet-offences",
  "pallet-session",
@@ -7239,7 +7582,7 @@
  "pallet-transaction-payment",
  "pallet-treasury",
  "pallet-vesting",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-primitives",
  "polkadot-runtime-parachains",
  "rustc-hex",
@@ -7260,13 +7603,15 @@
 
 [[package]]
 name = "polkadot-runtime-parachains"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "bitvec 0.20.4",
  "derive_more",
+ "frame-benchmarking",
  "frame-support",
  "frame-system",
+ "libsecp256k1 0.3.5",
  "log",
  "pallet-authority-discovery",
  "pallet-authorship",
@@ -7276,7 +7621,7 @@
  "pallet-staking",
  "pallet-timestamp",
  "pallet-vesting",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-primitives",
  "rand 0.8.4",
  "rand_chacha 0.3.1",
@@ -7297,14 +7642,16 @@
 
 [[package]]
 name = "polkadot-service"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
+ "async-trait",
  "beefy-gadget",
  "beefy-primitives",
  "frame-system-rpc-runtime-api",
- "futures 0.3.15",
+ "futures 0.3.16",
  "hex-literal",
+ "kusama-runtime",
  "kvdb",
  "kvdb-rocksdb",
  "pallet-babe",
@@ -7340,6 +7687,7 @@
  "polkadot-runtime",
  "polkadot-runtime-parachains",
  "polkadot-statement-distribution",
+ "rococo-runtime",
  "sc-authority-discovery",
  "sc-basic-authorship",
  "sc-block-builder",
@@ -7381,17 +7729,18 @@
  "substrate-prometheus-endpoint",
  "thiserror",
  "tracing",
+ "westend-runtime",
 ]
 
 [[package]]
 name = "polkadot-statement-distribution"
 version = "0.1.0"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "arrayvec 0.5.2",
- "futures 0.3.15",
+ "futures 0.3.16",
  "indexmap",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-node-network-protocol",
  "polkadot-node-primitives",
  "polkadot-node-subsystem",
@@ -7406,18 +7755,18 @@
 
 [[package]]
 name = "polkadot-statement-table"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-primitives",
  "sp-core",
 ]
 
 [[package]]
 name = "polkadot-test-runtime"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "beefy-primitives",
  "bitvec 0.20.4",
@@ -7436,7 +7785,6 @@
  "pallet-mmr-primitives",
  "pallet-nicks",
  "pallet-offences",
- "pallet-randomness-collective-flip",
  "pallet-session",
  "pallet-staking",
  "pallet-staking-reward-curve",
@@ -7445,7 +7793,7 @@
  "pallet-transaction-payment",
  "pallet-transaction-payment-rpc-runtime-api",
  "pallet-vesting",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-parachain",
  "polkadot-primitives",
  "polkadot-runtime-common",
@@ -7468,18 +7816,18 @@
  "sp-std",
  "sp-transaction-pool",
  "sp-version",
- "substrate-wasm-builder 3.0.0",
+ "substrate-wasm-builder 4.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8)",
 ]
 
 [[package]]
 name = "polkadot-test-service"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "frame-benchmarking",
  "frame-system",
  "futures 0.1.31",
- "futures 0.3.15",
+ "futures 0.3.16",
  "hex",
  "pallet-balances",
  "pallet-staking",
@@ -7565,28 +7913,15 @@
 
 [[package]]
 name = "primitive-types"
-version = "0.7.3"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dd39dcacf71411ba488570da7bbc89b717225e46478b30ba99b92db6b149809"
-dependencies = [
- "fixed-hash 0.6.1",
- "impl-codec 0.4.2",
- "impl-rlp 0.2.1",
- "impl-serde",
- "uint 0.8.5",
-]
-
-[[package]]
-name = "primitive-types"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2415937401cb030a2a0a4d922483f945fa068f52a7dbb22ce0fe5f2b6f6adace"
+checksum = "06345ee39fbccfb06ab45f3a1a5798d9dafa04cb8921a76d227040003a234b0e"
 dependencies = [
- "fixed-hash 0.7.0",
- "impl-codec 0.5.0",
- "impl-rlp 0.3.0",
+ "fixed-hash",
+ "impl-codec",
+ "impl-rlp",
  "impl-serde",
- "uint 0.9.0",
+ "uint",
 ]
 
 [[package]]
@@ -7646,9 +7981,9 @@
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.27"
+version = "1.0.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
+checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
 dependencies = [
  "unicode-xid",
 ]
@@ -7720,9 +8055,9 @@
 
 [[package]]
 name = "psm"
-version = "0.1.13"
+version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21ff0279b4a85e576b97e4a21d13e437ebcd56612706cde5d3f0d5c9399490c0"
+checksum = "14ce37fa8c0428a37307d163292add09b3aedc003472e6b3622486878404191d"
 dependencies = [
  "cc",
 ]
@@ -7772,9 +8107,9 @@
 
 [[package]]
 name = "radium"
-version = "0.3.0"
+version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac"
+checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
 
 [[package]]
 name = "radium"
@@ -8072,14 +8407,14 @@
 [[package]]
 name = "remote-externalities"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "env_logger 0.8.4",
  "hex",
  "jsonrpsee-proc-macros",
  "jsonrpsee-ws-client",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "serde_json",
  "sp-core",
@@ -8125,15 +8460,6 @@
  "untrusted",
  "web-sys",
  "winapi 0.3.9",
-]
-
-[[package]]
-name = "rlp"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1190dcc8c3a512f1eef5d09bb8c84c7f39e1054e174d1795482e18f5272f2e73"
-dependencies = [
- "rustc-hex",
 ]
 
 [[package]]
@@ -8168,6 +8494,73 @@
 ]
 
 [[package]]
+name = "rococo-runtime"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
+dependencies = [
+ "beefy-primitives",
+ "bp-rococo",
+ "bp-wococo",
+ "frame-executive",
+ "frame-support",
+ "frame-system",
+ "frame-system-rpc-runtime-api",
+ "hex-literal",
+ "log",
+ "max-encoded-len",
+ "pallet-authority-discovery",
+ "pallet-authorship",
+ "pallet-babe",
+ "pallet-balances",
+ "pallet-beefy",
+ "pallet-bridge-grandpa",
+ "pallet-collective",
+ "pallet-grandpa",
+ "pallet-im-online",
+ "pallet-indices",
+ "pallet-membership",
+ "pallet-mmr",
+ "pallet-mmr-primitives",
+ "pallet-offences",
+ "pallet-proxy",
+ "pallet-session",
+ "pallet-staking",
+ "pallet-staking-reward-curve",
+ "pallet-sudo",
+ "pallet-timestamp",
+ "pallet-transaction-payment",
+ "pallet-transaction-payment-rpc-runtime-api",
+ "pallet-utility",
+ "pallet-xcm",
+ "parity-scale-codec",
+ "polkadot-parachain",
+ "polkadot-primitives",
+ "polkadot-runtime-common",
+ "polkadot-runtime-parachains",
+ "serde",
+ "serde_derive",
+ "smallvec 1.6.1",
+ "sp-api",
+ "sp-authority-discovery",
+ "sp-block-builder",
+ "sp-consensus-babe",
+ "sp-core",
+ "sp-inherents",
+ "sp-io",
+ "sp-offchain",
+ "sp-runtime",
+ "sp-session",
+ "sp-staking",
+ "sp-std",
+ "sp-transaction-pool",
+ "sp-version",
+ "substrate-wasm-builder 4.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8)",
+ "xcm",
+ "xcm-builder",
+ "xcm-executor",
+]
+
+[[package]]
 name = "rpassword"
 version = "5.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -8179,9 +8572,9 @@
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.19"
+version = "0.1.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "410f7acf3cb3a44527c5d9546bad4bf4e6c460915d5f9f2fc524498bfe8f70ce"
+checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49"
 
 [[package]]
 name = "rustc-hash"
@@ -8205,6 +8598,15 @@
 ]
 
 [[package]]
+name = "rustc_version"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
+dependencies = [
+ "semver 0.11.0",
+]
+
+[[package]]
 name = "rustls"
 version = "0.18.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -8256,9 +8658,9 @@
 
 [[package]]
 name = "ruzstd"
-version = "0.2.2"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d425143485a37727c7a46e689bbe3b883a00f42b4a52c4ac0f44855c1009b00"
+checksum = "8cada0ef59efa6a5f4dc5e491f93d9f31e3fc7758df421ff1de8a706338e1100"
 dependencies = [
  "byteorder",
  "twox-hash",
@@ -8270,7 +8672,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "pin-project 0.4.28",
  "static_assertions",
 ]
@@ -8287,7 +8689,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6d3d055a2582e6b00ed7a31c1524040aa391092bf636328350813f3a0605215c"
 dependencies = [
- "rustc_version",
+ "rustc_version 0.2.3",
 ]
 
 [[package]]
@@ -8309,19 +8711,31 @@
 ]
 
 [[package]]
+name = "sc-allocator"
+version = "3.0.0"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
+dependencies = [
+ "log",
+ "sp-core",
+ "sp-std",
+ "sp-wasm-interface",
+ "thiserror",
+]
+
+[[package]]
 name = "sc-authority-discovery"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
  "derive_more",
  "either",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "ip_network",
  "libp2p",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "prost",
  "prost-build",
  "rand 0.7.3",
@@ -8340,12 +8754,12 @@
 [[package]]
 name = "sc-basic-authorship"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sc-block-builder",
  "sc-client-api",
  "sc-proposer-metrics",
@@ -8363,9 +8777,9 @@
 [[package]]
 name = "sc-block-builder"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sc-client-api",
  "sp-api",
  "sp-block-builder",
@@ -8379,10 +8793,10 @@
 [[package]]
 name = "sc-chain-spec"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "impl-trait-for-tuples 0.2.1",
- "parity-scale-codec 2.1.3",
+ "impl-trait-for-tuples",
+ "parity-scale-codec",
  "sc-chain-spec-derive",
  "sc-consensus-babe",
  "sc-consensus-epochs",
@@ -8391,7 +8805,6 @@
  "sc-telemetry",
  "serde",
  "serde_json",
- "sp-chain-spec",
  "sp-consensus-babe",
  "sp-core",
  "sp-runtime",
@@ -8400,7 +8813,7 @@
 [[package]]
 name = "sc-chain-spec-derive"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "proc-macro-crate 1.0.0",
  "proc-macro2",
@@ -8411,16 +8824,16 @@
 [[package]]
 name = "sc-cli"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "chrono",
  "fdlimit",
- "futures 0.3.15",
+ "futures 0.3.16",
  "hex",
  "libp2p",
  "log",
  "names",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "rand 0.7.3",
  "regex",
  "rpassword",
@@ -8449,16 +8862,16 @@
 [[package]]
 name = "sc-client-api"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "derive_more",
  "fnv",
- "futures 0.3.15",
+ "futures 0.3.16",
  "hash-db",
  "kvdb",
  "lazy_static",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "sc-executor",
  "sp-api",
@@ -8483,7 +8896,7 @@
 [[package]]
 name = "sc-client-db"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "blake2-rfc",
  "hash-db",
@@ -8493,7 +8906,7 @@
  "linked-hash-map",
  "log",
  "parity-db",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parity-util-mem",
  "parking_lot 0.11.1",
  "sc-client-api",
@@ -8513,8 +8926,9 @@
 [[package]]
 name = "sc-consensus"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
+ "async-trait",
  "parking_lot 0.11.1",
  "sc-client-api",
  "sp-blockchain",
@@ -8525,14 +8939,14 @@
 [[package]]
 name = "sc-consensus-aura"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
  "derive_more",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sc-block-builder",
  "sc-client-api",
  "sc-consensus-slots",
@@ -8556,19 +8970,19 @@
 [[package]]
 name = "sc-consensus-babe"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
  "derive_more",
  "fork-tree",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "log",
  "merlin",
  "num-bigint",
  "num-rational 0.2.4",
  "num-traits",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "pdqselect",
  "rand 0.7.3",
@@ -8602,10 +9016,10 @@
 [[package]]
 name = "sc-consensus-babe-rpc"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "derive_more",
- "futures 0.3.15",
+ "futures 0.3.16",
  "jsonrpc-core 15.1.0",
  "jsonrpc-core-client 15.1.0",
  "jsonrpc-derive 15.1.0",
@@ -8626,10 +9040,10 @@
 [[package]]
 name = "sc-consensus-epochs"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "fork-tree",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sc-client-api",
  "sc-consensus",
  "sp-blockchain",
@@ -8639,14 +9053,14 @@
 [[package]]
 name = "sc-consensus-slots"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
- "impl-trait-for-tuples 0.2.1",
+ "impl-trait-for-tuples",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sc-client-api",
  "sc-telemetry",
  "sp-api",
@@ -8667,7 +9081,7 @@
 [[package]]
 name = "sc-consensus-uncles"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "sc-client-api",
  "sp-authorship",
@@ -8678,13 +9092,13 @@
 [[package]]
 name = "sc-executor"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "derive_more",
  "lazy_static",
  "libsecp256k1 0.3.5",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parity-wasm 0.42.2",
  "parking_lot 0.11.1",
  "sc-executor-common",
@@ -8707,12 +9121,12 @@
 [[package]]
 name = "sc-executor-common"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "derive_more",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "pwasm-utils",
- "sp-allocator",
+ "sc-allocator",
  "sp-core",
  "sp-maybe-compressed-blob",
  "sp-serializer",
@@ -8724,12 +9138,12 @@
 [[package]]
 name = "sc-executor-wasmi"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
+ "sc-allocator",
  "sc-executor-common",
- "sp-allocator",
  "sp-core",
  "sp-runtime-interface",
  "sp-wasm-interface",
@@ -8739,14 +9153,16 @@
 [[package]]
 name = "sc-executor-wasmtime"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parity-wasm 0.42.2",
+ "sc-allocator",
  "sc-executor-common",
  "scoped-tls",
- "sp-allocator",
  "sp-core",
  "sp-runtime-interface",
  "sp-wasm-interface",
@@ -8756,20 +9172,20 @@
 [[package]]
 name = "sc-finality-grandpa"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
  "derive_more",
  "dyn-clone",
  "finality-grandpa",
  "fork-tree",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "linked-hash-map",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
- "pin-project 1.0.7",
+ "pin-project 1.0.8",
  "rand 0.7.3",
  "sc-block-builder",
  "sc-client-api",
@@ -8797,17 +9213,17 @@
 [[package]]
 name = "sc-finality-grandpa-rpc"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "derive_more",
  "finality-grandpa",
- "futures 0.3.15",
+ "futures 0.3.16",
  "jsonrpc-core 15.1.0",
  "jsonrpc-core-client 15.1.0",
  "jsonrpc-derive 15.1.0",
  "jsonrpc-pubsub 15.1.0",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sc-client-api",
  "sc-finality-grandpa",
  "sc-rpc",
@@ -8821,13 +9237,13 @@
 [[package]]
 name = "sc-finality-grandpa-warp-sync"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "derive_more",
- "futures 0.3.15",
+ "futures 0.3.16",
  "log",
  "num-traits",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "prost",
  "sc-client-api",
@@ -8842,10 +9258,10 @@
 [[package]]
 name = "sc-informant"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "ansi_term 0.12.1",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "log",
  "parity-util-mem",
@@ -8860,11 +9276,11 @@
 [[package]]
 name = "sc-keystore"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
  "derive_more",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-util",
  "hex",
  "merlin",
@@ -8874,17 +9290,17 @@
  "sp-application-crypto",
  "sp-core",
  "sp-keystore",
- "subtle 2.4.0",
+ "subtle 2.4.1",
 ]
 
 [[package]]
 name = "sc-light"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "hash-db",
  "lazy_static",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "sc-client-api",
  "sc-executor",
@@ -8899,7 +9315,7 @@
 [[package]]
 name = "sc-network"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-std",
  "async-trait",
@@ -8913,7 +9329,7 @@
  "erased-serde",
  "fnv",
  "fork-tree",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "hex",
  "ip_network",
@@ -8923,9 +9339,9 @@
  "log",
  "lru",
  "nohash-hasher",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
- "pin-project 1.0.7",
+ "pin-project 1.0.8",
  "prost",
  "prost-build",
  "rand 0.7.3",
@@ -8952,9 +9368,9 @@
 [[package]]
 name = "sc-network-gossip"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "libp2p",
  "log",
@@ -8969,18 +9385,18 @@
 [[package]]
 name = "sc-offchain"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "bytes 0.5.6",
  "fnv",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "hex",
  "hyper 0.13.10",
  "hyper-rustls",
  "log",
  "num_cpus",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "rand 0.7.3",
  "sc-client-api",
@@ -8997,9 +9413,9 @@
 [[package]]
 name = "sc-peerset"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "libp2p",
  "log",
  "serde_json",
@@ -9010,7 +9426,7 @@
 [[package]]
 name = "sc-proposer-metrics"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "log",
  "substrate-prometheus-endpoint",
@@ -9019,16 +9435,17 @@
 [[package]]
 name = "sc-rpc"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "hash-db",
  "jsonrpc-core 15.1.0",
  "jsonrpc-pubsub 15.1.0",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "sc-block-builder",
+ "sc-chain-spec",
  "sc-client-api",
  "sc-executor",
  "sc-keystore",
@@ -9037,7 +9454,6 @@
  "serde_json",
  "sp-api",
  "sp-blockchain",
- "sp-chain-spec",
  "sp-core",
  "sp-keystore",
  "sp-offchain",
@@ -9054,20 +9470,20 @@
 [[package]]
 name = "sc-rpc-api"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "derive_more",
- "futures 0.3.15",
+ "futures 0.3.16",
  "jsonrpc-core 15.1.0",
  "jsonrpc-core-client 15.1.0",
  "jsonrpc-derive 15.1.0",
  "jsonrpc-pubsub 15.1.0",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
+ "sc-chain-spec",
  "serde",
  "serde_json",
- "sp-chain-spec",
  "sp-core",
  "sp-rpc",
  "sp-runtime",
@@ -9079,7 +9495,7 @@
 [[package]]
 name = "sc-rpc-server"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "futures 0.1.31",
  "jsonrpc-core 15.1.0",
@@ -9097,23 +9513,23 @@
 [[package]]
 name = "sc-service"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
  "directories",
  "exit-future",
  "futures 0.1.31",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "hash-db",
  "jsonrpc-core 15.1.0",
  "jsonrpc-pubsub 15.1.0",
  "lazy_static",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parity-util-mem",
  "parking_lot 0.11.1",
- "pin-project 1.0.7",
+ "pin-project 1.0.8",
  "rand 0.7.3",
  "sc-block-builder",
  "sc-chain-spec",
@@ -9145,6 +9561,7 @@
  "sp-runtime",
  "sp-session",
  "sp-state-machine",
+ "sp-storage",
  "sp-tracing",
  "sp-transaction-pool",
  "sp-transaction-storage-proof",
@@ -9162,10 +9579,10 @@
 [[package]]
 name = "sc-state-db"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parity-util-mem",
  "parity-util-mem-derive",
  "parking_lot 0.11.1",
@@ -9177,7 +9594,7 @@
 [[package]]
 name = "sc-sync-state-rpc"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "jsonrpc-core 15.1.0",
  "jsonrpc-core-client 15.1.0",
@@ -9197,14 +9614,14 @@
 [[package]]
 name = "sc-telemetry"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "chrono",
- "futures 0.3.15",
+ "futures 0.3.16",
  "libp2p",
  "log",
  "parking_lot 0.11.1",
- "pin-project 1.0.7",
+ "pin-project 1.0.8",
  "rand 0.7.3",
  "serde",
  "serde_json",
@@ -9217,7 +9634,7 @@
 [[package]]
 name = "sc-tracing"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "ansi_term 0.12.1",
  "atty",
@@ -9254,7 +9671,7 @@
 [[package]]
 name = "sc-tracing-proc-macro"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "proc-macro-crate 1.0.0",
  "proc-macro2",
@@ -9265,10 +9682,10 @@
 [[package]]
 name = "sc-transaction-graph"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "derive_more",
- "futures 0.3.15",
+ "futures 0.3.16",
  "linked-hash-map",
  "log",
  "parity-util-mem",
@@ -9287,12 +9704,12 @@
 [[package]]
 name = "sc-transaction-pool"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "intervalier",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parity-util-mem",
  "parking_lot 0.11.1",
  "sc-client-api",
@@ -9327,13 +9744,13 @@
 dependencies = [
  "arrayref",
  "arrayvec 0.5.2",
- "curve25519-dalek 2.1.2",
+ "curve25519-dalek 2.1.3",
  "getrandom 0.1.16",
  "merlin",
  "rand 0.7.3",
  "rand_core 0.5.1",
  "sha2 0.8.2",
- "subtle 2.4.0",
+ "subtle 2.4.1",
  "zeroize",
 ]
 
@@ -9380,24 +9797,6 @@
 ]
 
 [[package]]
-name = "secp256k1"
-version = "0.19.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6179428c22c73ac0fbb7b5579a56353ce78ba29759b3b8575183336ea74cdfb"
-dependencies = [
- "secp256k1-sys",
-]
-
-[[package]]
-name = "secp256k1-sys"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11553d210db090930f4432bea123b31f70bbf693ace14504ea2a35e796c28dd2"
-dependencies = [
- "cc",
-]
-
-[[package]]
 name = "secrecy"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -9540,9 +9939,9 @@
 
 [[package]]
 name = "sha-1"
-version = "0.9.6"
+version = "0.9.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c4cfa741c5832d0ef7fab46cabed29c2aae926db0b11bb2069edd8db5e64e16"
+checksum = "1a0c8611594e2ab4ebbf06ec7cbbf0a99450b8570e96cbf5188b5d5f6ef18d81"
 dependencies = [
  "block-buffer 0.9.0",
  "cfg-if 1.0.0",
@@ -9612,9 +10011,9 @@
 
 [[package]]
 name = "shlex"
-version = "0.1.1"
+version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
+checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d"
 
 [[package]]
 name = "signal-hook"
@@ -9637,21 +10036,9 @@
 
 [[package]]
 name = "signature"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f0242b8e50dd9accdd56170e94ca1ebd223b098eb9c83539a6e367d0f36ae68"
-
-[[package]]
-name = "simba"
-version = "0.4.0"
+version = "1.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5132a955559188f3d13c9ba831e77c802ddc8782783f050ed0c52f5988b95f4c"
-dependencies = [
- "approx 0.4.0",
- "num-complex 0.3.1",
- "num-traits",
- "paste",
-]
+checksum = "c19772be3c4dd2ceaacf03cb41d5885f2a02c4d8804884918e3a258480803335"
 
 [[package]]
 name = "simba"
@@ -9659,8 +10046,8 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e82063457853d00243beda9952e910b82593e4b07ae9f721b9278a99a0d3d5c"
 dependencies = [
- "approx 0.5.0",
- "num-complex 0.4.0",
+ "approx",
+ "num-complex",
  "num-traits",
  "paste",
 ]
@@ -9682,11 +10069,11 @@
 
 [[package]]
 name = "slot-range-helper"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "enumn",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "paste",
  "sp-runtime",
  "sp-std",
@@ -9694,9 +10081,9 @@
 
 [[package]]
 name = "slotmap"
-version = "1.0.3"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "585cd5dffe4e9e06f6dfdf66708b70aca3f781bed561f4f667b2d9c0d4559e36"
+checksum = "a952280edbecfb1d4bd3cf2dbc309dc6ab523e53487c438ae21a6df09fe84bc4"
 dependencies = [
  "version_check",
 ]
@@ -9728,9 +10115,9 @@
  "rand 0.7.3",
  "rand_core 0.5.1",
  "ring",
- "rustc_version",
+ "rustc_version 0.2.3",
  "sha2 0.9.5",
- "subtle 2.4.0",
+ "subtle 2.4.1",
  "x25519-dalek",
 ]
 
@@ -9764,11 +10151,11 @@
  "base64 0.12.3",
  "bytes 0.5.6",
  "flate2",
- "futures 0.3.15",
+ "futures 0.3.16",
  "httparse",
  "log",
  "rand 0.7.3",
- "sha-1 0.9.6",
+ "sha-1 0.9.7",
 ]
 
 [[package]]
@@ -9779,33 +10166,21 @@
 dependencies = [
  "base64 0.13.0",
  "bytes 1.0.1",
- "futures 0.3.15",
+ "futures 0.3.16",
  "httparse",
  "log",
  "rand 0.8.4",
- "sha-1 0.9.6",
-]
-
-[[package]]
-name = "sp-allocator"
-version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
-dependencies = [
- "log",
- "sp-core",
- "sp-std",
- "sp-wasm-interface",
- "thiserror",
+ "sha-1 0.9.7",
 ]
 
 [[package]]
 name = "sp-api"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "hash-db",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-api-proc-macro",
  "sp-core",
  "sp-runtime",
@@ -9818,7 +10193,7 @@
 [[package]]
 name = "sp-api-proc-macro"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "blake2-rfc",
  "proc-macro-crate 1.0.0",
@@ -9830,10 +10205,10 @@
 [[package]]
 name = "sp-application-crypto"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "max-encoded-len",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-core",
  "sp-io",
@@ -9843,11 +10218,11 @@
 [[package]]
 name = "sp-arithmetic"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "integer-sqrt",
  "num-traits",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-debug-derive",
  "sp-std",
@@ -9857,9 +10232,9 @@
 [[package]]
 name = "sp-authority-discovery"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-api",
  "sp-application-crypto",
  "sp-runtime",
@@ -9869,10 +10244,10 @@
 [[package]]
 name = "sp-authorship"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-inherents",
  "sp-runtime",
  "sp-std",
@@ -9881,9 +10256,9 @@
 [[package]]
 name = "sp-block-builder"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-api",
  "sp-inherents",
  "sp-runtime",
@@ -9893,12 +10268,12 @@
 [[package]]
 name = "sp-blockchain"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "log",
  "lru",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "sp-api",
  "sp-consensus",
@@ -9909,25 +10284,16 @@
 ]
 
 [[package]]
-name = "sp-chain-spec"
-version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
-dependencies = [
- "serde",
- "serde_json",
-]
-
-[[package]]
 name = "sp-consensus"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-timer 3.0.2",
  "libp2p",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "serde",
  "sp-api",
@@ -9947,10 +10313,10 @@
 [[package]]
 name = "sp-consensus-aura"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-api",
  "sp-application-crypto",
  "sp-consensus",
@@ -9964,11 +10330,11 @@
 [[package]]
 name = "sp-consensus-babe"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
  "merlin",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-api",
  "sp-application-crypto",
@@ -9986,9 +10352,9 @@
 [[package]]
 name = "sp-consensus-slots"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-arithmetic",
  "sp-runtime",
 ]
@@ -9996,9 +10362,9 @@
 [[package]]
 name = "sp-consensus-vrf"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "schnorrkel",
  "sp-core",
  "sp-runtime",
@@ -10008,14 +10374,14 @@
 [[package]]
 name = "sp-core"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "base58",
  "blake2-rfc",
  "byteorder",
  "dyn-clonable",
  "ed25519-dalek",
- "futures 0.3.15",
+ "futures 0.3.16",
  "hash-db",
  "hash256-std-hasher",
  "hex",
@@ -10026,10 +10392,10 @@
  "max-encoded-len",
  "merlin",
  "num-traits",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parity-util-mem",
  "parking_lot 0.11.1",
- "primitive-types 0.9.0",
+ "primitive-types",
  "rand 0.7.3",
  "regex",
  "schnorrkel",
@@ -10053,7 +10419,7 @@
 [[package]]
 name = "sp-database"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "kvdb",
  "parking_lot 0.11.1",
@@ -10062,7 +10428,7 @@
 [[package]]
 name = "sp-debug-derive"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -10072,10 +10438,10 @@
 [[package]]
 name = "sp-externalities"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "environmental",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-std",
  "sp-storage",
 ]
@@ -10083,11 +10449,11 @@
 [[package]]
 name = "sp-finality-grandpa"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "finality-grandpa",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-api",
  "sp-application-crypto",
@@ -10100,11 +10466,11 @@
 [[package]]
 name = "sp-inherents"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
- "impl-trait-for-tuples 0.2.1",
- "parity-scale-codec 2.1.3",
+ "impl-trait-for-tuples",
+ "parity-scale-codec",
  "sp-core",
  "sp-runtime",
  "sp-std",
@@ -10114,13 +10480,13 @@
 [[package]]
 name = "sp-io"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "hash-db",
  "libsecp256k1 0.3.5",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "sp-core",
  "sp-externalities",
@@ -10139,7 +10505,7 @@
 [[package]]
 name = "sp-keyring"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "lazy_static",
  "sp-core",
@@ -10150,13 +10516,13 @@
 [[package]]
 name = "sp-keystore"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
  "derive_more",
- "futures 0.3.15",
+ "futures 0.3.16",
  "merlin",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "schnorrkel",
  "serde",
@@ -10167,7 +10533,7 @@
 [[package]]
 name = "sp-maybe-compressed-blob"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "ruzstd",
  "zstd",
@@ -10176,9 +10542,9 @@
 [[package]]
 name = "sp-npos-elections"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-arithmetic",
  "sp-core",
@@ -10189,7 +10555,7 @@
 [[package]]
 name = "sp-npos-elections-compact"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "proc-macro-crate 1.0.0",
  "proc-macro2",
@@ -10200,7 +10566,7 @@
 [[package]]
 name = "sp-offchain"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "sp-api",
  "sp-core",
@@ -10210,7 +10576,7 @@
 [[package]]
 name = "sp-panic-handler"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "backtrace",
 ]
@@ -10218,7 +10584,7 @@
 [[package]]
 name = "sp-rpc"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "rustc-hash",
  "serde",
@@ -10229,14 +10595,14 @@
 [[package]]
 name = "sp-runtime"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "either",
  "hash256-std-hasher",
- "impl-trait-for-tuples 0.2.1",
+ "impl-trait-for-tuples",
  "log",
  "max-encoded-len",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parity-util-mem",
  "paste",
  "rand 0.7.3",
@@ -10251,11 +10617,11 @@
 [[package]]
 name = "sp-runtime-interface"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "impl-trait-for-tuples 0.2.1",
- "parity-scale-codec 2.1.3",
- "primitive-types 0.9.0",
+ "impl-trait-for-tuples",
+ "parity-scale-codec",
+ "primitive-types",
  "sp-externalities",
  "sp-runtime-interface-proc-macro",
  "sp-std",
@@ -10268,7 +10634,7 @@
 [[package]]
 name = "sp-runtime-interface-proc-macro"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "Inflector",
  "proc-macro-crate 1.0.0",
@@ -10280,9 +10646,9 @@
 [[package]]
 name = "sp-sandbox"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-core",
  "sp-io",
  "sp-std",
@@ -10293,7 +10659,7 @@
 [[package]]
 name = "sp-serializer"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "serde",
  "serde_json",
@@ -10302,9 +10668,9 @@
 [[package]]
 name = "sp-session"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-api",
  "sp-core",
  "sp-runtime",
@@ -10315,9 +10681,9 @@
 [[package]]
 name = "sp-staking"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-runtime",
  "sp-std",
 ]
@@ -10325,12 +10691,12 @@
 [[package]]
 name = "sp-state-machine"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "hash-db",
  "log",
  "num-traits",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.11.1",
  "rand 0.7.3",
  "smallvec 1.6.1",
@@ -10348,15 +10714,15 @@
 [[package]]
 name = "sp-std"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 
 [[package]]
 name = "sp-storage"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "impl-serde",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "ref-cast",
  "serde",
  "sp-debug-derive",
@@ -10366,7 +10732,7 @@
 [[package]]
 name = "sp-tasks"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "log",
  "sp-core",
@@ -10379,12 +10745,12 @@
 [[package]]
 name = "sp-timestamp"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
  "futures-timer 3.0.2",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-api",
  "sp-inherents",
  "sp-runtime",
@@ -10396,11 +10762,11 @@
 [[package]]
 name = "sp-tracing"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "erased-serde",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "parking_lot 0.10.2",
  "serde",
  "serde_json",
@@ -10414,12 +10780,12 @@
 [[package]]
 name = "sp-transaction-pool"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "derive_more",
- "futures 0.3.15",
+ "futures 0.3.16",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-api",
  "sp-blockchain",
@@ -10430,11 +10796,11 @@
 [[package]]
 name = "sp-transaction-storage-proof"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-core",
  "sp-inherents",
  "sp-runtime",
@@ -10445,11 +10811,11 @@
 [[package]]
 name = "sp-trie"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "hash-db",
  "memory-db",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-core",
  "sp-std",
  "trie-db",
@@ -10459,9 +10825,9 @@
 [[package]]
 name = "sp-utils"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "futures-core",
  "futures-timer 3.0.2",
  "lazy_static",
@@ -10471,10 +10837,10 @@
 [[package]]
 name = "sp-version"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "impl-serde",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "serde",
  "sp-runtime",
  "sp-std",
@@ -10484,9 +10850,9 @@
 [[package]]
 name = "sp-version-proc-macro"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "proc-macro-crate 1.0.0",
  "proc-macro2",
  "quote",
@@ -10496,10 +10862,10 @@
 [[package]]
 name = "sp-wasm-interface"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "impl-trait-for-tuples 0.2.1",
- "parity-scale-codec 2.1.3",
+ "impl-trait-for-tuples",
+ "parity-scale-codec",
  "sp-std",
  "wasmi",
 ]
@@ -10549,13 +10915,13 @@
 
 [[package]]
 name = "statrs"
-version = "0.14.0"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e0c1f144861fbfd2a8cc82d564ccbf7fb3b7834d4fa128b84e9c2a73371aead"
+checksum = "05bdbb8e4e78216a85785a85d3ec3183144f98d0097b9281802c019bb07a6f05"
 dependencies = [
- "approx 0.4.0",
+ "approx",
  "lazy_static",
- "nalgebra 0.26.2",
+ "nalgebra",
  "num-traits",
  "rand 0.8.4",
 ]
@@ -10571,18 +10937,6 @@
 ]
 
 [[package]]
-name = "streamunordered"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e68576e37c8a37f5372796df15202190349dd80e7ed6a79544c0232213e90e35"
-dependencies = [
- "futures-core",
- "futures-sink",
- "futures-util",
- "slab",
-]
-
-[[package]]
 name = "string"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -10605,9 +10959,9 @@
 
 [[package]]
 name = "structopt"
-version = "0.3.21"
+version = "0.3.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c"
+checksum = "69b041cdcb67226aca307e6e7be44c8806423d83e018bd662360a93dabce4d71"
 dependencies = [
  "clap",
  "lazy_static",
@@ -10616,9 +10970,9 @@
 
 [[package]]
 name = "structopt-derive"
-version = "0.4.14"
+version = "0.4.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90"
+checksum = "7813934aecf5f51a54775e00068c237de98489463968231a51746bbbc03f9c10"
 dependencies = [
  "heck",
  "proc-macro-error",
@@ -10664,7 +11018,7 @@
 [[package]]
 name = "substrate-build-script-utils"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "platforms",
 ]
@@ -10672,15 +11026,15 @@
 [[package]]
 name = "substrate-frame-rpc-system"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-system-rpc-runtime-api",
- "futures 0.3.15",
+ "futures 0.3.16",
  "jsonrpc-core 15.1.0",
  "jsonrpc-core-client 15.1.0",
  "jsonrpc-derive 15.1.0",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sc-client-api",
  "sc-rpc-api",
  "serde",
@@ -10695,7 +11049,7 @@
 [[package]]
 name = "substrate-prometheus-endpoint"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-std",
  "derive_more",
@@ -10709,14 +11063,14 @@
 [[package]]
 name = "substrate-test-client"
 version = "2.0.1"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "async-trait",
  "futures 0.1.31",
- "futures 0.3.15",
+ "futures 0.3.16",
  "hash-db",
  "hex",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sc-client-api",
  "sc-client-db",
  "sc-consensus",
@@ -10738,9 +11092,9 @@
 [[package]]
 name = "substrate-test-utils"
 version = "3.0.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "substrate-test-utils-derive",
  "tokio 0.2.25",
 ]
@@ -10748,7 +11102,7 @@
 [[package]]
 name = "substrate-test-utils-derive"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "proc-macro-crate 1.0.0",
  "quote",
@@ -10757,14 +11111,14 @@
 
 [[package]]
 name = "substrate-wasm-builder"
-version = "3.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79091baab813855ddf65b191de9fe53e656b6b67c1e9bd23fdcbff8788164684"
+version = "4.0.0"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "ansi_term 0.12.1",
  "atty",
  "build-helper",
- "cargo_metadata",
+ "cargo_metadata 0.13.1",
+ "sp-maybe-compressed-blob",
  "tempfile",
  "toml",
  "walkdir",
@@ -10780,7 +11134,7 @@
  "ansi_term 0.12.1",
  "atty",
  "build-helper",
- "cargo_metadata",
+ "cargo_metadata 0.12.3",
  "tempfile",
  "toml",
  "walkdir",
@@ -10795,15 +11149,15 @@
 
 [[package]]
 name = "subtle"
-version = "2.4.0"
+version = "2.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
 
 [[package]]
 name = "syn"
-version = "1.0.73"
+version = "1.0.74"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
+checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -10812,9 +11166,9 @@
 
 [[package]]
 name = "synstructure"
-version = "0.12.4"
+version = "0.12.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
+checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -10836,9 +11190,9 @@
 
 [[package]]
 name = "target-lexicon"
-version = "0.12.0"
+version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64ae3b39281e4b14b8123bdbaddd472b7dfe215e444181f2f9d2443c2444f834"
+checksum = "b0652da4c4121005e9ed22b79f6c5f2d9e2752906b53a33e9490489ba421a6fb"
 
 [[package]]
 name = "tempfile"
@@ -10874,18 +11228,18 @@
 
 [[package]]
 name = "thiserror"
-version = "1.0.25"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6"
+checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.25"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d"
+checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -10963,9 +11317,9 @@
 
 [[package]]
 name = "tinyvec"
-version = "1.2.0"
+version = "1.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342"
+checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338"
 dependencies = [
  "tinyvec_macros",
 ]
@@ -11025,12 +11379,12 @@
 
 [[package]]
 name = "tokio"
-version = "1.8.1"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98c8b05dc14c75ea83d63dd391100353789f5f24b8b3866542a5e85c8be8e985"
+checksum = "4b7b349f11a7047e6d1276853e612d152f5e8a352c61917887cc2169e2366b4c"
 dependencies = [
  "autocfg",
- "pin-project-lite 0.2.6",
+ "pin-project-lite 0.2.7",
 ]
 
 [[package]]
@@ -11297,7 +11651,7 @@
 dependencies = [
  "cfg-if 1.0.0",
  "log",
- "pin-project-lite 0.2.6",
+ "pin-project-lite 0.2.7",
  "tracing-attributes",
  "tracing-core",
 ]
@@ -11328,7 +11682,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
 dependencies = [
- "pin-project 1.0.7",
+ "pin-project 1.0.8",
  "tracing",
 ]
 
@@ -11355,9 +11709,9 @@
 
 [[package]]
 name = "tracing-subscriber"
-version = "0.2.18"
+version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa5553bf0883ba7c9cbe493b085c29926bd41b66afc31ff72cf17ff4fb60dcd5"
+checksum = "ab69019741fca4d98be3c62d2b75254528b5432233fd8a4d2739fec20278de48"
 dependencies = [
  "ansi_term 0.12.1",
  "chrono",
@@ -11377,12 +11731,12 @@
 
 [[package]]
 name = "trie-db"
-version = "0.22.5"
+version = "0.22.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd81fe0c8bc2b528a51c9d2c31dae4483367a26a723a3c9a4a8120311d7774e3"
+checksum = "9eac131e334e81b6b3be07399482042838adcd7957aa0010231d0813e39e02fa"
 dependencies = [
  "hash-db",
- "hashbrown",
+ "hashbrown 0.11.2",
  "log",
  "rustc-hex",
  "smallvec 1.6.1",
@@ -11404,7 +11758,7 @@
 checksum = "a1631b201eb031b563d2e85ca18ec8092508e262a3196ce9bd10a67ec87b9f5c"
 dependencies = [
  "hash-db",
- "rlp 0.5.0",
+ "rlp",
 ]
 
 [[package]]
@@ -11459,11 +11813,11 @@
 [[package]]
 name = "try-runtime-cli"
 version = "0.9.0"
-source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.7#9c572625f6557dfdb19f47474369a0327d51dfbc"
+source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8#74101dc21cfffb4c2d014fcc28edc166d5ca1b16"
 dependencies = [
  "frame-try-runtime",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "remote-externalities",
  "sc-chain-spec",
  "sc-cli",
@@ -11475,6 +11829,7 @@
  "sp-blockchain",
  "sp-core",
  "sp-externalities",
+ "sp-io",
  "sp-keystore",
  "sp-runtime",
  "sp-state-machine",
@@ -11488,7 +11843,7 @@
 checksum = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59"
 dependencies = [
  "cfg-if 0.1.10",
- "rand 0.3.23",
+ "rand 0.7.3",
  "static_assertions",
 ]
 
@@ -11506,21 +11861,9 @@
 
 [[package]]
 name = "uint"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9db035e67dfaf7edd9aebfe8676afcd63eed53c8a4044fed514c8cccf1835177"
-dependencies = [
- "byteorder",
- "crunchy",
- "rustc-hex",
- "static_assertions",
-]
-
-[[package]]
-name = "uint"
-version = "0.9.0"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e11fe9a9348741cf134085ad57c249508345fe16411b3d7fb4ff2da2f1d6382e"
+checksum = "6470ab50f482bde894a037a57064480a246dbfdd5960bd65a44824693f08da5f"
 dependencies = [
  "byteorder",
  "crunchy",
@@ -11557,9 +11900,9 @@
 
 [[package]]
 name = "unicode-segmentation"
-version = "1.7.1"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
+checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
 
 [[package]]
 name = "unicode-width"
@@ -11575,12 +11918,12 @@
 
 [[package]]
 name = "universal-hash"
-version = "0.4.0"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402"
+checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
 dependencies = [
  "generic-array 0.14.4",
- "subtle 2.4.0",
+ "subtle 2.4.1",
 ]
 
 [[package]]
@@ -11623,7 +11966,7 @@
 name = "up-sponsorship"
 version = "0.1.0"
 dependencies = [
- "impl-trait-for-tuples 0.2.1",
+ "impl-trait-for-tuples",
 ]
 
 [[package]]
@@ -11661,9 +12004,9 @@
 
 [[package]]
 name = "vcpkg"
-version = "0.2.14"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70455df2fdf4e9bf580a92e443f1eb0303c390d682e2ea817312c9e81f8c3399"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
 
 [[package]]
 name = "vec_map"
@@ -11816,7 +12159,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "js-sys",
  "parking_lot 0.11.1",
  "pin-utils",
@@ -11931,7 +12274,7 @@
 checksum = "c5d2a763e7a6fc734218e0e463196762a4f409c483063d81e0e85f96343b2e0a"
 dependencies = [
  "anyhow",
- "gimli",
+ "gimli 0.24.0",
  "more-asserts",
  "object 0.24.0",
  "target-lexicon",
@@ -11950,7 +12293,7 @@
  "cranelift-codegen",
  "cranelift-entity",
  "cranelift-wasm",
- "gimli",
+ "gimli 0.24.0",
  "indexmap",
  "log",
  "more-asserts",
@@ -11976,7 +12319,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4d4539ea734422b7c868107e2187d7746d8affbcaa71916d72639f53757ad707"
 dependencies = [
- "addr2line",
+ "addr2line 0.15.2",
  "anyhow",
  "cfg-if 1.0.0",
  "cranelift-codegen",
@@ -11984,7 +12327,7 @@
  "cranelift-frontend",
  "cranelift-native",
  "cranelift-wasm",
- "gimli",
+ "gimli 0.24.0",
  "log",
  "more-asserts",
  "object 0.24.0",
@@ -12025,7 +12368,7 @@
 dependencies = [
  "anyhow",
  "cfg-if 1.0.0",
- "gimli",
+ "gimli 0.24.0",
  "lazy_static",
  "libc",
  "object 0.24.0",
@@ -12118,6 +12461,89 @@
 ]
 
 [[package]]
+name = "westend-runtime"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
+dependencies = [
+ "beefy-primitives",
+ "bitvec 0.20.4",
+ "frame-benchmarking",
+ "frame-election-provider-support",
+ "frame-executive",
+ "frame-support",
+ "frame-system",
+ "frame-system-benchmarking",
+ "frame-system-rpc-runtime-api",
+ "frame-try-runtime",
+ "hex-literal",
+ "log",
+ "max-encoded-len",
+ "pallet-authority-discovery",
+ "pallet-authorship",
+ "pallet-babe",
+ "pallet-balances",
+ "pallet-collective",
+ "pallet-democracy",
+ "pallet-election-provider-multi-phase",
+ "pallet-elections-phragmen",
+ "pallet-grandpa",
+ "pallet-identity",
+ "pallet-im-online",
+ "pallet-indices",
+ "pallet-membership",
+ "pallet-mmr-primitives",
+ "pallet-multisig",
+ "pallet-nicks",
+ "pallet-offences",
+ "pallet-offences-benchmarking",
+ "pallet-proxy",
+ "pallet-recovery",
+ "pallet-scheduler 3.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8)",
+ "pallet-session",
+ "pallet-session-benchmarking",
+ "pallet-society",
+ "pallet-staking",
+ "pallet-staking-reward-curve",
+ "pallet-sudo",
+ "pallet-timestamp",
+ "pallet-transaction-payment",
+ "pallet-transaction-payment-rpc-runtime-api",
+ "pallet-treasury",
+ "pallet-utility",
+ "pallet-vesting",
+ "pallet-xcm",
+ "parity-scale-codec",
+ "polkadot-parachain",
+ "polkadot-primitives",
+ "polkadot-runtime-common",
+ "polkadot-runtime-parachains",
+ "rustc-hex",
+ "serde",
+ "serde_derive",
+ "smallvec 1.6.1",
+ "sp-api",
+ "sp-authority-discovery",
+ "sp-block-builder",
+ "sp-consensus-babe",
+ "sp-core",
+ "sp-inherents",
+ "sp-io",
+ "sp-npos-elections",
+ "sp-offchain",
+ "sp-runtime",
+ "sp-session",
+ "sp-staking",
+ "sp-std",
+ "sp-transaction-pool",
+ "sp-version",
+ "static_assertions",
+ "substrate-wasm-builder 4.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.8)",
+ "xcm",
+ "xcm-builder",
+ "xcm-executor",
+]
+
+[[package]]
 name = "which"
 version = "4.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -12214,24 +12640,24 @@
 
 [[package]]
 name = "xcm"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "derivative",
- "impl-trait-for-tuples 0.2.1",
- "parity-scale-codec 2.1.3",
+ "impl-trait-for-tuples",
+ "parity-scale-codec",
 ]
 
 [[package]]
 name = "xcm-builder"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "frame-support",
  "frame-system",
- "impl-trait-for-tuples 0.2.1",
+ "impl-trait-for-tuples",
  "pallet-transaction-payment",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "polkadot-parachain",
  "sp-arithmetic",
  "sp-io",
@@ -12243,13 +12669,13 @@
 
 [[package]]
 name = "xcm-executor"
-version = "0.9.7"
-source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.7#5d35bac7408a4cb12a578764217d06f3920b36aa"
+version = "0.9.8"
+source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.8#3a10ee63c0b5703a1c802db3438ab7e01344a8ce"
 dependencies = [
  "frame-support",
- "impl-trait-for-tuples 0.2.1",
+ "impl-trait-for-tuples",
  "log",
- "parity-scale-codec 2.1.3",
+ "parity-scale-codec",
  "sp-arithmetic",
  "sp-core",
  "sp-io",
@@ -12264,7 +12690,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e7d9028f208dd5e63c614be69f115c1b53cacc1111437d4c765185856666c107"
 dependencies = [
- "futures 0.3.15",
+ "futures 0.3.16",
  "log",
  "nohash-hasher",
  "parking_lot 0.11.1",
@@ -12280,9 +12706,9 @@
 
 [[package]]
 name = "zeroize"
-version = "1.3.0"
+version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd"
+checksum = "377db0846015f7ae377174787dd452e1c5f5a9050bc6f954911d01f116daa0cd"
 dependencies = [
  "zeroize_derive",
 ]
modifiedCargo.tomldiffbeforeafterboth
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,8 +5,7 @@
     'pallets/*',
     'primitives/*',
     'runtime',
-    'crates/evm-coder',
-    'crates/evm-coder-macros',
+    'crates/*',
 ]
 [profile.release]
 panic = 'unwind'
addedMakefilediffbeforeafterboth
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,43 @@
+.PHONY: _eth_codegen
+_eth_codegen:
+
+.PHONY: regenerate_solidity
+regenerate_solidity:
+	PACKAGE=pallet-nft NAME=eth::erc::fungible_iface OUTPUT=./tests/src/eth/api/UniqueFungible.sol ./.maintain/scripts/generate_api.sh
+	PACKAGE=pallet-nft NAME=eth::erc::nft_iface OUTPUT=./tests/src/eth/api/UniqueNFT.sol ./.maintain/scripts/generate_api.sh
+	PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_iface OUTPUT=./tests/src/eth/api/ContractHelpers.sol ./.maintain/scripts/generate_api.sh
+
+	PACKAGE=pallet-nft NAME=eth::erc::fungible_impl OUTPUT=./pallets/nft/src/eth/stubs/UniqueFungible.sol ./.maintain/scripts/generate_api.sh
+	PACKAGE=pallet-nft NAME=eth::erc::nft_impl OUTPUT=./pallets/nft/src/eth/stubs/UniqueNFT.sol ./.maintain/scripts/generate_api.sh
+	PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_impl OUTPUT=./pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol ./.maintain/scripts/generate_api.sh
+
+NFT_EVM_STUBS=./pallets/nft/src/eth/stubs
+CONTRACT_HELPERS_STUBS=./pallets/evm-contract-helpers/src/stubs/
+
+$(NFT_EVM_STUBS)/UniqueFungible.raw: $(NFT_EVM_STUBS)/UniqueFungible.sol
+	INPUT=$< OUTPUT=$@ ./.maintain/scripts/compile_stub.sh
+$(NFT_EVM_STUBS)/UniqueNFT.raw: $(NFT_EVM_STUBS)/UniqueNFT.sol
+	INPUT=$< OUTPUT=$@ ./.maintain/scripts/compile_stub.sh
+$(CONTRACT_HELPERS_STUBS)/ContractHelpers.raw: $(CONTRACT_HELPERS_STUBS)/ContractHelpers.sol
+	INPUT=$< OUTPUT=$@ ./.maintain/scripts/compile_stub.sh
+
+evm_stubs: $(NFT_EVM_STUBS)/UniqueFungible.raw $(NFT_EVM_STUBS)/UniqueNFT.raw $(CONTRACT_HELPERS_STUBS)/ContractHelpers.raw
+
+.PHONY: _bench
+_bench:
+	cargo run --release --features runtime-benchmarks -- \
+	benchmark --pallet pallet-$(PALLET) \
+	--wasm-execution compiled --extrinsic '*' \
+	--template .maintain/frame-weight-template.hbs --steps=50 --repeat=20 \
+	--output=./pallets/$(PALLET)/src/weights.rs
+
+.PHONY: bench-evm-migration
+bench-evm-migration:
+	make _bench PALLET=evm-migration
+
+.PHONY: bench-nft
+bench-nft:
+	make _bench PALLET=nft
+
+.PHONY: bench
+bench: bench-evm-migration bench-nft
modifiedREADME.mddiffbeforeafterboth
--- a/README.md
+++ b/README.md
@@ -257,7 +257,7 @@
 Uncomment following lies:
 1. In node/rpc/Cargo.toml
 ```
-# pallet-contracts-rpc = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
+# pallet-contracts-rpc = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
 ```
 
 2. In node/rpc/src/lib.rs
@@ -280,19 +280,19 @@
     # [dependencies.pallet-contracts]
     # git = 'https://github.com/paritytech/substrate.git'
     # default-features = false
-    # branch = 'polkadot-v0.9.7'
+    # branch = 'polkadot-v0.9.8'
     # version = '3.0.0'
 
     # [dependencies.pallet-contracts-primitives]
     # git = 'https://github.com/paritytech/substrate.git'
     # default-features = false
-    # branch = 'polkadot-v0.9.7'
+    # branch = 'polkadot-v0.9.8'
     # version = '3.0.0'
 
     # [dependencies.pallet-contracts-rpc-runtime-api]
     # git = 'https://github.com/paritytech/substrate.git'
     # default-features = false
-    # branch = 'polkadot-v0.9.7'
+    # branch = 'polkadot-v0.9.8'
     # version = '3.0.0'
 ...
     # pallet-contract-helpers = { path = '../pallets/contract-helpers', default-features = false, version = '0.1.0' }
modifiedcrates/evm-coder-macros/src/lib.rsdiffbeforeafterboth
--- a/crates/evm-coder-macros/src/lib.rs
+++ b/crates/evm-coder-macros/src/lib.rs
@@ -6,7 +6,7 @@
 use quote::quote;
 use sha3::{Digest, Keccak256};
 use syn::{
-	AttributeArgs, DeriveInput, GenericArgument, Ident, ItemTrait, Pat, Path, PathArguments,
+	AttributeArgs, DeriveInput, GenericArgument, Ident, ItemImpl, Pat, Path, PathArguments,
 	PathSegment, Type, parse_macro_input, spanned::Spanned,
 };
 
@@ -106,8 +106,8 @@
 	}
 }
 
-fn parse_ident_from_segment(segment: &PathSegment) -> syn::Result<&Ident> {
-	if segment.arguments != PathArguments::None {
+fn parse_ident_from_segment(segment: &PathSegment, allow_generics: bool) -> syn::Result<&Ident> {
+	if segment.arguments != PathArguments::None && !allow_generics {
 		return Err(syn::Error::new(
 			segment.arguments.span(),
 			"unexpected generic type",
@@ -116,18 +116,18 @@
 	Ok(&segment.ident)
 }
 
-fn parse_ident_from_path(path: &Path) -> syn::Result<&Ident> {
+fn parse_ident_from_path(path: &Path, allow_generics: bool) -> syn::Result<&Ident> {
 	let segment = parse_path_segment(path)?;
-	parse_ident_from_segment(segment)
+	parse_ident_from_segment(segment, allow_generics)
 }
 
-fn parse_ident_from_type(ty: &Type) -> syn::Result<&Ident> {
+fn parse_ident_from_type(ty: &Type, allow_generics: bool) -> syn::Result<&Ident> {
 	let path = parse_path(ty)?;
-	parse_ident_from_path(path)
+	parse_ident_from_path(path, allow_generics)
 }
 
 // Gets T out of Result<T>
-fn parse_result_ok(ty: &Type) -> syn::Result<&Ident> {
+fn parse_result_ok(ty: &Type) -> syn::Result<&Type> {
 	let path = parse_path(ty)?;
 	let segment = parse_path_segment(path)?;
 
@@ -160,7 +160,7 @@
 		}
 	};
 
-	parse_ident_from_type(ty)
+	Ok(ty)
 }
 
 fn pascal_ident_to_call(ident: &Ident) -> Ident {
@@ -182,14 +182,6 @@
 	let name = cases::snakecase::to_snake_case(&name);
 	let name = format!("call_{}", name);
 	Ident::new(&name, ident.span())
-}
-
-fn format_ty(ty: &Ident) -> String {
-	if ty == "string" {
-		format!("{} memory", ty)
-	} else {
-		ty.to_string()
-	}
 }
 
 #[proc_macro_attribute]
@@ -197,15 +189,21 @@
 	let args = parse_macro_input!(args as AttributeArgs);
 	let args = solidity_interface::InterfaceInfo::from_list(&args).unwrap();
 
-	let input: ItemTrait = match syn::parse(stream) {
+	let input: ItemImpl = match syn::parse(stream) {
 		Ok(t) => t,
 		Err(e) => return e.to_compile_error().into(),
 	};
 
-	match solidity_interface::SolidityInterface::try_from(args, &input) {
+	let expanded = match solidity_interface::SolidityInterface::try_from(args, &input) {
 		Ok(v) => v.expand(),
 		Err(e) => e.to_compile_error(),
-	}
+	};
+
+	(quote! {
+		#input
+
+		#expanded
+	})
 	.into()
 }
 
modifiedcrates/evm-coder-macros/src/solidity_interface.rsdiffbeforeafterboth
--- a/crates/evm-coder-macros/src/solidity_interface.rs
+++ b/crates/evm-coder-macros/src/solidity_interface.rs
@@ -5,12 +5,12 @@
 use inflector::cases;
 use std::fmt::Write;
 use syn::{
-	FnArg, Ident, ItemTrait, Meta, NestedMeta, PatType, Path, ReturnType, TraitItem,
-	TraitItemMethod, Visibility, spanned::Spanned,
+	FnArg, Generics, Ident, ImplItem, ImplItemMethod, ItemImpl, Meta, NestedMeta, PatType, Path,
+	ReturnType, Type, spanned::Spanned,
 };
 
 use crate::{
-	fn_selector_str, format_ty, parse_ident_from_pat, parse_ident_from_path, parse_ident_from_type,
+	fn_selector_str, parse_ident_from_pat, parse_ident_from_path, parse_ident_from_type,
 	parse_result_ok, pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal,
 	snake_ident_to_screaming,
 };
@@ -22,7 +22,7 @@
 }
 impl Is {
 	fn try_from(path: &Path) -> syn::Result<Self> {
-		let name = parse_ident_from_path(path)?.clone();
+		let name = parse_ident_from_path(path, false)?.clone();
 		Ok(Self {
 			pascal_call_name: pascal_ident_to_call(&name),
 			snake_call_name: pascal_ident_to_snake_call(&name),
@@ -54,9 +54,9 @@
 
 	fn expand_variant_call(&self) -> proc_macro2::TokenStream {
 		let name = &self.name;
-		let snake_call_name = &self.snake_call_name;
+		let pascal_call_name = &self.pascal_call_name;
 		quote! {
-			InternalCall::#name(call) => return self.#snake_call_name(Msg {
+			InternalCall::#name(call) => return <Self as ::evm_coder::Callable<#pascal_call_name>>::call(self, Msg {
 				call,
 				caller: c.caller,
 				value: c.value,
@@ -64,23 +64,29 @@
 		}
 	}
 
-	fn expand_call_inner(&self) -> proc_macro2::TokenStream {
-		let snake_call_name = &self.snake_call_name;
+	fn expand_parse(&self) -> proc_macro2::TokenStream {
+		let name = &self.name;
 		let pascal_call_name = &self.pascal_call_name;
 		quote! {
-			fn #snake_call_name(&mut self, c: Msg<#pascal_call_name>) -> ::core::result::Result<::evm_coder::abi::AbiWriter, Self::Error>;
+			if let Some(parsed_call) = #pascal_call_name::parse(method_id, reader)? {
+				return Ok(Some(Self::#name(parsed_call)))
+			}
 		}
 	}
 
-	fn expand_parse(&self) -> proc_macro2::TokenStream {
-		let name = &self.name;
+	fn expand_generator(&self) -> proc_macro2::TokenStream {
 		let pascal_call_name = &self.pascal_call_name;
 		quote! {
-			if let Some(parsed_call) = #pascal_call_name::parse(method_id, reader)? {
-				return Ok(Some(Self::#name(parsed_call)))
-			}
+			#pascal_call_name::generate_solidity_interface(out_set, is_impl);
 		}
 	}
+
+	fn expand_event_generator(&self) -> proc_macro2::TokenStream {
+		let name = &self.name;
+		quote! {
+			#name::generate_solidity_interface(out_set, is_impl);
+		}
+	}
 }
 
 #[derive(Default)]
@@ -100,6 +106,7 @@
 
 #[derive(FromMeta)]
 pub struct InterfaceInfo {
+	name: Ident,
 	#[darling(default)]
 	is: IsList,
 	#[darling(default)]
@@ -116,13 +123,16 @@
 
 struct MethodArg {
 	name: Ident,
+	camel_name: String,
 	ty: Ident,
 }
 impl MethodArg {
 	fn try_from(value: &PatType) -> syn::Result<Self> {
+		let name = parse_ident_from_pat(&value.pat)?.clone();
 		Ok(Self {
-			name: parse_ident_from_pat(&value.pat)?.clone(),
-			ty: parse_ident_from_type(&value.ty)?.clone(),
+			camel_name: cases::camelcase::to_camel_case(&name.to_string()),
+			name,
+			ty: parse_ident_from_type(&value.ty, false)?.clone(),
 		})
 	}
 	fn is_value(&self) -> bool {
@@ -174,9 +184,12 @@
 		}
 	}
 
-	fn solidity_def(&self) -> String {
-		assert!(!self.is_special());
-		format!("{} {}", format_ty(&self.ty), self.name)
+	fn expand_solidity_argument(&self) -> proc_macro2::TokenStream {
+		let camel_name = &self.camel_name.to_string();
+		let ty = &self.ty;
+		quote! {
+			<NamedArgument<#ty>>::new(#camel_name)
+		}
 	}
 }
 
@@ -197,15 +210,15 @@
 	args: Vec<MethodArg>,
 	has_normal_args: bool,
 	mutability: Mutability,
-	result: Ident,
+	result: Type,
 }
 impl Method {
-	fn try_from(value: &TraitItemMethod) -> syn::Result<Self> {
+	fn try_from(value: &ImplItemMethod) -> syn::Result<Self> {
 		let mut info = MethodInfo {
 			rename_selector: None,
 		};
 		for attr in &value.attrs {
-			let ident = parse_ident_from_path(&attr.path)?;
+			let ident = parse_ident_from_path(&attr.path, false)?;
 			if ident == "solidity" {
 				let args = attr.parse_meta().unwrap();
 				info = MethodInfo::from_meta(&args).unwrap();
@@ -392,71 +405,64 @@
 		}
 	}
 
-	fn solidity_def(&self) -> String {
-		let mut out = format!("function {}(", self.camel_name);
-		for (i, arg) in self.args.iter().filter(|a| !a.is_special()).enumerate() {
-			if i != 0 {
-				out.push_str(", ");
+	fn expand_solidity_function(&self) -> proc_macro2::TokenStream {
+		let camel_name = &self.camel_name;
+		let mutability = match self.mutability {
+			Mutability::Mutable => quote! {SolidityMutability::Mutable},
+			Mutability::View => quote! { SolidityMutability::View },
+			Mutability::Pure => quote! {SolidityMutability::Pure},
+		};
+		let result = &self.result;
+
+		let args = self
+			.args
+			.iter()
+			.filter(|a| !a.is_special())
+			.map(MethodArg::expand_solidity_argument);
+
+		quote! {
+			SolidityFunction {
+				name: #camel_name,
+				mutability: #mutability,
+				args: (
+					#(
+						#args,
+					)*
+				),
+				result: <UnnamedArgument<#result>>::default(),
 			}
-			out.push_str(&arg.solidity_def());
 		}
-		out.push(')');
-		match self.mutability {
-			Mutability::Mutable => {}
-			Mutability::View => write!(out, " view").unwrap(),
-			Mutability::Pure => write!(out, " pure").unwrap(),
-		}
-		if self.result != "void" {
-			write!(out, " returns ({})", format_ty(&self.result)).unwrap();
-		}
-		out.push(';');
-		out
 	}
 }
 
 pub struct SolidityInterface {
-	vis: Visibility,
-	name: Ident,
+	generics: Generics,
+	name: Box<syn::Type>,
 	info: InterfaceInfo,
 	methods: Vec<Method>,
-	items: Vec<TraitItem>,
 }
 impl SolidityInterface {
-	pub fn try_from(info: InterfaceInfo, value: &ItemTrait) -> syn::Result<Self> {
-		let mut found_error = false;
+	pub fn try_from(info: InterfaceInfo, value: &ItemImpl) -> syn::Result<Self> {
 		let mut methods = Vec::new();
 
 		for item in &value.items {
-			match item {
-				TraitItem::Type(ty) => {
-					if ty.ident == "Error" {
-						found_error = true;
-					}
-				}
-				TraitItem::Method(method) => methods.push(Method::try_from(method)?),
-				_ => {}
+			if let ImplItem::Method(method) = item {
+				methods.push(Method::try_from(method)?)
 			}
 		}
-		if !found_error {
-			return Err(syn::Error::new(
-				value.span(),
-				"expected associated type called Error, which should implement From<&str>",
-			));
-		}
 		Ok(Self {
-			vis: value.vis.clone(),
-			name: value.ident.clone(),
+			generics: value.generics.clone(),
+			name: value.self_ty.clone(),
 			info,
 			methods,
-			items: value.items.clone(),
 		})
 	}
 	pub fn expand(self) -> proc_macro2::TokenStream {
-		let vis = self.vis;
 		let name = self.name;
-		let items = self.items;
 
-		let call_name = pascal_ident_to_call(&name);
+		let solidity_name = self.info.name.to_string();
+		let call_name = pascal_ident_to_call(&self.info.name);
+		let generics = self.generics;
 
 		let call_sub = self
 			.info
@@ -465,13 +471,6 @@
 			.iter()
 			.chain(self.info.is.0.iter())
 			.map(Is::expand_call_def);
-		let call_inner = self
-			.info
-			.inline_is
-			.0
-			.iter()
-			.chain(self.info.is.0.iter())
-			.map(Is::expand_call_inner);
 		let call_parse = self
 			.info
 			.inline_is
@@ -495,12 +494,31 @@
 		let interface_id = self.methods.iter().map(Method::expand_interface_id);
 		let parsers = self.methods.iter().map(Method::expand_parse);
 		let call_variants_this = self.methods.iter().map(Method::expand_variant_call);
+		let solidity_functions = self.methods.iter().map(Method::expand_solidity_function);
 
+		// TODO: Inline inline_is
+		let solidity_is = self
+			.info
+			.is
+			.0
+			.iter()
+			.chain(self.info.inline_is.0.iter())
+			.map(|is| is.name.to_string());
+		let solidity_events_is = self.info.events.0.iter().map(|is| is.name.to_string());
+		let solidity_generators = self
+			.info
+			.is
+			.0
+			.iter()
+			.chain(self.info.inline_is.0.iter())
+			.map(Is::expand_generator);
+		let solidity_event_generators = self.info.events.0.iter().map(Is::expand_event_generator);
+
 		// let methods = self.methods.iter().map(Method::solidity_def);
 
 		quote! {
 			#[derive(Debug)]
-			#vis enum #call_name {
+			pub enum #call_name {
 				#(
 					#calls,
 				)*
@@ -512,19 +530,6 @@
 				#(
 					#consts
 				)*
-				pub fn parse(method_id: u32, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::abi::Result<Option<Self>> {
-					use ::evm_coder::abi::AbiRead;
-					match method_id {
-						#(
-							#parsers,
-						)*
-						_ => {},
-					}
-					#(
-						#call_parse
-					)else*
-					return Ok(None);
-				}
 				pub const fn interface_id() -> u32 {
 					let mut interface_id = 0;
 					#(#interface_id)*
@@ -539,16 +544,60 @@
 						)*
 					)
 				}
+				pub fn generate_solidity_interface(out_set: &mut sp_std::collections::btree_set::BTreeSet<string>, is_impl: bool) {
+					use evm_coder::solidity::*;
+					use core::fmt::Write;
+					let interface = SolidityInterface {
+						name: #solidity_name,
+						is: &["Dummy", #(
+							#solidity_is,
+						)* #(
+							#solidity_events_is,
+						)* ],
+						functions: (#(
+							#solidity_functions,
+						)*),
+					};
+					if is_impl {
+						out_set.insert("// Common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\n".into());
+					} else {
+						out_set.insert("// Common stubs holder\ninterface Dummy {\n}\n".into());
+					}
+					#(
+						#solidity_generators
+					)*
+					#(
+						#solidity_event_generators
+					)*
+
+					let mut out = string::new();
+					// In solidity interface usage (is) should be preceeded by interface definition
+					// This comment helps to sort it in a set
+					if #solidity_name.starts_with("Inline") {
+						out.push_str("// Inline\n");
+					}
+					let _ = interface.format(is_impl, &mut out);
+					out_set.insert(out);
+				}
 			}
-			#vis trait #name {
-				#(
-					#items
-				)*
-				#(
-					#call_inner
-				)*
+			impl ::evm_coder::Call for #call_name {
+				fn parse(method_id: u32, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {
+					use ::evm_coder::abi::AbiRead;
+					match method_id {
+						#(
+							#parsers,
+						)*
+						_ => {},
+					}
+					#(
+						#call_parse
+					)else*
+					return Ok(None);
+				}
+			}
+			impl #generics ::evm_coder::Callable<#call_name> for #name {
 				#[allow(unreachable_code)] // In case of no inner calls
-				fn call(&mut self, c: Msg<#call_name>) -> ::core::result::Result<::evm_coder::abi::AbiWriter, Self::Error> {
+				fn call(&mut self, c: Msg<#call_name>) -> Result<::evm_coder::abi::AbiWriter> {
 					use ::evm_coder::abi::AbiWrite;
 					type InternalCall = #call_name;
 					match c.call {
modifiedcrates/evm-coder-macros/src/to_log.rsdiffbeforeafterboth
--- a/crates/evm-coder-macros/src/to_log.rs
+++ b/crates/evm-coder-macros/src/to_log.rs
@@ -1,3 +1,4 @@
+use inflector::cases;
 use syn::{Data, DeriveInput, Field, Fields, Ident, Variant, spanned::Spanned};
 use std::fmt::Write;
 use quote::quote;
@@ -6,6 +7,7 @@
 
 struct EventField {
 	name: Ident,
+	camel_name: String,
 	ty: Ident,
 	indexed: bool,
 }
@@ -13,10 +15,10 @@
 impl EventField {
 	fn try_from(field: &Field) -> syn::Result<Self> {
 		let name = field.ident.as_ref().unwrap();
-		let ty = parse_ident_from_type(&field.ty)?;
+		let ty = parse_ident_from_type(&field.ty, false)?;
 		let mut indexed = false;
 		for attr in &field.attrs {
-			if let Ok(ident) = parse_ident_from_path(&attr.path) {
+			if let Ok(ident) = parse_ident_from_path(&attr.path, false) {
 				if ident == "indexed" {
 					indexed = true;
 				}
@@ -24,10 +26,19 @@
 		}
 		Ok(Self {
 			name: name.to_owned(),
+			camel_name: cases::camelcase::to_camel_case(&name.to_string()),
 			ty: ty.to_owned(),
 			indexed,
 		})
 	}
+	fn expand_solidity_argument(&self) -> proc_macro2::TokenStream {
+		let camel_name = &self.camel_name;
+		let ty = &self.ty;
+		let indexed = self.indexed;
+		quote! {
+			<SolidityEventArgument<#ty>>::new(#indexed, #camel_name)
+		}
+	}
 }
 
 struct Event {
@@ -56,6 +67,12 @@
 		for field in &named.named {
 			fields.push(EventField::try_from(field)?);
 		}
+		if fields.iter().filter(|f| f.indexed).count() > 3 {
+			return Err(syn::Error::new(
+				variant.fields.span(),
+				"events can have at most 4 indexed fields (1 indexed field is reserved for event signature)"
+			));
+		}
 		let mut selector_str = format!("{}(", name);
 		for (i, arg) in fields.iter().enumerate() {
 			if i != 0 {
@@ -110,6 +127,21 @@
 			)*];
 		}
 	}
+
+	fn expand_solidity_function(&self) -> proc_macro2::TokenStream {
+		let name = self.name.to_string();
+		let args = self.fields.iter().map(EventField::expand_solidity_argument);
+		quote! {
+			SolidityEvent {
+				name: #name,
+				args: (
+					#(
+						#args,
+					)*
+				),
+			}
+		}
+	}
 }
 
 pub struct Events {
@@ -138,12 +170,30 @@
 
 		let consts = self.events.iter().map(Event::expand_consts);
 		let serializers = self.events.iter().map(Event::expand_serializers);
+		let solidity_name = self.name.to_string();
+		let solidity_functions = self.events.iter().map(Event::expand_solidity_function);
 
 		quote! {
 			impl #name {
 				#(
 					#consts
 				)*
+
+				pub fn generate_solidity_interface(out_set: &mut sp_std::collections::btree_set::BTreeSet<string>, is_impl: bool) {
+					use evm_coder::solidity::*;
+					use core::fmt::Write;
+					let interface = SolidityInterface {
+						name: #solidity_name,
+						is: &[],
+						functions: (#(
+							#solidity_functions,
+						)*),
+					};
+					let mut out = string::new();
+					out.push_str("// Inline\n");
+					let _ = interface.format(is_impl, &mut out);
+					out_set.insert(out);
+				}
 			}
 
 			#[automatically_derived]
modifiedcrates/evm-coder/Cargo.tomldiffbeforeafterboth
--- a/crates/evm-coder/Cargo.toml
+++ b/crates/evm-coder/Cargo.toml
@@ -8,10 +8,12 @@
 primitive-types = { version = "0.9", default-features = false }
 hex-literal = "0.3"
 ethereum = { version = "0.7.1", default-features = false }
+evm-core = { default-features = false, git = "https://github.com/uniquenetwork/evm.git", branch="precompile-output-parachain" }
+impl-trait-for-tuples = "0.2.1"
 
 [dev-dependencies]
 hex = "0.4.3"
 
 [features]
 default = ["std"]
-std = ["ethereum/std", "primitive-types/std"]
\ No newline at end of file
+std = ["ethereum/std", "primitive-types/std", "evm-core/std"]
\ No newline at end of file
modifiedcrates/evm-coder/src/abi.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/abi.rs
+++ b/crates/evm-coder/src/abi.rs
@@ -8,36 +8,48 @@
 	string::{String, ToString},
 	vec::Vec,
 };
+use evm_core::ExitError;
 use primitive_types::{H160, U256};
 
-use crate::types::string;
+use crate::{execution::Error, types::string};
+use crate::execution::Result;
 
 const ABI_ALIGNMENT: usize = 32;
 
-pub type Result<T> = core::result::Result<T, &'static str>;
-
 #[derive(Clone)]
 pub struct AbiReader<'i> {
 	buf: &'i [u8],
+	subresult_offset: usize,
 	offset: usize,
 }
 impl<'i> AbiReader<'i> {
 	pub fn new(buf: &'i [u8]) -> Self {
-		Self { buf, offset: 0 }
+		Self {
+			buf,
+			subresult_offset: 0,
+			offset: 0,
+		}
 	}
 	pub fn new_call(buf: &'i [u8]) -> Result<(u32, Self)> {
 		if buf.len() < 4 {
-			return Err("missing method id");
+			return Err(Error::Error(ExitError::OutOfOffset));
 		}
 		let mut method_id = [0; 4];
 		method_id.copy_from_slice(&buf[0..4]);
 
-		Ok((u32::from_be_bytes(method_id), Self { buf, offset: 4 }))
+		Ok((
+			u32::from_be_bytes(method_id),
+			Self {
+				buf,
+				subresult_offset: 4,
+				offset: 4,
+			},
+		))
 	}
 
 	fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {
-		if self.buf.len() - self.offset < 32 {
-			return Err("missing padding");
+		if self.buf.len() - self.offset < ABI_ALIGNMENT {
+			return Err(Error::Error(ExitError::OutOfOffset));
 		}
 		let mut block = [0; S];
 		// Verify padding is empty
@@ -45,7 +57,7 @@
 			.iter()
 			.all(|&v| v == 0)
 		{
-			return Err("non zero padding (wrong types?)");
+			return Err(Error::Error(ExitError::InvalidRange));
 		}
 		block.copy_from_slice(
 			&self.buf[self.offset + ABI_ALIGNMENT - S..self.offset + ABI_ALIGNMENT],
@@ -63,7 +75,7 @@
 		match data[0] {
 			0 => Ok(false),
 			1 => Ok(true),
-			_ => Err("wrong bool value"),
+			_ => Err(Error::Error(ExitError::InvalidRange)),
 		}
 	}
 
@@ -75,10 +87,13 @@
 		let mut subresult = self.subresult()?;
 		let length = subresult.read_usize()?;
 		if subresult.buf.len() <= subresult.offset + length {
-			return Err("bytes out of bounds");
+			return Err(Error::Error(ExitError::OutOfOffset));
 		}
 		Ok(subresult.buf[subresult.offset..subresult.offset + length].into())
 	}
+	pub fn string(&mut self) -> Result<string> {
+		string::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange))
+	}
 
 	pub fn uint32(&mut self) -> Result<u32> {
 		Ok(u32::from_be_bytes(self.read_padleft()?))
@@ -103,9 +118,13 @@
 
 	fn subresult(&mut self) -> Result<AbiReader<'i>> {
 		let offset = self.read_usize()?;
+		if offset + self.subresult_offset > self.buf.len() {
+			return Err(Error::Error(ExitError::InvalidRange));
+		}
 		Ok(AbiReader {
 			buf: self.buf,
-			offset: offset + self.offset,
+			subresult_offset: offset + self.subresult_offset,
+			offset: offset + self.subresult_offset,
 		})
 	}
 
@@ -163,8 +182,6 @@
 		self.write_padleft(&u128::to_be_bytes(*value))
 	}
 
-	/// This method writes u128, and exists only for convenience, because there is
-	/// no u256 support in rust
 	pub fn uint256(&mut self, value: &U256) {
 		let mut out = [0; 32];
 		value.to_big_endian(&mut out);
@@ -198,7 +215,7 @@
 		for (static_offset, part) in self.dynamic_part {
 			let part_offset = self.static_part.len();
 
-			let encoded_dynamic_offset = usize::to_be_bytes(part_offset - static_offset);
+			let encoded_dynamic_offset = usize::to_be_bytes(part_offset);
 			self.static_part[static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len()
 				..static_offset + ABI_ALIGNMENT]
 				.copy_from_slice(&encoded_dynamic_offset);
@@ -228,6 +245,7 @@
 impl_abi_readable!(H160, address);
 impl_abi_readable!(Vec<u8>, bytes);
 impl_abi_readable!(bool, bool);
+impl_abi_readable!(string, string);
 
 pub trait AbiWrite {
 	fn abi_write(&self, writer: &mut AbiWriter);
@@ -259,29 +277,7 @@
 impl AbiWrite for () {
 	fn abi_write(&self, _writer: &mut AbiWriter) {}
 }
-
-/// Error, which can be constructed from any ToString type
-/// Encoded to Abi as Error(string)
-#[derive(Debug)]
-pub struct StringError(String);
 
-impl<E> From<E> for StringError
-where
-	E: ToString,
-{
-	fn from(e: E) -> Self {
-		Self(e.to_string())
-	}
-}
-
-impl From<StringError> for AbiWriter {
-	fn from(v: StringError) -> Self {
-		let mut out = AbiWriter::new_call(crate::fn_selector!(Error(string)));
-		out.string(&v.0);
-		out
-	}
-}
-
 #[macro_export]
 macro_rules! abi_decode {
 	($reader:expr, $($name:ident: $typ:ident),+ $(,)?) => {
@@ -309,3 +305,54 @@
 		writer
 	}}
 }
+
+#[cfg(test)]
+pub mod test {
+	use super::{AbiReader, AbiWriter};
+	use hex_literal::hex;
+
+	#[test]
+	fn dynamic_after_static() {
+		let mut encoder = AbiWriter::new();
+		encoder.bool(&true);
+		encoder.string("test");
+		let encoded = encoder.finish();
+
+		let mut encoder = AbiWriter::new();
+		encoder.bool(&true);
+		// Offset to subresult
+		encoder.uint32(&(32 * 2));
+		// Len of "test"
+		encoder.uint32(&4);
+		encoder.write_padright(&[b't', b'e', b's', b't']);
+		let alternative_encoded = encoder.finish();
+
+		assert_eq!(encoded, alternative_encoded);
+
+		let mut decoder = AbiReader::new(&encoded);
+		assert_eq!(decoder.bool().unwrap(), true);
+		assert_eq!(decoder.string().unwrap(), "test");
+	}
+
+	#[test]
+	fn mint_sample() {
+		let (call, mut decoder) = AbiReader::new_call(&hex!(
+			"
+				50bb4e7f
+				000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374
+				0000000000000000000000000000000000000000000000000000000000000001
+				0000000000000000000000000000000000000000000000000000000000000060
+				0000000000000000000000000000000000000000000000000000000000000008
+				5465737420555249000000000000000000000000000000000000000000000000
+			"
+		))
+		.unwrap();
+		assert_eq!(call, 0x50bb4e7f);
+		assert_eq!(
+			format!("{:?}", decoder.address().unwrap()),
+			"0xad2c0954693c2b5404b7e50967d3481bea432374"
+		);
+		assert_eq!(decoder.uint32().unwrap(), 1);
+		assert_eq!(decoder.string().unwrap(), "Test URI");
+	}
+}
addedcrates/evm-coder/src/execution.rsdiffbeforeafterboth
--- /dev/null
+++ b/crates/evm-coder/src/execution.rs
@@ -0,0 +1,23 @@
+#[cfg(not(feature = "std"))]
+use alloc::string::{String, ToString};
+use evm_core::{ExitError, ExitFatal};
+#[cfg(feature = "std")]
+use std::string::{String, ToString};
+
+#[derive(Debug)]
+pub enum Error {
+	Revert(String),
+	Fatal(ExitFatal),
+	Error(ExitError),
+}
+
+impl<E> From<E> for Error
+where
+	E: ToString,
+{
+	fn from(e: E) -> Self {
+		Self::Revert(e.to_string())
+	}
+}
+
+pub type Result<T> = core::result::Result<T, Error>;
modifiedcrates/evm-coder/src/lib.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/lib.rs
+++ b/crates/evm-coder/src/lib.rs
@@ -2,10 +2,13 @@
 #[cfg(not(feature = "std"))]
 extern crate alloc;
 
+use abi::{AbiReader, AbiWriter};
 pub use evm_coder_macros::{event_topic, fn_selector, solidity_interface, solidity, ToLog};
 pub mod abi;
 pub mod events;
 pub use events::ToLog;
+pub mod execution;
+pub mod solidity;
 
 /// Solidity type definitions
 pub mod types {
@@ -50,6 +53,37 @@
 	}
 }
 
+pub trait Call: Sized {
+	fn parse(selector: u32, input: &mut AbiReader) -> execution::Result<Option<Self>>;
+}
+
+pub trait Callable<C: Call> {
+	fn call(&mut self, call: types::Msg<C>) -> execution::Result<AbiWriter>;
+}
+
+#[macro_export]
+macro_rules! generate_stubgen {
+	($name:ident, $decl:ident, $is_impl:literal) => {
+		#[test]
+		#[ignore]
+		fn $name() {
+			use sp_std::collections::btree_set::BTreeSet;
+			let mut out = BTreeSet::new();
+			$decl::generate_solidity_interface(&mut out, $is_impl);
+			println!("=== SNIP START ===");
+			println!("// SPDX-License-Identifier: OTHER");
+			println!("// This code is automatically generated");
+			println!();
+			println!("pragma solidity >=0.8.0 <0.9.0;");
+			println!();
+			for b in out {
+				println!("{}", b);
+			}
+			println!("=== SNIP END ===");
+		}
+	};
+}
+
 #[cfg(test)]
 mod tests {
 	use super::*;
addedcrates/evm-coder/src/solidity.rsdiffbeforeafterboth
--- /dev/null
+++ b/crates/evm-coder/src/solidity.rs
@@ -0,0 +1,333 @@
+#[cfg(not(feature = "std"))]
+use alloc::{string::String};
+use core::{fmt, marker::PhantomData};
+use impl_trait_for_tuples::impl_for_tuples;
+use crate::types::*;
+
+pub trait SolidityTypeName: 'static {
+	fn solidity_name(writer: &mut impl fmt::Write) -> fmt::Result;
+	fn solidity_default(writer: &mut impl fmt::Write) -> fmt::Result;
+	fn is_void() -> bool {
+		false
+	}
+}
+
+macro_rules! solidity_type_name {
+    ($($ty:ident => $name:literal = $default:literal),* $(,)?) => {
+        $(
+            impl SolidityTypeName for $ty {
+                fn solidity_name(writer: &mut impl core::fmt::Write) -> core::fmt::Result {
+                    write!(writer, $name)
+                }
+				fn solidity_default(writer: &mut impl core::fmt::Write) -> core::fmt::Result {
+					write!(writer, $default)
+				}
+            }
+        )*
+    };
+}
+
+solidity_type_name! {
+	uint8 => "uint8" = "0",
+	uint32 => "uint32" = "0",
+	uint128 => "uint128" = "0",
+	uint256 => "uint256" = "0",
+	address => "address" = "0x0000000000000000000000000000000000000000",
+	string => "string memory" = "\"\"",
+	bytes => "bytes memory" = "hex\"\"",
+	bool => "bool" = "false",
+}
+impl SolidityTypeName for void {
+	fn solidity_name(_writer: &mut impl fmt::Write) -> fmt::Result {
+		Ok(())
+	}
+	fn solidity_default(_writer: &mut impl fmt::Write) -> fmt::Result {
+		Ok(())
+	}
+	fn is_void() -> bool {
+		true
+	}
+}
+
+pub trait SolidityArguments {
+	fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result;
+	fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result;
+	fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result;
+	fn is_empty(&self) -> bool {
+		self.len() == 0
+	}
+	fn len(&self) -> usize;
+}
+
+#[derive(Default)]
+pub struct UnnamedArgument<T>(PhantomData<*const T>);
+
+impl<T: SolidityTypeName> SolidityArguments for UnnamedArgument<T> {
+	fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+		if !T::is_void() {
+			T::solidity_name(writer)
+		} else {
+			Ok(())
+		}
+	}
+	fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result {
+		Ok(())
+	}
+	fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+		T::solidity_default(writer)
+	}
+	fn len(&self) -> usize {
+		if T::is_void() {
+			0
+		} else {
+			1
+		}
+	}
+}
+
+pub struct NamedArgument<T>(&'static str, PhantomData<*const T>);
+
+impl<T> NamedArgument<T> {
+	pub fn new(name: &'static str) -> Self {
+		Self(name, Default::default())
+	}
+}
+
+impl<T: SolidityTypeName> SolidityArguments for NamedArgument<T> {
+	fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+		if !T::is_void() {
+			T::solidity_name(writer)?;
+			write!(writer, " {}", self.0)
+		} else {
+			Ok(())
+		}
+	}
+	fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+		writeln!(writer, "\t\t{};", self.0)
+	}
+	fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+		T::solidity_default(writer)
+	}
+	fn len(&self) -> usize {
+		if T::is_void() {
+			0
+		} else {
+			1
+		}
+	}
+}
+
+pub struct SolidityEventArgument<T>(pub bool, &'static str, PhantomData<*const T>);
+
+impl<T> SolidityEventArgument<T> {
+	pub fn new(indexed: bool, name: &'static str) -> Self {
+		Self(indexed, name, Default::default())
+	}
+}
+
+impl<T: SolidityTypeName> SolidityArguments for SolidityEventArgument<T> {
+	fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+		if !T::is_void() {
+			T::solidity_name(writer)?;
+			if self.0 {
+				write!(writer, " indexed")?;
+			}
+			write!(writer, " {}", self.1)
+		} else {
+			Ok(())
+		}
+	}
+	fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+		writeln!(writer, "\t\t{};", self.1)
+	}
+	fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+		T::solidity_default(writer)
+	}
+	fn len(&self) -> usize {
+		if T::is_void() {
+			0
+		} else {
+			1
+		}
+	}
+}
+
+impl SolidityArguments for () {
+	fn solidity_name(&self, _writer: &mut impl fmt::Write) -> fmt::Result {
+		Ok(())
+	}
+	fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result {
+		Ok(())
+	}
+	fn solidity_default(&self, _writer: &mut impl fmt::Write) -> fmt::Result {
+		Ok(())
+	}
+	fn len(&self) -> usize {
+		0
+	}
+}
+
+#[impl_for_tuples(1, 5)]
+impl SolidityArguments for Tuple {
+	for_tuples!( where #( Tuple: SolidityArguments ),* );
+
+	fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+		let mut first = true;
+		for_tuples!( #(
+            if !Tuple.is_empty() {
+                if !first {
+                    write!(writer, ", ")?;
+                }
+                first = false;
+                Tuple.solidity_name(writer)?;
+            }
+        )* );
+		Ok(())
+	}
+	fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+		for_tuples!( #(
+            Tuple.solidity_get(writer)?;
+        )* );
+		Ok(())
+	}
+	fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {
+		if self.is_empty() {
+			Ok(())
+		} else if self.len() == 1 {
+			for_tuples!( #(
+				Tuple.solidity_default(writer)?;
+			)* );
+			Ok(())
+		} else {
+			write!(writer, "(")?;
+			let mut first = true;
+			for_tuples!( #(
+				if !Tuple.is_empty() {
+					if !first {
+						write!(writer, ", ")?;
+					}
+					first = false;
+					Tuple.solidity_name(writer)?;
+				}
+			)* );
+			write!(writer, ")")?;
+			Ok(())
+		}
+	}
+	fn len(&self) -> usize {
+		for_tuples!( #( Tuple.len() )+* )
+	}
+}
+
+pub trait SolidityFunctions {
+	fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result;
+}
+
+pub enum SolidityMutability {
+	Pure,
+	View,
+	Mutable,
+}
+pub struct SolidityFunction<A, R> {
+	pub name: &'static str,
+	pub args: A,
+	pub result: R,
+	pub mutability: SolidityMutability,
+}
+impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {
+	fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {
+		write!(writer, "\tfunction {}(", self.name)?;
+		self.args.solidity_name(writer)?;
+		write!(writer, ")")?;
+		if is_impl {
+			write!(writer, " public")?;
+		} else {
+			write!(writer, " external")?;
+		}
+		match &self.mutability {
+			SolidityMutability::Pure => write!(writer, " pure")?,
+			SolidityMutability::View => write!(writer, " view")?,
+			SolidityMutability::Mutable => {}
+		}
+		if !self.result.is_empty() {
+			write!(writer, " returns (")?;
+			self.result.solidity_name(writer)?;
+			write!(writer, ")")?;
+		}
+		if is_impl {
+			writeln!(writer, " {{")?;
+			writeln!(writer, "\t\trequire(false, stub_error);")?;
+			self.args.solidity_get(writer)?;
+			match &self.mutability {
+				SolidityMutability::Pure => {}
+				SolidityMutability::View => writeln!(writer, "\t\tdummy;")?,
+				SolidityMutability::Mutable => writeln!(writer, "\t\tdummy = 0;")?,
+			}
+			if !self.result.is_empty() {
+				write!(writer, "\t\treturn ")?;
+				self.result.solidity_default(writer)?;
+				writeln!(writer, ";")?;
+			}
+			writeln!(writer, "\t}}")?;
+		} else {
+			writeln!(writer, ";")?;
+		}
+		Ok(())
+	}
+}
+
+#[impl_for_tuples(0, 12)]
+impl SolidityFunctions for Tuple {
+	for_tuples!( where #( Tuple: SolidityFunctions ),* );
+
+	fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {
+		let mut first = false;
+		for_tuples!( #(
+            Tuple.solidity_name(is_impl, writer)?;
+        )* );
+		Ok(())
+	}
+}
+
+pub struct SolidityInterface<F: SolidityFunctions> {
+	pub name: &'static str,
+	pub is: &'static [&'static str],
+	pub functions: F,
+}
+
+impl<F: SolidityFunctions> SolidityInterface<F> {
+	pub fn format(&self, is_impl: bool, out: &mut impl fmt::Write) -> fmt::Result {
+		if is_impl {
+			write!(out, "contract ")?;
+		} else {
+			write!(out, "interface ")?;
+		}
+		write!(out, "{}", self.name)?;
+		if !self.is.is_empty() {
+			write!(out, " is")?;
+			for (i, n) in self.is.iter().enumerate() {
+				if i != 0 {
+					write!(out, ",")?;
+				}
+				write!(out, " {}", n)?;
+			}
+		}
+		writeln!(out, " {{")?;
+		self.functions.solidity_name(is_impl, out)?;
+		writeln!(out, "}}")?;
+		Ok(())
+	}
+}
+
+pub struct SolidityEvent<A> {
+	pub name: &'static str,
+	pub args: A,
+}
+
+impl<A: SolidityArguments> SolidityFunctions for SolidityEvent<A> {
+	fn solidity_name(&self, _is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {
+		write!(writer, "\tevent {}(", self.name)?;
+		self.args.solidity_name(writer)?;
+		writeln!(writer, ");")
+	}
+}
modifiedcrates/evm-coder/tests/a.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/a.rs
+++ b/crates/evm-coder/tests/a.rs
@@ -1,29 +1,46 @@
 #![allow(dead_code)] // This test only checks that macros is not panicking
 
-use evm_coder::{solidity_interface, types::*, ToLog};
+use evm_coder::{solidity_interface, types::*, ToLog, execution::Result};
 use evm_coder_macros::solidity;
+use std as sp_std;
 
-#[solidity_interface]
-trait OurInterface {
-	type Error;
-	fn fn_a(&self, input: uint256) -> Result<bool, Self::Error>;
+struct Impls;
+
+#[solidity_interface(name = "OurInterface")]
+impl Impls {
+	fn fn_a(&self, _input: uint256) -> Result<bool> {
+		todo!()
+	}
 }
 
-#[solidity_interface]
-trait OurInterface1 {
-	type Error;
-	fn fn_b(&self, input: uint128) -> Result<uint32, Self::Error>;
+#[solidity_interface(name = "OurInterface1")]
+impl Impls {
+	fn fn_b(&self, _input: uint128) -> Result<uint32> {
+		todo!()
+	}
 }
 
-#[solidity_interface(is(OurInterface), inline_is(OurInterface1), events(ERC721Log))]
-trait OurInterface2 {
-	type Error;
+#[solidity_interface(
+	name = "OurInterface2",
+	is(OurInterface),
+	inline_is(OurInterface1),
+	events(ERC721Log)
+)]
+impl Impls {
 	#[solidity(rename_selector = "fnK")]
-	fn fn_c(&self, input: uint32) -> Result<uint8, Self::Error>;
-	fn fn_d(&self, value: uint32) -> Result<uint32, Self::Error>;
+	fn fn_c(&self, _input: uint32) -> Result<uint8> {
+		todo!()
+	}
+	fn fn_d(&self, _value: uint32) -> Result<uint32> {
+		todo!()
+	}
 
-	fn caller_sensitive(&self, caller: caller) -> Result<uint8, Self::Error>;
-	fn payable(&mut self, value: value) -> Result<uint8, Self::Error>;
+	fn caller_sensitive(&self, _caller: caller) -> Result<uint8> {
+		todo!()
+	}
+	fn payable(&mut self, _value: value) -> Result<uint8> {
+		todo!()
+	}
 }
 
 #[derive(ToLog)]
@@ -42,30 +59,32 @@
 	},
 }
 
-#[solidity_interface]
-trait ERC20 {
-	type Error;
+struct ERC20;
 
-	fn decimals(&self) -> Result<uint8, Self::Error>;
-	fn balance_of(&self, owner: address) -> Result<uint256, Self::Error>;
-	fn transfer(
-		&mut self,
-		caller: caller,
-		to: address,
-		value: uint256,
-	) -> Result<bool, Self::Error>;
+#[solidity_interface(name = "ERC20")]
+impl ERC20 {
+	fn decimals(&self) -> Result<uint8> {
+		todo!()
+	}
+	fn balance_of(&self, _owner: address) -> Result<uint256> {
+		todo!()
+	}
+	fn transfer(&mut self, _caller: caller, _to: address, _value: uint256) -> Result<bool> {
+		todo!()
+	}
 	fn transfer_from(
 		&mut self,
-		caller: caller,
-		from: address,
-		to: address,
-		value: uint256,
-	) -> Result<bool, Self::Error>;
-	fn approve(
-		&mut self,
-		caller: caller,
-		spender: address,
-		value: uint256,
-	) -> Result<bool, Self::Error>;
-	fn allowance(&self, owner: address, spender: address) -> Result<uint256, Self::Error>;
+		_caller: caller,
+		_from: address,
+		_to: address,
+		_value: uint256,
+	) -> Result<bool> {
+		todo!()
+	}
+	fn approve(&mut self, _caller: caller, _spender: address, _value: uint256) -> Result<bool> {
+		todo!()
+	}
+	fn allowance(&self, _owner: address, _spender: address) -> Result<uint256> {
+		todo!()
+	}
 }
modifiedlaunch-config.jsondiffbeforeafterboth
--- a/launch-config.json
+++ b/launch-config.json
@@ -1,71 +1,89 @@
 {
     "relaychain": {
-            "bin": "../polkadot/target/release/polkadot",
-            "chain": "rococo-local",
-            "nodes": [
-                    {
-                            "name": "alice",
-                            "wsPort": 9844,
-                            "rpcPort": 9843,
-                            "port": 30444
-                    },
-                    {
-                            "name": "bob",
-                            "wsPort": 9855,
-                            "rpcPort": 9854,
-                            "port": 30555
-                    },
-                    {
-                            "name": "charlie",
-                            "wsPort": 9866,
-                            "rpcPort": 9865,
-                            "port": 30666
-                    },
-                    {
-                            "name": "dave",
-                            "wsPort": 9877,
-                            "rpcPort": 9876,
-                            "port": 30777
+        "bin": "../polkadot/target/release/polkadot",
+        "chain": "rococo-local",
+        "nodes": [
+            {
+                "name": "alice",
+                "wsPort": 9844,
+                "rpcPort": 9843,
+                "port": 30444,
+                "flags": [
+                    "--rpc-port=9843"
+                ]
+            },
+            {
+                "name": "bob",
+                "wsPort": 9855,
+                "rpcPort": 9854,
+                "port": 30555,
+                "flags": [
+                    "--rpc-port=9854"
+                ]
+            },
+            {
+                "name": "charlie",
+                "wsPort": 9866,
+                "rpcPort": 9865,
+                "port": 30666,
+                "flags": [
+                    "--rpc-port=9865"
+                ]
+            },
+            {
+                "name": "dave",
+                "wsPort": 9877,
+                "rpcPort": 9876,
+                "port": 30777,
+                "flags": [
+                    "--rpc-port=9876"
+                ]
+            }
+        ],
+        "genesis": {
+            "runtime": {
+                "runtime_genesis_config": {
+                    "parachainsConfiguration": {
+                        "config": {
+                            "validation_upgrade_frequency": 1,
+                            "validation_upgrade_delay": 1
+                        }
                     }
-            ],
-            "genesis": {
-                    "runtime": {
-                            "runtime_genesis_config": {
-                                    "parachainsConfiguration": {
-                                            "config": {
-                                                    "validation_upgrade_frequency": 1,
-                                                    "validation_upgrade_delay": 1
-                                            }
-                                    }
-                            }
-                    }
+                }
             }
+        }
     },
     "parachains": [
-            {
-                    "bin": "../nft_private/target/release/nft",
-                    "id": "2000",
-                    "balance": "1000000000000000000000",
-                    "nodes": [
-                            {
-                                    "port": 31200,
-                                    "wsPort": 9944,
-                                    "rpcPort": 9933,
-                                    "name": "alice",
-                                    "flags": []
-                            },
-                            {
-                                    "port": 31201,
-                                    "wsPort": 9945,
-                                    "rpcPort": 9934,
-                                    "name": "bob",
-                                    "flags": []
-                            }
+        {
+            "bin": "../nft_private/target/release/nft",
+            "id": "2000",
+            "balance": "1000000000000000000000",
+            "nodes": [
+                {
+                    "port": 31200,
+                    "wsPort": 9944,
+                    "rpcPort": 9933,
+                    "name": "alice",
+                    "flags": [
+                        "--rpc-cors=all",
+                        "--rpc-port=9933"
+                    ]
+                },
+                {
+                    "port": 31201,
+                    "wsPort": 9945,
+                    "rpcPort": 9934,
+                    "name": "bob",
+                    "flags": [
+                        "--rpc-cors=all",
+                        "--rpc-port=9934"
                     ]
-            }
+                }
+            ]
+        }
     ],
     "simpleParachains": [],
     "hrmpChannels": [],
     "types": "./runtime_types.json",
     "finalization": false
-}
+}
\ No newline at end of file
modifiednode/cli/Cargo.tomldiffbeforeafterboth
--- a/node/cli/Cargo.toml
+++ b/node/cli/Cargo.toml
@@ -3,7 +3,7 @@
 
 [build-dependencies.substrate-build-script-utils]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 ################################################################################
@@ -17,185 +17,185 @@
 
 [dependencies.frame-benchmarking]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.frame-benchmarking-cli]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-transaction-payment-rpc]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.substrate-prometheus-endpoint]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.9.0'
 
 [dependencies.sc-basic-authorship]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.9.0'
 
 [dependencies.sc-chain-spec]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sc-cli]
 features = ['wasmtime']
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.9.0'
 
 [dependencies.sc-client-api]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sc-consensus]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.9.0'
 
 [dependencies.sc-consensus-aura]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.9.0'
 
 [dependencies.sc-executor]
 features = ['wasmtime']
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.9.0'
 
 [dependencies.sc-finality-grandpa]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.9.0'
 
 [dependencies.sc-keystore]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sc-rpc]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sc-rpc-api]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.9.0'
 
 [dependencies.sc-service]
 features = ['wasmtime']
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.9.0'
 
 [dependencies.sc-telemetry]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sc-transaction-pool]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sc-tracing]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-block-builder]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-api]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-blockchain]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-consensus]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.9.0'
 
 [dependencies.sp-consensus-aura]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.9.0'
 
 [dependencies.sp-core]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-finality-grandpa]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-inherents]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-keystore]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.9.0'
 
 [dependencies.sp-offchain]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-runtime]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-session]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-timestamp]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-transaction-pool]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-trie]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.substrate-frame-rpc-system]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sc-network]
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.9.0'
 
 [dependencies.serde]
@@ -211,58 +211,58 @@
 
 [dependencies.cumulus-client-consensus-aura]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 
 [dependencies.cumulus-client-consensus-common]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 
 [dependencies.cumulus-client-collator]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 
 [dependencies.cumulus-client-cli]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 
 [dependencies.cumulus-client-network]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 
 [dependencies.cumulus-primitives-core]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 
 [dependencies.cumulus-primitives-parachain-inherent]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 
 [dependencies.cumulus-client-service]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 
 
 ################################################################################
 # Polkadot dependencies
 [dependencies.polkadot-primitives]
 git = "https://github.com/paritytech/polkadot"
-branch = 'release-v0.9.7'
+branch = 'release-v0.9.8'
 
 [dependencies.polkadot-service]
 git = "https://github.com/paritytech/polkadot"
-branch = 'release-v0.9.7'
+branch = 'release-v0.9.8'
 
 [dependencies.polkadot-cli]
 git = "https://github.com/paritytech/polkadot"
-branch = 'release-v0.9.7'
+branch = 'release-v0.9.8'
 
 [dependencies.polkadot-test-service]
 git = "https://github.com/paritytech/polkadot"
-branch = 'release-v0.9.7'
+branch = 'release-v0.9.8'
 
 [dependencies.polkadot-parachain]
 git = "https://github.com/paritytech/polkadot"
-branch = 'release-v0.9.7'
+branch = 'release-v0.9.8'
 
 
 ################################################################################
@@ -273,7 +273,7 @@
 version = '3.0.0'
 
 [dependencies.nft-data-structs]
-path="../../primitives/nft"
+path = "../../primitives/nft"
 default-features = false
 
 ################################################################################
@@ -305,16 +305,19 @@
 jsonrpc-core = '15.0.0'
 jsonrpc-pubsub = "15.0.0"
 
-fc-rpc-core = { version = "1.1.0-dev", git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-fc-consensus = { version = "2.0.0-dev", git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-fc-mapping-sync = { version = "2.0.0-dev", git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-fc-rpc = { version = "2.0.0-dev", git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-fc-db = { version = "1.0.0", git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-fp-rpc = { version = "2.0.0", git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-pallet-ethereum = { version = "3.0.0-dev", git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
+fc-rpc-core = { version = "1.1.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fc-consensus = { version = "2.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fc-mapping-sync = { version = "2.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fc-rpc = { version = "2.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fc-db = { version = "1.0.0", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fp-rpc = { version = "2.0.0", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+pallet-ethereum = { version = "3.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
 
 nft-rpc = { path = "../rpc" }
 
 [features]
 default = []
-runtime-benchmarks = ['nft-runtime/runtime-benchmarks']
+runtime-benchmarks = [
+    'nft-runtime/runtime-benchmarks',
+    'polkadot-service/runtime-benchmarks',
+]
modifiednode/cli/src/chain_spec.rsdiffbeforeafterboth
--- a/node/cli/src/chain_spec.rs
+++ b/node/cli/src/chain_spec.rs
@@ -197,23 +197,12 @@
 					variable_on_chain_schema: vec![],
 					limits: CollectionLimits::default(),
 					meta_update_permission: MetaUpdatePermission::ItemOwner,
+					transfers_enabled: true,
 				},
 			)],
 			nft_item_id: vec![],
 			fungible_item_id: vec![],
 			refungible_item_id: vec![],
-			chain_limit: ChainLimits {
-				collection_numbers_limit: 100000,
-				account_token_ownership_limit: 1000000,
-				collections_admins_limit: 5,
-				custom_data_limit: 2048,
-				nft_sponsor_transfer_timeout: 15,
-				fungible_sponsor_transfer_timeout: 15,
-				refungible_sponsor_transfer_timeout: 15,
-				offchain_schema_limit: 1024,
-				variable_on_chain_schema_limit: 1024,
-				const_on_chain_schema_limit: 1024,
-			},
 		},
 		parachain_info: nft_runtime::ParachainInfoConfig { parachain_id: id },
 		aura: nft_runtime::AuraConfig {
modifiednode/cli/src/service.rsdiffbeforeafterboth
--- a/node/cli/src/service.rs
+++ b/node/cli/src/service.rs
@@ -10,6 +10,8 @@
 use std::sync::Mutex;
 use std::collections::BTreeMap;
 use std::collections::HashMap;
+use std::time::Duration;
+use futures::StreamExt;
 
 // Local Runtime Types
 use nft_runtime::RuntimeApi;
@@ -34,10 +36,12 @@
 use sp_keystore::SyncCryptoStorePtr;
 use sp_runtime::traits::BlakeTwo256;
 use substrate_prometheus_endpoint::Registry;
+use sc_client_api::BlockchainEvents;
 
 // Frontier Imports
 use fc_rpc_core::types::FilterPool;
 use fc_rpc_core::types::PendingTransactions;
+use fc_mapping_sync::MappingSyncWorker;
 
 // Runtime type overrides
 type BlockNumber = u32;
@@ -279,9 +283,11 @@
 	let select_chain = params.select_chain.clone();
 	let is_authority = parachain_config.role.clone().is_authority();
 	let rpc_network = network.clone();
+
+	let rpc_frontier_backend = frontier_backend.clone();
 	let rpc_extensions_builder = Box::new(move |deny_unsafe, _| {
 		let full_deps = nft_rpc::FullDeps {
-			backend: frontier_backend.clone(),
+			backend: rpc_frontier_backend.clone(),
 			deny_unsafe,
 			client: rpc_client.clone(),
 			pool: rpc_pool.clone(),
@@ -299,6 +305,18 @@
 		nft_rpc::create_full::<_, _, _, RuntimeApi, _>(full_deps, subscription_executor.clone())
 	});
 
+	task_manager.spawn_essential_handle().spawn(
+		"frontier-mapping-sync-worker",
+		MappingSyncWorker::new(
+			client.import_notification_stream(),
+			Duration::new(6, 0),
+			client.clone(),
+			backend.clone(),
+			frontier_backend.clone(),
+		)
+		.for_each(|()| futures::future::ready(())),
+	);
+
 	sc_service::spawn_tasks(sc_service::SpawnTasksParams {
 		on_demand: None,
 		remote_blockchain: None,
@@ -486,6 +504,7 @@
 				// We got around 500ms for proposing
 				block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32),
 				telemetry,
+				max_block_proposal_slot_portion: None,
 			}))
 		},
 	)
modifiednode/rpc/Cargo.tomldiffbeforeafterboth
--- a/node/rpc/Cargo.toml
+++ b/node/rpc/Cargo.toml
@@ -13,41 +13,41 @@
 futures = { version = "0.3.1", features = ["compat"] }
 jsonrpc-core = "15.0.0"
 jsonrpc-pubsub = "15.0.0"
-# pallet-contracts-rpc = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-pallet-transaction-payment-rpc = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-pallet-transaction-payment-rpc-runtime-api = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sc-client-api = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sc-consensus-aura = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sc-consensus-epochs = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sc-finality-grandpa = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sc-finality-grandpa-rpc = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sc-keystore = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sc-network = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sc-rpc-api = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sc-rpc = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sc-service = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-api = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-block-builder = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-blockchain = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-consensus = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-consensus-aura = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-core = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-offchain = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-runtime = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-storage = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-session = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-transaction-pool = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sc-transaction-pool = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sc-transaction-graph = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-substrate-frame-rpc-system = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
+# pallet-contracts-rpc = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+pallet-transaction-payment-rpc = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+pallet-transaction-payment-rpc-runtime-api = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sc-client-api = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sc-consensus-aura = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sc-consensus-epochs = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sc-finality-grandpa = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sc-finality-grandpa-rpc = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sc-keystore = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sc-network = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sc-rpc-api = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sc-rpc = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sc-service = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-api = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-block-builder = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-blockchain = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-consensus = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-consensus-aura = { version = "0.9", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-core = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-offchain = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-runtime = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-storage = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-session = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-transaction-pool = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sc-transaction-pool = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sc-transaction-graph = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+substrate-frame-rpc-system = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
 tokio = { version = "0.2.13", features = ["macros", "sync"] }
 
-pallet-ethereum = { git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-fc-rpc = { default-features = false, git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-fp-rpc = { default-features = false, git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-fc-rpc-core = { default-features = false, git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-fc-db = { default-features = false, git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-fc-mapping-sync = { default-features = false, git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
+pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fc-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fc-rpc-core = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fc-db = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
 
 pallet-nft = { path = "../../pallets/nft" }
 nft-runtime = { path = "../../runtime" }
modifiedpallets/contract-helpers/Cargo.tomldiffbeforeafterboth
--- a/pallets/contract-helpers/Cargo.toml
+++ b/pallets/contract-helpers/Cargo.toml
@@ -15,11 +15,11 @@
 version = '0.1.0'
 
 [dependencies]
-frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-pallet-contracts = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-runtime = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
+frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+pallet-contracts = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-runtime = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
 
 [features]
 default = ["std"]
@@ -29,4 +29,4 @@
     "pallet-contracts/std",
     "sp-runtime/std",
     "sp-std/std",
-]
\ No newline at end of file
+]
modifiedpallets/contract-helpers/src/lib.rsdiffbeforeafterboth
--- a/pallets/contract-helpers/src/lib.rs
+++ b/pallets/contract-helpers/src/lib.rs
@@ -22,7 +22,9 @@
 	}
 
 	#[pallet::config]
-	pub trait Config: frame_system::Config + pallet_contracts::Config {}
+	pub trait Config: frame_system::Config + pallet_contracts::Config {
+		type DefaultSponsoringRateLimit: Get<Self::BlockNumber>;
+	}
 
 	#[pallet::pallet]
 	#[pallet::generate_store(pub(super) trait Store)]
@@ -60,6 +62,7 @@
 		Key = T::AccountId,
 		Value = T::BlockNumber,
 		QueryKind = ValueQuery,
+		OnEmpty = T::DefaultSponsoringRateLimit,
 	>;
 
 	#[pallet::storage]
@@ -72,6 +75,15 @@
 		QueryKind = ValueQuery,
 	>;
 
+	impl<T: Config> Pallet<T> {
+		pub fn allowed(contract: T::AccountId, user: T::AccountId, default: bool) -> bool {
+			if !<AllowlistEnabled<T>>::get(&contract) {
+				return default;
+			}
+			<Allowlist<T>>::get(&contract, &user) || <Owner<T>>::get(contract) == user
+		}
+	}
+
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {
 		#[pallet::weight(0)]
@@ -191,10 +203,7 @@
 			{
 				let called_contract: T::AccountId =
 					T::Lookup::lookup((*dest).clone()).unwrap_or_default();
-				if <AllowlistEnabled<T>>::get(&called_contract)
-					&& !<Allowlist<T>>::get(&called_contract, who)
-					&& &<Owner<T>>::get(&called_contract) != who
-				{
+				if !<Pallet<T>>::allowed(called_contract, who.clone(), true) {
 					return Err(transaction_validity::InvalidTransaction::Call.into());
 				}
 			}
@@ -251,7 +260,9 @@
 			{
 				let called_contract: T::AccountId =
 					T::Lookup::lookup((*dest).clone()).unwrap_or_default();
-				if <SelfSponsoring<T>>::get(&called_contract) {
+				if <SelfSponsoring<T>>::get(&called_contract)
+					&& <Pallet<T>>::allowed(called_contract.clone(), who.clone(), false)
+				{
 					let last_tx_block = SponsorBasket::<T>::get(&called_contract, &who);
 					let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
 					let rate_limit = SponsoringRateLimit::<T>::get(&called_contract);
addedpallets/evm-coder-substrate/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-coder-substrate/Cargo.toml
@@ -0,0 +1,33 @@
+[package]
+name = "pallet-evm-coder-substrate"
+version = "0.1.0"
+edition = "2018"
+
+[dependencies]
+sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-core = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+ethereum = { default-features = false, version = "0.7.1" }
+evm-coder = { default-features = false, path = "../../crates/evm-coder" }
+pallet-ethereum = { default-features = false, version = "3.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+pallet-evm = { default-features = false, version = "5.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+
+[dependencies.codec]
+default-features = false
+features = ['derive']
+package = 'parity-scale-codec'
+version = '2.0.0'
+
+[features]
+default = ["std"]
+std = [
+    "sp-std/std",
+    "sp-core/std",
+    "ethereum/std",
+    "evm-coder/std",
+    "pallet-ethereum/std",
+    "pallet-evm/std",
+    "frame-support/std",
+    "frame-system/std",
+]
addedpallets/evm-coder-substrate/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-coder-substrate/src/lib.rs
@@ -0,0 +1,227 @@
+#![cfg_attr(not(feature = "std"), no_std)]
+
+#[cfg(not(feature = "std"))]
+extern crate alloc;
+
+pub use pallet::*;
+
+#[frame_support::pallet]
+pub mod pallet {
+	#[cfg(not(feature = "std"))]
+	use alloc::format;
+
+	use evm_coder::{
+		ToLog,
+		abi::{AbiReader, AbiWrite, AbiWriter},
+		execution::{self, Result},
+		types::{Msg, value},
+	};
+	use frame_support::ensure;
+	use pallet_evm::{ExitError, ExitReason, ExitRevert, ExitSucceed, PrecompileOutput};
+	pub use frame_support::dispatch::DispatchResult;
+	use pallet_ethereum::EthereumTransactionSender;
+	use sp_std::cell::RefCell;
+	use sp_std::vec::Vec;
+	use sp_core::{H160, H256};
+	use ethereum::Log;
+	use frame_support::{pallet_prelude::*, traits::PalletInfo};
+
+	/// DispatchError is opaque, but we need to somehow extract correct error in case of OutOfGas failure
+	/// So we have this pallet, which defines OutOfGas error, and knews its own id to check if DispatchError
+	/// is thrown because of it
+	///
+	/// These errors shouldn't end in extrinsic results, as they only used in evm execution path
+	#[pallet::error]
+	pub enum Error<T> {
+		OutOfGas,
+		OutOfFund,
+	}
+
+	#[pallet::config]
+	pub trait Config: frame_system::Config {
+		type EthereumTransactionSender: pallet_ethereum::EthereumTransactionSender;
+	}
+
+	#[pallet::pallet]
+	pub struct Pallet<T>(_);
+
+	// FIXME: those items are defined as private in evm_gasometer::consts, and we can't directly use it
+	pub const G_LOG: u64 = 375;
+	pub const G_LOGDATA: u64 = 8;
+	pub const G_LOGTOPIC: u64 = 375;
+
+	// From instabul hardfork configuration: https://github.com/rust-blockchain/evm/blob/fd4fd6acc0ca3208d6770fdb3ba407c94cdf97c6/runtime/src/lib.rs#L284
+	pub const G_SLOAD_WORD: u64 = 800;
+	pub const G_SSTORE_WORD: u64 = 20000;
+
+	fn log_price(data: usize, topics: usize) -> u64 {
+		G_LOG
+			.saturating_add((data as u64).saturating_mul(G_LOGDATA))
+			.saturating_add((topics as u64).saturating_mul(G_LOGTOPIC))
+	}
+
+	pub fn generate_transaction() -> ethereum::Transaction {
+		use ethereum::{Transaction, TransactionAction, TransactionSignature};
+		Transaction {
+			nonce: 0.into(),
+			gas_price: 0.into(),
+			gas_limit: 0.into(),
+			action: TransactionAction::Call(H160([0; 20])),
+			value: 0.into(),
+			// zero selector, this transaction always has same sender, so all data should be acquired from logs
+			input: Vec::from([0, 0, 0, 0]),
+			// if v is not 27 - then we need to pass some other validity checks
+			signature: TransactionSignature::new(27, H256([0x88; 32]), H256([0x88; 32])).unwrap(),
+		}
+	}
+
+	#[derive(Default)]
+	pub struct SubstrateRecorder<T: Config> {
+		contract: H160,
+		logs: RefCell<Vec<Log>>,
+		initial_gas: u64,
+		gas_limit: RefCell<u64>,
+		_phantom: PhantomData<*const T>,
+	}
+
+	impl<T: Config> SubstrateRecorder<T> {
+		pub fn new(contract: H160, gas_limit: u64) -> Self {
+			Self {
+				contract,
+				logs: RefCell::new(Vec::new()),
+				initial_gas: gas_limit,
+				gas_limit: RefCell::new(gas_limit),
+				_phantom: PhantomData,
+			}
+		}
+
+		pub fn is_empty(&self) -> bool {
+			self.logs.borrow().is_empty()
+		}
+		pub fn log_sub(&self, log: impl ToLog) -> DispatchResult {
+			self.log_raw_sub(log.to_log(self.contract))
+		}
+		pub fn log_raw_sub(&self, log: Log) -> DispatchResult {
+			self.consume_gas_sub(log_price(log.data.len(), log.topics.len()))?;
+			self.logs.borrow_mut().push(log);
+			Ok(())
+		}
+		pub fn retrieve_logs(self) -> Vec<Log> {
+			self.logs.into_inner()
+		}
+
+		pub fn gas_left(&self) -> u64 {
+			*self.gas_limit.borrow()
+		}
+		pub fn consume_sload_sub(&self) -> DispatchResult {
+			self.consume_gas_sub(G_SLOAD_WORD)
+		}
+		pub fn consume_sstore_sub(&self) -> DispatchResult {
+			self.consume_gas_sub(G_SSTORE_WORD)
+		}
+		pub fn consume_gas_sub(&self, gas: u64) -> DispatchResult {
+			ensure!(gas != u64::MAX, Error::<T>::OutOfGas);
+			let mut gas_limit = self.gas_limit.borrow_mut();
+			ensure!(gas <= *gas_limit, Error::<T>::OutOfGas);
+			*gas_limit -= gas;
+			Ok(())
+		}
+
+		pub fn consume_sload(&self) -> Result<()> {
+			self.consume_gas(G_SLOAD_WORD)
+		}
+		pub fn consume_sstore(&self) -> Result<()> {
+			self.consume_gas(G_SSTORE_WORD)
+		}
+		pub fn consume_gas(&self, gas: u64) -> Result<()> {
+			if gas == u64::MAX {
+				return Err(execution::Error::Error(ExitError::OutOfGas));
+			}
+			let mut gas_limit = self.gas_limit.borrow_mut();
+			if gas > *gas_limit {
+				return Err(execution::Error::Error(ExitError::OutOfGas));
+			}
+			*gas_limit -= gas;
+			Ok(())
+		}
+
+		pub fn evm_to_precompile_output(
+			self,
+			result: evm_coder::execution::Result<Option<AbiWriter>>,
+		) -> Option<PrecompileOutput> {
+			use evm_coder::execution::Error;
+			let (writer, reason) = match result {
+				Ok(Some(v)) => (v, ExitReason::Succeed(ExitSucceed::Returned)),
+				Ok(None) => return None,
+				Err(Error::Revert(e)) => {
+					let mut writer = AbiWriter::new_call(evm_coder::fn_selector!(Error(string)));
+					(&e as &str).abi_write(&mut writer);
+
+					(writer, ExitReason::Revert(ExitRevert::Reverted))
+				}
+				Err(Error::Fatal(f)) => (AbiWriter::new(), ExitReason::Fatal(f)),
+				Err(Error::Error(e)) => (AbiWriter::new(), ExitReason::Error(e)),
+			};
+
+			Some(PrecompileOutput {
+				cost: self.initial_gas - self.gas_left(),
+				exit_status: reason,
+				logs: self.retrieve_logs(),
+				output: writer.finish(),
+			})
+		}
+
+		pub fn submit_logs(self) -> DispatchResult {
+			let logs = self.retrieve_logs();
+			if logs.is_empty() {
+				return Ok(());
+			}
+			T::EthereumTransactionSender::submit_logs_transaction(generate_transaction(), logs)
+		}
+	}
+
+	pub fn dispatch_to_evm<T: Config>(err: DispatchError) -> evm_coder::execution::Error {
+		use evm_coder::execution::Error as ExError;
+		match err {
+			DispatchError::Module { index, error, .. }
+				if index
+					== T::PalletInfo::index::<Pallet<T>>()
+						.expect("evm-coder-substrate is a pallet, which should be added to runtime")
+						as u8 =>
+			{
+				match error {
+					v if v == Error::<T>::OutOfGas.as_u8() => ExError::Error(ExitError::OutOfGas),
+					v if v == Error::<T>::OutOfFund.as_u8() => ExError::Error(ExitError::OutOfFund),
+					_ => unreachable!("this pallet only defines two possible errors"),
+				}
+			}
+			DispatchError::Module {
+				message: Some(msg), ..
+			} => ExError::Revert(msg.into()),
+			DispatchError::Module { index, error, .. } => {
+				ExError::Revert(format!("error {} in pallet {}", error, index))
+			}
+			e => ExError::Revert(format!("substrate error: {:?}", e)),
+		}
+	}
+
+	pub fn call_internal<C: evm_coder::Call, E: evm_coder::Callable<C>>(
+		caller: H160,
+		e: &mut E,
+		value: value,
+		input: &[u8],
+	) -> evm_coder::execution::Result<Option<AbiWriter>> {
+		let (selector, mut reader) = AbiReader::new_call(input)?;
+		let call = C::parse(selector, &mut reader)?;
+		if call.is_none() {
+			return Ok(None);
+		}
+		let call = call.unwrap();
+		e.call(Msg {
+			call,
+			caller,
+			value,
+		})
+		.map(Some)
+	}
+}
addedpallets/evm-contract-helpers/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-contract-helpers/Cargo.toml
@@ -0,0 +1,36 @@
+[package]
+name = "pallet-evm-contract-helpers"
+version = "0.1.0"
+edition = "2018"
+
+[dependencies]
+frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-runtime = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-core = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+evm-coder = { default-features = false, path = '../../crates/evm-coder' }
+pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
+pallet-evm = { default-features = false, version = "5.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+up-sponsorship = { default-features = false, path = '../../primitives/sponsorship' }
+log = "0.4.14"
+
+[dependencies.codec]
+default-features = false
+features = ['derive']
+package = 'parity-scale-codec'
+version = '2.0.0'
+
+[features]
+default = ["std"]
+std = [
+    "frame-support/std",
+    "frame-system/std",
+    "sp-runtime/std",
+    "sp-std/std",
+    "sp-core/std",
+    "evm-coder/std",
+    "pallet-evm-coder-substrate/std",
+    "pallet-evm/std",
+    "up-sponsorship/std",
+]
addedpallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -0,0 +1,167 @@
+use core::marker::PhantomData;
+use evm_coder::{abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*};
+use pallet_evm_coder_substrate::SubstrateRecorder;
+use pallet_evm::{ExitReason, ExitRevert, OnCreate, OnMethodCall, PrecompileOutput};
+use sp_core::H160;
+use crate::{
+	AllowlistEnabled, Config, Owner, Pallet, SelfSponsoring, SponsorBasket, SponsoringRateLimit,
+};
+use frame_support::traits::Get;
+use up_sponsorship::SponsorshipHandler;
+use sp_std::vec::Vec;
+
+struct ContractHelpers<T: Config>(SubstrateRecorder<T>);
+
+#[solidity_interface(name = "ContractHelpers")]
+impl<T: Config> ContractHelpers<T> {
+	fn contract_owner(&self, contract_address: address) -> Result<address> {
+		self.0.consume_sload()?;
+		Ok(<Owner<T>>::get(contract_address))
+	}
+
+	fn sponsoring_enabled(&self, contract_address: address) -> Result<bool> {
+		self.0.consume_sload()?;
+		Ok(<SelfSponsoring<T>>::get(contract_address))
+	}
+
+	fn toggle_sponsoring(
+		&mut self,
+		caller: caller,
+		contract_address: address,
+		enabled: bool,
+	) -> Result<void> {
+		self.0.consume_sload()?;
+		<Pallet<T>>::ensure_owner(contract_address, caller)?;
+		self.0.consume_sstore()?;
+		<Pallet<T>>::toggle_sponsoring(contract_address, enabled);
+		Ok(())
+	}
+
+	fn set_sponsoring_rate_limit(
+		&mut self,
+		caller: caller,
+		contract_address: address,
+		rate_limit: uint32,
+	) -> Result<void> {
+		self.0.consume_sload()?;
+		<Pallet<T>>::ensure_owner(contract_address, caller)?;
+		self.0.consume_sstore()?;
+		<Pallet<T>>::set_sponsoring_rate_limit(contract_address, rate_limit.into());
+		Ok(())
+	}
+
+	fn allowed(&self, contract_address: address, user: address) -> Result<bool> {
+		self.0.consume_sload()?;
+		Ok(<Pallet<T>>::allowed(contract_address, user, true))
+	}
+
+	fn allowlist_enabled(&self, contract_address: address) -> Result<bool> {
+		self.0.consume_sload()?;
+		Ok(<AllowlistEnabled<T>>::get(contract_address))
+	}
+
+	fn toggle_allowlist(
+		&mut self,
+		caller: caller,
+		contract_address: address,
+		enabled: bool,
+	) -> Result<void> {
+		self.0.consume_sload()?;
+		<Pallet<T>>::ensure_owner(contract_address, caller)?;
+		self.0.consume_sstore()?;
+		<Pallet<T>>::toggle_allowlist(contract_address, enabled);
+		Ok(())
+	}
+
+	fn toggle_allowed(
+		&mut self,
+		caller: caller,
+		contract_address: address,
+		user: address,
+		allowed: bool,
+	) -> Result<void> {
+		self.0.consume_sload()?;
+		<Pallet<T>>::ensure_owner(contract_address, caller)?;
+		self.0.consume_sstore()?;
+		<Pallet<T>>::toggle_allowed(contract_address, user, allowed);
+		Ok(())
+	}
+}
+
+pub struct HelpersOnMethodCall<T: Config>(PhantomData<*const T>);
+impl<T: Config> OnMethodCall<T> for HelpersOnMethodCall<T> {
+	fn is_reserved(contract: &sp_core::H160) -> bool {
+		contract == &T::ContractAddress::get()
+	}
+
+	fn is_used(contract: &sp_core::H160) -> bool {
+		contract == &T::ContractAddress::get()
+	}
+
+	fn call(
+		source: &sp_core::H160,
+		target: &sp_core::H160,
+		gas_left: u64,
+		input: &[u8],
+		value: sp_core::U256,
+	) -> Option<PrecompileOutput> {
+		// TODO: Extract to another OnMethodCall handler
+		if !<Pallet<T>>::allowed(*target, *source, true) {
+			return Some(PrecompileOutput {
+				exit_status: ExitReason::Revert(ExitRevert::Reverted),
+				cost: 0,
+				output: {
+					let mut writer = AbiWriter::new_call(evm_coder::fn_selector!(Error(string)));
+					writer.string("Target contract is allowlisted");
+					writer.finish()
+				},
+				logs: sp_std::vec![],
+			});
+		}
+
+		if target != &T::ContractAddress::get() {
+			return None;
+		}
+
+		let mut helpers = ContractHelpers::<T>(SubstrateRecorder::<T>::new(*target, gas_left));
+		let result = pallet_evm_coder_substrate::call_internal(*source, &mut helpers, value, input);
+		helpers.0.evm_to_precompile_output(result)
+	}
+
+	fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {
+		(contract == &T::ContractAddress::get())
+			.then(|| include_bytes!("./stubs/ContractHelpers.raw").to_vec())
+	}
+}
+
+pub struct HelpersOnCreate<T: Config>(PhantomData<*const T>);
+impl<T: Config> OnCreate<T> for HelpersOnCreate<T> {
+	fn on_create(owner: H160, contract: H160) {
+		<Owner<T>>::insert(contract, owner);
+	}
+}
+
+pub struct HelpersContractSponsoring<T: Config>(PhantomData<*const T>);
+impl<T: Config> SponsorshipHandler<H160, (H160, Vec<u8>)> for HelpersContractSponsoring<T> {
+	fn get_sponsor(who: &H160, call: &(H160, Vec<u8>)) -> Option<H160> {
+		if <SelfSponsoring<T>>::get(&call.0) && <Pallet<T>>::allowed(call.0, *who, false) {
+			let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+			if let Some(last_tx_block) = <SponsorBasket<T>>::get(&call.0, who) {
+				let rate_limit = <SponsoringRateLimit<T>>::get(&call.0);
+				let limit_time = last_tx_block + rate_limit;
+
+				if block_number > limit_time {
+					<SponsorBasket<T>>::insert(&call.0, who, block_number);
+					return Some(call.0);
+				}
+			} else {
+				<SponsorBasket<T>>::insert(&call.0, who, block_number);
+				return Some(call.0);
+			}
+		}
+		None
+	}
+}
+
+generate_stubgen!(contract_helpers_impl, ContractHelpersCall, true);
+generate_stubgen!(contract_helpers_iface, ContractHelpersCall, false);
addedpallets/evm-contract-helpers/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-contract-helpers/src/lib.rs
@@ -0,0 +1,100 @@
+#![cfg_attr(not(feature = "std"), no_std)]
+
+pub use pallet::*;
+pub use eth::*;
+pub mod eth;
+
+#[frame_support::pallet]
+pub mod pallet {
+	use evm_coder::execution::Result;
+	use frame_support::pallet_prelude::*;
+	use sp_core::H160;
+
+	#[pallet::config]
+	pub trait Config: frame_system::Config + pallet_evm_coder_substrate::Config {
+		type ContractAddress: Get<H160>;
+		type DefaultSponsoringRateLimit: Get<Self::BlockNumber>;
+	}
+
+	#[pallet::error]
+	pub enum Error<T> {
+		/// This method is only executable by owner
+		NoPermission,
+	}
+
+	#[pallet::pallet]
+	#[pallet::generate_store(pub(super) trait Store)]
+	pub struct Pallet<T>(_);
+
+	#[pallet::storage]
+	pub(super) type Owner<T: Config> =
+		StorageMap<Hasher = Twox128, Key = H160, Value = H160, QueryKind = ValueQuery>;
+
+	#[pallet::storage]
+	pub(super) type SelfSponsoring<T: Config> =
+		StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;
+
+	#[pallet::storage]
+	pub(super) type SponsoringRateLimit<T: Config> = StorageMap<
+		Hasher = Twox128,
+		Key = H160,
+		Value = T::BlockNumber,
+		QueryKind = ValueQuery,
+		OnEmpty = T::DefaultSponsoringRateLimit,
+	>;
+
+	#[pallet::storage]
+	pub(super) type SponsorBasket<T: Config> = StorageDoubleMap<
+		Hasher1 = Twox128,
+		Key1 = H160,
+		Hasher2 = Twox128,
+		Key2 = H160,
+		Value = T::BlockNumber,
+		QueryKind = OptionQuery,
+	>;
+
+	#[pallet::storage]
+	pub(super) type AllowlistEnabled<T: Config> =
+		StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;
+
+	#[pallet::storage]
+	pub(super) type Allowlist<T: Config> = StorageDoubleMap<
+		Hasher1 = Twox128,
+		Key1 = H160,
+		Hasher2 = Twox128,
+		Key2 = H160,
+		Value = bool,
+		QueryKind = ValueQuery,
+	>;
+
+	impl<T: Config> Pallet<T> {
+		pub fn toggle_sponsoring(contract: H160, enabled: bool) {
+			<SelfSponsoring<T>>::insert(contract, enabled);
+		}
+
+		pub fn set_sponsoring_rate_limit(contract: H160, rate_limit: T::BlockNumber) {
+			<SponsoringRateLimit<T>>::insert(contract, rate_limit);
+		}
+
+		/// Default is returned if allowlist is disabled
+		pub fn allowed(contract: H160, user: H160, default: bool) -> bool {
+			if !<AllowlistEnabled<T>>::get(contract) {
+				return default;
+			}
+			<Allowlist<T>>::get(&contract, &user) || <Owner<T>>::get(&contract) == user
+		}
+
+		pub fn toggle_allowlist(contract: H160, enabled: bool) {
+			<AllowlistEnabled<T>>::insert(contract, enabled)
+		}
+
+		pub fn toggle_allowed(contract: H160, user: H160, allowed: bool) {
+			<Allowlist<T>>::insert(contract, user, allowed);
+		}
+
+		pub fn ensure_owner(contract: H160, user: H160) -> Result<()> {
+			ensure!(<Owner<T>>::get(&contract) == user, "no permission");
+			Ok(())
+		}
+	}
+}
addedpallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterboth

binary blob — no preview

addedpallets/evm-contract-helpers/src/stubs/ContractHelpers.soldiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: OTHER
+// This code is automatically generated
+
+pragma solidity >=0.8.0 <0.9.0;
+
+// Common stubs holder
+contract Dummy {
+	uint8 dummy;
+	string stub_error = "this contract is implemented in native";
+}
+
+contract ContractHelpers is Dummy {
+	function contractOwner(address contractAddress)
+		public
+		view
+		returns (address)
+	{
+		require(false, stub_error);
+		contractAddress;
+		dummy;
+		return 0x0000000000000000000000000000000000000000;
+	}
+
+	function sponsoringEnabled(address contractAddress)
+		public
+		view
+		returns (bool)
+	{
+		require(false, stub_error);
+		contractAddress;
+		dummy;
+		return false;
+	}
+
+	function toggleSponsoring(address contractAddress, bool enabled) public {
+		require(false, stub_error);
+		contractAddress;
+		enabled;
+		dummy = 0;
+	}
+
+	function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)
+		public
+	{
+		require(false, stub_error);
+		contractAddress;
+		rateLimit;
+		dummy = 0;
+	}
+
+	function allowed(address contractAddress, address user)
+		public
+		view
+		returns (bool)
+	{
+		require(false, stub_error);
+		contractAddress;
+		user;
+		dummy;
+		return false;
+	}
+
+	function allowlistEnabled(address contractAddress)
+		public
+		view
+		returns (bool)
+	{
+		require(false, stub_error);
+		contractAddress;
+		dummy;
+		return false;
+	}
+
+	function toggleAllowlist(address contractAddress, bool enabled) public {
+		require(false, stub_error);
+		contractAddress;
+		enabled;
+		dummy = 0;
+	}
+
+	function toggleAllowed(
+		address contractAddress,
+		address user,
+		bool allowed
+	) public {
+		require(false, stub_error);
+		contractAddress;
+		user;
+		allowed;
+		dummy = 0;
+	}
+}
addedpallets/evm-migration/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-migration/Cargo.toml
@@ -0,0 +1,36 @@
+[package]
+name = "pallet-evm-migration"
+version = "0.1.0"
+edition = "2018"
+
+[dependencies]
+frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-benchmarking = { default-features = false, version = '3.0.0', optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-runtime = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-io = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-core = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+pallet-evm = { default-features = false, version = "5.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fp-evm = { default-features = false, version = "2.0.0", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+
+[dependencies.codec]
+default-features = false
+features = ['derive']
+package = 'parity-scale-codec'
+version = '2.0.0'
+
+[features]
+default = ["std", "runtime-benchmarks"]
+std = [
+    "frame-support/std",
+    "frame-system/std",
+    "frame-benchmarking/std",
+    "sp-runtime/std",
+    "sp-std/std",
+    "sp-io/std",
+    "sp-core/std",
+    "pallet-evm/std",
+    "fp-evm/std",
+]
+runtime-benchmarks = ["frame-benchmarking"]
addedpallets/evm-migration/src/benchmarking.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-migration/src/benchmarking.rs
@@ -0,0 +1,30 @@
+use super::{Call, Config, Pallet};
+use frame_benchmarking::benchmarks;
+use frame_system::RawOrigin;
+use sp_core::{H160, H256};
+use sp_std::vec::Vec;
+
+benchmarks! {
+	begin {
+	}: _(RawOrigin::Root, H160::default())
+
+	set_data {
+		let b in 0..80;
+		let address = H160::from_low_u64_be(b as u64);
+		let mut data = Vec::new();
+		for i in 0..b {
+			data.push((
+				H256::from_low_u64_be(i as u64),
+				H256::from_low_u64_be(i as u64),
+			));
+		}
+		<Pallet<T>>::begin(RawOrigin::Root.into(), address)?;
+	}: _(RawOrigin::Root, address, data)
+
+	finish {
+		let b in 0..80;
+		let address = H160::from_low_u64_be(b as u64);
+		let data: Vec<u8> = (0..b as u8).collect();
+		<Pallet<T>>::begin(RawOrigin::Root.into(), address)?;
+	}: _(RawOrigin::Root, address, data)
+}
addedpallets/evm-migration/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-migration/src/lib.rs
@@ -0,0 +1,111 @@
+#![cfg_attr(not(feature = "std"), no_std)]
+
+pub use pallet::*;
+#[cfg(feature = "runtime-benchmarks")]
+pub mod benchmarking;
+pub mod weights;
+
+#[frame_support::pallet]
+pub mod pallet {
+	use frame_support::{pallet_prelude::*, transactional};
+	use frame_system::pallet_prelude::*;
+	use sp_core::{H160, H256};
+	use sp_std::vec::Vec;
+	use super::weights::WeightInfo;
+
+	#[pallet::config]
+	pub trait Config: frame_system::Config + pallet_evm::Config {
+		type WeightInfo: WeightInfo;
+	}
+
+	type SelfWeightOf<T> = <T as Config>::WeightInfo;
+
+	#[pallet::pallet]
+	#[pallet::generate_store(pub(super) trait Store)]
+	pub struct Pallet<T>(_);
+
+	#[pallet::error]
+	pub enum Error<T> {
+		AccountNotEmpty,
+		AccountIsNotMigrating,
+	}
+
+	#[pallet::storage]
+	pub(super) type MigrationPending<T: Config> =
+		StorageMap<Hasher = Twox64Concat, Key = H160, Value = bool, QueryKind = ValueQuery>;
+
+	#[pallet::call]
+	impl<T: Config> Pallet<T> {
+		#[pallet::weight(<SelfWeightOf<T>>::begin())]
+		pub fn begin(origin: OriginFor<T>, address: H160) -> DispatchResult {
+			ensure_root(origin)?;
+			ensure!(
+				<pallet_evm::Pallet<T>>::is_account_empty(&address)
+					&& !<MigrationPending<T>>::get(&address),
+				<Error<T>>::AccountNotEmpty,
+			);
+
+			<MigrationPending<T>>::insert(address, true);
+			Ok(())
+		}
+
+		#[pallet::weight(<SelfWeightOf<T>>::set_data(data.len() as u32))]
+		pub fn set_data(
+			origin: OriginFor<T>,
+			address: H160,
+			data: Vec<(H256, H256)>,
+		) -> DispatchResult {
+			use frame_support::StorageDoubleMap;
+			ensure_root(origin)?;
+			ensure!(
+				<MigrationPending<T>>::get(&address),
+				<Error<T>>::AccountIsNotMigrating,
+			);
+
+			for (k, v) in data {
+				pallet_evm::AccountStorages::insert(&address, k, v);
+			}
+			Ok(())
+		}
+
+		#[pallet::weight(<SelfWeightOf<T>>::finish(code.len() as u32))]
+		#[transactional]
+		pub fn finish(origin: OriginFor<T>, address: H160, code: Vec<u8>) -> DispatchResult {
+			use frame_support::StorageMap;
+			ensure_root(origin)?;
+			ensure!(
+				<MigrationPending<T>>::get(&address),
+				<Error<T>>::AccountIsNotMigrating,
+			);
+
+			pallet_evm::AccountCodes::insert(&address, code);
+			<MigrationPending<T>>::remove(address);
+			Ok(())
+		}
+	}
+
+	pub struct OnMethodCall<T>(PhantomData<T>);
+	impl<T: Config> pallet_evm::OnMethodCall<T> for OnMethodCall<T> {
+		fn is_reserved(contract: &H160) -> bool {
+			<MigrationPending<T>>::get(&contract)
+		}
+
+		fn is_used(_contract: &H160) -> bool {
+			false
+		}
+
+		fn call(
+			_source: &H160,
+			_arget: &H160,
+			_gas_left: u64,
+			_input: &[u8],
+			_value: sp_core::U256,
+		) -> Option<pallet_evm::PrecompileOutput> {
+			None
+		}
+
+		fn get_code(_contract: &H160) -> Option<Vec<u8>> {
+			None
+		}
+	}
+}
addedpallets/evm-migration/src/weights.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-migration/src/weights.rs
@@ -0,0 +1,80 @@
+// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs
+
+//! Autogenerated weights for pallet_evm_migration
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
+//! DATE: 2021-08-12, STEPS: `[50, ]`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 128
+
+// Executed Command:
+// target/release/nft
+// benchmark
+// --pallet
+// pallet-evm-migration
+// --wasm-execution
+// compiled
+// --extrinsic
+// *
+// --template
+// .maintain/frame-weight-template.hbs
+// --steps=50
+// --repeat=20
+// --output=./pallets/evm-migration/src/weights.rs
+
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use sp_std::marker::PhantomData;
+
+/// Weight functions needed for pallet_evm_migration.
+pub trait WeightInfo {
+	fn begin() -> Weight;
+	fn set_data(b: u32, ) -> Weight;
+	fn finish(b: u32, ) -> Weight;
+}
+
+/// Weights for pallet_evm_migration using the Substrate node and recommended hardware.
+pub struct SubstrateWeight<T>(PhantomData<T>);
+impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
+	fn begin() -> Weight {
+		(6_210_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(3 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn set_data(b: u32, ) -> Weight {
+		(2_926_000 as Weight)
+			// Standard Error: 4_000
+			.saturating_add((649_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(b as Weight)))
+	}
+	fn finish(_b: u32, ) -> Weight {
+		(4_309_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(2 as Weight))
+	}
+}
+
+// For backwards compatibility and tests
+impl WeightInfo for () {
+	fn begin() -> Weight {
+		(6_210_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(3 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn set_data(b: u32, ) -> Weight {
+		(2_926_000 as Weight)
+			// Standard Error: 4_000
+			.saturating_add((649_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(b as Weight)))
+	}
+	fn finish(_b: u32, ) -> Weight {
+		(4_309_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(2 as Weight))
+	}
+}
\ No newline at end of file
addedpallets/evm-transaction-payment/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-transaction-payment/Cargo.toml
@@ -0,0 +1,37 @@
+[package]
+name = "pallet-evm-transaction-payment"
+version = "0.1.0"
+edition = "2018"
+
+[dependencies]
+frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-runtime = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-io = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-core = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+pallet-evm = { default-features = false, version = "5.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fp-evm = { default-features = false, version = "2.0.0", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+pallet-ethereum = { default-features = false, version = "3.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+up-sponsorship = { default-features = false, path = '../../primitives/sponsorship' }
+
+[dependencies.codec]
+default-features = false
+features = ['derive']
+package = 'parity-scale-codec'
+version = '2.0.0'
+
+[features]
+default = ["std"]
+std = [
+    "frame-support/std",
+    "frame-system/std",
+    "sp-runtime/std",
+    "sp-std/std",
+    "sp-io/std",
+    "sp-core/std",
+    "pallet-evm/std",
+    "pallet-ethereum/std",
+    "fp-evm/std",
+    "up-sponsorship/std",
+]
addedpallets/evm-transaction-payment/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-transaction-payment/src/lib.rs
@@ -0,0 +1,98 @@
+#![cfg_attr(not(feature = "std"), no_std)]
+
+pub use pallet::*;
+
+#[frame_support::pallet]
+pub mod pallet {
+	use core::marker::PhantomData;
+	use frame_support::traits::Currency;
+	use pallet_evm::EVMCurrencyAdapter;
+	use fp_evm::WithdrawReason;
+	use sp_core::{H160, U256};
+	use sp_runtime::TransactionOutcome;
+	use up_sponsorship::SponsorshipHandler;
+	use sp_std::vec::Vec;
+
+	type NegativeImbalanceOf<C, T> =
+		<C as Currency<<T as frame_system::Config>::AccountId>>::NegativeImbalance;
+
+	#[pallet::config]
+	pub trait Config: frame_system::Config {
+		type SponsorshipHandler: SponsorshipHandler<H160, (H160, Vec<u8>)>;
+		type Currency: Currency<Self::AccountId>;
+	}
+
+	#[pallet::pallet]
+	#[pallet::generate_store(pub(super) trait Store)]
+	pub struct Pallet<T>(_);
+
+	pub struct ChargeEvmLiquidityInfo<T>
+	where
+		T: Config,
+		T: pallet_evm::Config,
+	{
+		who: H160,
+		negative_imbalance: NegativeImbalanceOf<<T as Config>::Currency, T>,
+	}
+
+	pub struct TransactionValidityHack<T: Config>(PhantomData<*const T>);
+	impl<T: Config> fp_evm::TransactionValidityHack for TransactionValidityHack<T> {
+		fn who_pays_fee(origin: H160, reason: &WithdrawReason) -> Option<H160> {
+			match reason {
+				WithdrawReason::Call { target, input } => {
+					// This method is only used for checking, we shouldn't touch storage in it
+					frame_support::storage::with_transaction(|| {
+						TransactionOutcome::Rollback(T::SponsorshipHandler::get_sponsor(
+							&origin,
+							&(*target, input.clone()),
+						))
+					})
+				}
+				_ => None,
+			}
+		}
+	}
+
+	pub struct OnChargeTransaction<T: Config>(PhantomData<*const T>);
+	impl<T> pallet_evm::OnChargeEVMTransaction<T> for OnChargeTransaction<T>
+	where
+		T: Config,
+		T: pallet_evm::Config,
+	{
+		type LiquidityInfo = Option<ChargeEvmLiquidityInfo<T>>;
+
+		fn withdraw_fee(
+			who: &H160,
+			reason: WithdrawReason,
+			fee: U256,
+		) -> core::result::Result<Self::LiquidityInfo, pallet_evm::Error<T>> {
+			let mut who_pays_fee = *who;
+			if let WithdrawReason::Call { target, input } = &reason {
+				who_pays_fee = T::SponsorshipHandler::get_sponsor(who, &(*target, input.clone()))
+					.unwrap_or(who_pays_fee);
+			}
+			let negative_imbalance =
+				EVMCurrencyAdapter::<<T as Config>::Currency, ()>::withdraw_fee(
+					&who_pays_fee,
+					reason,
+					fee,
+				)?;
+			Ok(negative_imbalance.map(|i| ChargeEvmLiquidityInfo {
+				who: who_pays_fee,
+				negative_imbalance: i,
+			}))
+		}
+
+		fn correct_and_deposit_fee(
+			who: &H160,
+			corrected_fee: U256,
+			already_withdrawn: Self::LiquidityInfo,
+		) -> core::result::Result<(), pallet_evm::Error<T>> {
+			EVMCurrencyAdapter::<<T as Config>::Currency, ()>::correct_and_deposit_fee(
+				&already_withdrawn.as_ref().map(|e| e.who).unwrap_or(*who),
+				corrected_fee,
+				already_withdrawn.map(|e| e.negative_imbalance),
+			)
+		}
+	}
+}
modifiedpallets/inflation/Cargo.tomldiffbeforeafterboth
--- a/pallets/inflation/Cargo.toml
+++ b/pallets/inflation/Cargo.toml
@@ -43,43 +43,43 @@
 default-features = false
 optional = true
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.frame-support]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.frame-system]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-balances]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-timestamp]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-randomness-collective-flip]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-std]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.serde]
@@ -90,18 +90,18 @@
 [dependencies.sp-runtime]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-core]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-io]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
modifiedpallets/inflation/src/tests.rsdiffbeforeafterboth
--- a/pallets/inflation/src/tests.rs
+++ b/pallets/inflation/src/tests.rs
@@ -32,7 +32,7 @@
 	type WeightInfo = ();
 	type MaxLocks = MaxLocks;
 	type MaxReserves = ();
-	type ReserveIdentifier = [u8; 8];
+	type ReserveIdentifier = ();
 }
 
 frame_support::construct_runtime!(
@@ -91,7 +91,6 @@
 	type InflationBlockInterval = InflationBlockInterval;
 }
 
-// Build genesis storage according to the mock runtime.
 pub fn new_test_ext() -> sp_io::TestExternalities {
 	frame_system::GenesisConfig::default()
 		.build_storage::<Test>()
@@ -110,7 +109,9 @@
 		// BlockInflation should be set after 1st block and
 		// first inflation deposit should be equal to BlockInflation
 		Inflation::on_initialize(1);
-		assert!(Inflation::block_inflation() > 0);
+
+		// SBP M2 review: Verify expected block inflation for year 1
+		assert_eq!(Inflation::block_inflation(), 1901);
 		assert_eq!(
 			Balances::free_balance(1234) - initial_issuance,
 			Inflation::block_inflation()
@@ -157,11 +158,24 @@
 		Inflation::on_initialize(1);
 		let block_inflation_year_0 = Inflation::block_inflation();
 
+		// SBP M2 review: go through all the block inflations for year 1,
+		// total issuance will be updated accordingly
+		for block in (100..YEAR).step_by(100) {
+			Inflation::on_initialize(block);
+		}
+		assert_eq!(
+			initial_issuance + (1901 * (YEAR / 100)),
+			<Balances as Currency<_>>::total_issuance()
+		);
+
 		Inflation::on_initialize(YEAR);
 		let block_inflation_year_1 = Inflation::block_inflation();
+		// SBP M2 review: Verify expected block inflation for year 2
+		assert_eq!(block_inflation_year_1, 1952);
 
+		// SBP M2 review: this is actually not true
 		// Assert that year 1 inflation is less than year 0
-		assert!(block_inflation_year_0 > block_inflation_year_1);
+		// assert!(block_inflation_year_0 > block_inflation_year_1);
 	});
 }
 
@@ -179,6 +193,7 @@
 			Inflation::on_initialize(YEAR * year);
 			let block_inflation_year_after = Inflation::block_inflation();
 
+			// SBP M2 review: this is actually not true (not for the first few years)
 			// Assert that next year inflation is less than previous year inflation
 			assert!(block_inflation_year_before > block_inflation_year_after);
 		}
modifiedpallets/nft-charge-transaction/Cargo.tomldiffbeforeafterboth
--- a/pallets/nft-charge-transaction/Cargo.toml
+++ b/pallets/nft-charge-transaction/Cargo.toml
@@ -20,15 +20,15 @@
 
 [dependencies]
 serde = { version = "1.0.119", default-features = false }
-frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-pallet-balances = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-pallet-transaction-payment = { default-features = false, version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-frame-benchmarking = { default-features = false, version = "3.0.0", optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-core = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-io = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-runtime = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
+frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+pallet-balances = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+pallet-transaction-payment = { default-features = false, version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-benchmarking = { default-features = false, version = "3.0.0", optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-core = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-io = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-runtime = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
 
 pallet-nft-transaction-payment = { default-features = false, path="../nft-transaction-payment" }
 
modifiedpallets/nft-charge-transaction/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft-charge-transaction/src/lib.rs
+++ b/pallets/nft-charge-transaction/src/lib.rs
@@ -76,7 +76,7 @@
 	where
 		T::Call: Dispatchable<Info = DispatchInfo>,
 	{
-		<pallet_transaction_payment::Module<T>>::compute_fee(len as u32, info, tip)
+		<pallet_transaction_payment::Pallet<T>>::compute_fee(len as u32, info, tip)
 	}
 
 	fn get_priority(
modifiedpallets/nft-transaction-payment/Cargo.tomldiffbeforeafterboth
--- a/pallets/nft-transaction-payment/Cargo.toml
+++ b/pallets/nft-transaction-payment/Cargo.toml
@@ -20,14 +20,14 @@
 
 [dependencies]
 serde = { version = "1.0.119", default-features = false }
-frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-pallet-transaction-payment = { default-features = false, version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-frame-benchmarking = { default-features = false, version = "3.0.0", optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-core = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-io = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-runtime = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
+frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+pallet-transaction-payment = { default-features = false, version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-benchmarking = { default-features = false, version = "3.0.0", optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-core = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-io = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-runtime = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
 
 up-sponsorship = { default-features = false, path = "../../primitives/sponsorship", version = "0.1.0" }
 
deletedpallets/nft-transaction-payment/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/nft-transaction-payment/src/benchmarking.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#![cfg(feature = "runtime-benchmarks")]
-
-use super::*;
-
-use sp_std::prelude::*;
-use frame_system::RawOrigin;
-use frame_benchmarking::{benchmarks};
-use frame_support::traits::OnInitialize;
-
-benchmarks! {
-
-	// on_initialize {
-		// let block1: T::BlockNumber = T::BlockNumber::from(1u32);
-		// let block2: T::BlockNumber = T::BlockNumber::from(2u32);
-		// Inflation::<T>::on_initialize(block1); // Create Treasury account
-	// }: { Inflation::<T>::on_initialize(block2); } // Benchmark deposit_into_existing path
-
-}
modifiedpallets/nft-transaction-payment/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft-transaction-payment/src/lib.rs
+++ b/pallets/nft-transaction-payment/src/lib.rs
@@ -11,9 +11,6 @@
 #[cfg(feature = "std")]
 pub use serde::*;
 
-#[cfg(feature = "runtime-benchmarks")]
-mod benchmarking;
-
 use frame_support::{decl_module, decl_storage};
 use sp_std::prelude::*;
 use up_sponsorship::SponsorshipHandler;
modifiedpallets/nft/Cargo.tomldiffbeforeafterboth
--- a/pallets/nft/Cargo.toml
+++ b/pallets/nft/Cargo.toml
@@ -37,10 +37,11 @@
     'ethereum/std',
     'rlp/std',
 
-    'ethereum-tx-sign',
     'primitive-types/std',
     'evm-coder/std',
+    'pallet-evm-coder-substrate/std',
 ]
+limit-testing = ["nft-data-structs/limit-testing"]
 
 ################################################################################
 # Substrate Dependencies
@@ -55,49 +56,49 @@
 default-features = false
 optional = true
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.frame-support]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.frame-system]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-balances]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-timestamp]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-randomness-collective-flip]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-std]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-transaction-payment]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.serde]
@@ -108,19 +109,19 @@
 [dependencies.sp-runtime]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-core]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-io]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 
@@ -139,15 +140,17 @@
 
 
 [dependencies]
-ethereum-tx-sign = { version = "3.0.4", optional = true }
 ethereum = { default-features = false, version = "0.7.1" }
 rlp = { default-features = false, version = "0.5.0" }
-sp-api = { default-features = false, version = '3.0.0', git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.7" }
+sp-api = { default-features = false, version = '3.0.0', git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.8" }
 
 evm-coder = { default-features = false, path = "../../crates/evm-coder" }
-primitive-types = { version = "0.9.0", default-features = false, features = ["serde_no_std"] }
+pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }
+primitive-types = { version = "0.9.0", default-features = false, features = [
+    "serde_no_std",
+] }
 
-pallet-evm = { default-features = false, version = "5.0.0-dev", git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-pallet-ethereum = { default-features = false, version = "3.0.0-dev", git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-fp-evm = { default-features = false, version = '2.0.0', git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-hex-literal = "0.3.1"
\ No newline at end of file
+pallet-evm = { default-features = false, version = "5.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+pallet-ethereum = { default-features = false, version = "3.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fp-evm = { default-features = false, version = '2.0.0', git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+hex-literal = "0.3.1"
modifiedpallets/nft/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/nft/src/benchmarking.rs
+++ b/pallets/nft/src/benchmarking.rs
@@ -1,419 +1,342 @@
 #![cfg(feature = "runtime-benchmarks")]
 
 use super::*;
-use crate::Module as Nft;
-
-use sp_std::prelude::*;
+use crate::Pallet;
 use frame_system::RawOrigin;
-use frame_benchmarking::{benchmarks, account, whitelisted_caller}; // , TrackedStorageKey,
+use frame_benchmarking::{benchmarks, account};
+use nft_data_structs::*;
+use core::convert::TryInto;
+use sp_runtime::DispatchError;
 
 const SEED: u32 = 1;
-/*
+
+fn create_data(size: usize) -> Vec<u8> {
+	(0..size).map(|v| (v & 0xff) as u8).collect()
+}
+fn create_u16_data(size: usize) -> Vec<u16> {
+	(0..size).map(|v| (v & 0xffff) as u16).collect()
+}
+
 fn default_nft_data() -> CreateItemData {
-	CreateItemData::NFT(CreateNftData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] })
+	CreateItemData::NFT(CreateNftData {
+		const_data: create_data(CUSTOM_DATA_LIMIT as usize).try_into().unwrap(),
+		variable_data: create_data(CUSTOM_DATA_LIMIT as usize).try_into().unwrap(),
+	})
 }
 
-fn default_fungible_data () -> CreateItemData {
-	CreateItemData::Fungible(CreateFungibleData { })
+fn default_fungible_data() -> CreateItemData {
+	CreateItemData::Fungible(CreateFungibleData { value: 1000 })
 }
 
-fn default_re_fungible_data () -> CreateItemData {
-	CreateItemData::ReFungible(CreateReFungibleData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] })
+fn default_re_fungible_data() -> CreateItemData {
+	CreateItemData::ReFungible(CreateReFungibleData {
+		const_data: create_data(CUSTOM_DATA_LIMIT as usize).try_into().unwrap(),
+		variable_data: create_data(CUSTOM_DATA_LIMIT as usize).try_into().unwrap(),
+		pieces: 1000,
+	})
+}
+
+fn create_collection_helper<T: Config>(
+	owner: T::AccountId,
+	mode: CollectionMode,
+) -> Result<CollectionId, DispatchError> {
+	T::Currency::deposit_creating(&owner, T::CollectionCreationPrice::get());
+	let col_name = create_u16_data(MAX_COLLECTION_NAME_LENGTH)
+		.try_into()
+		.unwrap();
+	let col_desc = create_u16_data(MAX_COLLECTION_DESCRIPTION_LENGTH)
+		.try_into()
+		.unwrap();
+	let token_prefix = create_data(MAX_TOKEN_PREFIX_LENGTH).try_into().unwrap();
+	<Pallet<T>>::create_collection(
+		RawOrigin::Signed(owner).into(),
+		col_name,
+		col_desc,
+		token_prefix,
+		mode,
+	)?;
+	Ok(CreatedCollectionCount::get())
+}
+fn create_nft_collection<T: Config>(owner: T::AccountId) -> Result<CollectionId, DispatchError> {
+	create_collection_helper::<T>(owner, CollectionMode::NFT)
+}
+fn create_fungible_collection<T: Config>(
+	owner: T::AccountId,
+) -> Result<CollectionId, DispatchError> {
+	create_collection_helper::<T>(owner, CollectionMode::Fungible(0))
+}
+fn create_refungible_collection<T: Config>(
+	owner: T::AccountId,
+) -> Result<CollectionId, DispatchError> {
+	create_collection_helper::<T>(owner, CollectionMode::ReFungible)
 }
-*/
 
 benchmarks! {
 
 	create_collection {
-		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 col_name: Vec<u16> = create_u16_data(MAX_COLLECTION_NAME_LENGTH);
+		let col_desc: Vec<u16> = create_u16_data(MAX_COLLECTION_DESCRIPTION_LENGTH);
+		let token_prefix: Vec<u8> = create_data(MAX_TOKEN_PREFIX_LENGTH);
 		let mode: CollectionMode = CollectionMode::NFT;
 		let caller: T::AccountId = account("caller", 0, SEED);
-	}: _(RawOrigin::Signed(caller.clone()), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode)
-/*
+		T::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get());
+	}: _(RawOrigin::Signed(caller.clone()), col_name.clone(), col_desc.clone(), token_prefix.clone(), mode)
 	verify {
-		assert_eq!(Nft::<T>::collection_id(2).owner, caller);
+		assert_eq!(<Pallet<T>>::collection_id(2).unwrap().owner, caller);
 	}
+
 	destroy_collection {
-		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())?;
-	}: _(RawOrigin::Signed(caller.clone()), 2)
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection)
 
 	add_to_white_list {
-		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());
+		let caller: T::AccountId = account("caller", 0, SEED);
 		let whitelist_account: T::AccountId = account("admin", 0, SEED);
-		Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
-	}: add_to_white_list(RawOrigin::Signed(caller.clone()), 2, whitelist_account)
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(whitelist_account))
 
 	remove_from_white_list {
-		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());
+		let caller: T::AccountId = account("caller", 0, SEED);
 		let whitelist_account: T::AccountId = account("admin", 0, SEED);
-		Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
-		Nft::<T>::add_to_white_list(RawOrigin::Signed(caller.clone()).into(), 2, whitelist_account.clone())?;
-	}: remove_from_white_list(RawOrigin::Signed(caller.clone()), 2, whitelist_account)
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		<Pallet<T>>::add_to_white_list(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(whitelist_account.clone()))?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(whitelist_account))
 
 	set_public_access_mode {
-		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_public_access_mode(RawOrigin::Signed(caller.clone()), 2, AccessMode::WhiteList)
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, AccessMode::WhiteList)
 
 	set_mint_permission {
-		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_mint_permission(RawOrigin::Signed(caller.clone()), 2, true)
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, true)
 
 	change_collection_owner {
-		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 caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
 		let new_owner: T::AccountId = account("admin", 0, SEED);
-	}: change_collection_owner(RawOrigin::Signed(caller.clone()), 2, new_owner)
+	}: _(RawOrigin::Signed(caller.clone()), collection, new_owner)
 
 	add_collection_admin {
-		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 caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
 		let new_admin: T::AccountId = account("admin", 0, SEED);
-	}: add_collection_admin(RawOrigin::Signed(caller.clone()), 2, new_admin)
+	}: _(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(new_admin))
 
 	remove_collection_admin {
-		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 caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
 		let new_admin: T::AccountId = account("admin", 0, SEED);
-		Nft::<T>::add_collection_admin(RawOrigin::Signed(caller.clone()).into(), 2, new_admin.clone())?;
-	}: remove_collection_admin(RawOrigin::Signed(caller.clone()), 2, new_admin)
+		<Pallet<T>>::add_collection_admin(RawOrigin::Signed(caller.clone()).into(), 2, T::CrossAccountId::from_sub(new_admin.clone()))?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(new_admin))
 
 	set_collection_sponsor {
-		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_collection_sponsor(RawOrigin::Signed(caller.clone()), 2, caller.clone())
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, caller.clone())
 
 	confirm_sponsorship {
-		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())?;
-		Nft::<T>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone())?;
-	}: confirm_sponsorship(RawOrigin::Signed(caller.clone()), 2)
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		<Pallet<T>>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection)
 
 	remove_collection_sponsor {
-		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())?;
-		Nft::<T>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone())?;
-		Nft::<T>::confirm_sponsorship(RawOrigin::Signed(caller.clone()).into(), 2)?;
-	}: remove_collection_sponsor(RawOrigin::Signed(caller.clone()), 2)
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		<Pallet<T>>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone())?;
+		<Pallet<T>>::confirm_sponsorship(RawOrigin::Signed(caller.clone()).into(), 2)?;
+	}: _(RawOrigin::Signed(caller.clone()), collection)
 
 	// nft item
 	create_item_nft {
-		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 data = default_nft_data();
+		let b in 0..(CUSTOM_DATA_LIMIT * 2);
 
-	}: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		let data = CreateItemData::NFT(CreateNftData {
+			const_data: create_data(b.min(CUSTOM_DATA_LIMIT) as usize).try_into().unwrap(),
+			variable_data: create_data(b.saturating_sub(CUSTOM_DATA_LIMIT) as usize).try_into().unwrap(),
+		});
+	}: create_item(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(caller.clone()), data)
 
-	#[extra]
-	create_item_nft_large {
-		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());
-		let mut nft_data = CreateNftData {
-			const_data: vec![],
-			variable_data: vec![]
-		};
-		for i in 0..1998 {
-			nft_data.const_data.push(10);
-			nft_data.variable_data.push(10);
-		}
-		let data = CreateItemData::NFT(nft_data);
-		Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
+	create_multiple_items_nft {
+		// TODO: Take item data size into account. As create_item_nft bench shows, this parameter has no effect on execution time,
+		// but it may if we increase CUSTOM_DATA_LIMIT
+		let b in 1..1000;
 
-	}: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		let data = (0..b).map(|_| default_nft_data()).collect();
+	}: create_multiple_items(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(caller.clone()), data)
 
 	// fungible item
 	create_item_fungible {
-		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::Fungible(3);
-		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 data = default_fungible_data();
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_fungible_collection::<T>(caller.clone())?;
+		let data = CreateItemData::Fungible(CreateFungibleData {
+			value: 1000,
+		});
+	}: create_item(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(caller.clone()), data)
+
+	create_multiple_items_fungible {
+		let b in 1..1000;
 
-	}: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_fungible_collection::<T>(caller.clone())?;
+		let data = (0..b).map(|_| default_fungible_data()).collect();
+	}: create_multiple_items(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(caller.clone()), data)
 
 	// refungible item
 	create_item_refungible {
-		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::ReFungible(3);
-		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 data = default_re_fungible_data();
+		let b in 0..(CUSTOM_DATA_LIMIT * 2);
 
-	}: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_refungible_collection::<T>(caller.clone())?;
+		let data = CreateItemData::ReFungible(CreateReFungibleData {
+			const_data: create_data(b.min(CUSTOM_DATA_LIMIT) as usize).try_into().unwrap(),
+			variable_data: create_data(b.saturating_sub(CUSTOM_DATA_LIMIT) as usize).try_into().unwrap(),
+			pieces: 1000,
+		});
+	}: create_item(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(caller.clone()), data)
 
-	burn_item {
-		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 data = default_nft_data();
-		Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
+	create_multiple_items_refungible {
+		// TODO: Take item data size into account. As create_item_nft bench shows, this parameter has no effect on execution time,
+		// but it may if we increase CUSTOM_DATA_LIMIT
+		let b in 1..1000;
 
-	}: burn_item(RawOrigin::Signed(caller.clone()), 2, 1)
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_refungible_collection::<T>(caller.clone())?;
+		let data = (0..b).map(|_| default_re_fungible_data()).collect();
+	}: create_multiple_items(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(caller.clone()), data)
 
+	burn_item_nft {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		let data = default_nft_data();
+		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(caller.clone()), data)?;
+	}: burn_item(RawOrigin::Signed(caller.clone()), collection, 1, 1)
+
 	transfer_nft {
-		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 = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
 		let recipient: T::AccountId = account("recipient", 0, SEED);
-		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 data = default_nft_data();
-		Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
-
-	}: transfer(RawOrigin::Signed(caller.clone()), recipient.clone(), 2, 1, 1)
+		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(caller.clone()), data)?;
+	}: transfer(RawOrigin::Signed(caller.clone()), T::CrossAccountId::from_sub(recipient.clone()), collection, 1, 1)
 
 	transfer_fungible {
-		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::Fungible(3);
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_fungible_collection::<T>(caller.clone())?;
 		let recipient: T::AccountId = account("recipient", 0, SEED);
-		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 data = default_fungible_data();
-		Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
-
-	}: transfer(RawOrigin::Signed(caller.clone()), recipient.clone(), 2, 1, 1)
+		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(caller.clone()), data)?;
+	}: transfer(RawOrigin::Signed(caller.clone()), T::CrossAccountId::from_sub(recipient.clone()), collection, 1, 1)
 
 	transfer_refungible {
-		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::ReFungible(3);
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_refungible_collection::<T>(caller.clone())?;
 		let recipient: T::AccountId = account("recipient", 0, SEED);
-		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 data = default_re_fungible_data();
-		Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
+		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(caller.clone()), data)?;
+	}: transfer(RawOrigin::Signed(caller.clone()), T::CrossAccountId::from_sub(recipient.clone()), collection, 1, 1)
 
-	}: transfer(RawOrigin::Signed(caller.clone()), recipient.clone(), 2, 1, 1)
+	set_transfers_enabled_flag {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, false)
 
-	approve {
-		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::ReFungible(3);
+	approve_nft {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
 		let recipient: T::AccountId = account("recipient", 0, SEED);
-		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 data = default_re_fungible_data();
-		Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
-
-	}: approve(RawOrigin::Signed(caller.clone()), recipient.clone(), 2, 1)
+		let data = default_nft_data();
+		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, T::CrossAccountId::from_sub(caller.clone()), data)?;
+	}: approve(RawOrigin::Signed(caller.clone()), T::CrossAccountId::from_sub(recipient.clone()), collection, 1, 1)
 
 	// Nft
 	transfer_from_nft {
-		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 = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
 		let recipient: T::AccountId = account("recipient", 0, SEED);
-		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 data = default_nft_data();
-		Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
-		Nft::<T>::approve(RawOrigin::Signed(caller.clone()).into(), recipient.clone(), 2, 1)?;
-
-	}: transfer_from(RawOrigin::Signed(caller.clone()), caller.clone(), recipient.clone(), 2, 1, 1)
+		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, T::CrossAccountId::from_sub(caller.clone()), data)?;
+		<Pallet<T>>::approve(RawOrigin::Signed(caller.clone()).into(), T::CrossAccountId::from_sub(recipient.clone()), 2, 1, 1)?;
+	}: transfer_from(RawOrigin::Signed(caller.clone()), T::CrossAccountId::from_sub(caller.clone()), T::CrossAccountId::from_sub(recipient.clone()), 2, 1, 1)
 
 	// Fungible
 	transfer_from_fungible {
-		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::Fungible(3);
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_fungible_collection::<T>(caller.clone())?;
 		let recipient: T::AccountId = account("recipient", 0, SEED);
-		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 data = default_fungible_data();
-		Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
-		Nft::<T>::approve(RawOrigin::Signed(caller.clone()).into(), recipient.clone(), 2, 1)?;
-
-	}: transfer_from(RawOrigin::Signed(caller.clone()), caller.clone(), recipient.clone(), 2, 1, 1)
+		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, T::CrossAccountId::from_sub(caller.clone()), data)?;
+		<Pallet<T>>::approve(RawOrigin::Signed(caller.clone()).into(), T::CrossAccountId::from_sub(recipient.clone()), 2, 1, 1)?;
+	}: transfer_from(RawOrigin::Signed(caller.clone()), T::CrossAccountId::from_sub(caller.clone()), T::CrossAccountId::from_sub(recipient.clone()), 2, 1, 1)
 
 	// ReFungible
 	transfer_from_refungible {
-		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::ReFungible(3);
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_refungible_collection::<T>(caller.clone())?;
 		let recipient: T::AccountId = account("recipient", 0, SEED);
-		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 data = default_re_fungible_data();
-		Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
-		Nft::<T>::approve(RawOrigin::Signed(caller.clone()).into(), recipient.clone(), 2, 1)?;
-
-	}: transfer_from(RawOrigin::Signed(caller.clone()), caller.clone(), recipient.clone(), 2, 1, 1)
-
-	enable_contract_sponsoring {
-		let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
-
-	}: enable_contract_sponsoring(RawOrigin::Signed(caller.clone()), caller.clone(), true)
+		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, T::CrossAccountId::from_sub(caller.clone()), data)?;
+		<Pallet<T>>::approve(RawOrigin::Signed(caller.clone()).into(), T::CrossAccountId::from_sub(recipient.clone()), 2, 1, 1)?;
+	}: transfer_from(RawOrigin::Signed(caller.clone()), T::CrossAccountId::from_sub(caller.clone()), T::CrossAccountId::from_sub(recipient.clone()), 2, 1, 1)
 
 	set_offchain_schema {
-		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::ReFungible(3);
-		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 b in 0..OFFCHAIN_SCHEMA_LIMIT;
 
-	}: set_offchain_schema(RawOrigin::Signed(caller.clone()), 2, [1,2,3].to_vec())
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		let data = create_data(b as usize);
+	}: set_offchain_schema(RawOrigin::Signed(caller.clone()), collection, data)
 
 	set_const_on_chain_schema {
-		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::ReFungible(3);
-		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_const_on_chain_schema(RawOrigin::Signed(caller.clone()), 2, [1,2,3].to_vec())
+		let b in 0..CONST_ON_CHAIN_SCHEMA_LIMIT;
 
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		let data = create_data(b as usize);
+	}: set_const_on_chain_schema(RawOrigin::Signed(caller.clone()), collection, data)
+
 	set_variable_on_chain_schema {
-		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::ReFungible(3);
-		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_variable_on_chain_schema(RawOrigin::Signed(caller.clone()), 2, [1,2,3].to_vec())
+		let b in 0..VARIABLE_ON_CHAIN_SCHEMA_LIMIT;
 
-	set_variable_meta_data {
-		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 data = default_nft_data();
-		Nft::<T>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone(), data)?;
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		let data = create_data(b as usize);
+	}: set_variable_on_chain_schema(RawOrigin::Signed(caller.clone()), 2, data)
 
-	}: set_variable_meta_data(RawOrigin::Signed(caller.clone()), 2, 1, [1, 2, 3].to_vec())
+	set_variable_meta_data_nft {
+		let b in 0..CUSTOM_DATA_LIMIT;
 
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		let data = default_nft_data();
+		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, T::CrossAccountId::from_sub(caller.clone()), data)?;
+		let data = create_data(b as usize);
+	}: set_variable_meta_data(RawOrigin::Signed(caller.clone()), collection, 1, data)
+
 	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())?;
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.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 caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
 
 		let cl = CollectionLimits {
 			account_token_ownership_limit: 0,
 			sponsored_data_size: 0,
-			token_limit: 0,
-			sponsor_transfer_timeout: 0
+			token_limit: 1,
+			sponsor_transfer_timeout: 0,
+			owner_can_destroy: true,
+			owner_can_transfer: true,
+			sponsored_data_rate_limit: None,
 		};
-
 	}: 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)
-*/
 }
deletedpallets/nft/src/default_weights.rsdiffbeforeafterboth
--- a/pallets/nft/src/default_weights.rs
+++ /dev/null
@@ -1,155 +0,0 @@
-use frame_support::weights::{Weight, constants::RocksDbWeight as DbWeight};
-
-impl crate::WeightInfo for () {
-	fn create_collection() -> Weight {
-		70_000_000_u64
-			.saturating_add(DbWeight::get().reads(7_u64))
-			.saturating_add(DbWeight::get().writes(5_u64))
-	}
-	fn destroy_collection() -> Weight {
-		90_000_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(5_u64))
-	}
-	fn add_to_white_list() -> Weight {
-		30_000_000_u64
-			.saturating_add(DbWeight::get().reads(3_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn remove_from_white_list() -> Weight {
-		35_000_000_u64
-			.saturating_add(DbWeight::get().reads(3_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_public_access_mode() -> Weight {
-		27_000_000_u64
-			.saturating_add(DbWeight::get().reads(1_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_mint_permission() -> Weight {
-		27_000_000_u64
-			.saturating_add(DbWeight::get().reads(1_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn change_collection_owner() -> Weight {
-		27_000_000_u64
-			.saturating_add(DbWeight::get().reads(1_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn add_collection_admin() -> Weight {
-		32_000_000_u64
-			.saturating_add(DbWeight::get().reads(3_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn remove_collection_admin() -> Weight {
-		50_000_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_collection_sponsor() -> Weight {
-		32_000_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn confirm_sponsorship() -> Weight {
-		22_000_000_u64
-			.saturating_add(DbWeight::get().reads(1_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn remove_collection_sponsor() -> Weight {
-		24_000_000_u64
-			.saturating_add(DbWeight::get().reads(1_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn create_item(s: usize) -> Weight {
-		130_000_000_u64
-			.saturating_add(2135_u64.saturating_mul(s as Weight).saturating_mul(500_u64)) // 500 is temporary multiplier, fee for storage
-			.saturating_add(DbWeight::get().reads(10_u64))
-			.saturating_add(DbWeight::get().writes(8_u64))
-	}
-	fn burn_item() -> Weight {
-		170_000_000_u64
-			.saturating_add(DbWeight::get().reads(9_u64))
-			.saturating_add(DbWeight::get().writes(7_u64))
-	}
-	fn transfer() -> Weight {
-		125_000_000_u64
-			.saturating_add(DbWeight::get().reads(7_u64))
-			.saturating_add(DbWeight::get().writes(7_u64))
-	}
-	fn approve() -> Weight {
-		45_000_000_u64
-			.saturating_add(DbWeight::get().reads(3_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn transfer_from() -> Weight {
-		150_000_000_u64
-			.saturating_add(DbWeight::get().reads(9_u64))
-			.saturating_add(DbWeight::get().writes(8_u64))
-	}
-	fn set_offchain_schema() -> Weight {
-		33_000_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_const_on_chain_schema() -> Weight {
-		11_100_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_variable_on_chain_schema() -> Weight {
-		11_100_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_variable_meta_data() -> Weight {
-		17_500_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn enable_contract_sponsoring() -> Weight {
-		13_000_000_u64
-			.saturating_add(DbWeight::get().reads(1_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_schema_version() -> Weight {
-		8_500_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_chain_limits() -> Weight {
-		1_300_000_u64
-			.saturating_add(DbWeight::get().reads(0_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_contract_sponsoring_rate_limit() -> Weight {
-		3_500_000_u64
-			.saturating_add(DbWeight::get().reads(0_u64))
-			.saturating_add(DbWeight::get().writes(2_u64))
-	}
-	fn set_variable_meta_data_sponsoring_rate_limit() -> Weight {
-		3_500_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn toggle_contract_white_list() -> Weight {
-		3_000_000_u64
-			.saturating_add(DbWeight::get().reads(0_u64))
-			.saturating_add(DbWeight::get().writes(2_u64))
-	}
-	fn add_to_contract_white_list() -> Weight {
-		3_000_000_u64
-			.saturating_add(DbWeight::get().reads(0_u64))
-			.saturating_add(DbWeight::get().writes(2_u64))
-	}
-	fn remove_from_contract_white_list() -> Weight {
-		3_200_000_u64
-			.saturating_add(DbWeight::get().reads(0_u64))
-			.saturating_add(DbWeight::get().writes(2_u64))
-	}
-	fn set_collection_limits() -> Weight {
-		8_900_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-}
modifiedpallets/nft/src/eth/erc.rsdiffbeforeafterboth
--- a/pallets/nft/src/eth/erc.rs
+++ b/pallets/nft/src/eth/erc.rs
@@ -1,46 +1,72 @@
-use evm_coder::{solidity_interface, solidity, types::*, ToLog};
-use sp_std::vec::Vec;
+use core::char::{decode_utf16, REPLACEMENT_CHARACTER};
+use evm_coder::{ToLog, execution::Result, generate_stubgen, solidity, solidity_interface, types::*};
+use nft_data_structs::{CreateItemData, CreateNftData};
+use core::convert::TryInto;
+use crate::{
+	Allowances, Module, Balance, CollectionHandle, CollectionMode, Config, NftItemList,
+	ItemListIndex,
+};
+use frame_support::storage::{StorageMap, StorageDoubleMap};
+use pallet_evm::AddressMapping;
+use super::account::CrossAccountId;
+use sp_std::{vec, vec::Vec};
 
-#[solidity_interface]
-pub trait InlineNameSymbol {
-	type Error;
-
-	fn name(&self) -> Result<string, Self::Error>;
-	fn symbol(&self) -> Result<string, Self::Error>;
+#[solidity_interface(name = "ERC165")]
+impl<T: Config> CollectionHandle<T> {
+	fn supports_interface(&self, interface_id: bytes4) -> Result<bool> {
+		Ok(match self.mode {
+			CollectionMode::Fungible(_) => UniqueFungibleCall::supports_interface(interface_id),
+			CollectionMode::NFT => UniqueNFTCall::supports_interface(interface_id),
+			_ => false,
+		})
+	}
 }
 
-#[solidity_interface]
-pub trait InlineTotalSupply {
-	type Error;
+#[solidity_interface(name = "InlineNameSymbol")]
+impl<T: Config> CollectionHandle<T> {
+	fn name(&self) -> Result<string> {
+		Ok(decode_utf16(self.name.iter().copied())
+			.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
+			.collect::<string>())
+	}
 
-	fn total_supply(&self) -> Result<uint256, Self::Error>;
+	fn symbol(&self) -> Result<string> {
+		Ok(string::from_utf8_lossy(&self.token_prefix).into())
+	}
 }
 
-#[solidity_interface]
-pub trait ERC165 {
-	type Error;
-
-	fn supports_interface(&self, interface_id: bytes4) -> Result<bool, Self::Error>;
+#[solidity_interface(name = "InlineTotalSupply")]
+impl<T: Config> CollectionHandle<T> {
+	fn total_supply(&self) -> Result<uint256> {
+		// TODO: we do not track total amount of all tokens
+		Ok(0.into())
+	}
 }
 
-#[solidity_interface(inline_is(InlineNameSymbol))]
-pub trait ERC721Metadata {
-	type Error;
-
+#[solidity_interface(name = "ERC721Metadata", inline_is(InlineNameSymbol))]
+impl<T: Config> CollectionHandle<T> {
 	#[solidity(rename_selector = "tokenURI")]
-	fn token_uri(&self, token_id: uint256) -> Result<string, Self::Error>;
+	fn token_uri(&self, token_id: uint256) -> Result<string> {
+		let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
+		Ok(string::from_utf8_lossy(
+			&<NftItemList<T>>::get(self.id, token_id)
+				.ok_or("token not found")?
+				.const_data,
+		)
+		.into())
+	}
 }
 
-#[solidity_interface(inline_is(InlineTotalSupply))]
-pub trait ERC721Enumerable {
-	type Error;
+#[solidity_interface(name = "ERC721Enumerable", inline_is(InlineTotalSupply))]
+impl<T: Config> CollectionHandle<T> {
+	fn token_by_index(&self, index: uint256) -> Result<uint256> {
+		Ok(index)
+	}
 
-	fn token_by_index(&self, index: uint256) -> Result<uint256, Self::Error>;
-	fn token_of_owner_by_index(
-		&self,
-		owner: address,
-		index: uint256,
-	) -> Result<uint256, Self::Error>;
+	fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {
+		// TODO: Not implemetable
+		Err("not implemented".into())
+	}
 }
 
 #[derive(ToLog)]
@@ -71,29 +97,40 @@
 	},
 }
 
-#[solidity_interface(is(ERC165), events(ERC721Events))]
-pub trait ERC721 {
-	type Error;
-
-	fn balance_of(&self, owner: address) -> Result<uint256, Self::Error>;
-	fn owner_of(&self, token_id: uint256) -> Result<address, Self::Error>;
-
-	#[solidity(rename_selector = "safeTransferFrom")]
+#[solidity_interface(name = "ERC721", is(ERC165), events(ERC721Events))]
+impl<T: Config> CollectionHandle<T> {
+	#[solidity(rename_selector = "balanceOf")]
+	fn balance_of_nft(&self, owner: address) -> Result<uint256> {
+		let owner = T::EvmAddressMapping::into_account_id(owner);
+		let balance = <Balance<T>>::get(self.id, owner);
+		Ok(balance.into())
+	}
+	fn owner_of(&self, token_id: uint256) -> Result<address> {
+		let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
+		let token = <NftItemList<T>>::get(self.id, token_id).ok_or("unknown token")?;
+		Ok(*token.owner.as_eth())
+	}
 	fn safe_transfer_from_with_data(
 		&mut self,
-		from: address,
-		to: address,
-		token_id: uint256,
-		data: bytes,
-		value: value,
-	) -> Result<void, Self::Error>;
+		_from: address,
+		_to: address,
+		_token_id: uint256,
+		_data: bytes,
+		_value: value,
+	) -> Result<void> {
+		// TODO: Not implemetable
+		Err("not implemented".into())
+	}
 	fn safe_transfer_from(
 		&mut self,
-		from: address,
-		to: address,
-		token_id: uint256,
-		value: value,
-	) -> Result<void, Self::Error>;
+		_from: address,
+		_to: address,
+		_token_id: uint256,
+		_value: value,
+	) -> Result<void> {
+		// TODO: Not implemetable
+		Err("not implemented".into())
+	}
 
 	fn transfer_from(
 		&mut self,
@@ -101,54 +138,183 @@
 		from: address,
 		to: address,
 		token_id: uint256,
-		value: value,
-	) -> Result<void, Self::Error>;
+		_value: value,
+	) -> Result<void> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let from = T::CrossAccountId::from_eth(from);
+		let to = T::CrossAccountId::from_eth(to);
+		let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;
+
+		<Module<T>>::transfer_from_internal(&caller, &from, &to, self, token_id, 1)
+			.map_err(|_| "transferFrom error")?;
+		Ok(())
+	}
+
 	fn approve(
 		&mut self,
 		caller: caller,
 		approved: address,
 		token_id: uint256,
-		value: value,
-	) -> Result<void, Self::Error>;
+		_value: value,
+	) -> Result<void> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let approved = T::CrossAccountId::from_eth(approved);
+		let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;
+
+		<Module<T>>::approve_internal(&caller, &approved, self, token_id, 1)
+			.map_err(|_| "approve internal")?;
+		Ok(())
+	}
+
 	fn set_approval_for_all(
 		&mut self,
-		caller: caller,
-		operator: address,
-		approved: bool,
-	) -> Result<void, Self::Error>;
+		_caller: caller,
+		_operator: address,
+		_approved: bool,
+	) -> Result<void> {
+		// TODO: Not implemetable
+		Err("not implemented".into())
+	}
 
-	fn get_approved(&self, token_id: uint256) -> Result<address, Self::Error>;
-	fn is_approved_for_all(
-		&self,
-		owner: address,
-		operator: address,
-	) -> Result<address, Self::Error>;
+	fn get_approved(&self, _token_id: uint256) -> Result<address> {
+		// TODO: Not implemetable
+		Err("not implemented".into())
+	}
+
+	fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {
+		// TODO: Not implemetable
+		Err("not implemented".into())
+	}
+}
+
+#[solidity_interface(name = "ERC721Burnable")]
+impl<T: Config> CollectionHandle<T> {
+	fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let token_id = token_id.try_into().map_err(|_| "amount overflow")?;
+
+		<Module<T>>::burn_item_internal(&caller, &self, token_id, 1).map_err(|_| "burn error")?;
+		Ok(())
+	}
+}
+
+#[derive(ToLog)]
+pub enum ERC721MintableEvents {
+	#[allow(dead_code)]
+	MintingFinished {},
 }
 
-#[solidity_interface]
-pub trait ERC721UniqueExtensions {
-	type Error;
+#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))]
+impl<T: Config> CollectionHandle<T> {
+	fn minting_finished(&self) -> Result<bool> {
+		Ok(false)
+	}
+
+	fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let to = T::CrossAccountId::from_eth(to);
+		let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;
+		if <ItemListIndex>::get(self.id)
+			.checked_add(1)
+			.ok_or("item id overflow")?
+			!= token_id
+		{
+			return Err("item id should be next".into());
+		}
+
+		<Module<T>>::create_item_internal(
+			&caller,
+			&self,
+			&to,
+			CreateItemData::NFT(CreateNftData {
+				const_data: vec![].try_into().unwrap(),
+				variable_data: vec![].try_into().unwrap(),
+			}),
+		)
+		.map_err(|_| "mint error")?;
+		Ok(true)
+	}
 
-	fn transfer(
+	#[solidity(rename_selector = "mintWithTokenURI")]
+	fn mint_with_token_uri(
 		&mut self,
 		caller: caller,
 		to: address,
 		token_id: uint256,
-		value: value,
-	) -> Result<void, Self::Error>;
+		token_uri: string,
+	) -> Result<bool> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let to = T::CrossAccountId::from_eth(to);
+		let token_id: u32 = token_id.try_into().map_err(|_| "amount overflow")?;
+		if <ItemListIndex>::get(self.id)
+			.checked_add(1)
+			.ok_or("item id overflow")?
+			!= token_id
+		{
+			return Err("item id should be next".into());
+		}
+
+		<Module<T>>::create_item_internal(
+			&caller,
+			&self,
+			&to,
+			CreateItemData::NFT(CreateNftData {
+				const_data: Vec::<u8>::from(token_uri)
+					.try_into()
+					.map_err(|_| "token uri is too long")?,
+				variable_data: vec![].try_into().unwrap(),
+			}),
+		)
+		.map_err(|_| "mint error")?;
+		Ok(true)
+	}
+
+	fn finish_minting(&mut self, _caller: caller) -> Result<bool> {
+		Err("not implementable".into())
+	}
 }
 
-#[solidity_interface(is(
-	ERC165,
-	ERC721,
-	ERC721Metadata,
-	ERC721Enumerable,
-	ERC721UniqueExtensions
-))]
-pub trait UniqueNFT {
-	type Error;
+#[solidity_interface(name = "ERC721UniqueExtensions")]
+impl<T: Config> CollectionHandle<T> {
+	#[solidity(rename_selector = "transfer")]
+	fn transfer_nft(
+		&mut self,
+		caller: caller,
+		to: address,
+		token_id: uint256,
+		_value: value,
+	) -> Result<void> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let to = T::CrossAccountId::from_eth(to);
+		let token_id = token_id.try_into().map_err(|_| "amount overflow")?;
+
+		<Module<T>>::transfer_internal(&caller, &to, self, token_id, 1)
+			.map_err(|_| "transfer error")?;
+		Ok(())
+	}
+
+	fn next_token_id(&self) -> Result<uint256> {
+		Ok(ItemListIndex::get(self.id)
+			.checked_add(1)
+			.ok_or("item id overflow")?
+			.into())
+	}
 }
 
+#[solidity_interface(
+	name = "UniqueNFT",
+	is(
+		ERC165,
+		ERC721,
+		ERC721Metadata,
+		ERC721Enumerable,
+		ERC721UniqueExtensions,
+		ERC721Mintable,
+		ERC721Burnable,
+	)
+)]
+impl<T: Config> CollectionHandle<T> {}
+
 #[derive(ToLog)]
 pub enum ERC20Events {
 	Transfer {
@@ -167,35 +333,79 @@
 	},
 }
 
-#[solidity_interface(inline_is(InlineNameSymbol, InlineTotalSupply), events(ERC20Events))]
-pub trait ERC20 {
-	type Error;
+#[solidity_interface(
+	name = "ERC20",
+	inline_is(InlineNameSymbol, InlineTotalSupply),
+	events(ERC20Events)
+)]
+impl<T: Config> CollectionHandle<T> {
+	fn decimals(&self) -> Result<uint8> {
+		Ok(if let CollectionMode::Fungible(decimals) = &self.mode {
+			*decimals
+		} else {
+			unreachable!()
+		})
+	}
+	fn balance_of(&self, owner: address) -> Result<uint256> {
+		let owner = T::EvmAddressMapping::into_account_id(owner);
+		let balance = <Balance<T>>::get(self.id, owner);
+		Ok(balance.into())
+	}
+	fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let to = T::CrossAccountId::from_eth(to);
+		let amount = amount.try_into().map_err(|_| "amount overflow")?;
 
-	fn decimals(&self) -> Result<uint8, Self::Error>;
-	fn balance_of(&self, owner: address) -> Result<uint256, Self::Error>;
-	fn transfer(
-		&mut self,
-		caller: caller,
-		to: address,
-		value: uint256,
-	) -> Result<bool, Self::Error>;
-	fn transfer_from(
+		<Module<T>>::transfer_internal(&caller, &to, self, 1, amount)
+			.map_err(|_| "transfer error")?;
+		Ok(true)
+	}
+	#[solidity(rename_selector = "transferFrom")]
+	fn transfer_from_fungible(
 		&mut self,
 		caller: caller,
 		from: address,
 		to: address,
-		value: uint256,
-	) -> Result<bool, Self::Error>;
-	fn approve(
+		amount: uint256,
+	) -> Result<bool> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let from = T::CrossAccountId::from_eth(from);
+		let to = T::CrossAccountId::from_eth(to);
+		let amount = amount.try_into().map_err(|_| "amount overflow")?;
+
+		<Module<T>>::transfer_from_internal(&caller, &from, &to, self, 1, amount)
+			.map_err(|_| "transferFrom error")?;
+		Ok(true)
+	}
+	#[solidity(rename_selector = "approve")]
+	fn approve_fungible(
 		&mut self,
 		caller: caller,
 		spender: address,
-		value: uint256,
-	) -> Result<bool, Self::Error>;
-	fn allowance(&self, owner: address, spender: address) -> Result<uint256, Self::Error>;
-}
+		amount: uint256,
+	) -> Result<bool> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let spender = T::CrossAccountId::from_eth(spender);
+		let amount = amount.try_into().map_err(|_| "amount overflow")?;
 
-#[solidity_interface(is(ERC165, ERC20))]
-pub trait UniqueFungible {
-	type Error;
+		<Module<T>>::approve_internal(&caller, &spender, self, 1, amount)
+			.map_err(|_| "approve internal")?;
+		Ok(true)
+	}
+	fn allowance(&self, owner: address, spender: address) -> Result<uint256> {
+		let owner = T::CrossAccountId::from_eth(owner);
+		let spender = T::CrossAccountId::from_eth(spender);
+
+		Ok(<Allowances<T>>::get(self.id, (1, owner.as_sub(), spender.as_sub())).into())
+	}
 }
+
+#[solidity_interface(name = "UniqueFungible", is(ERC165, ERC20))]
+impl<T: Config> CollectionHandle<T> {}
+
+// Not a tests, but code generators
+generate_stubgen!(nft_impl, UniqueNFTCall, true);
+generate_stubgen!(nft_iface, UniqueNFTCall, false);
+
+generate_stubgen!(fungible_impl, UniqueFungibleCall, true);
+generate_stubgen!(fungible_iface, UniqueFungibleCall, false);
deletedpallets/nft/src/eth/erc_impl.rsdiffbeforeafterboth
--- a/pallets/nft/src/eth/erc_impl.rs
+++ /dev/null
@@ -1,283 +0,0 @@
-use core::char::{decode_utf16, REPLACEMENT_CHARACTER};
-use evm_coder::{
-	abi::{AbiWriter, StringError},
-	types::*,
-};
-use core::convert::TryInto;
-use alloc::format;
-use crate::{Allowances, Module, Balance, CollectionHandle, CollectionMode, Config, NftItemList};
-use frame_support::storage::StorageDoubleMap;
-use pallet_evm::AddressMapping;
-use super::erc::*;
-use super::account::CrossAccountId;
-
-type Result<T> = core::result::Result<T, StringError>;
-
-impl<T: Config> InlineNameSymbol for CollectionHandle<T> {
-	type Error = StringError;
-
-	fn name(&self) -> Result<string> {
-		Ok(decode_utf16(self.name.iter().copied())
-			.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
-			.collect::<string>())
-	}
-
-	fn symbol(&self) -> Result<string> {
-		Ok(string::from_utf8_lossy(&self.token_prefix).into())
-	}
-}
-
-impl<T: Config> InlineTotalSupply for CollectionHandle<T> {
-	type Error = StringError;
-
-	fn total_supply(&self) -> Result<uint256> {
-		// TODO: we do not track total amount of all tokens
-		Ok(0.into())
-	}
-}
-
-impl<T: Config> ERC721Metadata for CollectionHandle<T> {
-	type Error = StringError;
-
-	fn token_uri(&self, token_id: uint256) -> Result<string> {
-		// TODO: We should standartize url prefix, maybe via offchain schema?
-		Ok(format!("unique.network/{}/{}", self.id, token_id))
-	}
-
-	fn call_inline_name_symbol(&mut self, c: Msg<InlineNameSymbolCall>) -> Result<AbiWriter> {
-		<Self as InlineNameSymbol>::call(self, c)
-	}
-}
-
-impl<T: Config> ERC721Enumerable for CollectionHandle<T> {
-	type Error = StringError;
-
-	fn token_by_index(&self, index: uint256) -> Result<uint256> {
-		Ok(index)
-	}
-
-	fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {
-		// TODO: Not implemetable
-		Err("not implemented".into())
-	}
-
-	fn call_inline_total_supply(&mut self, c: Msg<InlineTotalSupplyCall>) -> Result<AbiWriter> {
-		<Self as InlineTotalSupply>::call(self, c)
-	}
-}
-
-impl<T: Config> ERC721 for CollectionHandle<T> {
-	type Error = StringError;
-
-	fn balance_of(&self, owner: address) -> Result<uint256> {
-		let owner = T::EvmAddressMapping::into_account_id(owner);
-		let balance = <Balance<T>>::get(self.id, owner);
-		Ok(balance.into())
-	}
-	fn owner_of(&self, token_id: uint256) -> Result<address> {
-		let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
-		let token = <NftItemList<T>>::get(self.id, token_id).ok_or("unknown token")?;
-		Ok(*token.owner.as_eth())
-	}
-	fn safe_transfer_from_with_data(
-		&mut self,
-		_from: address,
-		_to: address,
-		_token_id: uint256,
-		_data: bytes,
-		_value: value,
-	) -> Result<void> {
-		// TODO: Not implemetable
-		Err("not implemented".into())
-	}
-	fn safe_transfer_from(
-		&mut self,
-		_from: address,
-		_to: address,
-		_token_id: uint256,
-		_value: value,
-	) -> Result<void> {
-		// TODO: Not implemetable
-		Err("not implemented".into())
-	}
-
-	fn transfer_from(
-		&mut self,
-		caller: caller,
-		from: address,
-		to: address,
-		token_id: uint256,
-		_value: value,
-	) -> Result<void> {
-		let caller = T::CrossAccountId::from_eth(caller);
-		let from = T::CrossAccountId::from_eth(from);
-		let to = T::CrossAccountId::from_eth(to);
-		let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;
-
-		<Module<T>>::transfer_from_internal(&caller, &from, &to, self, token_id, 1)
-			.map_err(|_| "transferFrom error")?;
-		Ok(())
-	}
-
-	fn approve(
-		&mut self,
-		caller: caller,
-		approved: address,
-		token_id: uint256,
-		_value: value,
-	) -> Result<void> {
-		let caller = T::CrossAccountId::from_eth(caller);
-		let approved = T::CrossAccountId::from_eth(approved);
-		let token_id = token_id.try_into().map_err(|_| "token_id overflow")?;
-
-		<Module<T>>::approve_internal(&caller, &approved, self, token_id, 1)
-			.map_err(|_| "approve internal")?;
-		Ok(())
-	}
-
-	fn set_approval_for_all(
-		&mut self,
-		_caller: caller,
-		_operator: address,
-		_approved: bool,
-	) -> Result<void> {
-		// TODO: Not implemetable
-		Err("not implemented".into())
-	}
-
-	fn get_approved(&self, _token_id: uint256) -> Result<address> {
-		// TODO: Not implemetable
-		Err("not implemented".into())
-	}
-
-	fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {
-		// TODO: Not implemetable
-		Err("not implemented".into())
-	}
-
-	fn call_erc165(&mut self, c: Msg<ERC165Call>) -> Result<AbiWriter> {
-		let ERC165Call::SupportsInterface { interface_id } = c.call;
-		Ok(evm_coder::abi_encode!(bool(
-			&ERC721Call::supports_interface(interface_id)
-		)))
-	}
-}
-
-impl<T: Config> ERC721UniqueExtensions for CollectionHandle<T> {
-	type Error = StringError;
-	fn transfer(
-		&mut self,
-		caller: caller,
-		to: address,
-		token_id: uint256,
-		_value: value,
-	) -> Result<void> {
-		let caller = T::CrossAccountId::from_eth(caller);
-		let to = T::CrossAccountId::from_eth(to);
-		let token_id = token_id.try_into().map_err(|_| "amount overflow")?;
-
-		<Module<T>>::transfer_internal(&caller, &to, self, token_id, 1)
-			.map_err(|_| "transfer error")?;
-		Ok(())
-	}
-}
-
-impl<T: Config> UniqueNFT for CollectionHandle<T> {
-	type Error = StringError;
-	fn call_erc165(&mut self, c: Msg<ERC165Call>) -> Result<AbiWriter> {
-		let ERC165Call::SupportsInterface { interface_id } = c.call;
-		Ok(evm_coder::abi_encode!(bool(
-			&UniqueNFTCall::supports_interface(interface_id)
-		)))
-	}
-	fn call_erc721(&mut self, c: Msg<ERC721Call>) -> Result<AbiWriter> {
-		<Self as ERC721>::call(self, c)
-	}
-	fn call_erc721_metadata(&mut self, c: Msg<ERC721MetadataCall>) -> Result<AbiWriter> {
-		<Self as ERC721Metadata>::call(self, c)
-	}
-	fn call_erc721_enumerable(&mut self, c: Msg<ERC721EnumerableCall>) -> Result<AbiWriter> {
-		<Self as ERC721Enumerable>::call(self, c)
-	}
-	fn call_erc721_unique_extensions(
-		&mut self,
-		c: Msg<ERC721UniqueExtensionsCall>,
-	) -> Result<AbiWriter> {
-		<Self as ERC721UniqueExtensions>::call(self, c)
-	}
-}
-
-impl<T: Config> ERC20 for CollectionHandle<T> {
-	type Error = StringError;
-	fn decimals(&self) -> Result<uint8> {
-		Ok(if let CollectionMode::Fungible(decimals) = &self.mode {
-			*decimals
-		} else {
-			unreachable!()
-		})
-	}
-	fn balance_of(&self, owner: address) -> Result<uint256> {
-		let owner = T::EvmAddressMapping::into_account_id(owner);
-		let balance = <Balance<T>>::get(self.id, owner);
-		Ok(balance.into())
-	}
-	fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {
-		let caller = T::CrossAccountId::from_eth(caller);
-		let to = T::CrossAccountId::from_eth(to);
-		let amount = amount.try_into().map_err(|_| "amount overflow")?;
-
-		<Module<T>>::transfer_internal(&caller, &to, self, 1, amount)
-			.map_err(|_| "transfer error")?;
-		Ok(true)
-	}
-	fn transfer_from(
-		&mut self,
-		caller: caller,
-		from: address,
-		to: address,
-		amount: uint256,
-	) -> Result<bool> {
-		let caller = T::CrossAccountId::from_eth(caller);
-		let from = T::CrossAccountId::from_eth(from);
-		let to = T::CrossAccountId::from_eth(to);
-		let amount = amount.try_into().map_err(|_| "amount overflow")?;
-
-		<Module<T>>::transfer_from_internal(&caller, &from, &to, self, 1, amount)
-			.map_err(|_| "transferFrom error")?;
-		Ok(true)
-	}
-	fn approve(&mut self, caller: caller, spender: address, amount: uint256) -> Result<bool> {
-		let caller = T::CrossAccountId::from_eth(caller);
-		let spender = T::CrossAccountId::from_eth(spender);
-		let amount = amount.try_into().map_err(|_| "amount overflow")?;
-
-		<Module<T>>::approve_internal(&caller, &spender, self, 1, amount)
-			.map_err(|_| "approve internal")?;
-		Ok(true)
-	}
-	fn allowance(&self, owner: address, spender: address) -> Result<uint256> {
-		let owner = T::CrossAccountId::from_eth(owner);
-		let spender = T::CrossAccountId::from_eth(spender);
-
-		Ok(<Allowances<T>>::get(self.id, (1, owner.as_sub(), spender.as_sub())).into())
-	}
-	fn call_inline_name_symbol(&mut self, c: Msg<InlineNameSymbolCall>) -> Result<AbiWriter> {
-		<Self as InlineNameSymbol>::call(self, c)
-	}
-	fn call_inline_total_supply(&mut self, c: Msg<InlineTotalSupplyCall>) -> Result<AbiWriter> {
-		<Self as InlineTotalSupply>::call(self, c)
-	}
-}
-
-impl<T: Config> UniqueFungible for CollectionHandle<T> {
-	type Error = StringError;
-	fn call_erc165(&mut self, c: Msg<ERC165Call>) -> Result<AbiWriter> {
-		let ERC165Call::SupportsInterface { interface_id } = c.call;
-		Ok(evm_coder::abi_encode!(bool(
-			&UniqueNFTCall::supports_interface(interface_id)
-		)))
-	}
-	fn call_erc20(&mut self, c: Msg<ERC20Call>) -> Result<AbiWriter> {
-		<Self as ERC20>::call(self, c)
-	}
-}
deletedpallets/nft/src/eth/log.rsdiffbeforeafterboth
--- a/pallets/nft/src/eth/log.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-use sp_std::cell::RefCell;
-use sp_std::vec::Vec;
-
-use ethereum::Log;
-
-#[derive(Default)]
-pub struct LogRecorder(RefCell<Vec<Log>>);
-
-impl LogRecorder {
-	pub fn is_empty(&self) -> bool {
-		self.0.borrow().is_empty()
-	}
-	pub fn log(&self, log: Log) {
-		self.0.borrow_mut().push(log);
-	}
-	pub fn retrieve_logs(self) -> Vec<Log> {
-		self.0.into_inner()
-	}
-}
modifiedpallets/nft/src/eth/mod.rsdiffbeforeafterboth
--- a/pallets/nft/src/eth/mod.rs
+++ b/pallets/nft/src/eth/mod.rs
@@ -1,23 +1,15 @@
 pub mod account;
 pub mod erc;
-mod erc_impl;
-pub mod log;
 pub mod sponsoring;
 
-use evm_coder::abi::AbiWriter;
-use evm_coder::abi::StringError;
-use sp_std::prelude::*;
+use pallet_evm_coder_substrate::call_internal;
 use sp_std::borrow::ToOwned;
 use sp_std::vec::Vec;
-
-use pallet_evm::{PrecompileOutput, ExitReason, ExitRevert, ExitSucceed};
+use pallet_evm::{PrecompileOutput};
 use sp_core::{H160, U256};
 use frame_support::storage::StorageMap;
-
 use crate::{Config, CollectionById, CollectionHandle, CollectionId, CollectionMode};
-
-use erc::{UniqueFungible, UniqueFungibleCall, UniqueNFT, UniqueNFTCall};
-use evm_coder::{types::*, abi::AbiReader};
+use erc::{UniqueFungibleCall, UniqueNFTCall};
 
 pub struct NftErcSupport<T: Config>(core::marker::PhantomData<T>);
 
@@ -42,19 +34,17 @@
 	H160(out)
 }
 
+/*
 fn call_internal<T: Config>(
 	collection: &mut CollectionHandle<T>,
 	caller: caller,
 	method_id: u32,
 	mut input: AbiReader,
 	value: U256,
-) -> Result<Option<AbiWriter>, evm_coder::abi::StringError> {
+) -> Result<Option<AbiWriter>> {
 	match collection.mode.clone() {
 		CollectionMode::Fungible(_) => {
-			#[cfg(feature = "std")]
-			{
-				println!("Parse fungible call {:x}", method_id);
-			}
+			call_internal();
 			let call = match UniqueFungibleCall::parse(method_id, &mut input)? {
 				Some(v) => v,
 				None => {
@@ -65,10 +55,6 @@
 					return Ok(None);
 				}
 			};
-			#[cfg(feature = "std")]
-			{
-				dbg!(&call);
-			}
 			Ok(Some(<CollectionHandle<T> as UniqueFungible>::call(
 				collection,
 				Msg {
@@ -92,11 +78,9 @@
 				},
 			)?))
 		}
-		_ => Err(StringError::from(
-			"erc calls only supported to fungible and nft collections for now",
-		)),
+		_ => Err("erc calls only supported to fungible and nft collections for now".into()),
 	}
-}
+}*/
 
 impl<T: Config> pallet_evm::OnMethodCall<T> for NftErcSupport<T> {
 	fn is_reserved(target: &H160) -> bool {
@@ -112,10 +96,14 @@
 			.and_then(<CollectionById<T>>::get)
 			.map(|collection| {
 				match collection.mode {
-					CollectionMode::NFT => include_bytes!("stubs/ERC721.bin") as &[u8],
-					CollectionMode::Fungible(_) => include_bytes!("stubs/ERC20.bin") as &[u8],
-					CollectionMode::ReFungible => include_bytes!("stubs/ERC1633.bin") as &[u8],
-					CollectionMode::Invalid => include_bytes!("stubs/Invalid.bin") as &[u8],
+					CollectionMode::NFT => include_bytes!("stubs/UniqueNFT.raw") as &[u8],
+					CollectionMode::Fungible(_) => {
+						include_bytes!("stubs/UniqueFungible.raw") as &[u8]
+					}
+					CollectionMode::ReFungible => {
+						include_bytes!("stubs/UniqueRefungible.raw") as &[u8]
+					}
+					CollectionMode::Invalid => include_bytes!("stubs/UniqueInvalid.raw") as &[u8],
 				}
 				.to_owned()
 			})
@@ -129,56 +117,15 @@
 	) -> Option<PrecompileOutput> {
 		let mut collection = map_eth_to_id(target)
 			.and_then(|id| <CollectionHandle<T>>::get_with_gas_limit(id, gas_limit))?;
-		let (method_id, input) = AbiReader::new_call(input).unwrap();
-		let result = call_internal(&mut collection, *source, method_id, input, value);
-		let cost = gas_limit - collection.gas_left();
-		let logs = collection.logs.retrieve_logs();
-		match result {
-			Ok(Some(v)) => Some(PrecompileOutput {
-				exit_status: ExitReason::Succeed(ExitSucceed::Returned),
-				cost,
-				logs,
-				output: v.finish(),
-			}),
-			Ok(None) => None,
-			Err(e) => Some(PrecompileOutput {
-				exit_status: ExitReason::Revert(ExitRevert::Reverted),
-				cost: 0,
-				logs: Default::default(),
-				output: AbiWriter::from(e).finish(),
-			}),
-		}
-	}
-}
-
-// TODO: This function is slow, and output can be memoized
-pub fn generate_transaction(collection_id: u32, chain_id: u64) -> ethereum::Transaction {
-	// FIXME: Can be done on wasm runtime with https://github.com/paritytech/substrate/pull/8728
-	#[cfg(feature = "std")]
-	{
-		let contract = collection_id_to_address(collection_id);
-		let signed = ethereum_tx_sign::RawTransaction {
-			nonce: 0.into(),
-			to: Some(contract.0.into()),
-			value: 0.into(),
-			gas_price: 0.into(),
-			gas: 0.into(),
-			// zero selector, this transaction always have same sender, so all data should be acquired from logs
-			data: Vec::from([0, 0, 0, 0]),
-		}
-		.sign(
-			// TODO: move to pallet config
-			// 0xF70631E55faff9f3FD3681545aa6c724226a3853
-			// 9dbaef9b3ebc00e53f67c6a77bcfbf2c4f2aebe4d70d94af4f2df01744b7a91a
-			&hex_literal::hex!("9dbaef9b3ebc00e53f67c6a77bcfbf2c4f2aebe4d70d94af4f2df01744b7a91a")
-				.into(),
-			&chain_id,
-		);
-		rlp::decode::<ethereum::Transaction>(&signed)
-			.expect("transaction is just created, it can't be broken")
-	}
-	#[cfg(not(feature = "std"))]
-	{
-		panic!("transaction generation not yet supported by wasm runtime while generating transaction for collection_id {}, chain_id {}", collection_id, chain_id)
+		let result = match collection.mode {
+			CollectionMode::NFT => {
+				call_internal::<UniqueNFTCall, _>(*source, &mut collection, value, input)
+			}
+			CollectionMode::Fungible(_) => {
+				call_internal::<UniqueFungibleCall, _>(*source, &mut collection, value, input)
+			}
+			_ => return None,
+		};
+		collection.recorder.evm_to_precompile_output(result)
 	}
 }
modifiedpallets/nft/src/eth/sponsoring.rsdiffbeforeafterboth
--- a/pallets/nft/src/eth/sponsoring.rs
+++ b/pallets/nft/src/eth/sponsoring.rs
@@ -1,35 +1,23 @@
 //! Implements EVM sponsoring logic via OnChargeEVMTransaction
 
 use crate::{
-	Collection, ChainLimit, CollectionById, Config, NftTransferBasket, FungibleTransferBasket,
-	eth::account::EvmBackwardsAddressMapping,
+	Collection, CollectionById, Config, FungibleTransferBasket, NftTransferBasket,
+	eth::{account::EvmBackwardsAddressMapping, map_eth_to_id},
 };
-use evm_coder::abi::AbiReader;
+use evm_coder::{Call, abi::AbiReader};
 use frame_support::{
-	storage::{StorageMap, StorageDoubleMap, StorageValue},
-	traits::Currency,
+	storage::{StorageMap, StorageDoubleMap},
 };
-use pallet_evm::{EVMCurrencyAdapter, WithdrawReason};
-use sp_core::{H160, U256};
+use sp_core::H160;
 use sp_std::prelude::*;
+use up_sponsorship::SponsorshipHandler;
 use super::{
 	account::CrossAccountId,
 	erc::{UniqueFungibleCall, UniqueNFTCall, ERC721Call, ERC20Call, ERC721UniqueExtensionsCall},
 };
 use core::convert::TryInto;
-
-type NegativeImbalanceOf<C, T> =
-	<C as Currency<<T as frame_system::Config>::AccountId>>::NegativeImbalance;
-
-pub struct ChargeEvmTransaction;
-pub struct ChargeEvmLiquidityInfo<T>
-where
-	T: Config,
-	T: pallet_evm::Config,
-{
-	who: H160,
-	negative_imbalance: NegativeImbalanceOf<<T as Config>::Currency, T>,
-}
+use core::marker::PhantomData;
+use nft_data_structs::{NFT_SPONSOR_TRANSFER_TIMEOUT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT};
 
 struct AnyError;
 
@@ -46,10 +34,9 @@
 				.map_err(|_| AnyError)?
 				.ok_or(AnyError)?;
 			match call {
-				UniqueNFTCall::ERC721UniqueExtensions(ERC721UniqueExtensionsCall::Transfer {
-					token_id,
-					..
-				})
+				UniqueNFTCall::ERC721UniqueExtensions(
+					ERC721UniqueExtensionsCall::TransferNft { token_id, .. },
+				)
 				| UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, .. }) => {
 					let token_id: u32 = token_id.try_into().map_err(|_| AnyError)?;
 					let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
@@ -57,7 +44,7 @@
 					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
 						collection_limits.sponsor_transfer_timeout
 					} else {
-						ChainLimit::get().nft_sponsor_transfer_timeout
+						NFT_SPONSOR_TRANSFER_TIMEOUT
 					};
 
 					let mut sponsor = true;
@@ -88,7 +75,7 @@
 					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
 						collection_limits.sponsor_transfer_timeout
 					} else {
-						ChainLimit::get().fungible_sponsor_transfer_timeout
+						FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT
 					};
 
 					let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
@@ -117,54 +104,24 @@
 	}
 	Err(AnyError)
 }
-
-impl<T> pallet_evm::OnChargeEVMTransaction<T> for ChargeEvmTransaction
-where
-	T: Config,
-	T: pallet_evm::Config,
-{
-	type LiquidityInfo = Option<ChargeEvmLiquidityInfo<T>>;
 
-	fn withdraw_fee(
-		who: &H160,
-		reason: WithdrawReason,
-		fee: U256,
-	) -> Result<Self::LiquidityInfo, pallet_evm::Error<T>> {
-		let mut who_pays_fee = *who;
-		if let WithdrawReason::Call { target, input } = &reason {
-			if let Some(collection_id) = crate::eth::map_eth_to_id(target) {
-				if let Some(collection) = <CollectionById<T>>::get(collection_id) {
-					if let Some(sponsor) = collection.sponsorship.sponsor() {
-						if try_sponsor(who, collection_id, &collection, input).is_ok() {
-							who_pays_fee =
-								T::EvmBackwardsAddressMapping::from_account_id(sponsor.clone());
-						}
-					}
+pub struct NftEthSponsorshipHandler<T: Config>(PhantomData<*const T>);
+impl<T: Config> SponsorshipHandler<H160, (H160, Vec<u8>)> for NftEthSponsorshipHandler<T> {
+	fn get_sponsor(who: &H160, call: &(H160, Vec<u8>)) -> Option<H160> {
+		if let Some(collection_id) = map_eth_to_id(&call.0) {
+			if let Some(collection) = <CollectionById<T>>::get(collection_id) {
+				if !collection.sponsorship.confirmed() {
+					return None;
+				}
+				if try_sponsor(who, collection_id, &collection, &call.1).is_ok() {
+					return collection
+						.sponsorship
+						.sponsor()
+						.cloned()
+						.map(T::EvmBackwardsAddressMapping::from_account_id);
 				}
 			}
 		}
-
-		// TODO: Pay fee from substrate address
-		let negative_imbalance = EVMCurrencyAdapter::<<T as Config>::Currency, ()>::withdraw_fee(
-			&who_pays_fee,
-			reason,
-			fee,
-		)?;
-		Ok(negative_imbalance.map(|i| ChargeEvmLiquidityInfo {
-			who: who_pays_fee,
-			negative_imbalance: i,
-		}))
-	}
-
-	fn correct_and_deposit_fee(
-		who: &H160,
-		corrected_fee: U256,
-		already_withdrawn: Self::LiquidityInfo,
-	) -> Result<(), pallet_evm::Error<T>> {
-		EVMCurrencyAdapter::<<T as Config>::Currency, ()>::correct_and_deposit_fee(
-			&already_withdrawn.as_ref().map(|e| e.who).unwrap_or(*who),
-			corrected_fee,
-			already_withdrawn.map(|e| e.negative_imbalance),
-		)
+		None
 	}
 }
deletedpallets/nft/src/eth/stubs/ERC1633.bindiffbeforeafterboth
--- a/pallets/nft/src/eth/stubs/ERC1633.bin
+++ /dev/null
@@ -1 +0,0 @@
-TODO
\ No newline at end of file
deletedpallets/nft/src/eth/stubs/ERC20.bindiffbeforeafterboth

binary blob — no preview

deletedpallets/nft/src/eth/stubs/ERC20.soldiffbeforeafterboth
--- a/pallets/nft/src/eth/stubs/ERC20.sol
+++ /dev/null
@@ -1,69 +0,0 @@
-// SPDX-License-Identifier: OTHER
-
-pragma solidity >=0.8.0 <0.9.0;
-
-contract ERC20 {
-	uint8 _dummy = 0;
-	string stub_error = "this contract does not exists, code for collections is implemented at pallet side";
-
-	// 0x18160ddd
-	function totalSupply() external view returns (uint256) {
-		require(false, stub_error);
-		_dummy;
-		return 0;
-	}
-
-	// 0x70a08231
-	function balanceOf(address account) external view returns (uint256) {
-		require(false, stub_error);
-		account;
-		_dummy;
-		return 0;
-	}
-
-	// 0xa9059cbb
-	function transfer(address recipient, uint256 amount) external returns (bool) {
-		require(false, stub_error);
-		recipient;
-		amount;
-		_dummy = 0;
-		return false;
-	}
-
-	// 0xdd62ed3e
-	function allowance(address owner, address spender) external view returns (uint256) {
-		require(false, stub_error);
-		owner;
-		spender;
-		return _dummy;
-	}
-
-	// 0x095ea7b3
-	function approve(address spender, uint256 amount) external returns (bool) {
-		require(false, stub_error);
-		spender;
-		amount;
-		_dummy = 0;
-		return false;
-	}
-
-	// 0x23b872dd
-	function transferFrom(address sender, address recipient, uint256 amount) external returns (bool) {
-		require(false, stub_error);
-		sender;
-		recipient;
-		amount;
-		_dummy = 0;
-		return false;
-	}
-
-	// While ERC165 is not required by spec of ERC20, better implement it
-	// 0x01ffc9a7
-	function supportsInterface(bytes4 interfaceID) public pure returns (bool) {
-		return 
-			// ERC20
-			interfaceID == 0x36372b07 || 
-			// ERC165
-			interfaceID == 0x01ffc9a7;
-	}
-}
\ No newline at end of file
deletedpallets/nft/src/eth/stubs/ERC721.bindiffbeforeafterboth
--- a/pallets/nft/src/eth/stubs/ERC721.bin
+++ /dev/null
@@ -1 +0,0 @@
-0x608060405260008060006101000a81548160ff021916908360ff16021790555060008060016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180608001604052806051815260200162000cd6605191396001908051906020019061008f9291906100a2565b5034801561009c57600080fd5b506101a6565b8280546100ae90610145565b90600052602060002090601f0160209004810192826100d05760008555610117565b82601f106100e957805160ff1916838001178555610117565b82800160010185558215610117579182015b828111156101165782518255916020019190600101906100fb565b5b5090506101249190610128565b5090565b5b80821115610141576000816000905550600101610129565b5090565b6000600282049050600182168061015d57607f821691505b6020821081141561017157610170610177565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b610b2080620001b66000396000f3fe6080604052600436106100915760003560e01c80636352211e116100595780636352211e1461016457806370a08231146101a1578063a22cb465146101de578063b88d4fde14610207578063e985e9c51461022357610091565b806301ffc9a714610096578063081812fc146100d3578063095ea7b31461011057806323b872dd1461012c57806342842e0e14610148575b600080fd5b3480156100a257600080fd5b506100bd60048036038101906100b89190610821565b610260565b6040516100ca919061093b565b60405180910390f35b3480156100df57600080fd5b506100fa60048036038101906100f5919061084a565b6102c2565b6040516101079190610920565b60405180910390f35b61012a600480360381019061012591906107e5565b610333565b005b610146600480360381019061014191906106da565b61037d565b005b610162600480360381019061015d91906106da565b6103c8565b005b34801561017057600080fd5b5061018b6004803603810190610186919061084a565b610413565b6040516101989190610920565b60405180910390f35b3480156101ad57600080fd5b506101c860048036038101906101c39190610675565b610484565b6040516101d59190610978565b60405180910390f35b3480156101ea57600080fd5b50610205600480360381019061020091906107a9565b6104d4565b005b610221600480360381019061021c9190610729565b610539565b005b34801561022f57600080fd5b5061024a6004803603810190610245919061069e565b610586565b604051610257919061093b565b60405180910390f35b60006380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806102bb57506301ffc9a760e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b600080600190610308576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ff9190610956565b60405180910390fd5b50600060019054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600190610378576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161036f9190610956565b60405180910390fd5b505050565b60006001906103c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103b99190610956565b60405180910390fd5b50505050565b600060019061040d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104049190610956565b60405180910390fd5b50505050565b600080600190610459576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104509190610956565b60405180910390fd5b50600060019054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000806001906104ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104c19190610956565b60405180910390fd5b5060009050919050565b6000600190610519576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105109190610956565b60405180910390fd5b5060008060006101000a81548160ff021916908360ff1602179055505050565b600060019061057e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105759190610956565b60405180910390fd5b505050505050565b6000806001906105cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105c39190610956565b60405180910390fd5b506000905092915050565b6000813590506105e681610a8e565b92915050565b6000813590506105fb81610aa5565b92915050565b60008135905061061081610abc565b92915050565b60008083601f84011261062857600080fd5b8235905067ffffffffffffffff81111561064157600080fd5b60208301915083600182028301111561065957600080fd5b9250929050565b60008135905061066f81610ad3565b92915050565b60006020828403121561068757600080fd5b6000610695848285016105d7565b91505092915050565b600080604083850312156106b157600080fd5b60006106bf858286016105d7565b92505060206106d0858286016105d7565b9150509250929050565b6000806000606084860312156106ef57600080fd5b60006106fd868287016105d7565b935050602061070e868287016105d7565b925050604061071f86828701610660565b9150509250925092565b60008060008060006080868803121561074157600080fd5b600061074f888289016105d7565b9550506020610760888289016105d7565b945050604061077188828901610660565b935050606086013567ffffffffffffffff81111561078e57600080fd5b61079a88828901610616565b92509250509295509295909350565b600080604083850312156107bc57600080fd5b60006107ca858286016105d7565b92505060206107db858286016105ec565b9150509250929050565b600080604083850312156107f857600080fd5b6000610806858286016105d7565b925050602061081785828601610660565b9150509250929050565b60006020828403121561083357600080fd5b600061084184828501610601565b91505092915050565b60006020828403121561085c57600080fd5b600061086a84828501610660565b91505092915050565b61087c816109b9565b82525050565b61088b816109cb565b82525050565b6000815461089e81610a2d565b6108a881866109a8565b945060018216600081146108c357600181146108d557610908565b60ff1983168652602086019350610908565b6108de85610993565b60005b83811015610900578154818901526001820191506020810190506108e1565b808801955050505b50505092915050565b61091a81610a23565b82525050565b60006020820190506109356000830184610873565b92915050565b60006020820190506109506000830184610882565b92915050565b600060208201905081810360008301526109708184610891565b905092915050565b600060208201905061098d6000830184610911565b92915050565b60008190508160005260206000209050919050565b600082825260208201905092915050565b60006109c482610a03565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006002820490506001821680610a4557607f821691505b60208210811415610a5957610a58610a5f565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b610a97816109b9565b8114610aa257600080fd5b50565b610aae816109cb565b8114610ab957600080fd5b50565b610ac5816109d7565b8114610ad057600080fd5b50565b610adc81610a23565b8114610ae757600080fd5b5056fea26469706673582212206e53fcc41e6b23f5bd49a262462ecf5ff647f480649658ee8b67c91a8f733ba864736f6c634300080100337468697320636f6e747261637420646f6573206e6f74206578697374732c20636f646520666f7220636f6c6c656374696f6e7320697320696d706c656d656e7465642061742070616c6c65742073696465
\ No newline at end of file
deletedpallets/nft/src/eth/stubs/ERC721.soldiffbeforeafterboth
--- a/pallets/nft/src/eth/stubs/ERC721.sol
+++ /dev/null
@@ -1,163 +0,0 @@
-// SPDX-License-Identifier: OTHER
-
-pragma solidity >=0.8.0 <0.9.0;
-
-contract ERC721 {
-    uint8 _dummy = 0;
-    address _dummy_addr = 0x0000000000000000000000000000000000000000;
-    string _dummy_string = "";
-    string stub_error =
-        "this contract does not exists, code for collections is implemented at pallet side";
-
-    event Transfer(
-        address indexed from,
-        address indexed to,
-        uint256 indexed tokenId
-    );
-
-    event Approval(
-        address indexed owner,
-        address indexed approved,
-        uint256 indexed tokenId
-    );
-
-    event ApprovalForAll(
-        address indexed owner,
-        address indexed operator,
-        bool approved
-    );
-
-	// 0x18160ddd
-    function totalSupply() external view returns (uint256) {
-        require(false, stub_error);
-        return 0;
-    }
-
-    function name() external view returns (string memory res_name) {
-        require(false, stub_error);
-        res_name = _dummy_string;
-    }
-
-    function symbol() external view returns (string memory res_symbol) {
-        require(false, stub_error);
-        res_symbol = _dummy_string;
-    }
-
-    function tokenURI(uint256 tokenId) external view returns (string memory) {
-        require(false, stub_error);
-        tokenId;
-        return _dummy_string;
-    }
-
-    function tokenByIndex(uint256 index) external view returns (uint256) {
-        require(false, stub_error);
-        index;
-		return 0;
-    }
-
-    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256) {
-        require(false, stub_error);
-		owner;
-		index;
-		return 0;
-    }
-
-    // 0x70a08231
-    function balanceOf(address owner) external view returns (uint256) {
-        require(false, stub_error);
-        owner;
-        return 0;
-    }
-
-    // 0x6352211e
-    function ownerOf(uint256 tokenId) external view returns (address) {
-        require(false, stub_error);
-        tokenId;
-        return _dummy_addr;
-    }
-
-    // 0xb88d4fde
-    function safeTransferFrom(
-        address from,
-        address to,
-        uint256 tokenId,
-        bytes calldata data
-    ) external payable {
-        require(false, stub_error);
-        from;
-        to;
-        tokenId;
-        data;
-    }
-
-    // 0x42842e0e
-    function safeTransferFrom(
-        address from,
-        address to,
-        uint256 tokenId
-    ) external payable {
-        require(false, stub_error);
-        from;
-        to;
-        tokenId;
-    }
-
-    // 0x23b872dd
-    function transferFrom(
-        address from,
-        address to,
-        uint256 tokenId
-    ) external payable {
-        require(false, stub_error);
-        from;
-        to;
-        tokenId;
-    }
-
-    // 0x095ea7b3
-    function approve(address approved, uint256 tokenId) external payable {
-        require(false, stub_error);
-        approved;
-        tokenId;
-    }
-
-    // 0xa22cb465
-    function setApprovalForAll(address operator, bool approved) external {
-        require(false, stub_error);
-        operator;
-        approved;
-        _dummy = 0;
-    }
-
-    // 0x081812fc
-    function getApproved(uint256 tokenId) external view returns (address) {
-        require(false, stub_error);
-        tokenId;
-        return _dummy_addr;
-    }
-
-    // 0xe985e9c5
-    function isApprovedForAll(address owner, address operator)
-        external
-        view
-        returns (bool)
-    {
-        require(false, stub_error);
-        owner;
-        operator;
-        return false;
-    }
-
-    // 0x01ffc9a7
-    function supportsInterface(bytes4 interfaceID) public pure returns (bool) {
-        return
-            // ERC721
-            interfaceID == 0x80ac58cd ||
-            // ERC721Metadata
-            interfaceID == 0x5b5e139f ||
-            // ERC721Enumerable
-            interfaceID == 0x780e9d63 ||
-            // ERC165
-            interfaceID == 0x01ffc9a7;
-    }
-}
deletedpallets/nft/src/eth/stubs/Invalid.bindiffbeforeafterboth
--- a/pallets/nft/src/eth/stubs/Invalid.bin
+++ /dev/null
@@ -1 +0,0 @@
-TODO
\ No newline at end of file
addedpallets/nft/src/eth/stubs/UniqueFungible.rawdiffbeforeafterboth

binary blob — no preview

addedpallets/nft/src/eth/stubs/UniqueFungible.soldiffbeforeafterboth
--- /dev/null
+++ b/pallets/nft/src/eth/stubs/UniqueFungible.sol
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: OTHER
+// This code is automatically generated
+
+pragma solidity >=0.8.0 <0.9.0;
+
+// Common stubs holder
+contract Dummy {
+	uint8 dummy;
+	string stub_error = "this contract is implemented in native";
+}
+
+// Inline
+contract ERC20Events {
+	event Transfer(address indexed from, address indexed to, uint256 value);
+	event Approval(
+		address indexed owner,
+		address indexed spender,
+		uint256 value
+	);
+}
+
+// Inline
+contract InlineNameSymbol is Dummy {
+	function name() public view returns (string memory) {
+		require(false, stub_error);
+		dummy;
+		return "";
+	}
+
+	function symbol() public view returns (string memory) {
+		require(false, stub_error);
+		dummy;
+		return "";
+	}
+}
+
+// Inline
+contract InlineTotalSupply is Dummy {
+	function totalSupply() public view returns (uint256) {
+		require(false, stub_error);
+		dummy;
+		return 0;
+	}
+}
+
+contract ERC165 is Dummy {
+	function supportsInterface(uint32 interfaceId) public view returns (bool) {
+		require(false, stub_error);
+		interfaceId;
+		dummy;
+		return false;
+	}
+}
+
+contract ERC20 is Dummy, InlineNameSymbol, InlineTotalSupply, ERC20Events {
+	function decimals() public view returns (uint8) {
+		require(false, stub_error);
+		dummy;
+		return 0;
+	}
+
+	function balanceOf(address owner) public view returns (uint256) {
+		require(false, stub_error);
+		owner;
+		dummy;
+		return 0;
+	}
+
+	function transfer(address to, uint256 amount) public returns (bool) {
+		require(false, stub_error);
+		to;
+		amount;
+		dummy = 0;
+		return false;
+	}
+
+	function transferFrom(
+		address from,
+		address to,
+		uint256 amount
+	) public returns (bool) {
+		require(false, stub_error);
+		from;
+		to;
+		amount;
+		dummy = 0;
+		return false;
+	}
+
+	function approve(address spender, uint256 amount) public returns (bool) {
+		require(false, stub_error);
+		spender;
+		amount;
+		dummy = 0;
+		return false;
+	}
+
+	function allowance(address owner, address spender)
+		public
+		view
+		returns (uint256)
+	{
+		require(false, stub_error);
+		owner;
+		spender;
+		dummy;
+		return 0;
+	}
+}
+
+contract UniqueFungible is Dummy, ERC165, ERC20 {}
addedpallets/nft/src/eth/stubs/UniqueInvalid.rawdiffbeforeafterboth
--- /dev/null
+++ b/pallets/nft/src/eth/stubs/UniqueInvalid.raw
@@ -0,0 +1 @@
+TODO
\ No newline at end of file
addedpallets/nft/src/eth/stubs/UniqueNFT.rawdiffbeforeafterboth

binary blob — no preview

addedpallets/nft/src/eth/stubs/UniqueNFT.soldiffbeforeafterboth
--- /dev/null
+++ b/pallets/nft/src/eth/stubs/UniqueNFT.sol
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: OTHER
+// This code is automatically generated
+
+pragma solidity >=0.8.0 <0.9.0;
+
+// Common stubs holder
+contract Dummy {
+	uint8 dummy;
+	string stub_error = "this contract is implemented in native";
+}
+
+// Inline
+contract ERC721Events {
+	event Transfer(
+		address indexed from,
+		address indexed to,
+		uint256 indexed tokenId
+	);
+	event Approval(
+		address indexed owner,
+		address indexed approved,
+		uint256 indexed tokenId
+	);
+	event ApprovalForAll(
+		address indexed owner,
+		address indexed operator,
+		bool approved
+	);
+}
+
+// Inline
+contract ERC721MintableEvents {
+	event MintingFinished();
+}
+
+// Inline
+contract InlineNameSymbol is Dummy {
+	function name() public view returns (string memory) {
+		require(false, stub_error);
+		dummy;
+		return "";
+	}
+
+	function symbol() public view returns (string memory) {
+		require(false, stub_error);
+		dummy;
+		return "";
+	}
+}
+
+// Inline
+contract InlineTotalSupply is Dummy {
+	function totalSupply() public view returns (uint256) {
+		require(false, stub_error);
+		dummy;
+		return 0;
+	}
+}
+
+contract ERC165 is Dummy {
+	function supportsInterface(uint32 interfaceId) public view returns (bool) {
+		require(false, stub_error);
+		interfaceId;
+		dummy;
+		return false;
+	}
+}
+
+contract ERC721 is Dummy, ERC165, ERC721Events {
+	function balanceOf(address owner) public view returns (uint256) {
+		require(false, stub_error);
+		owner;
+		dummy;
+		return 0;
+	}
+
+	function ownerOf(uint256 tokenId) public view returns (address) {
+		require(false, stub_error);
+		tokenId;
+		dummy;
+		return 0x0000000000000000000000000000000000000000;
+	}
+
+	function safeTransferFromWithData(
+		address from,
+		address to,
+		uint256 tokenId,
+		bytes memory data
+	) public {
+		require(false, stub_error);
+		from;
+		to;
+		tokenId;
+		data;
+		dummy = 0;
+	}
+
+	function safeTransferFrom(
+		address from,
+		address to,
+		uint256 tokenId
+	) public {
+		require(false, stub_error);
+		from;
+		to;
+		tokenId;
+		dummy = 0;
+	}
+
+	function transferFrom(
+		address from,
+		address to,
+		uint256 tokenId
+	) public {
+		require(false, stub_error);
+		from;
+		to;
+		tokenId;
+		dummy = 0;
+	}
+
+	function approve(address approved, uint256 tokenId) public {
+		require(false, stub_error);
+		approved;
+		tokenId;
+		dummy = 0;
+	}
+
+	function setApprovalForAll(address operator, bool approved) public {
+		require(false, stub_error);
+		operator;
+		approved;
+		dummy = 0;
+	}
+
+	function getApproved(uint256 tokenId) public view returns (address) {
+		require(false, stub_error);
+		tokenId;
+		dummy;
+		return 0x0000000000000000000000000000000000000000;
+	}
+
+	function isApprovedForAll(address owner, address operator)
+		public
+		view
+		returns (address)
+	{
+		require(false, stub_error);
+		owner;
+		operator;
+		dummy;
+		return 0x0000000000000000000000000000000000000000;
+	}
+}
+
+contract ERC721Burnable is Dummy {
+	function burn(uint256 tokenId) public {
+		require(false, stub_error);
+		tokenId;
+		dummy = 0;
+	}
+}
+
+contract ERC721Enumerable is Dummy, InlineTotalSupply {
+	function tokenByIndex(uint256 index) public view returns (uint256) {
+		require(false, stub_error);
+		index;
+		dummy;
+		return 0;
+	}
+
+	function tokenOfOwnerByIndex(address owner, uint256 index)
+		public
+		view
+		returns (uint256)
+	{
+		require(false, stub_error);
+		owner;
+		index;
+		dummy;
+		return 0;
+	}
+}
+
+contract ERC721Metadata is Dummy, InlineNameSymbol {
+	function tokenURI(uint256 tokenId) public view returns (string memory) {
+		require(false, stub_error);
+		tokenId;
+		dummy;
+		return "";
+	}
+}
+
+contract ERC721Mintable is Dummy, ERC721MintableEvents {
+	function mintingFinished() public view returns (bool) {
+		require(false, stub_error);
+		dummy;
+		return false;
+	}
+
+	function mint(address to, uint256 tokenId) public returns (bool) {
+		require(false, stub_error);
+		to;
+		tokenId;
+		dummy = 0;
+		return false;
+	}
+
+	function mintWithTokenURI(
+		address to,
+		uint256 tokenId,
+		string memory tokenUri
+	) public returns (bool) {
+		require(false, stub_error);
+		to;
+		tokenId;
+		tokenUri;
+		dummy = 0;
+		return false;
+	}
+
+	function finishMinting() public returns (bool) {
+		require(false, stub_error);
+		dummy = 0;
+		return false;
+	}
+}
+
+contract ERC721UniqueExtensions is Dummy {
+	function transfer(address to, uint256 tokenId) public {
+		require(false, stub_error);
+		to;
+		tokenId;
+		dummy = 0;
+	}
+
+	function nextTokenId() public view returns (uint256) {
+		require(false, stub_error);
+		dummy;
+		return 0;
+	}
+}
+
+contract UniqueNFT is
+	Dummy,
+	ERC165,
+	ERC721,
+	ERC721Metadata,
+	ERC721Enumerable,
+	ERC721UniqueExtensions,
+	ERC721Mintable,
+	ERC721Burnable
+{}
addedpallets/nft/src/eth/stubs/UniqueRefungible.rawdiffbeforeafterboth
--- /dev/null
+++ b/pallets/nft/src/eth/stubs/UniqueRefungible.raw
@@ -0,0 +1 @@
+TODO
\ No newline at end of file
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -31,19 +31,20 @@
 	StorageValue, transactional,
 };
 
-use frame_system::{self as system, ensure_signed, ensure_root};
+use frame_system::{self as system, ensure_signed};
 use sp_core::H160;
 use sp_std::vec;
-use sp_runtime::sp_std::prelude::Vec;
+use sp_runtime::{DispatchError, sp_std::prelude::Vec};
 use core::ops::{Deref, DerefMut};
-use core::cell::RefCell;
 use nft_data_structs::{
 	MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, MAX_REFUNGIBLE_PIECES,
-	AccessMode, ChainLimits, Collection, CreateItemData, CollectionLimits, CollectionId,
-	CollectionMode, TokenId, SchemaVersion, SponsorshipState, Ownership, NftItemType,
-	FungibleItemType, ReFungibleItemType, MetaUpdatePermission,
+	CUSTOM_DATA_LIMIT, COLLECTION_NUMBER_LIMIT, ACCOUNT_TOKEN_OWNERSHIP_LIMIT,
+	VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, COLLECTION_ADMINS_LIMIT,
+	OFFCHAIN_SCHEMA_LIMIT, MAX_TOKEN_PREFIX_LENGTH, MAX_COLLECTION_NAME_LENGTH,
+	MAX_COLLECTION_DESCRIPTION_LENGTH, AccessMode, Collection, CreateItemData, CollectionLimits,
+	CollectionId, CollectionMode, TokenId, SchemaVersion, SponsorshipState, Ownership, NftItemType,
+	FungibleItemType, ReFungibleItemType,
 };
-use pallet_ethereum::EthereumTransactionSender;
 
 #[cfg(test)]
 mod mock;
@@ -51,10 +52,10 @@
 #[cfg(test)]
 mod tests;
 
-mod default_weights;
 mod eth;
 mod sponsorship;
 pub use sponsorship::NftSponsorshipHandler;
+pub use eth::sponsoring::NftEthSponsorshipHandler;
 
 pub use eth::NftErcSupport;
 pub use eth::account::*;
@@ -62,39 +63,8 @@
 
 #[cfg(feature = "runtime-benchmarks")]
 mod benchmarking;
-
-pub trait WeightInfo {
-	fn create_collection() -> Weight;
-	fn destroy_collection() -> Weight;
-	fn add_to_white_list() -> Weight;
-	fn remove_from_white_list() -> Weight;
-	fn set_public_access_mode() -> Weight;
-	fn set_mint_permission() -> Weight;
-	fn change_collection_owner() -> Weight;
-	fn add_collection_admin() -> Weight;
-	fn remove_collection_admin() -> Weight;
-	fn set_collection_sponsor() -> Weight;
-	fn confirm_sponsorship() -> Weight;
-	fn remove_collection_sponsor() -> Weight;
-	fn create_item(s: usize) -> Weight;
-	fn burn_item() -> Weight;
-	fn transfer() -> Weight;
-	fn approve() -> Weight;
-	fn transfer_from() -> Weight;
-	fn set_offchain_schema() -> Weight;
-	fn set_const_on_chain_schema() -> Weight;
-	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 set_variable_meta_data_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;
-}
+pub mod weights;
+use weights::WeightInfo;
 
 decl_error! {
 	/// Error for non-fungible-token module.
@@ -179,45 +149,53 @@
 		MetadataUpdateDenied,
 		/// Metadata update flag become unmutable with None option
 		MetadataFlagFrozen,
+		/// Collection settings not allowing items transferring
+		TransferNotAllowed,
+		/// Can't transfer tokens to ethereum zero address
+		AddressIsZero,
 	}
 }
 
+#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]
 pub struct CollectionHandle<T: Config> {
 	pub id: CollectionId,
 	collection: Collection<T>,
-	logs: eth::log::LogRecorder,
-	evm_address: H160,
-	gas_limit: RefCell<u64>,
+	recorder: pallet_evm_coder_substrate::SubstrateRecorder<T>,
 }
 impl<T: Config> CollectionHandle<T> {
 	pub fn get_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {
 		<CollectionById<T>>::get(id).map(|collection| Self {
 			id,
 			collection,
-			logs: eth::log::LogRecorder::default(),
-			evm_address: eth::collection_id_to_address(id),
-			gas_limit: RefCell::new(gas_limit),
+			recorder: pallet_evm_coder_substrate::SubstrateRecorder::new(
+				eth::collection_id_to_address(id),
+				gas_limit,
+			),
 		})
 	}
 	pub fn get(id: CollectionId) -> Option<Self> {
 		Self::get_with_gas_limit(id, u64::MAX)
 	}
-	pub fn gas_left(&self) -> u64 {
-		*self.gas_limit.borrow()
+	pub fn log(&self, log: impl evm_coder::ToLog) -> DispatchResult {
+		self.recorder.log_sub(log)
 	}
-	pub fn consume_gas(&self, gas: u64) -> DispatchResult {
-		let mut gas_limit = self.gas_limit.borrow_mut();
-		if *gas_limit < gas {
-			fail!(Error::<T>::OutOfGas);
-		}
-		*gas_limit -= gas;
-		Ok(())
+	#[allow(dead_code)]
+	fn consume_gas(&self, gas: u64) -> DispatchResult {
+		self.recorder.consume_gas_sub(gas)
+	}
+	fn consume_sload(&self) -> DispatchResult {
+		self.recorder.consume_sload_sub()
+	}
+	fn consume_sstore(&self) -> DispatchResult {
+		self.recorder.consume_sstore_sub()
 	}
-	pub fn log(&self, log: impl evm_coder::ToLog) {
-		self.logs.log(log.to_log(self.evm_address))
+	pub fn submit_logs(self) -> DispatchResult {
+		self.recorder.submit_logs()
 	}
-	pub fn into_inner(self) -> Collection<T> {
-		self.collection
+	pub fn save(self) -> DispatchResult {
+		self.recorder.submit_logs()?;
+		<CollectionById<T>>::insert(self.id, self.collection);
+		Ok(())
 	}
 }
 impl<T: Config> Deref for CollectionHandle<T> {
@@ -234,7 +212,7 @@
 	}
 }
 
-pub trait Config: system::Config + Sized {
+pub trait Config: system::Config + pallet_evm_coder_substrate::Config + Sized {
 	type Event: From<Event<Self>> + Into<<Self as system::Config>::Event>;
 
 	/// Weight information for extrinsics in this pallet.
@@ -249,10 +227,40 @@
 		<<Self as Config>::Currency as Currency<Self::AccountId>>::Balance,
 	>;
 	type TreasuryAccountId: Get<Self::AccountId>;
+}
+
+type SelfWeightOf<T> = <T as Config>::WeightInfo;
 
-	type EthereumChainId: Get<u64>;
-	type EthereumTransactionSender: pallet_ethereum::EthereumTransactionSender;
+trait WeightInfoHelpers: WeightInfo {
+	fn transfer() -> Weight {
+		Self::transfer_nft()
+			.max(Self::transfer_fungible())
+			.max(Self::transfer_refungible())
+	}
+	fn transfer_from() -> Weight {
+		Self::transfer_from_nft()
+			.max(Self::transfer_from_fungible())
+			.max(Self::transfer_from_refungible())
+	}
+	fn approve() -> Weight {
+		// TODO: refungible, fungible
+		Self::approve_nft()
+	}
+	fn set_variable_meta_data(data: u32) -> Weight {
+		// TODO: refungible
+		Self::set_variable_meta_data_nft(data)
+	}
+	fn create_item(data: u32) -> Weight {
+		Self::create_item_nft(data)
+			.max(Self::create_item_fungible())
+			.max(Self::create_item_refungible(data))
+	}
+	fn burn_item() -> Weight {
+		// TODO: refungible, fungible
+		Self::burn_item_nft()
+	}
 }
+impl<T: WeightInfo> WeightInfoHelpers for T {}
 
 // # Used definitions
 //
@@ -287,10 +295,6 @@
 		/// Id of last collection token
 		/// Collection id (controlled?1)
 		ItemListIndex: map hasher(blake2_128_concat) CollectionId => TokenId;
-		//#endregion
-
-		//#region Chain limits struct
-		pub ChainLimit get(fn chain_limit) config(): ChainLimits;
 		//#endregion
 
 		//#region Bound counters
@@ -444,6 +448,7 @@
 		origin: T::Origin
 	{
 		fn deposit_event() = default;
+		const CollectionAdminsLimit: u64 = COLLECTION_ADMINS_LIMIT;
 		type Error = Error<T>;
 
 		fn on_initialize(_now: T::BlockNumber) -> Weight {
@@ -466,7 +471,7 @@
 		///
 		/// * mode: [CollectionMode] collection type and type dependent data.
 		// returns collection ID
-		#[weight = <T as Config>::WeightInfo::create_collection()]
+		#[weight = <SelfWeightOf<T>>::create_collection()]
 		#[transactional]
 		pub fn create_collection(origin,
 								 collection_name: Vec<u16>,
@@ -495,19 +500,17 @@
 				_ => 0
 			};
 
-			let chain_limit = ChainLimit::get();
-
 			let created_count = CreatedCollectionCount::get();
 			let destroyed_count = DestroyedCollectionCount::get();
 
 			// bound Total number of collections
-			ensure!(created_count - destroyed_count < chain_limit.collection_numbers_limit, Error::<T>::TotalCollectionsLimitExceeded);
+			ensure!(created_count - destroyed_count < COLLECTION_NUMBER_LIMIT, Error::<T>::TotalCollectionsLimitExceeded);
 
 			// check params
 			ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::<T>::CollectionDecimalPointLimitExceeded);
-			ensure!(collection_name.len() <= 64, Error::<T>::CollectionNameLimitExceeded);
-			ensure!(collection_description.len() <= 256, Error::<T>::CollectionDescriptionLimitExceeded);
-			ensure!(token_prefix.len() <= 16, Error::<T>::CollectionTokenPrefixLimitExceeded);
+			ensure!(collection_name.len() <= MAX_COLLECTION_NAME_LENGTH, Error::<T>::CollectionNameLimitExceeded);
+			ensure!(collection_description.len() <= MAX_COLLECTION_DESCRIPTION_LENGTH, Error::<T>::CollectionDescriptionLimitExceeded);
+			ensure!(token_prefix.len() <= MAX_TOKEN_PREFIX_LENGTH, Error::<T>::CollectionTokenPrefixLimitExceeded);
 
 			// Generate next collection ID
 			let next_id = created_count
@@ -517,7 +520,7 @@
 			CreatedCollectionCount::put(next_id);
 
 			let limits = CollectionLimits {
-				sponsored_data_size: chain_limit.custom_data_limit,
+				sponsored_data_size: CUSTOM_DATA_LIMIT,
 				..Default::default()
 			};
 
@@ -538,6 +541,7 @@
 				const_on_chain_schema: Vec::new(),
 				limits,
 				meta_update_permission: MetaUpdatePermission::default(),
+				transfers_enabled: true,
 			};
 
 			// Add new collection to map
@@ -558,7 +562,7 @@
 		/// # Arguments
 		///
 		/// * collection_id: collection to destroy.
-		#[weight = <T as Config>::WeightInfo::destroy_collection()]
+		#[weight = <SelfWeightOf<T>>::destroy_collection()]
 		#[transactional]
 		pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {
 
@@ -569,23 +573,23 @@
 				fail!(Error::<T>::NoPermission);
 			}
 
-			<AddressTokens<T>>::remove_prefix(collection_id);
-			<Allowances<T>>::remove_prefix(collection_id);
-			<Balance<T>>::remove_prefix(collection_id);
+			<AddressTokens<T>>::remove_prefix(collection_id, None);
+			<Allowances<T>>::remove_prefix(collection_id, None);
+			<Balance<T>>::remove_prefix(collection_id, None);
 			<ItemListIndex>::remove(collection_id);
 			<AdminList<T>>::remove(collection_id);
 			<CollectionById<T>>::remove(collection_id);
-			<WhiteList<T>>::remove_prefix(collection_id);
+			<WhiteList<T>>::remove_prefix(collection_id, None);
 
-			<NftItemList<T>>::remove_prefix(collection_id);
-			<FungibleItemList<T>>::remove_prefix(collection_id);
-			<ReFungibleItemList<T>>::remove_prefix(collection_id);
+			<NftItemList<T>>::remove_prefix(collection_id, None);
+			<FungibleItemList<T>>::remove_prefix(collection_id, None);
+			<ReFungibleItemList<T>>::remove_prefix(collection_id, None);
 
-			<NftTransferBasket<T>>::remove_prefix(collection_id);
-			<FungibleTransferBasket<T>>::remove_prefix(collection_id);
-			<ReFungibleTransferBasket<T>>::remove_prefix(collection_id);
+			<NftTransferBasket<T>>::remove_prefix(collection_id, None);
+			<FungibleTransferBasket<T>>::remove_prefix(collection_id, None);
+			<ReFungibleTransferBasket<T>>::remove_prefix(collection_id, None);
 
-			<VariableMetaDataBasket<T>>::remove_prefix(collection_id);
+			<VariableMetaDataBasket<T>>::remove_prefix(collection_id, None);
 
 			DestroyedCollectionCount::put(DestroyedCollectionCount::get()
 				.checked_add(1)
@@ -606,7 +610,7 @@
 		/// * collection_id.
 		///
 		/// * address.
-		#[weight = <T as Config>::WeightInfo::add_to_white_list()]
+		#[weight = <SelfWeightOf<T>>::add_to_white_list()]
 		#[transactional]
 		pub fn add_to_white_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{
 
@@ -635,7 +639,7 @@
 		/// * collection_id.
 		///
 		/// * address.
-		#[weight = <T as Config>::WeightInfo::remove_from_white_list()]
+		#[weight = <SelfWeightOf<T>>::remove_from_white_list()]
 		#[transactional]
 		pub fn remove_from_white_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{
 
@@ -663,7 +667,7 @@
 		/// * collection_id.
 		///
 		/// * mode: [AccessMode]
-		#[weight = <T as Config>::WeightInfo::set_public_access_mode()]
+		#[weight = <SelfWeightOf<T>>::set_public_access_mode()]
 		#[transactional]
 		pub fn set_public_access_mode(origin, collection_id: CollectionId, mode: AccessMode) -> DispatchResult
 		{
@@ -672,9 +676,7 @@
 			let mut target_collection = Self::get_collection(collection_id)?;
 			Self::check_owner_permissions(&target_collection, &sender)?;
 			target_collection.access = mode;
-			Self::save_collection(target_collection);
-
-			Ok(())
+			target_collection.save()
 		}
 
 		/// Allows Anyone to create tokens if:
@@ -690,7 +692,7 @@
 		/// * collection_id.
 		///
 		/// * mint_permission: Boolean parameter. If True, allows minting to Anyone with conditions above.
-		#[weight = <T as Config>::WeightInfo::set_mint_permission()]
+		#[weight = <SelfWeightOf<T>>::set_mint_permission()]
 		#[transactional]
 		pub fn set_mint_permission(origin, collection_id: CollectionId, mint_permission: bool) -> DispatchResult
 		{
@@ -699,9 +701,7 @@
 			let mut target_collection = Self::get_collection(collection_id)?;
 			Self::check_owner_permissions(&target_collection, &sender)?;
 			target_collection.mint_mode = mint_permission;
-			Self::save_collection(target_collection);
-
-			Ok(())
+			target_collection.save()
 		}
 
 		/// Change the owner of the collection.
@@ -715,7 +715,7 @@
 		/// * collection_id.
 		///
 		/// * new_owner.
-		#[weight = <T as Config>::WeightInfo::change_collection_owner()]
+		#[weight = <SelfWeightOf<T>>::change_collection_owner()]
 		#[transactional]
 		pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {
 
@@ -723,9 +723,7 @@
 			let mut target_collection = Self::get_collection(collection_id)?;
 			Self::check_owner_permissions(&target_collection, &sender)?;
 			target_collection.owner = new_owner;
-			Self::save_collection(target_collection);
-
-			Ok(())
+			target_collection.save()
 		}
 
 		/// Adds an admin of the Collection.
@@ -741,7 +739,7 @@
 		/// * collection_id: ID of the Collection to add admin for.
 		///
 		/// * new_admin_id: Address of new admin to add.
-		#[weight = <T as Config>::WeightInfo::add_collection_admin()]
+		#[weight = <SelfWeightOf<T>>::add_collection_admin()]
 		#[transactional]
 		pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -752,8 +750,7 @@
 			match admin_arr.binary_search(&new_admin_id) {
 				Ok(_) => {},
 				Err(idx) => {
-					let limits = ChainLimit::get();
-					ensure!(admin_arr.len() < limits.collections_admins_limit as usize, Error::<T>::CollectionAdminsLimitExceeded);
+					ensure!(admin_arr.len() < COLLECTION_ADMINS_LIMIT as usize, Error::<T>::CollectionAdminsLimitExceeded);
 					admin_arr.insert(idx, new_admin_id);
 					<AdminList<T>>::insert(collection_id, admin_arr);
 				}
@@ -773,7 +770,7 @@
 		/// * collection_id: ID of the Collection to remove admin for.
 		///
 		/// * account_id: Address of admin to remove.
-		#[weight = <T as Config>::WeightInfo::remove_collection_admin()]
+		#[weight = <SelfWeightOf<T>>::remove_collection_admin()]
 		#[transactional]
 		pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -797,7 +794,7 @@
 		/// * collection_id.
 		///
 		/// * new_sponsor.
-		#[weight = <T as Config>::WeightInfo::set_collection_sponsor()]
+		#[weight = <SelfWeightOf<T>>::set_collection_sponsor()]
 		#[transactional]
 		pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {
 			let sender = ensure_signed(origin)?;
@@ -805,9 +802,7 @@
 			Self::check_owner_permissions(&target_collection, &sender)?;
 
 			target_collection.sponsorship = SponsorshipState::Unconfirmed(new_sponsor);
-			Self::save_collection(target_collection);
-
-			Ok(())
+			target_collection.save()
 		}
 
 		/// # Permissions
@@ -817,7 +812,7 @@
 		/// # Arguments
 		///
 		/// * collection_id.
-		#[weight = <T as Config>::WeightInfo::confirm_sponsorship()]
+		#[weight = <SelfWeightOf<T>>::confirm_sponsorship()]
 		#[transactional]
 		pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {
 			let sender = ensure_signed(origin)?;
@@ -829,9 +824,7 @@
 			);
 
 			target_collection.sponsorship = SponsorshipState::Confirmed(sender);
-			Self::save_collection(target_collection);
-
-			Ok(())
+			target_collection.save()
 		}
 
 		/// Switch back to pay-per-own-transaction model.
@@ -843,7 +836,7 @@
 		/// # Arguments
 		///
 		/// * collection_id.
-		#[weight = <T as Config>::WeightInfo::remove_collection_sponsor()]
+		#[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]
 		#[transactional]
 		pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {
 			let sender = ensure_signed(origin)?;
@@ -852,9 +845,7 @@
 			Self::check_owner_permissions(&target_collection, &sender)?;
 
 			target_collection.sponsorship = SponsorshipState::Disabled;
-			Self::save_collection(target_collection);
-
-			Ok(())
+			target_collection.save()
 		}
 
 		/// This method creates a concrete instance of NFT Collection created with CreateCollection method.
@@ -881,7 +872,7 @@
 		// .saturating_add(RocksDbWeight::get().reads(10 as Weight))
 		// .saturating_add(RocksDbWeight::get().writes(8 as Weight))]
 
-		#[weight = <T as Config>::WeightInfo::create_item(data.data_size())]
+		#[weight = <SelfWeightOf<T>>::create_item(data.data_size() as u32)]
 		#[transactional]
 		pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResult {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -889,8 +880,7 @@
 
 			Self::create_item_internal(&sender, &collection, &owner, data)?;
 
-			// Self::submit_logs(collection)?;
-			Ok(())
+			collection.submit_logs()
 		}
 
 		/// This method creates multiple items in a collection created with CreateCollection method.
@@ -911,8 +901,8 @@
 		/// * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].
 		///
 		/// * owner: Address, initial owner of the NFT.
-		#[weight = <T as Config>::WeightInfo::create_item(items_data.iter()
-							   .map(|data| { data.data_size() })
+		#[weight = <SelfWeightOf<T>>::create_item(items_data.iter()
+							   .map(|data| { data.data_size() as u32 })
 							   .sum())]
 		#[transactional]
 		pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResult {
@@ -923,11 +913,36 @@
 
 			Self::create_multiple_items_internal(&sender, &collection, &owner, items_data)?;
 
-			// Self::submit_logs(collection)?;
-			Ok(())
+			collection.submit_logs()
 		}
 
 		// TODO! transaction weight
+
+		/// Set transfers_enabled value for particular collection
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner.
+		///
+		/// # Arguments
+		///
+		/// * collection_id: ID of the collection.
+		///
+		/// * value: New flag value.
+		#[weight = <SelfWeightOf<T>>::burn_item()]
+		#[transactional]
+		pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {
+
+			let sender = ensure_signed(origin)?;
+			let mut target_collection = Self::get_collection(collection_id)?;
+
+			Self::check_owner_permissions(&target_collection, &sender)?;
+
+			target_collection.transfers_enabled = value;
+			target_collection.save()
+		}
+
+		// TODO! transaction weight
 		/// Set meta_update_permission value for particular collection
 		///
 		/// # Permissions
@@ -971,7 +986,7 @@
 		/// * collection_id: ID of the collection.
 		///
 		/// * item_id: ID of NFT to burn.
-		#[weight = <T as Config>::WeightInfo::burn_item()]
+		#[weight = <SelfWeightOf<T>>::burn_item()]
 		#[transactional]
 		pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResult {
 
@@ -980,8 +995,7 @@
 
 			Self::burn_item_internal(&sender, &target_collection, item_id, value)?;
 
-			// Self::submit_logs(target_collection)?;
-			Ok(())
+			target_collection.submit_logs()
 		}
 
 		/// Change ownership of the token.
@@ -1007,7 +1021,7 @@
 		///     * Non-Fungible Mode: Ignored
 		///     * Fungible Mode: Must specify transferred amount
 		///     * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)
-		#[weight = <T as Config>::WeightInfo::transfer()]
+		#[weight = <SelfWeightOf<T>>::transfer()]
 		#[transactional]
 		pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResult {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -1015,8 +1029,7 @@
 
 			Self::transfer_internal(&sender, &recipient, &collection, item_id, value)?;
 
-			// Self::submit_logs(collection)?;
-			Ok(())
+			collection.submit_logs()
 		}
 
 		/// Set, change, or remove approved address to transfer the ownership of the NFT.
@@ -1034,7 +1047,7 @@
 		/// * collection_id.
 		///
 		/// * item_id: ID of the item.
-		#[weight = <T as Config>::WeightInfo::approve()]
+		#[weight = <SelfWeightOf<T>>::approve()]
 		#[transactional]
 		pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResult {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -1042,8 +1055,7 @@
 
 			Self::approve_internal(&sender, &spender, &collection, item_id, amount)?;
 
-			// Self::submit_logs(collection)?;
-			Ok(())
+			collection.submit_logs()
 		}
 
 		/// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.
@@ -1065,7 +1077,7 @@
 		/// * item_id: ID of the item.
 		///
 		/// * value: Amount to transfer.
-		#[weight = <T as Config>::WeightInfo::transfer_from()]
+		#[weight = <SelfWeightOf<T>>::transfer_from()]
 		#[transactional]
 		pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResult {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -1073,8 +1085,7 @@
 
 			Self::transfer_from_internal(&sender, &from, &recipient, &collection, item_id, value)?;
 
-			// Self::submit_logs(collection)?;
-			Ok(())
+			collection.submit_logs()
 		}
 		// #[weight = 0]
 		//     // let no_perm_mes = "You do not have permissions to modify this collection";
@@ -1101,7 +1112,7 @@
 		/// * collection_id.
 		///
 		/// * schema: String representing the offchain data schema.
-		#[weight = <T as Config>::WeightInfo::set_variable_meta_data()]
+		#[weight = <SelfWeightOf<T>>::set_variable_meta_data(data.len() as u32)]
 		#[transactional]
 		pub fn set_variable_meta_data (
 			origin,
@@ -1132,7 +1143,7 @@
 		/// * collection_id.
 		///
 		/// * schema: SchemaVersion: enum
-		#[weight = <T as Config>::WeightInfo::set_schema_version()]
+		#[weight = <SelfWeightOf<T>>::set_schema_version()]
 		#[transactional]
 		pub fn set_schema_version(
 			origin,
@@ -1143,9 +1154,7 @@
 			let mut target_collection = Self::get_collection(collection_id)?;
 			Self::check_owner_or_admin_permissions(&target_collection, &sender)?;
 			target_collection.schema_version = version;
-			Self::save_collection(target_collection);
-
-			Ok(())
+			target_collection.save()
 		}
 
 		/// Set off-chain data schema.
@@ -1160,7 +1169,7 @@
 		/// * collection_id.
 		///
 		/// * schema: String representing the offchain data schema.
-		#[weight = <T as Config>::WeightInfo::set_offchain_schema()]
+		#[weight = <SelfWeightOf<T>>::set_offchain_schema(schema.len() as u32)]
 		#[transactional]
 		pub fn set_offchain_schema(
 			origin,
@@ -1172,12 +1181,10 @@
 			Self::check_owner_or_admin_permissions(&target_collection, &sender)?;
 
 			// check schema limit
-			ensure!(schema.len() as u32 <= ChainLimit::get().offchain_schema_limit, "");
+			ensure!(schema.len() as u32 <= OFFCHAIN_SCHEMA_LIMIT, "");
 
 			target_collection.offchain_schema = schema;
-			Self::save_collection(target_collection);
-
-			Ok(())
+			target_collection.save()
 		}
 
 		/// Set const on-chain data schema.
@@ -1192,7 +1199,7 @@
 		/// * collection_id.
 		///
 		/// * schema: String representing the const on-chain data schema.
-		#[weight = <T as Config>::WeightInfo::set_const_on_chain_schema()]
+		#[weight = <SelfWeightOf<T>>::set_const_on_chain_schema(schema.len() as u32)]
 		#[transactional]
 		pub fn set_const_on_chain_schema (
 			origin,
@@ -1204,12 +1211,10 @@
 			Self::check_owner_or_admin_permissions(&target_collection, &sender)?;
 
 			// check schema limit
-			ensure!(schema.len() as u32 <= ChainLimit::get().const_on_chain_schema_limit, "");
+			ensure!(schema.len() as u32 <= CONST_ON_CHAIN_SCHEMA_LIMIT, "");
 
 			target_collection.const_on_chain_schema = schema;
-			Self::save_collection(target_collection);
-
-			Ok(())
+			target_collection.save()
 		}
 
 		/// Set variable on-chain data schema.
@@ -1224,7 +1229,7 @@
 		/// * collection_id.
 		///
 		/// * schema: String representing the variable on-chain data schema.
-		#[weight = <T as Config>::WeightInfo::set_const_on_chain_schema()]
+		#[weight = <SelfWeightOf<T>>::set_const_on_chain_schema(schema.len() as u32)]
 		#[transactional]
 		pub fn set_variable_on_chain_schema (
 			origin,
@@ -1236,30 +1241,13 @@
 			Self::check_owner_or_admin_permissions(&target_collection, &sender)?;
 
 			// check schema limit
-			ensure!(schema.len() as u32 <= ChainLimit::get().variable_on_chain_schema_limit, "");
+			ensure!(schema.len() as u32 <= VARIABLE_ON_CHAIN_SCHEMA_LIMIT, "");
 
 			target_collection.variable_on_chain_schema = schema;
-			Self::save_collection(target_collection);
-
-			Ok(())
-		}
-
-		// Sudo permissions function
-		#[weight = <T as Config>::WeightInfo::set_chain_limits()]
-		#[transactional]
-		pub fn set_chain_limits(
-			origin,
-			limits: ChainLimits
-		) -> DispatchResult {
-
-			#[cfg(not(feature = "runtime-benchmarks"))]
-			ensure_root(origin)?;
-
-			<ChainLimit>::put(limits);
-			Ok(())
+			target_collection.save()
 		}
 
-		#[weight = <T as Config>::WeightInfo::set_collection_limits()]
+		#[weight = <SelfWeightOf<T>>::set_collection_limits()]
 		#[transactional]
 		pub fn set_collection_limits(
 			origin,
@@ -1270,12 +1258,11 @@
 			let mut target_collection = Self::get_collection(collection_id)?;
 			Self::check_owner_permissions(&target_collection, sender.as_sub())?;
 			let old_limits = &target_collection.limits;
-			let chain_limits = ChainLimit::get();
 
 			// collection bounds
 			ensure!(new_limits.sponsor_transfer_timeout <= MAX_SPONSOR_TIMEOUT &&
 				new_limits.account_token_ownership_limit <= MAX_TOKEN_OWNERSHIP &&
-				new_limits.sponsored_data_size <= chain_limits.custom_data_limit,
+				new_limits.sponsored_data_size <= CUSTOM_DATA_LIMIT,
 				Error::<T>::CollectionLimitBoundsExceeded);
 
 			// token_limit   check  prev
@@ -1289,9 +1276,8 @@
 			);
 
 			target_collection.limits = new_limits;
-			Self::save_collection(target_collection);
 
-			Ok(())
+			target_collection.save()
 		}
 	}
 }
@@ -1303,6 +1289,11 @@
 		owner: &T::CrossAccountId,
 		data: CreateItemData,
 	) -> DispatchResult {
+		ensure!(
+			owner != &T::CrossAccountId::from_eth(H160([0; 20])),
+			Error::<T>::AddressIsZero
+		);
+
 		Self::can_create_items_in_collection(collection, sender, owner, 1)?;
 		Self::validate_create_item_args(collection, &data)?;
 		Self::create_item_no_validation(collection, owner, data)?;
@@ -1317,14 +1308,18 @@
 		item_id: TokenId,
 		value: u128,
 	) -> DispatchResult {
-		target_collection.consume_gas(2000000)?;
+		ensure!(
+			recipient != &T::CrossAccountId::from_eth(H160([0; 20])),
+			Error::<T>::AddressIsZero
+		);
+
 		// Limits check
 		Self::is_correct_transfer(target_collection, recipient)?;
 
 		// Transfer permissions check
 		ensure!(
-			Self::is_item_owner(sender, target_collection, item_id)
-				|| Self::is_owner_or_admin_permissions(target_collection, sender),
+			Self::is_item_owner(sender, target_collection, item_id)?
+				|| Self::is_owner_or_admin_permissions(target_collection, sender)?,
 			Error::<T>::NoPermission
 		);
 
@@ -1371,16 +1366,15 @@
 		item_id: TokenId,
 		amount: u128,
 	) -> DispatchResult {
-		collection.consume_gas(2000000)?;
 		Self::token_exists(collection, item_id)?;
 
 		// Transfer permissions check
 		let bypasses_limits = collection.limits.owner_can_transfer
-			&& Self::is_owner_or_admin_permissions(collection, sender);
+			&& Self::is_owner_or_admin_permissions(collection, sender)?;
 
 		let allowance_limit = if bypasses_limits {
 			None
-		} else if let Some(amount) = Self::owned_amount(sender, collection, item_id) {
+		} else if let Some(amount) = Self::owned_amount(sender, collection, item_id)? {
 			Some(amount)
 		} else {
 			fail!(Error::<T>::NoPermission);
@@ -1391,6 +1385,7 @@
 			Self::check_white_list(collection, spender)?;
 		}
 
+		collection.consume_sload()?;
 		let allowance: u128 = amount
 			.checked_add(<Allowances<T>>::get(
 				collection.id,
@@ -1400,6 +1395,7 @@
 		if let Some(limit) = allowance_limit {
 			ensure!(limit >= allowance, Error::<T>::TokenValueTooLow);
 		}
+		collection.consume_sstore()?;
 		<Allowances<T>>::insert(
 			collection.id,
 			(item_id, sender.as_sub(), spender.as_sub()),
@@ -1412,7 +1408,7 @@
 				owner: *sender.as_eth(),
 				approved: *spender.as_eth(),
 				token_id: item_id.into(),
-			});
+			})?;
 		}
 
 		if matches!(collection.mode, CollectionMode::Fungible(_)) {
@@ -1421,7 +1417,7 @@
 				owner: *sender.as_eth(),
 				spender: *spender.as_eth(),
 				value: allowance.into(),
-			});
+			})?;
 		}
 
 		Self::deposit_event(RawEvent::Approved(
@@ -1442,8 +1438,13 @@
 		item_id: TokenId,
 		amount: u128,
 	) -> DispatchResult {
-		collection.consume_gas(2000000)?;
+		if sender == from {
+			// Transfer by `from`, because it is either equal to sender, or derived from him
+			return Self::transfer_internal(from, recipient, collection, item_id, amount);
+		}
+
 		// Check approval
+		collection.consume_sload()?;
 		let approval: u128 =
 			<Allowances<T>>::get(collection.id, (item_id, from.as_sub(), sender.as_sub()));
 
@@ -1454,7 +1455,7 @@
 		ensure!(
 			approval >= amount
 				|| (collection.limits.owner_can_transfer
-					&& Self::is_owner_or_admin_permissions(collection, sender)),
+					&& Self::is_owner_or_admin_permissions(collection, sender)?),
 			Error::<T>::NoPermission
 		);
 
@@ -1465,6 +1466,7 @@
 
 		// Reduce approval by transferred amount or remove if remaining approval drops to 0
 		let allowance = approval.saturating_sub(amount);
+		collection.consume_sstore()?;
 		if allowance > 0 {
 			<Allowances<T>>::insert(
 				collection.id,
@@ -1497,7 +1499,7 @@
 				owner: *from.as_eth(),
 				spender: *sender.as_eth(),
 				value: allowance.into(),
-			});
+			})?;
 		}
 
 		Ok(())
@@ -1512,12 +1514,16 @@
 		Self::token_exists(collection, item_id)?;
 
 		ensure!(
-			ChainLimit::get().custom_data_limit >= data.len() as u32,
+			CUSTOM_DATA_LIMIT >= data.len() as u32,
 			Error::<T>::TokenVariableDataLimitExceeded
 		);
 
 		// Modify permissions check
-		Self::meta_update_check(sender, collection, item_id)?;
+		ensure!(
+			Self::is_item_owner(sender, collection, item_id)?
+				|| Self::is_owner_or_admin_permissions(collection, sender)?,
+			Error::<T>::NoPermission
+		);
 
 		match collection.mode {
 			CollectionMode::NFT => Self::set_nft_variable_data(collection, item_id, data)?,
@@ -1582,9 +1588,9 @@
 		value: u128,
 	) -> DispatchResult {
 		ensure!(
-			Self::is_item_owner(sender, collection, item_id)
+			Self::is_item_owner(sender, collection, item_id)?
 				|| (collection.limits.owner_can_transfer
-					&& Self::is_owner_or_admin_permissions(collection, sender)),
+					&& Self::is_owner_or_admin_permissions(collection, sender)?),
 			Error::<T>::NoPermission
 		);
 
@@ -1626,6 +1632,7 @@
 		let collection_id = collection.id;
 
 		// check token limit and account token limit
+		collection.consume_sload()?;
 		let account_items: u32 =
 			<AddressTokens<T>>::get(collection_id, recipient.as_sub()).len() as u32;
 		ensure!(
@@ -1633,6 +1640,9 @@
 			Error::<T>::AccountTokenLimitExceeded
 		);
 
+		// preliminary transfer check
+		ensure!(collection.transfers_enabled, Error::<T>::TransferNotAllowed);
+
 		Ok(())
 	}
 
@@ -1661,7 +1671,7 @@
 			Error::<T>::AccountTokenLimitExceeded
 		);
 
-		if !Self::is_owner_or_admin_permissions(collection, sender) {
+		if !Self::is_owner_or_admin_permissions(collection, sender)? {
 			ensure!(collection.mint_mode, Error::<T>::PublicMintingNotAllowed);
 			Self::check_white_list(collection, owner)?;
 			Self::check_white_list(collection, sender)?;
@@ -1676,38 +1686,17 @@
 	) -> DispatchResult {
 		match target_collection.mode {
 			CollectionMode::NFT => {
-				if let CreateItemData::NFT(data) = data {
-					// check sizes
-					ensure!(
-						ChainLimit::get().custom_data_limit >= data.const_data.len() as u32,
-						Error::<T>::TokenConstDataLimitExceeded
-					);
-					ensure!(
-						ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32,
-						Error::<T>::TokenVariableDataLimitExceeded
-					);
-				} else {
+				if !matches!(data, CreateItemData::NFT(_)) {
 					fail!(Error::<T>::NotNftDataUsedToMintNftCollectionToken);
 				}
 			}
 			CollectionMode::Fungible(_) => {
-				if let CreateItemData::Fungible(_) = data {
-				} else {
+				if !matches!(data, CreateItemData::Fungible(_)) {
 					fail!(Error::<T>::NotFungibleDataUsedToMintFungibleCollectionToken);
 				}
 			}
 			CollectionMode::ReFungible => {
 				if let CreateItemData::ReFungible(data) = data {
-					// check sizes
-					ensure!(
-						ChainLimit::get().custom_data_limit >= data.const_data.len() as u32,
-						Error::<T>::TokenConstDataLimitExceeded
-					);
-					ensure!(
-						ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32,
-						Error::<T>::TokenVariableDataLimitExceeded
-					);
-
 					// Check refungibility limits
 					ensure!(
 						data.pieces <= MAX_REFUNGIBLE_PIECES,
@@ -1735,8 +1724,8 @@
 			CreateItemData::NFT(data) => {
 				let item = NftItemType {
 					owner: owner.clone(),
-					const_data: data.const_data,
-					variable_data: data.variable_data,
+					const_data: data.const_data.into_inner(),
+					variable_data: data.variable_data.into_inner(),
 				};
 
 				Self::add_nft_item(collection, item)?;
@@ -1752,8 +1741,8 @@
 
 				let item = ReFungibleItemType {
 					owner: owner_list,
-					const_data: data.const_data,
-					variable_data: data.variable_data,
+					const_data: data.const_data.into_inner(),
+					variable_data: data.variable_data.into_inner(),
 				};
 
 				Self::add_refungible_item(collection, item)?;
@@ -1771,20 +1760,29 @@
 		let collection_id = collection.id;
 
 		// Does new owner already have an account?
+		collection.consume_sload()?;
 		let balance: u128 = <FungibleItemList<T>>::get(collection_id, owner.as_sub()).value;
 
 		// Mint
 		let item = FungibleItemType {
 			value: balance.checked_add(value).ok_or(Error::<T>::NumOverflow)?,
 		};
+		collection.consume_sstore()?;
 		<FungibleItemList<T>>::insert(collection_id, owner.as_sub(), item);
 
 		// Update balance
+		collection.consume_sload()?;
 		let new_balance = <Balance<T>>::get(collection_id, owner.as_sub())
 			.checked_add(value)
 			.ok_or(Error::<T>::NumOverflow)?;
+		collection.consume_sstore()?;
 		<Balance<T>>::insert(collection_id, owner.as_sub(), new_balance);
 
+		collection.log(ERC20Events::Transfer {
+			from: H160::default(),
+			to: *owner.as_eth(),
+			value: value.into(),
+		})?;
 		Self::deposit_event(RawEvent::ItemCreated(collection_id, 0, owner.clone()));
 		Ok(())
 	}
@@ -1806,7 +1804,7 @@
 		let value = item_owner.fraction;
 		let owner = item_owner.owner.clone();
 
-		Self::add_token_index(collection_id, current_index, &owner)?;
+		Self::add_token_index(collection, current_index, &owner)?;
 
 		<ItemListIndex>::insert(collection_id, current_index);
 		<ReFungibleItemList<T>>::insert(collection_id, current_index, itemcopy);
@@ -1832,7 +1830,7 @@
 			.ok_or(Error::<T>::NumOverflow)?;
 
 		let item_owner = item.owner.clone();
-		Self::add_token_index(collection_id, current_index, &item.owner)?;
+		Self::add_token_index(collection, current_index, &item.owner)?;
 
 		<ItemListIndex>::insert(collection_id, current_index);
 		<NftItemList<T>>::insert(collection_id, current_index, item);
@@ -1847,7 +1845,7 @@
 			from: H160::default(),
 			to: *item_owner.as_eth(),
 			token_id: current_index.into(),
-		});
+		})?;
 		Self::deposit_event(RawEvent::ItemCreated(
 			collection_id,
 			current_index,
@@ -1870,7 +1868,7 @@
 			.iter()
 			.find(|&i| i.owner == *owner)
 			.ok_or(Error::<T>::TokenNotFound)?;
-		Self::remove_token_index(collection_id, item_id, owner)?;
+		Self::remove_token_index(collection, item_id, owner)?;
 
 		// update balance
 		let new_balance = <Balance<T>>::get(collection_id, rft_balance.owner.as_sub())
@@ -1903,7 +1901,7 @@
 
 		let item =
 			<NftItemList<T>>::get(collection_id, item_id).ok_or(Error::<T>::TokenNotFound)?;
-		Self::remove_token_index(collection_id, item_id, &item.owner)?;
+		Self::remove_token_index(collection, item_id, &item.owner)?;
 
 		// update balance
 		let new_balance = <Balance<T>>::get(collection_id, item.owner.as_sub())
@@ -1913,6 +1911,11 @@
 		<NftItemList<T>>::remove(collection_id, item_id);
 		<VariableMetaDataBasket<T>>::remove(collection_id, item_id);
 
+		collection.log(ERC721Events::Transfer {
+			from: *item.owner.as_eth(),
+			to: H160::default(),
+			token_id: item_id.into(),
+		})?;
 		Self::deposit_event(RawEvent::ItemDestroyed(collection.id, item_id));
 		Ok(())
 	}
@@ -1944,7 +1947,7 @@
 			from: *owner.as_eth(),
 			to: H160::default(),
 			value: value.into(),
-		});
+		})?;
 		Ok(())
 	}
 
@@ -1952,20 +1955,6 @@
 		collection_id: CollectionId,
 	) -> Result<CollectionHandle<T>, sp_runtime::DispatchError> {
 		Ok(<CollectionHandle<T>>::get(collection_id).ok_or(Error::<T>::CollectionNotFound)?)
-	}
-
-	fn save_collection(collection: CollectionHandle<T>) {
-		<CollectionById<T>>::insert(collection.id, collection.into_inner());
-	}
-
-	pub fn submit_logs(collection: CollectionHandle<T>) -> DispatchResult {
-		if collection.logs.is_empty() {
-			return Ok(());
-		}
-		T::EthereumTransactionSender::submit_logs_transaction(
-			eth::generate_transaction(collection.id, T::EthereumChainId::get()),
-			collection.logs.retrieve_logs(),
-		)
 	}
 
 	fn check_owner_permissions(
@@ -1983,9 +1972,10 @@
 	fn is_owner_or_admin_permissions(
 		collection: &CollectionHandle<T>,
 		subject: &T::CrossAccountId,
-	) -> bool {
-		*subject.as_sub() == collection.owner
-			|| <AdminList<T>>::get(collection.id).contains(subject)
+	) -> Result<bool, DispatchError> {
+		collection.consume_sload()?;
+		Ok(*subject.as_sub() == collection.owner
+			|| <AdminList<T>>::get(collection.id).contains(subject))
 	}
 
 	fn check_owner_or_admin_permissions(
@@ -1993,7 +1983,7 @@
 		subject: &T::CrossAccountId,
 	) -> DispatchResult {
 		ensure!(
-			Self::is_owner_or_admin_permissions(collection, subject),
+			Self::is_owner_or_admin_permissions(collection, subject)?,
 			Error::<T>::NoPermission
 		);
 
@@ -2002,6 +1992,15 @@
 
 	fn owned_amount(
 		subject: &T::CrossAccountId,
+		collection: &CollectionHandle<T>,
+		item_id: TokenId,
+	) -> Result<Option<u128>, DispatchError> {
+		collection.consume_sload()?;
+		Ok(Self::owned_amount_unchecked(subject, collection, item_id))
+	}
+
+	fn owned_amount_unchecked(
+		subject: &T::CrossAccountId,
 		target_collection: &CollectionHandle<T>,
 		item_id: TokenId,
 	) -> Option<u128> {
@@ -2027,25 +2026,22 @@
 		subject: &T::CrossAccountId,
 		target_collection: &CollectionHandle<T>,
 		item_id: TokenId,
-	) -> bool {
-		match target_collection.mode {
+	) -> Result<bool, DispatchError> {
+		Ok(match target_collection.mode {
 			CollectionMode::Fungible(_) => true,
-			_ => Self::owned_amount(subject, target_collection, item_id).is_some(),
-		}
+			_ => Self::owned_amount(subject, target_collection, item_id)?.is_some(),
+		})
 	}
 
 	fn check_white_list(
 		collection: &CollectionHandle<T>,
 		address: &T::CrossAccountId,
 	) -> DispatchResult {
-		let collection_id = collection.id;
-
-		let mes = Error::<T>::AddresNotInWhiteList;
+		collection.consume_sload()?;
 		ensure!(
-			<WhiteList<T>>::contains_key(collection_id, address.as_sub()),
-			mes
+			<WhiteList<T>>::contains_key(collection.id, address.as_sub()),
+			Error::<T>::AddresNotInWhiteList,
 		);
-
 		Ok(())
 	}
 
@@ -2074,28 +2070,45 @@
 	) -> DispatchResult {
 		let collection_id = collection.id;
 
+		collection.consume_sload()?;
+		collection.consume_sload()?;
+		let mut recipient_balance = <FungibleItemList<T>>::get(collection_id, recipient.as_sub());
 		let mut balance = <FungibleItemList<T>>::get(collection_id, owner.as_sub());
-		ensure!(balance.value >= value, Error::<T>::TokenValueTooLow);
 
-		// Send balance to recipient (updates balanceOf of recipient)
-		Self::add_fungible_item(collection, recipient, value)?;
+		recipient_balance.value = recipient_balance
+			.value
+			.checked_add(value)
+			.ok_or(Error::<T>::NumOverflow)?;
+		balance.value = balance
+			.value
+			.checked_sub(value)
+			.ok_or(Error::<T>::TokenValueTooLow)?;
 
-		// update balanceOf of sender
-		<Balance<T>>::insert(collection_id, owner.as_sub(), balance.value - value);
+		// update balanceOf
+		collection.consume_sstore()?;
+		collection.consume_sstore()?;
+		if balance.value != 0 {
+			<Balance<T>>::insert(collection_id, owner.as_sub(), balance.value);
+		} else {
+			<Balance<T>>::remove(collection_id, owner.as_sub());
+		}
+		<Balance<T>>::insert(collection_id, recipient.as_sub(), recipient_balance.value);
 
 		// Reduce or remove sender
-		if balance.value == value {
-			<FungibleItemList<T>>::remove(collection_id, owner.as_sub());
-		} else {
-			balance.value -= value;
+		collection.consume_sstore()?;
+		collection.consume_sstore()?;
+		if balance.value != 0 {
 			<FungibleItemList<T>>::insert(collection_id, owner.as_sub(), balance);
+		} else {
+			<FungibleItemList<T>>::remove(collection_id, owner.as_sub());
 		}
+		<FungibleItemList<T>>::insert(collection_id, recipient.as_sub(), recipient_balance);
 
 		collection.log(ERC20Events::Transfer {
 			from: *owner.as_eth(),
 			to: *recipient.as_eth(),
 			value: value.into(),
-		});
+		})?;
 		Self::deposit_event(RawEvent::Transfer(
 			collection.id,
 			1,
@@ -2115,6 +2128,7 @@
 		new_owner: T::CrossAccountId,
 	) -> DispatchResult {
 		let collection_id = collection.id;
+		collection.consume_sload()?;
 		let full_item = <ReFungibleItemList<T>>::get(collection_id, item_id)
 			.ok_or(Error::<T>::TokenNotFound)?;
 
@@ -2127,15 +2141,19 @@
 
 		ensure!(amount >= value, Error::<T>::TokenValueTooLow);
 
+		collection.consume_sload()?;
 		// update balance
 		let balance_old_owner = <Balance<T>>::get(collection_id, item.owner.as_sub())
 			.checked_sub(value)
 			.ok_or(Error::<T>::NumOverflow)?;
+		collection.consume_sstore()?;
 		<Balance<T>>::insert(collection_id, item.owner.as_sub(), balance_old_owner);
 
+		collection.consume_sload()?;
 		let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.as_sub())
 			.checked_add(value)
 			.ok_or(Error::<T>::NumOverflow)?;
+		collection.consume_sstore()?;
 		<Balance<T>>::insert(collection_id, new_owner.as_sub(), balance_new_owner);
 
 		let old_owner = item.owner.clone();
@@ -2152,10 +2170,11 @@
 				.find(|i| i.owner == owner)
 				.expect("old owner does present in refungible")
 				.owner = new_owner.clone();
+			collection.consume_sstore()?;
 			<ReFungibleItemList<T>>::insert(collection_id, item_id, new_full_item);
 
 			// update index collection
-			Self::move_token_index(collection_id, item_id, &old_owner, &new_owner)?;
+			Self::move_token_index(collection, item_id, &old_owner, &new_owner)?;
 		} else {
 			new_full_item
 				.owner
@@ -2179,9 +2198,10 @@
 					owner: new_owner.clone(),
 					fraction: value,
 				});
-				Self::add_token_index(collection_id, item_id, &new_owner)?;
+				Self::add_token_index(collection, item_id, &new_owner)?;
 			}
 
+			collection.consume_sstore()?;
 			<ReFungibleItemList<T>>::insert(collection_id, item_id, new_full_item);
 		}
 
@@ -2203,35 +2223,41 @@
 		new_owner: T::CrossAccountId,
 	) -> DispatchResult {
 		let collection_id = collection.id;
+		collection.consume_sload()?;
 		let mut item =
 			<NftItemList<T>>::get(collection_id, item_id).ok_or(Error::<T>::TokenNotFound)?;
 
 		ensure!(sender == item.owner, Error::<T>::MustBeTokenOwner);
 
+		collection.consume_sload()?;
 		// update balance
 		let balance_old_owner = <Balance<T>>::get(collection_id, item.owner.as_sub())
 			.checked_sub(1)
 			.ok_or(Error::<T>::NumOverflow)?;
+		collection.consume_sstore()?;
 		<Balance<T>>::insert(collection_id, item.owner.as_sub(), balance_old_owner);
 
+		collection.consume_sload()?;
 		let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.as_sub())
 			.checked_add(1)
 			.ok_or(Error::<T>::NumOverflow)?;
+		collection.consume_sstore()?;
 		<Balance<T>>::insert(collection_id, new_owner.as_sub(), balance_new_owner);
 
 		// change owner
 		let old_owner = item.owner.clone();
 		item.owner = new_owner.clone();
+		collection.consume_sstore()?;
 		<NftItemList<T>>::insert(collection_id, item_id, item);
 
 		// update index collection
-		Self::move_token_index(collection_id, item_id, &old_owner, &new_owner)?;
+		Self::move_token_index(collection, item_id, &old_owner, &new_owner)?;
 
 		collection.log(ERC721Events::Transfer {
 			from: *sender.as_eth(),
 			to: *new_owner.as_eth(),
 			token_id: item_id.into(),
-		});
+		})?;
 		Self::deposit_event(RawEvent::Transfer(
 			collection.id,
 			item_id,
@@ -2305,7 +2331,12 @@
 	fn init_nft_token(collection_id: CollectionId, item: &NftItemType<T::CrossAccountId>) {
 		let current_index = <ItemListIndex>::get(collection_id).checked_add(1).unwrap();
 
-		Self::add_token_index(collection_id, current_index, &item.owner).unwrap();
+		Self::add_token_index(
+			&CollectionHandle::get(collection_id).unwrap(),
+			current_index,
+			&item.owner,
+		)
+		.unwrap();
 
 		<ItemListIndex>::insert(collection_id, current_index);
 
@@ -2324,7 +2355,12 @@
 	) {
 		let current_index = <ItemListIndex>::get(collection_id).checked_add(1).unwrap();
 
-		Self::add_token_index(collection_id, current_index, owner).unwrap();
+		Self::add_token_index(
+			&CollectionHandle::get(collection_id).unwrap(),
+			current_index,
+			owner,
+		)
+		.unwrap();
 
 		<ItemListIndex>::insert(collection_id, current_index);
 
@@ -2345,7 +2381,12 @@
 		let value = item.owner.first().unwrap().fraction;
 		let owner = item.owner.first().unwrap().owner.clone();
 
-		Self::add_token_index(collection_id, current_index, &owner).unwrap();
+		Self::add_token_index(
+			&CollectionHandle::get(collection_id).unwrap(),
+			current_index,
+			&owner,
+		)
+		.unwrap();
 
 		<ItemListIndex>::insert(collection_id, current_index);
 
@@ -2357,51 +2398,61 @@
 	}
 
 	fn add_token_index(
-		collection_id: CollectionId,
+		collection: &CollectionHandle<T>,
 		item_index: TokenId,
 		owner: &T::CrossAccountId,
 	) -> DispatchResult {
 		// add to account limit
+		collection.consume_sload()?;
 		if <AccountItemCount<T>>::contains_key(owner.as_sub()) {
 			// bound Owned tokens by a single address
+			collection.consume_sload()?;
 			let count = <AccountItemCount<T>>::get(owner.as_sub());
 			ensure!(
-				count < ChainLimit::get().account_token_ownership_limit,
+				count < ACCOUNT_TOKEN_OWNERSHIP_LIMIT,
 				Error::<T>::AddressOwnershipLimitExceeded
 			);
 
+			collection.consume_sstore()?;
 			<AccountItemCount<T>>::insert(
 				owner.as_sub(),
 				count.checked_add(1).ok_or(Error::<T>::NumOverflow)?,
 			);
 		} else {
+			collection.consume_sstore()?;
 			<AccountItemCount<T>>::insert(owner.as_sub(), 1);
 		}
 
-		let list_exists = <AddressTokens<T>>::contains_key(collection_id, owner.as_sub());
+		collection.consume_sload()?;
+		let list_exists = <AddressTokens<T>>::contains_key(collection.id, owner.as_sub());
 		if list_exists {
-			let mut list = <AddressTokens<T>>::get(collection_id, owner.as_sub());
+			collection.consume_sload()?;
+			let mut list = <AddressTokens<T>>::get(collection.id, owner.as_sub());
 			let item_contains = list.contains(&item_index.clone());
 
 			if !item_contains {
 				list.push(item_index);
 			}
 
-			<AddressTokens<T>>::insert(collection_id, owner.as_sub(), list);
+			collection.consume_sstore()?;
+			<AddressTokens<T>>::insert(collection.id, owner.as_sub(), list);
 		} else {
 			let itm = vec![item_index];
-			<AddressTokens<T>>::insert(collection_id, owner.as_sub(), itm);
+			collection.consume_sstore()?;
+			<AddressTokens<T>>::insert(collection.id, owner.as_sub(), itm);
 		}
 
 		Ok(())
 	}
 
 	fn remove_token_index(
-		collection_id: CollectionId,
+		collection: &CollectionHandle<T>,
 		item_index: TokenId,
 		owner: &T::CrossAccountId,
 	) -> DispatchResult {
 		// update counter
+		collection.consume_sload()?;
+		collection.consume_sstore()?;
 		<AccountItemCount<T>>::insert(
 			owner.as_sub(),
 			<AccountItemCount<T>>::get(owner.as_sub())
@@ -2409,14 +2460,17 @@
 				.ok_or(Error::<T>::NumOverflow)?,
 		);
 
-		let list_exists = <AddressTokens<T>>::contains_key(collection_id, owner.as_sub());
+		collection.consume_sload()?;
+		let list_exists = <AddressTokens<T>>::contains_key(collection.id, owner.as_sub());
 		if list_exists {
-			let mut list = <AddressTokens<T>>::get(collection_id, owner.as_sub());
+			collection.consume_sload()?;
+			let mut list = <AddressTokens<T>>::get(collection.id, owner.as_sub());
 			let item_contains = list.contains(&item_index.clone());
 
 			if item_contains {
 				list.retain(|&item| item != item_index);
-				<AddressTokens<T>>::insert(collection_id, owner.as_sub(), list);
+				collection.consume_sstore()?;
+				<AddressTokens<T>>::insert(collection.id, owner.as_sub(), list);
 			}
 		}
 
@@ -2424,13 +2478,13 @@
 	}
 
 	fn move_token_index(
-		collection_id: CollectionId,
+		collection: &CollectionHandle<T>,
 		item_index: TokenId,
 		old_owner: &T::CrossAccountId,
 		new_owner: &T::CrossAccountId,
 	) -> DispatchResult {
-		Self::remove_token_index(collection_id, item_index, old_owner)?;
-		Self::add_token_index(collection_id, item_index, new_owner)?;
+		Self::remove_token_index(collection, item_index, old_owner)?;
+		Self::add_token_index(collection, item_index, new_owner)?;
 
 		Ok(())
 	}
modifiedpallets/nft/src/mock.rsdiffbeforeafterboth
--- a/pallets/nft/src/mock.rs
+++ b/pallets/nft/src/mock.rs
@@ -6,7 +6,6 @@
 use sp_runtime::{
 	traits::{BlakeTwo256, IdentityLookup},
 	testing::Header,
-	Perbill,
 };
 use pallet_transaction_payment::{CurrencyAdapter};
 use frame_system as system;
@@ -99,9 +98,12 @@
 	type WeightInfo = ();
 }
 
+<<<<<<< HEAD
 type Timestamp = pallet_timestamp::Pallet<Test>;
 type Randomness = pallet_randomness_collective_flip::Pallet<Test>;
 
+=======
+>>>>>>> origin/develop
 parameter_types! {
 	pub const CollectionCreationPrice: u32 = 0;
 	pub TreasuryAccountId: u64 = 1234;
@@ -133,8 +135,11 @@
 	fn as_sub(&self) -> &u64 {
 		&self.0
 	}
-	fn from_eth(_eth: sp_core::H160) -> Self {
-		unimplemented!()
+	fn from_eth(eth: sp_core::H160) -> Self {
+		let mut sub_raw = [0; 8];
+		sub_raw.copy_from_slice(&eth.0[0..8]);
+		let sub = u64::from_be_bytes(sub_raw);
+		Self(sub, eth)
 	}
 	fn as_eth(&self) -> &sp_core::H160 {
 		&self.1
@@ -151,6 +156,10 @@
 	}
 }
 
+impl pallet_evm_coder_substrate::Config for Test {
+	type EthereumTransactionSender = TestEtheremTransactionSender;
+}
+
 impl pallet_template::Config for Test {
 	type Event = ();
 	type WeightInfo = ();
@@ -160,8 +169,6 @@
 	type EvmAddressMapping = TestEvmAddressMapping;
 	type EvmBackwardsAddressMapping = TestEvmBackwardsAddressMapping;
 	type CrossAccountId = TestCrossAccountId;
-	type EthereumChainId = EthereumChainId;
-	type EthereumTransactionSender = TestEtheremTransactionSender;
 }
 
 // Build genesis storage according to the mock runtime.
modifiedpallets/nft/src/sponsorship.rsdiffbeforeafterboth
--- a/pallets/nft/src/sponsorship.rs
+++ b/pallets/nft/src/sponsorship.rs
@@ -1,15 +1,18 @@
 use crate::{
 	Config, Call, CollectionById, CreateItemBasket, VariableMetaDataBasket,
-	ReFungibleTransferBasket, FungibleTransferBasket, NftTransferBasket, ChainLimit,
-	CreateItemData, CollectionMode,
+	ReFungibleTransferBasket, FungibleTransferBasket, NftTransferBasket, CreateItemData,
+	CollectionMode,
 };
 use core::marker::PhantomData;
 use up_sponsorship::SponsorshipHandler;
 use frame_support::{
-	traits::IsSubType,
-	storage::{StorageMap, StorageDoubleMap, StorageValue},
+	traits::{IsSubType},
+	storage::{StorageMap, StorageDoubleMap},
+};
+use nft_data_structs::{
+	TokenId, CollectionId, NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+	FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
 };
-use nft_data_structs::{TokenId, CollectionId};
 
 pub struct NftSponsorshipHandler<T>(PhantomData<T>);
 impl<T: Config> NftSponsorshipHandler<T> {
@@ -47,7 +50,6 @@
 		item_id: &TokenId,
 	) -> Option<T::AccountId> {
 		let collection = CollectionById::<T>::get(collection_id)?;
-		let limits = ChainLimit::get();
 
 		let mut sponsor_transfer = false;
 		if collection.sponsorship.confirmed() {
@@ -62,7 +64,7 @@
 					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
 						collection_limits.sponsor_transfer_timeout
 					} else {
-						limits.nft_sponsor_transfer_timeout
+						NFT_SPONSOR_TRANSFER_TIMEOUT
 					};
 
 					let mut sponsored = true;
@@ -84,7 +86,7 @@
 					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
 						collection_limits.sponsor_transfer_timeout
 					} else {
-						limits.fungible_sponsor_transfer_timeout
+						FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT
 					};
 
 					let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
@@ -107,7 +109,7 @@
 					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
 						collection_limits.sponsor_transfer_timeout
 					} else {
-						limits.refungible_sponsor_transfer_timeout
+						REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT
 					};
 
 					let mut sponsored = true;
modifiedpallets/nft/src/tests.rsdiffbeforeafterboth
1// Tests to be written here1// Tests to be written here
2use super::*;2use super::*;
3use crate::mock::*;3use crate::mock::*;
4use crate::{AccessMode, CollectionMode, Ownership, ChainLimits, CreateItemData};4use crate::{AccessMode, CollectionMode, Ownership, CreateItemData};
5use nft_data_structs::{5use nft_data_structs::{
6 CreateNftData, CreateFungibleData, CreateReFungibleData, CollectionId, TokenId,6 CreateNftData, CreateFungibleData, CreateReFungibleData, CollectionId, TokenId,
7 MAX_DECIMAL_POINTS,7 MAX_DECIMAL_POINTS,
8};8};
9use frame_support::{assert_noop, assert_ok};9use frame_support::{assert_noop, assert_ok};
10use frame_system::{RawOrigin};10use sp_std::convert::TryInto;
1111
12fn default_collection_numbers_limit() -> u32 {
13 10
14}
15
16fn default_limits() {
17 assert_ok!(TemplateModule::set_chain_limits(
18 RawOrigin::Root.into(),
19 ChainLimits {
20 collection_numbers_limit: default_collection_numbers_limit(),
21 account_token_ownership_limit: 10,
22 collections_admins_limit: 5,
23 custom_data_limit: 2048,
24 nft_sponsor_transfer_timeout: 15,
25 fungible_sponsor_transfer_timeout: 15,
26 refungible_sponsor_transfer_timeout: 15,
27 const_on_chain_schema_limit: 1024,
28 offchain_schema_limit: 1024,
29 variable_on_chain_schema_limit: 1024,
30 }
31 ));
32}
33
34fn default_nft_data() -> CreateNftData {12fn default_nft_data() -> CreateNftData {
35 CreateNftData {13 CreateNftData {
36 const_data: vec![1, 2, 3],14 const_data: vec![1, 2, 3].try_into().unwrap(),
37 variable_data: vec![3, 2, 1],15 variable_data: vec![3, 2, 1].try_into().unwrap(),
38 }16 }
39}17}
4018
4422
45fn default_re_fungible_data() -> CreateReFungibleData {23fn default_re_fungible_data() -> CreateReFungibleData {
46 CreateReFungibleData {24 CreateReFungibleData {
47 const_data: vec![1, 2, 3],25 const_data: vec![1, 2, 3].try_into().unwrap(),
48 variable_data: vec![3, 2, 1],26 variable_data: vec![3, 2, 1].try_into().unwrap(),
49 pieces: 1023,27 pieces: 1023,
50 }28 }
51}29}
112#[test]90#[test]
113fn set_version_schema() {91fn set_version_schema() {
114 new_test_ext().execute_with(|| {92 new_test_ext().execute_with(|| {
115 default_limits();
116 let origin1 = Origin::signed(1);93 let origin1 = Origin::signed(1);
117 let collection_id = create_test_collection(&CollectionMode::NFT, 1);94 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
11895
133#[test]110#[test]
134fn create_fungible_collection_fails_with_large_decimal_numbers() {111fn create_fungible_collection_fails_with_large_decimal_numbers() {
135 new_test_ext().execute_with(|| {112 new_test_ext().execute_with(|| {
136 default_limits();
137
138 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();113 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
139 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();114 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
140 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();115 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
156#[test]131#[test]
157fn create_nft_item() {132fn create_nft_item() {
158 new_test_ext().execute_with(|| {133 new_test_ext().execute_with(|| {
159 default_limits();
160 let collection_id = create_test_collection(&CollectionMode::NFT, 1);134 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
161135
162 let data = default_nft_data();136 let data = default_nft_data();
163 create_test_item(collection_id, &data.clone().into());137 create_test_item(collection_id, &data.clone().into());
164 let item = TemplateModule::nft_item_id(collection_id, 1).unwrap();138 let item = TemplateModule::nft_item_id(collection_id, 1).unwrap();
165 assert_eq!(item.const_data, data.const_data);139 assert_eq!(item.const_data, data.const_data.into_inner());
166 assert_eq!(item.variable_data, data.variable_data);140 assert_eq!(item.variable_data, data.variable_data.into_inner());
167 });141 });
168}142}
169143
172#[test]146#[test]
173fn create_nft_multiple_items() {147fn create_nft_multiple_items() {
174 new_test_ext().execute_with(|| {148 new_test_ext().execute_with(|| {
175 default_limits();
176
177 create_test_collection(&CollectionMode::NFT, 1);149 create_test_collection(&CollectionMode::NFT, 1);
178150
179 let origin1 = Origin::signed(1);151 let origin1 = Origin::signed(1);
190 .map(|d| { d.into() })162 .map(|d| { d.into() })
191 .collect()163 .collect()
192 ));164 ));
193 for (index, data) in items_data.iter().enumerate() {165 for (index, data) in items_data.into_iter().enumerate() {
194 let item = TemplateModule::nft_item_id(1, (index + 1) as TokenId).unwrap();166 let item = TemplateModule::nft_item_id(1, (index + 1) as TokenId).unwrap();
195 assert_eq!(item.const_data.to_vec(), data.const_data);167 assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());
196 assert_eq!(item.variable_data.to_vec(), data.variable_data);168 assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());
197 }169 }
198 });170 });
199}171}
200172
201#[test]173#[test]
202fn create_refungible_item() {174fn create_refungible_item() {
203 new_test_ext().execute_with(|| {175 new_test_ext().execute_with(|| {
204 default_limits();
205 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);176 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
206177
207 let data = default_re_fungible_data();178 let data = default_re_fungible_data();
208 create_test_item(collection_id, &data.clone().into());179 create_test_item(collection_id, &data.clone().into());
209 let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap();180 let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap();
210 assert_eq!(item.const_data, data.const_data);181 assert_eq!(item.const_data, data.const_data.into_inner());
211 assert_eq!(item.variable_data, data.variable_data);182 assert_eq!(item.variable_data, data.variable_data.into_inner());
212 assert_eq!(183 assert_eq!(
213 item.owner[0],184 item.owner[0],
214 Ownership {185 Ownership {
222#[test]193#[test]
223fn create_multiple_refungible_items() {194fn create_multiple_refungible_items() {
224 new_test_ext().execute_with(|| {195 new_test_ext().execute_with(|| {
225 default_limits();
226
227 create_test_collection(&CollectionMode::ReFungible, 1);196 create_test_collection(&CollectionMode::ReFungible, 1);
228197
229 let origin1 = Origin::signed(1);198 let origin1 = Origin::signed(1);
244 .map(|d| { d.into() })213 .map(|d| { d.into() })
245 .collect()214 .collect()
246 ));215 ));
247 for (index, data) in items_data.iter().enumerate() {216 for (index, data) in items_data.into_iter().enumerate() {
248 let item = TemplateModule::refungible_item_id(1, (index + 1) as TokenId).unwrap();217 let item = TemplateModule::refungible_item_id(1, (index + 1) as TokenId).unwrap();
249 assert_eq!(item.const_data.to_vec(), data.const_data);218 assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());
250 assert_eq!(item.variable_data.to_vec(), data.variable_data);219 assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());
251 assert_eq!(220 assert_eq!(
252 item.owner[0],221 item.owner[0],
253 Ownership {222 Ownership {
262#[test]231#[test]
263fn create_fungible_item() {232fn create_fungible_item() {
264 new_test_ext().execute_with(|| {233 new_test_ext().execute_with(|| {
265 default_limits();
266
267 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);234 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
268235
269 let data = default_fungible_data();236 let data = default_fungible_data();
302#[test]269#[test]
303fn transfer_fungible_item() {270fn transfer_fungible_item() {
304 new_test_ext().execute_with(|| {271 new_test_ext().execute_with(|| {
305 default_limits();
306
307 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);272 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
308273
309 let origin1 = Origin::signed(1);274 let origin1 = Origin::signed(1);
344#[test]309#[test]
345fn transfer_refungible_item() {310fn transfer_refungible_item() {
346 new_test_ext().execute_with(|| {311 new_test_ext().execute_with(|| {
347 default_limits();
348
349 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);312 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
350313
351 let data = default_re_fungible_data();314 let data = default_re_fungible_data();
355 let origin2 = Origin::signed(2);318 let origin2 = Origin::signed(2);
356 {319 {
357 let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap();320 let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap();
358 assert_eq!(item.const_data, data.const_data);321 assert_eq!(item.const_data, data.const_data.into_inner());
359 assert_eq!(item.variable_data, data.variable_data);322 assert_eq!(item.variable_data, data.variable_data.into_inner());
360 assert_eq!(323 assert_eq!(
361 item.owner[0],324 item.owner[0],
362 Ownership {325 Ownership {
441#[test]404#[test]
442fn transfer_nft_item() {405fn transfer_nft_item() {
443 new_test_ext().execute_with(|| {406 new_test_ext().execute_with(|| {
444 default_limits();
445
446 let collection_id = create_test_collection(&CollectionMode::NFT, 1);407 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
447408
448 let data = default_nft_data();409 let data = default_nft_data();
464#[test]425#[test]
465fn nft_approve_and_transfer_from() {426fn nft_approve_and_transfer_from() {
466 new_test_ext().execute_with(|| {427 new_test_ext().execute_with(|| {
467 default_limits();
468
469 let collection_id = create_test_collection(&CollectionMode::NFT, 1);428 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
470429
471 let data = default_nft_data();430 let data = default_nft_data();
503#[test]462#[test]
504fn nft_approve_and_transfer_from_white_list() {463fn nft_approve_and_transfer_from_white_list() {
505 new_test_ext().execute_with(|| {464 new_test_ext().execute_with(|| {
506 default_limits();
507
508 let collection_id = create_test_collection(&CollectionMode::NFT, 1);465 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
509466
510 let origin1 = Origin::signed(1);467 let origin1 = Origin::signed(1);
514 create_test_item(collection_id, &data.clone().into());471 create_test_item(collection_id, &data.clone().into());
515472
516 assert_eq!(473 assert_eq!(
517 TemplateModule::nft_item_id(1, 1).unwrap().const_data,474 &TemplateModule::nft_item_id(1, 1).unwrap().const_data,
518 data.const_data475 &data.const_data.into_inner()
519 );476 );
520 assert_eq!(TemplateModule::balance_count(1, 1), 1);477 assert_eq!(TemplateModule::balance_count(1, 1), 1);
521 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);478 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
573#[test]530#[test]
574fn refungible_approve_and_transfer_from() {531fn refungible_approve_and_transfer_from() {
575 new_test_ext().execute_with(|| {532 new_test_ext().execute_with(|| {
576 default_limits();
577
578 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);533 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
579534
580 let origin1 = Origin::signed(1);535 let origin1 = Origin::signed(1);
636#[test]591#[test]
637fn fungible_approve_and_transfer_from() {592fn fungible_approve_and_transfer_from() {
638 new_test_ext().execute_with(|| {593 new_test_ext().execute_with(|| {
639 default_limits();
640
641 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);594 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
642595
643 let data = default_fungible_data();596 let data = default_fungible_data();
710#[test]663#[test]
711fn change_collection_owner() {664fn change_collection_owner() {
712 new_test_ext().execute_with(|| {665 new_test_ext().execute_with(|| {
713 default_limits();
714
715 let collection_id = create_test_collection(&CollectionMode::NFT, 1);666 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
716667
717 let origin1 = Origin::signed(1);668 let origin1 = Origin::signed(1);
730#[test]681#[test]
731fn destroy_collection() {682fn destroy_collection() {
732 new_test_ext().execute_with(|| {683 new_test_ext().execute_with(|| {
733 default_limits();
734
735 let collection_id = create_test_collection(&CollectionMode::NFT, 1);684 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
736685
737 let origin1 = Origin::signed(1);686 let origin1 = Origin::signed(1);
742#[test]691#[test]
743fn burn_nft_item() {692fn burn_nft_item() {
744 new_test_ext().execute_with(|| {693 new_test_ext().execute_with(|| {
745 default_limits();
746
747 let collection_id = create_test_collection(&CollectionMode::NFT, 1);694 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
748695
749 let origin1 = Origin::signed(1);696 let origin1 = Origin::signed(1);
773#[test]720#[test]
774fn burn_fungible_item() {721fn burn_fungible_item() {
775 new_test_ext().execute_with(|| {722 new_test_ext().execute_with(|| {
776 default_limits();
777
778 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);723 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
779724
780 let origin1 = Origin::signed(1);725 let origin1 = Origin::signed(1);
804#[test]749#[test]
805fn burn_refungible_item() {750fn burn_refungible_item() {
806 new_test_ext().execute_with(|| {751 new_test_ext().execute_with(|| {
807 default_limits();
808
809 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);752 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
810 let origin1 = Origin::signed(1);753 let origin1 = Origin::signed(1);
811754
851#[test]794#[test]
852fn add_collection_admin() {795fn add_collection_admin() {
853 new_test_ext().execute_with(|| {796 new_test_ext().execute_with(|| {
854 default_limits();
855
856 let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);797 let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);
857 create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);798 create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);
858 create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);799 create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);
879#[test]820#[test]
880fn remove_collection_admin() {821fn remove_collection_admin() {
881 new_test_ext().execute_with(|| {822 new_test_ext().execute_with(|| {
882 default_limits();
883
884 let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);823 let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);
885 create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);824 create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);
886 create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);825 create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);
916#[test]855#[test]
917fn balance_of() {856fn balance_of() {
918 new_test_ext().execute_with(|| {857 new_test_ext().execute_with(|| {
919 default_limits();
920
921 let nft_collection_id = create_test_collection(&CollectionMode::NFT, 1);858 let nft_collection_id = create_test_collection(&CollectionMode::NFT, 1);
922 let fungible_collection_id = create_test_collection(&CollectionMode::Fungible(3), 2);859 let fungible_collection_id = create_test_collection(&CollectionMode::Fungible(3), 2);
923 let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible, 3);860 let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible, 3);
969#[test]906#[test]
970fn approve() {907fn approve() {
971 new_test_ext().execute_with(|| {908 new_test_ext().execute_with(|| {
972 default_limits();
973
974 let collection_id = create_test_collection(&CollectionMode::NFT, 1);909 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
975910
976 let data = default_nft_data();911 let data = default_nft_data();
987#[test]922#[test]
988fn transfer_from() {923fn transfer_from() {
989 new_test_ext().execute_with(|| {924 new_test_ext().execute_with(|| {
990 default_limits();
991
992 let collection_id = create_test_collection(&CollectionMode::NFT, 1);925 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
993 let origin1 = Origin::signed(1);926 let origin1 = Origin::signed(1);
994 let origin2 = Origin::signed(2);927 let origin2 = Origin::signed(2);
1051#[test]984#[test]
1052fn owner_can_add_address_to_white_list() {985fn owner_can_add_address_to_white_list() {
1053 new_test_ext().execute_with(|| {986 new_test_ext().execute_with(|| {
1054 default_limits();
1055
1056 let collection_id = create_test_collection(&CollectionMode::NFT, 1);987 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
1057988
1058 let origin1 = Origin::signed(1);989 let origin1 = Origin::signed(1);
1068#[test]999#[test]
1069fn admin_can_add_address_to_white_list() {1000fn admin_can_add_address_to_white_list() {
1070 new_test_ext().execute_with(|| {1001 new_test_ext().execute_with(|| {
1071 default_limits();
1072
1073 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1002 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
1074 let origin1 = Origin::signed(1);1003 let origin1 = Origin::signed(1);
1075 let origin2 = Origin::signed(2);1004 let origin2 = Origin::signed(2);
1091#[test]1020#[test]
1092fn nonprivileged_user_cannot_add_address_to_white_list() {1021fn nonprivileged_user_cannot_add_address_to_white_list() {
1093 new_test_ext().execute_with(|| {1022 new_test_ext().execute_with(|| {
1094 default_limits();
1095
1096 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1023 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
10971024
1098 let origin2 = Origin::signed(2);1025 let origin2 = Origin::signed(2);
1106#[test]1033#[test]
1107fn nobody_can_add_address_to_white_list_of_nonexisting_collection() {1034fn nobody_can_add_address_to_white_list_of_nonexisting_collection() {
1108 new_test_ext().execute_with(|| {1035 new_test_ext().execute_with(|| {
1109 default_limits();
1110
1111 let origin1 = Origin::signed(1);1036 let origin1 = Origin::signed(1);
11121037
1113 assert_noop!(1038 assert_noop!(
1120#[test]1045#[test]
1121fn nobody_can_add_address_to_white_list_of_deleted_collection() {1046fn nobody_can_add_address_to_white_list_of_deleted_collection() {
1122 new_test_ext().execute_with(|| {1047 new_test_ext().execute_with(|| {
1123 default_limits();
1124
1125 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1048 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
11261049
1127 let origin1 = Origin::signed(1);1050 let origin1 = Origin::signed(1);
1140#[test]1063#[test]
1141fn address_is_already_added_to_white_list() {1064fn address_is_already_added_to_white_list() {
1142 new_test_ext().execute_with(|| {1065 new_test_ext().execute_with(|| {
1143 default_limits();
1144
1145 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1066 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
1146 let origin1 = Origin::signed(1);1067 let origin1 = Origin::signed(1);
11471068
1162#[test]1083#[test]
1163fn owner_can_remove_address_from_white_list() {1084fn owner_can_remove_address_from_white_list() {
1164 new_test_ext().execute_with(|| {1085 new_test_ext().execute_with(|| {
1165 default_limits();
1166
1167 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1086 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
11681087
1169 let origin1 = Origin::signed(1);1088 let origin1 = Origin::signed(1);
1184#[test]1103#[test]
1185fn admin_can_remove_address_from_white_list() {1104fn admin_can_remove_address_from_white_list() {
1186 new_test_ext().execute_with(|| {1105 new_test_ext().execute_with(|| {
1187 default_limits();
1188
1189 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1106 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
1190 let origin1 = Origin::signed(1);1107 let origin1 = Origin::signed(1);
1191 let origin2 = Origin::signed(2);1108 let origin2 = Origin::signed(2);
1213#[test]1130#[test]
1214fn nonprivileged_user_cannot_remove_address_from_white_list() {1131fn nonprivileged_user_cannot_remove_address_from_white_list() {
1215 new_test_ext().execute_with(|| {1132 new_test_ext().execute_with(|| {
1216 default_limits();
1217
1218 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1133 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
1219 let origin1 = Origin::signed(1);1134 let origin1 = Origin::signed(1);
1220 let origin2 = Origin::signed(2);1135 let origin2 = Origin::signed(2);
1235#[test]1150#[test]
1236fn nobody_can_remove_address_from_white_list_of_nonexisting_collection() {1151fn nobody_can_remove_address_from_white_list_of_nonexisting_collection() {
1237 new_test_ext().execute_with(|| {1152 new_test_ext().execute_with(|| {
1238 default_limits();
1239 let origin1 = Origin::signed(1);1153 let origin1 = Origin::signed(1);
12401154
1241 assert_noop!(1155 assert_noop!(
1248#[test]1162#[test]
1249fn nobody_can_remove_address_from_white_list_of_deleted_collection() {1163fn nobody_can_remove_address_from_white_list_of_deleted_collection() {
1250 new_test_ext().execute_with(|| {1164 new_test_ext().execute_with(|| {
1251 default_limits();
1252
1253 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1165 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
1254 let origin1 = Origin::signed(1);1166 let origin1 = Origin::signed(1);
1255 let origin2 = Origin::signed(2);1167 let origin2 = Origin::signed(2);
1272#[test]1184#[test]
1273fn address_is_already_removed_from_white_list() {1185fn address_is_already_removed_from_white_list() {
1274 new_test_ext().execute_with(|| {1186 new_test_ext().execute_with(|| {
1275 default_limits();
1276
1277 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1187 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
1278 let origin1 = Origin::signed(1);1188 let origin1 = Origin::signed(1);
12791189
1300#[test]1210#[test]
1301fn white_list_test_1() {1211fn white_list_test_1() {
1302 new_test_ext().execute_with(|| {1212 new_test_ext().execute_with(|| {
1303 default_limits();
1304
1305 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1213 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
13061214
1307 let origin1 = Origin::signed(1);1215 let origin1 = Origin::signed(1);
1330#[test]1238#[test]
1331fn white_list_test_2() {1239fn white_list_test_2() {
1332 new_test_ext().execute_with(|| {1240 new_test_ext().execute_with(|| {
1333 default_limits();
1334
1335 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1241 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
1336 let origin1 = Origin::signed(1);1242 let origin1 = Origin::signed(1);
13371243
1381#[test]1287#[test]
1382fn white_list_test_3() {1288fn white_list_test_3() {
1383 new_test_ext().execute_with(|| {1289 new_test_ext().execute_with(|| {
1384 default_limits();
1385
1386 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1290 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
13871291
1388 let origin1 = Origin::signed(1);1292 let origin1 = Origin::signed(1);
1411#[test]1315#[test]
1412fn white_list_test_4() {1316fn white_list_test_4() {
1413 new_test_ext().execute_with(|| {1317 new_test_ext().execute_with(|| {
1414 default_limits();
1415
1416 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1318 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
14171319
1418 let origin1 = Origin::signed(1);1320 let origin1 = Origin::signed(1);
1463#[test]1365#[test]
1464fn white_list_test_5() {1366fn white_list_test_5() {
1465 new_test_ext().execute_with(|| {1367 new_test_ext().execute_with(|| {
1466 default_limits();
1467
1468 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1368 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
14691369
1470 let origin1 = Origin::signed(1);1370 let origin1 = Origin::signed(1);
1488#[test]1388#[test]
1489fn white_list_test_6() {1389fn white_list_test_6() {
1490 new_test_ext().execute_with(|| {1390 new_test_ext().execute_with(|| {
1491 default_limits();
1492
1493 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1391 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
14941392
1495 let origin1 = Origin::signed(1);1393 let origin1 = Origin::signed(1);
1516#[test]1414#[test]
1517fn white_list_test_7() {1415fn white_list_test_7() {
1518 new_test_ext().execute_with(|| {1416 new_test_ext().execute_with(|| {
1519 default_limits();
1520
1521 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1417 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
15221418
1523 let data = default_nft_data();1419 let data = default_nft_data();
1548#[test]1444#[test]
1549fn white_list_test_8() {1445fn white_list_test_8() {
1550 new_test_ext().execute_with(|| {1446 new_test_ext().execute_with(|| {
1551 default_limits();
1552
1553 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1447 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
15541448
1555 let data = default_nft_data();1449 let data = default_nft_data();
1598#[test]1492#[test]
1599fn white_list_test_9() {1493fn white_list_test_9() {
1600 new_test_ext().execute_with(|| {1494 new_test_ext().execute_with(|| {
1601 default_limits();
1602
1603 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1495 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
1604 let origin1 = Origin::signed(1);1496 let origin1 = Origin::signed(1);
16051497
1623#[test]1515#[test]
1624fn white_list_test_10() {1516fn white_list_test_10() {
1625 new_test_ext().execute_with(|| {1517 new_test_ext().execute_with(|| {
1626 default_limits();
1627
1628 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1518 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
16291519
1630 let origin1 = Origin::signed(1);1520 let origin1 = Origin::signed(1);
1660#[test]1550#[test]
1661fn white_list_test_11() {1551fn white_list_test_11() {
1662 new_test_ext().execute_with(|| {1552 new_test_ext().execute_with(|| {
1663 default_limits();
1664
1665 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1553 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
16661554
1667 let origin1 = Origin::signed(1);1555 let origin1 = Origin::signed(1);
1694#[test]1582#[test]
1695fn white_list_test_12() {1583fn white_list_test_12() {
1696 new_test_ext().execute_with(|| {1584 new_test_ext().execute_with(|| {
1697 default_limits();
1698
1699 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1585 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
17001586
1701 let origin1 = Origin::signed(1);1587 let origin1 = Origin::signed(1);
1723#[test]1609#[test]
1724fn white_list_test_13() {1610fn white_list_test_13() {
1725 new_test_ext().execute_with(|| {1611 new_test_ext().execute_with(|| {
1726 default_limits();
1727
1728 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1612 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
17291613
1730 let origin1 = Origin::signed(1);1614 let origin1 = Origin::signed(1);
1749#[test]1633#[test]
1750fn white_list_test_14() {1634fn white_list_test_14() {
1751 new_test_ext().execute_with(|| {1635 new_test_ext().execute_with(|| {
1752 default_limits();
1753
1754 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1636 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
17551637
1756 let origin1 = Origin::signed(1);1638 let origin1 = Origin::signed(1);
1786#[test]1668#[test]
1787fn white_list_test_15() {1669fn white_list_test_15() {
1788 new_test_ext().execute_with(|| {1670 new_test_ext().execute_with(|| {
1789 default_limits();
1790
1791 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1671 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
17921672
1793 let origin1 = Origin::signed(1);1673 let origin1 = Origin::signed(1);
1815#[test]1695#[test]
1816fn white_list_test_16() {1696fn white_list_test_16() {
1817 new_test_ext().execute_with(|| {1697 new_test_ext().execute_with(|| {
1818 default_limits();
1819
1820 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1698 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
18211699
1822 let origin1 = Origin::signed(1);1700 let origin1 = Origin::signed(1);
1851#[test]1729#[test]
1852fn total_number_collections_bound() {1730fn total_number_collections_bound() {
1853 new_test_ext().execute_with(|| {1731 new_test_ext().execute_with(|| {
1854 default_limits();
1855
1856 create_test_collection(&CollectionMode::NFT, 1);1732 create_test_collection(&CollectionMode::NFT, 1);
1857 });1733 });
1858}1734}
1861#[test]1737#[test]
1862fn total_number_collections_bound_neg() {1738fn total_number_collections_bound_neg() {
1863 new_test_ext().execute_with(|| {1739 new_test_ext().execute_with(|| {
1864 default_limits();
1865
1866 let origin1 = Origin::signed(1);1740 let origin1 = Origin::signed(1);
18671741
1868 for i in 0..default_collection_numbers_limit() {1742 for i in 0..COLLECTION_NUMBER_LIMIT {
1869 create_test_collection(&CollectionMode::NFT, i + 1);1743 create_test_collection(&CollectionMode::NFT, i + 1);
1870 }1744 }
18711745
1891#[test]1765#[test]
1892fn owned_tokens_bound() {1766fn owned_tokens_bound() {
1893 new_test_ext().execute_with(|| {1767 new_test_ext().execute_with(|| {
1894 default_limits();
1895
1896 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1768 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
18971769
1898 let data = default_nft_data();1770 let data = default_nft_data();
1905#[test]1777#[test]
1906fn owned_tokens_bound_neg() {1778fn owned_tokens_bound_neg() {
1907 new_test_ext().execute_with(|| {1779 new_test_ext().execute_with(|| {
1908 assert_ok!(TemplateModule::set_chain_limits(
1909 RawOrigin::Root.into(),
1910 ChainLimits {
1911 collection_numbers_limit: 10,
1912 account_token_ownership_limit: 1,
1913 collections_admins_limit: 5,
1914 custom_data_limit: 2048,
1915 nft_sponsor_transfer_timeout: 15,
1916 fungible_sponsor_transfer_timeout: 15,
1917 refungible_sponsor_transfer_timeout: 15,
1918 const_on_chain_schema_limit: 1024,
1919 offchain_schema_limit: 1024,
1920 variable_on_chain_schema_limit: 1024,
1921 }
1922 ));
1923
1924 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1780 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
19251781
1926 let origin1 = Origin::signed(1);1782 let origin1 = Origin::signed(1);
1927 let data = default_nft_data();
1928 create_test_item(collection_id, &data.clone().into());
19291783
1784 for _ in 0..ACCOUNT_TOKEN_OWNERSHIP_LIMIT {
1785 let data = default_nft_data();
1786 create_test_item(collection_id, &data.clone().into());
1787 }
1788
1789 let data = default_nft_data();
1930 assert_noop!(1790 assert_noop!(
1931 TemplateModule::create_item(origin1, 1, account(1), data.into()),1791 TemplateModule::create_item(origin1, 1, account(1), data.into()),
1932 Error::<Test>::AddressOwnershipLimitExceeded1792 Error::<Test>::AddressOwnershipLimitExceeded
1938#[test]1798#[test]
1939fn collection_admins_bound() {1799fn collection_admins_bound() {
1940 new_test_ext().execute_with(|| {1800 new_test_ext().execute_with(|| {
1941 assert_ok!(TemplateModule::set_chain_limits(
1942 RawOrigin::Root.into(),
1943 ChainLimits {
1944 collection_numbers_limit: 10,
1945 account_token_ownership_limit: 10,
1946 collections_admins_limit: 2,
1947 custom_data_limit: 2048,
1948 nft_sponsor_transfer_timeout: 15,
1949 fungible_sponsor_transfer_timeout: 15,
1950 refungible_sponsor_transfer_timeout: 15,
1951 const_on_chain_schema_limit: 1024,
1952 offchain_schema_limit: 1024,
1953 variable_on_chain_schema_limit: 1024,
1954 }
1955 ));
1956
1957 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1801 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
19581802
1959 let origin1 = Origin::signed(1);1803 let origin1 = Origin::signed(1);
1975#[test]1819#[test]
1976fn collection_admins_bound_neg() {1820fn collection_admins_bound_neg() {
1977 new_test_ext().execute_with(|| {1821 new_test_ext().execute_with(|| {
1978 assert_ok!(TemplateModule::set_chain_limits(
1979 RawOrigin::Root.into(),
1980 ChainLimits {
1981 collection_numbers_limit: 10,
1982 account_token_ownership_limit: 1,
1983 collections_admins_limit: 1,
1984 custom_data_limit: 2048,
1985 nft_sponsor_transfer_timeout: 15,
1986 fungible_sponsor_transfer_timeout: 15,
1987 refungible_sponsor_transfer_timeout: 15,
1988 const_on_chain_schema_limit: 1024,
1989 offchain_schema_limit: 1024,
1990 variable_on_chain_schema_limit: 1024,
1991 }
1992 ));
1993
1994 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1822 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
19951823
1996 let origin1 = Origin::signed(1);1824 let origin1 = Origin::signed(1);
19971825
1998 assert_ok!(TemplateModule::add_collection_admin(1826 for i in 0..COLLECTION_ADMINS_LIMIT {
1827 assert_ok!(TemplateModule::add_collection_admin(
1999 origin1.clone(),1828 origin1.clone(),
2000 collection_id,1829 collection_id,
2001 account(2)1830 account(2 + i)
2002 ));1831 ));
1832 }
2003 assert_noop!(1833 assert_noop!(
2004 TemplateModule::add_collection_admin(origin1, collection_id, account(3)),1834 TemplateModule::add_collection_admin(
1835 origin1,
1836 collection_id,
1837 account(3 + COLLECTION_ADMINS_LIMIT)
1838 ),
2005 Error::<Test>::CollectionAdminsLimitExceeded1839 Error::<Test>::CollectionAdminsLimitExceeded
2006 );1840 );
2007 });1841 });
2008}1842}
2009
2010// NFT custom data size. Negative test const_data.
2011#[test]
2012fn custom_data_size_nft_const_data_bound_neg() {
2013 new_test_ext().execute_with(|| {
2014 assert_ok!(TemplateModule::set_chain_limits(
2015 RawOrigin::Root.into(),
2016 ChainLimits {
2017 collection_numbers_limit: 10,
2018 account_token_ownership_limit: 10,
2019 collections_admins_limit: 5,
2020 custom_data_limit: 2,
2021 nft_sponsor_transfer_timeout: 15,
2022 fungible_sponsor_transfer_timeout: 15,
2023 refungible_sponsor_transfer_timeout: 15,
2024 const_on_chain_schema_limit: 1024,
2025 offchain_schema_limit: 1024,
2026 variable_on_chain_schema_limit: 1024,
2027 }
2028 ));
2029
2030 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
2031
2032 let origin1 = Origin::signed(1);
2033 let too_big_const_data = CreateItemData::NFT(CreateNftData {
2034 const_data: vec![1, 2, 3, 4],
2035 variable_data: vec![],
2036 });
2037
2038 assert_noop!(
2039 TemplateModule::create_item(origin1, collection_id, account(1), too_big_const_data),
2040 Error::<Test>::TokenConstDataLimitExceeded
2041 );
2042 });
2043}
2044
2045// NFT custom data size. Negative test variable_data.
2046#[test]
2047fn custom_data_size_nft_variable_data_bound_neg() {
2048 new_test_ext().execute_with(|| {
2049 assert_ok!(TemplateModule::set_chain_limits(
2050 RawOrigin::Root.into(),
2051 ChainLimits {
2052 collection_numbers_limit: 10,
2053 account_token_ownership_limit: 10,
2054 collections_admins_limit: 5,
2055 custom_data_limit: 2,
2056 nft_sponsor_transfer_timeout: 15,
2057 fungible_sponsor_transfer_timeout: 15,
2058 refungible_sponsor_transfer_timeout: 15,
2059 const_on_chain_schema_limit: 1024,
2060 offchain_schema_limit: 1024,
2061 variable_on_chain_schema_limit: 1024,
2062 }
2063 ));
2064
2065 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
2066
2067 let origin1 = Origin::signed(1);
2068 let too_big_const_data = CreateItemData::NFT(CreateNftData {
2069 const_data: vec![],
2070 variable_data: vec![1, 2, 3, 4],
2071 });
2072
2073 assert_noop!(
2074 TemplateModule::create_item(origin1, collection_id, account(1), too_big_const_data),
2075 Error::<Test>::TokenVariableDataLimitExceeded
2076 );
2077 });
2078}
2079
2080// Re fungible custom data size. Negative test const_data.
2081#[test]
2082fn custom_data_size_re_fungible_const_data_bound_neg() {
2083 new_test_ext().execute_with(|| {
2084 assert_ok!(TemplateModule::set_chain_limits(
2085 RawOrigin::Root.into(),
2086 ChainLimits {
2087 collection_numbers_limit: 10,
2088 account_token_ownership_limit: 10,
2089 collections_admins_limit: 5,
2090 custom_data_limit: 2,
2091 nft_sponsor_transfer_timeout: 15,
2092 fungible_sponsor_transfer_timeout: 15,
2093 refungible_sponsor_transfer_timeout: 15,
2094 const_on_chain_schema_limit: 1024,
2095 offchain_schema_limit: 1024,
2096 variable_on_chain_schema_limit: 1024,
2097 }
2098 ));
2099
2100 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
2101
2102 let origin1 = Origin::signed(1);
2103 let too_big_const_data = CreateItemData::NFT(CreateNftData {
2104 const_data: vec![1, 2, 3, 4],
2105 variable_data: vec![],
2106 });
2107
2108 assert_noop!(
2109 TemplateModule::create_item(origin1, collection_id, account(1), too_big_const_data),
2110 Error::<Test>::TokenConstDataLimitExceeded
2111 );
2112 });
2113}
2114
2115// Re fungible custom data size. Negative test variable_data.
2116#[test]
2117fn custom_data_size_re_fungible_variable_data_bound_neg() {
2118 new_test_ext().execute_with(|| {
2119 assert_ok!(TemplateModule::set_chain_limits(
2120 RawOrigin::Root.into(),
2121 ChainLimits {
2122 collection_numbers_limit: 10,
2123 account_token_ownership_limit: 10,
2124 collections_admins_limit: 5,
2125 custom_data_limit: 2,
2126 nft_sponsor_transfer_timeout: 15,
2127 fungible_sponsor_transfer_timeout: 15,
2128 refungible_sponsor_transfer_timeout: 15,
2129 const_on_chain_schema_limit: 1024,
2130 offchain_schema_limit: 1024,
2131 variable_on_chain_schema_limit: 1024,
2132 }
2133 ));
2134
2135 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
2136
2137 let origin1 = Origin::signed(1);
2138 let too_big_const_data = CreateItemData::NFT(CreateNftData {
2139 const_data: vec![],
2140 variable_data: vec![1, 2, 3, 4],
2141 });
2142
2143 assert_noop!(
2144 TemplateModule::create_item(origin1, collection_id, account(1), too_big_const_data),
2145 Error::<Test>::TokenVariableDataLimitExceeded
2146 );
2147 });
2148}
2149// #endregion1843// #endregion
21501844
2151#[test]1845#[test]
2152fn set_const_on_chain_schema() {1846fn set_const_on_chain_schema() {
2153 new_test_ext().execute_with(|| {1847 new_test_ext().execute_with(|| {
2154 default_limits();
2155
2156 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1848 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
21571849
2158 let origin1 = Origin::signed(1);1850 let origin1 = Origin::signed(1);
2180#[test]1872#[test]
2181fn set_variable_on_chain_schema() {1873fn set_variable_on_chain_schema() {
2182 new_test_ext().execute_with(|| {1874 new_test_ext().execute_with(|| {
2183 default_limits();
2184
2185 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1875 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
21861876
2187 let origin1 = Origin::signed(1);1877 let origin1 = Origin::signed(1);
2209#[test]1899#[test]
2210fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {1900fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {
2211 new_test_ext().execute_with(|| {1901 new_test_ext().execute_with(|| {
2212 default_limits();
2213
2214 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1902 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
22151903
2216 let origin1 = Origin::signed(1);1904 let origin1 = Origin::signed(1);
22171905
2218 let data = default_nft_data();1906 let data = default_nft_data();
2219 create_test_item(1, &data.into());1907 create_test_item(1, &data.into());
22201908
2221 let variable_data = b"test set_variable_meta_data method.".to_vec();1909 let variable_data = b"test data".to_vec();
2222 assert_ok!(TemplateModule::set_variable_meta_data(1910 assert_ok!(TemplateModule::set_variable_meta_data(
2223 origin1,1911 origin1,
2224 collection_id,1912 collection_id,
2238#[test]1926#[test]
2239fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {1927fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {
2240 new_test_ext().execute_with(|| {1928 new_test_ext().execute_with(|| {
2241 default_limits();
2242
2243 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);1929 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
22441930
2245 let origin1 = Origin::signed(1);1931 let origin1 = Origin::signed(1);
22461932
2247 let data = default_re_fungible_data();1933 let data = default_re_fungible_data();
2248 create_test_item(1, &data.into());1934 create_test_item(1, &data.into());
22491935
2250 let variable_data = b"test set_variable_meta_data method.".to_vec();1936 let variable_data = b"test data".to_vec();
2251 assert_ok!(TemplateModule::set_variable_meta_data(1937 assert_ok!(TemplateModule::set_variable_meta_data(
2252 origin1,1938 origin1,
2253 collection_id,1939 collection_id,
2267#[test]1953#[test]
2268fn set_variable_meta_data_on_fungible_token_fails() {1954fn set_variable_meta_data_on_fungible_token_fails() {
2269 new_test_ext().execute_with(|| {1955 new_test_ext().execute_with(|| {
2270 default_limits();
2271
2272 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);1956 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
22731957
2274 let origin1 = Origin::signed(1);1958 let origin1 = Origin::signed(1);
22751959
2276 let data = default_fungible_data();1960 let data = default_fungible_data();
2277 create_test_item(1, &data.into());1961 create_test_item(1, &data.into());
22781962
2279 let variable_data = b"test set_variable_meta_data method.".to_vec();1963 let variable_data = b"test data".to_vec();
2280 assert_noop!(1964 assert_noop!(
2281 TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data),1965 TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data),
2282 Error::<Test>::CantStoreMetadataInFungibleTokens1966 Error::<Test>::CantStoreMetadataInFungibleTokens
2287#[test]1971#[test]
2288fn set_variable_meta_data_on_nft_token_fails_for_big_data() {1972fn set_variable_meta_data_on_nft_token_fails_for_big_data() {
2289 new_test_ext().execute_with(|| {1973 new_test_ext().execute_with(|| {
2290 assert_ok!(TemplateModule::set_chain_limits(
2291 RawOrigin::Root.into(),
2292 ChainLimits {
2293 collection_numbers_limit: default_collection_numbers_limit(),
2294 account_token_ownership_limit: 10,
2295 collections_admins_limit: 5,
2296 custom_data_limit: 10,
2297 nft_sponsor_transfer_timeout: 15,
2298 fungible_sponsor_transfer_timeout: 15,
2299 refungible_sponsor_transfer_timeout: 15,
2300 const_on_chain_schema_limit: 1024,
2301 offchain_schema_limit: 1024,
2302 variable_on_chain_schema_limit: 1024,
2303 }
2304 ));
2305
2306 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1974 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
23071975
2308 let origin1 = Origin::signed(1);1976 let origin1 = Origin::signed(1);
2321#[test]1989#[test]
2322fn set_variable_meta_data_on_re_fungible_token_fails_for_big_data() {1990fn set_variable_meta_data_on_re_fungible_token_fails_for_big_data() {
2323 new_test_ext().execute_with(|| {1991 new_test_ext().execute_with(|| {
2324 assert_ok!(TemplateModule::set_chain_limits(
2325 RawOrigin::Root.into(),
2326 ChainLimits {
2327 collection_numbers_limit: default_collection_numbers_limit(),
2328 account_token_ownership_limit: 10,
2329 collections_admins_limit: 5,
2330 custom_data_limit: 10,
2331 nft_sponsor_transfer_timeout: 15,
2332 fungible_sponsor_transfer_timeout: 15,
2333 refungible_sponsor_transfer_timeout: 15,
2334 const_on_chain_schema_limit: 1024,
2335 offchain_schema_limit: 1024,
2336 variable_on_chain_schema_limit: 1024,
2337 }
2338 ));
2339
2340 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);1992 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
23411993
2342 let origin1 = Origin::signed(1);1994 let origin1 = Origin::signed(1);
2427 ),2079 ),
2428 Error::<Test>::NoPermission2080 Error::<Test>::NoPermission
2429 );2081 );
2082
2083#[test]
2084fn collection_transfer_flag_works() {
2085 new_test_ext().execute_with(|| {
2086 let origin1 = Origin::signed(1);
2087
2088 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
2089 assert_ok!(TemplateModule::set_transfers_enabled_flag(origin1, 1, true));
2090
2091 let data = default_nft_data();
2092 create_test_item(collection_id, &data.into());
2093 assert_eq!(TemplateModule::balance_count(1, 1), 1);
2094 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
2095
2096 let origin1 = Origin::signed(1);
2097
2098 // default scenario
2099 assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1000));
2100 assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(2));
2101 assert_eq!(TemplateModule::balance_count(1, 1), 0);
2102 assert_eq!(TemplateModule::balance_count(1, 2), 1);
2103
2104 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
2430 });2105 });
2431}2106}
24322107
2578 ),2253 ),
2579 Error::<Test>::MetadataUpdateDenied2254 Error::<Test>::MetadataUpdateDenied
2580 );2255 );
2256
2257#[test]
2258fn collection_transfer_flag_works_neg() {
2259 new_test_ext().execute_with(|| {
2260 let origin1 = Origin::signed(1);
2261
2262 let collection_id = create_test_collection(&CollectionMode::NFT, 1);
2263 assert_ok!(TemplateModule::set_transfers_enabled_flag(
2264 origin1, 1, false
2265 ));
2266
2267 let data = default_nft_data();
2268 create_test_item(collection_id, &data.into());
2269 assert_eq!(TemplateModule::balance_count(1, 1), 1);
2270 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
2271
2272 let origin1 = Origin::signed(1);
2273
2274 // default scenario
2275 assert_noop!(
2276 TemplateModule::transfer(origin1, account(2), 1, 1, 1000),
2277 Error::<Test>::TransferNotAllowed
2278 );
2279 assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(1));
2280 assert_eq!(TemplateModule::balance_count(1, 1), 1);
2281 assert_eq!(TemplateModule::balance_count(1, 2), 0);
2282
2283 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
2581 });2284 });
2582}2285}
25832286
addedpallets/nft/src/weights.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/nft/src/weights.rs
@@ -0,0 +1,424 @@
+// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs
+
+//! Autogenerated weights for pallet_nft
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
+//! DATE: 2021-08-31, STEPS: `[50, ]`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 128
+
+// Executed Command:
+// target/release/nft
+// benchmark
+// --pallet
+// pallet-nft
+// --wasm-execution
+// compiled
+// --extrinsic
+// *
+// --template
+// .maintain/frame-weight-template.hbs
+// --steps=50
+// --repeat=20
+// --output=./pallets/nft/src/weights.rs
+
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use sp_std::marker::PhantomData;
+
+/// Weight functions needed for pallet_nft.
+pub trait WeightInfo {
+	fn create_collection() -> Weight;
+	fn destroy_collection() -> Weight;
+	fn add_to_white_list() -> Weight;
+	fn remove_from_white_list() -> Weight;
+	fn set_public_access_mode() -> Weight;
+	fn set_mint_permission() -> Weight;
+	fn change_collection_owner() -> Weight;
+	fn add_collection_admin() -> Weight;
+	fn remove_collection_admin() -> Weight;
+	fn set_collection_sponsor() -> Weight;
+	fn confirm_sponsorship() -> Weight;
+	fn remove_collection_sponsor() -> Weight;
+	fn create_item_nft(b: u32, ) -> Weight;
+	fn create_multiple_items_nft(b: u32, ) -> Weight;
+	fn create_item_fungible() -> Weight;
+	fn create_multiple_items_fungible(b: u32, ) -> Weight;
+	fn create_item_refungible(b: u32, ) -> Weight;
+	fn create_multiple_items_refungible(b: u32, ) -> Weight;
+	fn burn_item_nft() -> Weight;
+	fn transfer_nft() -> Weight;
+	fn transfer_fungible() -> Weight;
+	fn transfer_refungible() -> Weight;
+	fn set_transfers_enabled_flag() -> Weight;
+	fn approve_nft() -> Weight;
+	fn transfer_from_nft() -> Weight;
+	fn transfer_from_fungible() -> Weight;
+	fn transfer_from_refungible() -> Weight;
+	fn set_offchain_schema(b: u32, ) -> Weight;
+	fn set_const_on_chain_schema(b: u32, ) -> Weight;
+	fn set_variable_on_chain_schema(b: u32, ) -> Weight;
+	fn set_variable_meta_data_nft(b: u32, ) -> Weight;
+	fn set_schema_version() -> Weight;
+	fn set_collection_limits() -> Weight;
+}
+
+/// Weights for pallet_nft using the Substrate node and recommended hardware.
+pub struct SubstrateWeight<T>(PhantomData<T>);
+impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
+	fn create_collection() -> Weight {
+		(25_851_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(8 as Weight))
+			.saturating_add(T::DbWeight::get().writes(6 as Weight))
+	}
+	fn destroy_collection() -> Weight {
+		(28_737_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(2 as Weight))
+			.saturating_add(T::DbWeight::get().writes(4 as Weight))
+	}
+	fn add_to_white_list() -> Weight {
+		(6_237_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn remove_from_white_list() -> Weight {
+		(6_252_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn set_public_access_mode() -> Weight {
+		(6_691_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn set_mint_permission() -> Weight {
+		(6_630_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn change_collection_owner() -> Weight {
+		(6_521_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn add_collection_admin() -> Weight {
+		(8_057_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(2 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn remove_collection_admin() -> Weight {
+		(8_307_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(2 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn set_collection_sponsor() -> Weight {
+		(6_484_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn confirm_sponsorship() -> Weight {
+		(6_530_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn remove_collection_sponsor() -> Weight {
+		(6_733_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn create_item_nft(_b: u32, ) -> Weight {
+		(167_909_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(11 as Weight))
+			.saturating_add(T::DbWeight::get().writes(8 as Weight))
+	}
+	fn create_multiple_items_nft(b: u32, ) -> Weight {
+		(336_830_000 as Weight)
+			// Standard Error: 42_000
+			.saturating_add((11_627_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(T::DbWeight::get().reads(11 as Weight))
+			.saturating_add(T::DbWeight::get().writes(7 as Weight))
+			.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(b as Weight)))
+	}
+	fn create_item_fungible() -> Weight {
+		(24_123_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(9 as Weight))
+			.saturating_add(T::DbWeight::get().writes(4 as Weight))
+	}
+	fn create_multiple_items_fungible(b: u32, ) -> Weight {
+		(48_227_000 as Weight)
+			// Standard Error: 13_000
+			.saturating_add((2_918_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(T::DbWeight::get().reads(9 as Weight))
+			.saturating_add(T::DbWeight::get().writes(4 as Weight))
+	}
+	fn create_item_refungible(_b: u32, ) -> Weight {
+		(26_293_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(9 as Weight))
+			.saturating_add(T::DbWeight::get().writes(7 as Weight))
+	}
+	fn create_multiple_items_refungible(b: u32, ) -> Weight {
+		(0 as Weight)
+			// Standard Error: 16_000
+			.saturating_add((8_374_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(T::DbWeight::get().reads(9 as Weight))
+			.saturating_add(T::DbWeight::get().writes(6 as Weight))
+			.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(b as Weight)))
+	}
+	fn burn_item_nft() -> Weight {
+		(32_237_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(9 as Weight))
+			.saturating_add(T::DbWeight::get().writes(7 as Weight))
+	}
+	fn transfer_nft() -> Weight {
+		(192_578_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(14 as Weight))
+			.saturating_add(T::DbWeight::get().writes(10 as Weight))
+	}
+	fn transfer_fungible() -> Weight {
+		(170_749_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(11 as Weight))
+			.saturating_add(T::DbWeight::get().writes(7 as Weight))
+	}
+	fn transfer_refungible() -> Weight {
+		(35_949_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(10 as Weight))
+			.saturating_add(T::DbWeight::get().writes(7 as Weight))
+	}
+	fn set_transfers_enabled_flag() -> Weight {
+		(6_376_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn approve_nft() -> Weight {
+		(169_825_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(9 as Weight))
+			.saturating_add(T::DbWeight::get().writes(4 as Weight))
+	}
+	fn transfer_from_nft() -> Weight {
+		(197_912_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(15 as Weight))
+			.saturating_add(T::DbWeight::get().writes(11 as Weight))
+	}
+	fn transfer_from_fungible() -> Weight {
+		(183_789_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(12 as Weight))
+			.saturating_add(T::DbWeight::get().writes(8 as Weight))
+	}
+	fn transfer_from_refungible() -> Weight {
+		(37_149_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(11 as Weight))
+			.saturating_add(T::DbWeight::get().writes(8 as Weight))
+	}
+	fn set_offchain_schema(_b: u32, ) -> Weight {
+		(6_435_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn set_const_on_chain_schema(_b: u32, ) -> Weight {
+		(6_646_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn set_variable_on_chain_schema(_b: u32, ) -> Weight {
+		(6_542_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn set_variable_meta_data_nft(_b: u32, ) -> Weight {
+		(14_697_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(2 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn set_schema_version() -> Weight {
+		(6_566_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	fn set_collection_limits() -> Weight {
+		(6_349_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+}
+
+// For backwards compatibility and tests
+impl WeightInfo for () {
+	fn create_collection() -> Weight {
+		(25_851_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(8 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(6 as Weight))
+	}
+	fn destroy_collection() -> Weight {
+		(28_737_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
+	}
+	fn add_to_white_list() -> Weight {
+		(6_237_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn remove_from_white_list() -> Weight {
+		(6_252_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn set_public_access_mode() -> Weight {
+		(6_691_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn set_mint_permission() -> Weight {
+		(6_630_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn change_collection_owner() -> Weight {
+		(6_521_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn add_collection_admin() -> Weight {
+		(8_057_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn remove_collection_admin() -> Weight {
+		(8_307_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn set_collection_sponsor() -> Weight {
+		(6_484_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn confirm_sponsorship() -> Weight {
+		(6_530_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn remove_collection_sponsor() -> Weight {
+		(6_733_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn create_item_nft(b: u32, ) -> Weight {
+		(167_180_000 as Weight)
+			// Standard Error: 1_000
+			.saturating_add((10_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(RocksDbWeight::get().reads(11 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(8 as Weight))
+	}
+	fn create_multiple_items_nft(b: u32, ) -> Weight {
+		(336_830_000 as Weight)
+			// Standard Error: 42_000
+			.saturating_add((11_627_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(RocksDbWeight::get().reads(11 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(7 as Weight))
+			.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(b as Weight)))
+	}
+	fn create_item_fungible() -> Weight {
+		(24_123_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(9 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
+	}
+	fn create_multiple_items_fungible(b: u32, ) -> Weight {
+		(13_217_000 as Weight)
+			// Standard Error: 4_000
+			.saturating_add((2_971_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(RocksDbWeight::get().reads(9 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
+	}
+	fn create_item_refungible(_b: u32, ) -> Weight {
+		(26_293_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(9 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(7 as Weight))
+	}
+	fn create_multiple_items_refungible(b: u32, ) -> Weight {
+		(0 as Weight)
+			// Standard Error: 16_000
+			.saturating_add((8_374_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(RocksDbWeight::get().reads(9 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(6 as Weight))
+			.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(b as Weight)))
+	}
+	fn burn_item_nft() -> Weight {
+		(32_237_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(9 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(7 as Weight))
+	}
+	fn transfer_nft() -> Weight {
+		(192_578_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(14 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(10 as Weight))
+	}
+	fn transfer_fungible() -> Weight {
+		(170_749_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(11 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(7 as Weight))
+	}
+	fn transfer_refungible() -> Weight {
+		(35_949_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(10 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(7 as Weight))
+	}
+	fn set_transfers_enabled_flag() -> Weight {
+		(6_376_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn approve_nft() -> Weight {
+		(169_825_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(9 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
+	}
+	fn transfer_from_nft() -> Weight {
+		(197_912_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(15 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(11 as Weight))
+	}
+	fn transfer_from_fungible() -> Weight {
+		(183_789_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(12 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(8 as Weight))
+	}
+	fn transfer_from_refungible() -> Weight {
+		(37_149_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(11 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(8 as Weight))
+	}
+	fn set_offchain_schema(_b: u32, ) -> Weight {
+		(6_435_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn set_const_on_chain_schema(_b: u32, ) -> Weight {
+		(6_646_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn set_variable_on_chain_schema(_b: u32, ) -> Weight {
+		(6_542_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn set_variable_meta_data_nft(_b: u32, ) -> Weight {
+		(14_697_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn set_schema_version() -> Weight {
+		(6_566_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	fn set_collection_limits() -> Weight {
+		(6_349_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+}
\ No newline at end of file
modifiedpallets/scheduler/Cargo.tomldiffbeforeafterboth
--- a/pallets/scheduler/Cargo.toml
+++ b/pallets/scheduler/Cargo.toml
@@ -12,19 +12,19 @@
 [dependencies]
 serde = { version = "1.0.119", default-features = false }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false }
-frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-runtime = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-io = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-frame-benchmarking = { default-features = false, version = '3.0.0', optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
+frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-runtime = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-std = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-io = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-benchmarking = { default-features = false, version = '3.0.0', optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
 
 up-sponsorship = { default-features = false, path = "../../primitives/sponsorship", version = "0.1.0" }
 log = { version = "0.4.14", default-features = false }
 
 [dev-dependencies]
-sp-core = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-substrate-test-utils = { version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
+sp-core = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+substrate-test-utils = { version = "3.0.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
 
 [features]
 default = ["std"]
modifiedprimitives/nft/Cargo.tomldiffbeforeafterboth
--- a/primitives/nft/Cargo.toml
+++ b/primitives/nft/Cargo.toml
@@ -9,20 +9,28 @@
 version = '0.9.0'
 
 [dependencies]
-codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ['derive'] }
-serde = { version = "1.0.119", features = ['derive'], default-features = false }
-frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-core = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
-sp-runtime = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.7' }
+codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ['derive'] }
+serde = { version = "1.0.119", features = ['derive'], default-features = false, optional = true }
+max-encoded-len = { default-features = false, features = ['derive'], version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-support = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+frame-system = { default-features = false, version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-core = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-std = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+sp-runtime = { version = "3.0.0", default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+derivative = "2.2.0"
 
 [features]
 default = ["std"]
 std = [
+  "serde1",
   "serde/std",
   "codec/std",
+  "max-encoded-len/std",
   "frame-system/std",
   "frame-support/std",
   "sp-runtime/std",
   "sp-core/std",
-]
\ No newline at end of file
+  "sp-std/std",
+]
+serde1 = ["serde"]
+limit-testing = []
\ No newline at end of file
modifiedprimitives/nft/src/lib.rsdiffbeforeafterboth
--- a/primitives/nft/src/lib.rs
+++ b/primitives/nft/src/lib.rs
@@ -1,11 +1,13 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 
+#[cfg(feature = "serde")]
 pub use serde::{Serialize, Deserialize};
 
 use sp_runtime::sp_std::prelude::Vec;
 use codec::{Decode, Encode};
+use max_encoded_len::MaxEncodedLen;
 pub use frame_support::{
-	construct_runtime, decl_event, decl_module, decl_storage, decl_error,
+	BoundedVec, construct_runtime, decl_event, decl_module, decl_storage, decl_error,
 	dispatch::DispatchResult,
 	ensure, fail, parameter_types,
 	traits::{
@@ -19,18 +21,58 @@
 	},
 	StorageValue, transactional,
 };
+use derivative::Derivative;
 
 pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;
 pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;
 pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;
 pub const MAX_TOKEN_OWNERSHIP: u32 = 10_000_000;
 
+pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {
+	100000
+} else {
+	10
+};
+pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {
+	2048
+} else {
+	10
+};
+pub const COLLECTION_ADMINS_LIMIT: u64 = 5;
+pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {
+	1000000
+} else {
+	10
+};
+
+// Timeouts for item types in passed blocks
+pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;
+pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;
+pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;
+
+// Schema limits
+pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 1024;
+pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 1024;
+pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 1024;
+
+pub const MAX_COLLECTION_NAME_LENGTH: usize = 64;
+pub const MAX_COLLECTION_DESCRIPTION_LENGTH: usize = 256;
+pub const MAX_TOKEN_PREFIX_LENGTH: usize = 16;
+
+/// How much items can be created per single
+/// create_many call
+pub const MAX_ITEMS_PER_BATCH: u32 = 200;
+
+parameter_types! {
+	pub const CustomDataLimit: u32 = CUSTOM_DATA_LIMIT;
+}
+
 pub type CollectionId = u32;
 pub type TokenId = u32;
 pub type DecimalPoints = u8;
 
 #[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
 pub enum CollectionMode {
 	Invalid,
 	NFT,
@@ -61,7 +103,7 @@
 }
 
 #[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
 pub enum AccessMode {
 	Normal,
 	WhiteList,
@@ -73,7 +115,7 @@
 }
 
 #[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
 pub enum SchemaVersion {
 	ImageURL,
 	Unique,
@@ -85,14 +127,14 @@
 }
 
 #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
 pub struct Ownership<AccountId> {
 	pub owner: AccountId,
 	pub fraction: u128,
 }
 
 #[derive(Encode, Decode, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
 pub enum SponsorshipState<AccountId> {
 	/// The fees are applied to the transaction sender
 	Disabled,
@@ -128,7 +170,7 @@
 }
 
 #[derive(Encode, Decode, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
 pub struct Collection<T: frame_system::Config> {
 	pub owner: T::AccountId,
 	pub mode: CollectionMode,
@@ -145,10 +187,11 @@
 	pub variable_on_chain_schema: Vec<u8>,        //
 	pub const_on_chain_schema: Vec<u8>,           //
 	pub meta_update_permission: MetaUpdatePermission,
+	pub transfers_enabled: bool,
 }
 
 #[derive(Encode, Decode, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
 pub struct NftItemType<AccountId> {
 	pub owner: AccountId,
 	pub const_data: Vec<u8>,
@@ -156,13 +199,13 @@
 }
 
 #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
 pub struct FungibleItemType {
 	pub value: u128,
 }
 
 #[derive(Encode, Decode, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
 pub struct ReFungibleItemType<AccountId> {
 	pub owner: Vec<Ownership<AccountId>>,
 	pub const_data: Vec<u8>,
@@ -170,7 +213,7 @@
 }
 
 #[derive(Encode, Decode, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
 pub struct CollectionLimits<BlockNumber: Encode + Decode> {
 	pub account_token_ownership_limit: u32,
 	pub sponsored_data_size: u32,
@@ -200,43 +243,67 @@
 	}
 }
 
-#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-pub struct ChainLimits {
-	pub collection_numbers_limit: u32,
-	pub account_token_ownership_limit: u32,
-	pub collections_admins_limit: u64,
-	pub custom_data_limit: u32,
+/// BoundedVec doesn't supports serde
+#[cfg(feature = "serde1")]
+mod bounded_serde {
+	use core::convert::TryFrom;
+	use frame_support::{BoundedVec, traits::Get};
+	use serde::{
+		ser::{self, Serialize},
+		de::{self, Deserialize, Error},
+	};
+	use sp_std::vec::Vec;
 
-	// Timeouts for item types in passed blocks
-	pub nft_sponsor_transfer_timeout: u32,
-	pub fungible_sponsor_transfer_timeout: u32,
-	pub refungible_sponsor_transfer_timeout: u32,
+	pub fn serialize<D, V, S>(value: &BoundedVec<V, S>, serializer: D) -> Result<D::Ok, D::Error>
+	where
+		D: ser::Serializer,
+		V: Serialize,
+	{
+		let vec: &Vec<_> = &value;
+		vec.serialize(serializer)
+	}
 
-	// Schema limits
-	pub offchain_schema_limit: u32,
-	pub variable_on_chain_schema_limit: u32,
-	pub const_on_chain_schema_limit: u32,
+	pub fn deserialize<'de, D, V, S>(deserializer: D) -> Result<BoundedVec<V, S>, D::Error>
+	where
+		D: de::Deserializer<'de>,
+		V: de::Deserialize<'de>,
+		S: Get<u32>,
+	{
+		// TODO: Implement custom visitor, which will limit vec size at parse time? Will serde only be used by chainspec?
+		let vec = <Vec<V>>::deserialize(deserializer)?;
+		let len = vec.len();
+		TryFrom::try_from(vec).map_err(|_| D::Error::invalid_length(len, &"lesser size"))
+	}
 }
 
-#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+#[derivative(Debug)]
 pub struct CreateNftData {
-	pub const_data: Vec<u8>,
-	pub variable_data: Vec<u8>,
+	#[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+	#[derivative(Debug = "ignore")]
+	pub const_data: BoundedVec<u8, CustomDataLimit>,
+	#[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+	#[derivative(Debug = "ignore")]
+	pub variable_data: BoundedVec<u8, CustomDataLimit>,
 }
 
-#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
 pub struct CreateFungibleData {
 	pub value: u128,
 }
 
-#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+#[derivative(Debug)]
 pub struct CreateReFungibleData {
-	pub const_data: Vec<u8>,
-	pub variable_data: Vec<u8>,
+	#[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+	#[derivative(Debug = "ignore")]
+	pub const_data: BoundedVec<u8, CustomDataLimit>,
+	#[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+	#[derivative(Debug = "ignore")]
+	pub variable_data: BoundedVec<u8, CustomDataLimit>,
 	pub pieces: u128,
 }
 
@@ -254,8 +321,8 @@
 	}
 }
 
-#[derive(Encode, Decode, Debug, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
 pub enum CreateItemData {
 	NFT(CreateNftData),
 	Fungible(CreateFungibleData),
modifiedruntime/Cargo.tomldiffbeforeafterboth
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -23,25 +23,29 @@
     'frame-support/runtime-benchmarks',
     'frame-system-benchmarking',
     'frame-system/runtime-benchmarks',
+    'pallet-evm-migration/runtime-benchmarks',
     'pallet-balances/runtime-benchmarks',
     'pallet-timestamp/runtime-benchmarks',
     'pallet-nft/runtime-benchmarks',
     'pallet-inflation/runtime-benchmarks',
+    'pallet-xcm/runtime-benchmarks',
     'sp-runtime/runtime-benchmarks',
+    'xcm-builder/runtime-benchmarks',
 ]
 std = [
     'codec/std',
-	'cumulus-pallet-aura-ext/std',
-	'cumulus-pallet-parachain-system/std',
-	'cumulus-pallet-xcm/std',
-	'cumulus-pallet-xcmp-queue/std',
-	'cumulus-primitives-core/std',
-	'cumulus-primitives-utility/std',
+    'max-encoded-len/std',
+    'cumulus-pallet-aura-ext/std',
+    'cumulus-pallet-parachain-system/std',
+    'cumulus-pallet-xcm/std',
+    'cumulus-pallet-xcmp-queue/std',
+    'cumulus-primitives-core/std',
+    'cumulus-primitives-utility/std',
     'frame-executive/std',
     'frame-support/std',
     'frame-system/std',
     'frame-system-rpc-runtime-api/std',
-	'pallet-aura/std',
+    'pallet-aura/std',
     'pallet-balances/std',
     # 'pallet-contracts/std',
     # 'pallet-contracts-primitives/std',
@@ -55,31 +59,39 @@
     'pallet-treasury/std',
     'pallet-vesting/std',
     'pallet-evm/std',
+    'pallet-evm-migration/std',
+    'pallet-evm-contract-helpers/std',
+    'pallet-evm-transaction-payment/std',
+    'pallet-evm-coder-substrate/std',
     'pallet-ethereum/std',
     'fp-rpc/std',
-	'parachain-info/std',
+    'parachain-info/std',
     'serde',
     'pallet-inflation/std',
     'pallet-nft/std',
     'pallet-scheduler/std',
     'pallet-nft-charge-transaction/std',
-    'pallet-nft-transaction-payment/std', 
+    'pallet-nft-transaction-payment/std',
     'nft-data-structs/std',
     'sp-api/std',
     'sp-block-builder/std',
-	"sp-consensus-aura/std",
+    "sp-consensus-aura/std",
     'sp-core/std',
     'sp-inherents/std',
-	'sp-io/std',
+    'sp-io/std',
     'sp-offchain/std',
     'sp-runtime/std',
     'sp-session/std',
     'sp-std/std',
     'sp-transaction-pool/std',
     'sp-version/std',
-	'xcm/std',
-	'xcm-builder/std',
-	'xcm-executor/std',
+    'xcm/std',
+    'xcm-builder/std',
+    'xcm-executor/std',
+]
+limit-testing = [
+    'pallet-nft/limit-testing',
+    'nft-data-structs/limit-testing',
 ]
 
 ################################################################################
@@ -95,38 +107,38 @@
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
 optional = true
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.frame-executive]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.frame-support]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.frame-system]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.frame-system-benchmarking]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
 optional = true
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.frame-system-rpc-runtime-api]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.hex-literal]
@@ -142,152 +154,152 @@
 [dependencies.pallet-aura]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-balances]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 # Contracts specific packages
 # [dependencies.pallet-contracts]
 # git = 'https://github.com/paritytech/substrate.git'
 # default-features = false
-# branch = 'polkadot-v0.9.7'
+# branch = 'polkadot-v0.9.8'
 # version = '3.0.0'
 
 # [dependencies.pallet-contracts-primitives]
 # git = 'https://github.com/paritytech/substrate.git'
 # default-features = false
-# branch = 'polkadot-v0.9.7'
+# branch = 'polkadot-v0.9.8'
 # version = '3.0.0'
 
 # [dependencies.pallet-contracts-rpc-runtime-api]
 # git = 'https://github.com/paritytech/substrate.git'
 # default-features = false
-# branch = 'polkadot-v0.9.7'
+# branch = 'polkadot-v0.9.8'
 # version = '3.0.0'
 
 [dependencies.pallet-randomness-collective-flip]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-sudo]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-timestamp]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-transaction-payment]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-transaction-payment-rpc-runtime-api]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-treasury]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.pallet-vesting]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-arithmetic]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-api]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-block-builder]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-core]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-consensus-aura]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.9.0'
 
 [dependencies.sp-inherents]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-io]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-offchain]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-runtime]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-session]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-std]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-transaction-pool]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.sp-version]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '3.0.0'
 
 [dependencies.smallvec]
@@ -299,47 +311,47 @@
 [dependencies.parachain-info]
 default-features = false
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 version = '0.1.0'
 
 [dependencies.cumulus-pallet-aura-ext]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 default-features = false
 
 [dependencies.cumulus-pallet-parachain-system]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 default-features = false
 
 [dependencies.cumulus-primitives-core]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 default-features = false
 
 [dependencies.cumulus-pallet-xcm]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 default-features = false
 
 [dependencies.cumulus-pallet-dmp-queue]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 default-features = false
 
 [dependencies.cumulus-pallet-xcmp-queue]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 default-features = false
 
 [dependencies.cumulus-primitives-utility]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 default-features = false
 
 [dependencies.cumulus-primitives-timestamp]
 git = 'https://github.com/paritytech/cumulus.git'
-branch = 'polkadot-v0.9.7'
+branch = 'polkadot-v0.9.8'
 default-features = false
 
 ################################################################################
@@ -347,49 +359,54 @@
 
 [dependencies.polkadot-parachain]
 git = 'https://github.com/paritytech/polkadot'
-branch = 'release-v0.9.7'
+branch = 'release-v0.9.8'
 default-features = false
 
 [dependencies.xcm]
 git = 'https://github.com/paritytech/polkadot'
-branch = 'release-v0.9.7'
+branch = 'release-v0.9.8'
 default-features = false
 
 [dependencies.xcm-builder]
 git = 'https://github.com/paritytech/polkadot'
-branch = 'release-v0.9.7'
+branch = 'release-v0.9.8'
 default-features = false
 
 [dependencies.xcm-executor]
 git = 'https://github.com/paritytech/polkadot'
-branch = 'release-v0.9.7'
+branch = 'release-v0.9.8'
 default-features = false
 
 [dependencies.pallet-xcm]
 git = 'https://github.com/paritytech/polkadot'
-branch = 'release-v0.9.7'
+branch = 'release-v0.9.8'
 default-features = false
-
 
 
 ################################################################################
 # local dependencies
 
 [dependencies]
+max-encoded-len = { default-features = false, features = ['derive'], version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.8' }
+derivative = "2.2.0"
 pallet-nft = { path = '../pallets/nft', default-features = false, version = '3.0.0' }
 pallet-inflation = { path = '../pallets/inflation', default-features = false, version = '3.0.0' }
-nft-data-structs = { path = '../primitives/nft', default-features = false,  version = '0.9.0' }
+nft-data-structs = { path = '../primitives/nft', default-features = false, version = '0.9.0' }
 pallet-scheduler = { path = '../pallets/scheduler', default-features = false, version = '3.0.0' }
 # pallet-contract-helpers = { path = '../pallets/contract-helpers', default-features = false, version = '0.1.0' }
 pallet-nft-transaction-payment = { path = '../pallets/nft-transaction-payment', default-features = false, version = '3.0.0' }
 pallet-nft-charge-transaction = { path = '../pallets/nft-charge-transaction', default-features = false, version = '3.0.0' }
+pallet-evm-migration = { path = '../pallets/evm-migration', default-features = false }
+pallet-evm-contract-helpers = { path = '../pallets/evm-contract-helpers', default-features = false }
+pallet-evm-transaction-payment = { path = '../pallets/evm-transaction-payment', default-features = false }
+pallet-evm-coder-substrate = { default-features = false, path = "../pallets/evm-coder-substrate" }
 
-pallet-evm = { default-features = false, version = "5.0.0-dev", git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-pallet-ethereum = { default-features = false, version = "3.0.0-dev", git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
-fp-rpc = { default-features = false, version = "2.0.0", git = "https://github.com/usetech-llc/frontier.git", branch = "injected-transactions-parachain" }
+pallet-evm = { default-features = false, version = "5.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+pallet-ethereum = { default-features = false, version = "3.0.0-dev", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
+fp-rpc = { default-features = false, version = "2.0.0", git = "https://github.com/uniquenetwork/frontier.git", branch = "injected-transactions-parachain" }
 
 ################################################################################
 # Build Dependencies
 
 [build-dependencies]
-substrate-wasm-builder = '4.0.0'
\ No newline at end of file
+substrate-wasm-builder = '4.0.0'
modifiedruntime/src/chain_extension.rsdiffbeforeafterboth
--- a/runtime/src/chain_extension.rs
+++ b/runtime/src/chain_extension.rs
@@ -6,6 +6,8 @@
 //
 
 use codec::{Decode, Encode};
+use max_encoded_len::MaxEncodedLen;
+use derivative::Derivative;
 
 pub use pallet_contracts::chain_extension::RetVal;
 use pallet_contracts::chain_extension::{
@@ -19,61 +21,63 @@
 pub use pallet_nft::*;
 use pallet_nft::CrossAccountId;
 use nft_data_structs::*;
-
-use crate::Vec;
 
 /// Create item parameters
-#[derive(Debug, PartialEq, Encode, Decode)]
-pub struct NFTExtCreateItem<E: Ext> {
-	pub owner: <E::T as SysConfig>::AccountId,
+#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)]
+pub struct NFTExtCreateItem<AccountId> {
+	pub owner: AccountId,
 	pub collection_id: u32,
 	pub data: CreateItemData,
 }
 
 /// Transfer parameters
-#[derive(Debug, PartialEq, Encode, Decode)]
-pub struct NFTExtTransfer<E: Ext> {
-	pub recipient: <E::T as SysConfig>::AccountId,
+#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)]
+pub struct NFTExtTransfer<AccountId> {
+	pub recipient: AccountId,
 	pub collection_id: u32,
 	pub token_id: u32,
 	pub amount: u128,
 }
 
-#[derive(Debug, PartialEq, Encode, Decode)]
-pub struct NFTExtCreateMultipleItems<E: Ext> {
-	pub owner: <E::T as SysConfig>::AccountId,
+#[derive(Derivative, PartialEq, Encode, Decode, MaxEncodedLen)]
+#[derivative(Debug)]
+pub struct NFTExtCreateMultipleItems<AccountId> {
+	pub owner: AccountId,
 	pub collection_id: u32,
-	pub data: Vec<CreateItemData>,
+	#[derivative(Debug = "ignore")]
+	pub data: BoundedVec<CreateItemData, MaxItemsPerBatch>,
 }
 
-#[derive(Debug, PartialEq, Encode, Decode)]
-pub struct NFTExtApprove<E: Ext> {
-	pub spender: <E::T as SysConfig>::AccountId,
+#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)]
+pub struct NFTExtApprove<AccountId> {
+	pub spender: AccountId,
 	pub collection_id: u32,
 	pub item_id: u32,
 	pub amount: u128,
 }
 
-#[derive(Debug, PartialEq, Encode, Decode)]
-pub struct NFTExtTransferFrom<E: Ext> {
-	pub owner: <E::T as SysConfig>::AccountId,
-	pub recipient: <E::T as SysConfig>::AccountId,
+#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)]
+pub struct NFTExtTransferFrom<AccountId> {
+	pub owner: AccountId,
+	pub recipient: AccountId,
 	pub collection_id: u32,
 	pub item_id: u32,
 	pub amount: u128,
 }
 
-#[derive(Debug, PartialEq, Encode, Decode)]
+#[derive(Derivative, PartialEq, Encode, Decode, MaxEncodedLen)]
+#[derivative(Debug)]
 pub struct NFTExtSetVariableMetaData {
 	pub collection_id: u32,
 	pub item_id: u32,
-	pub data: Vec<u8>,
+	#[derivative(Debug = "ignore")]
+	pub data: BoundedVec<u8, MaxDataSize>,
 }
 
-#[derive(Debug, PartialEq, Encode, Decode)]
-pub struct NFTExtToggleWhiteList<E: Ext> {
+#[derive(Debug, PartialEq, Encode, Decode, MaxEncodedLen)]
+pub struct NFTExtToggleWhiteList<AccountId> {
 	pub collection_id: u32,
-	pub address: <E::T as SysConfig>::AccountId,
+	pub address: AccountId,
 	pub whitelisted: bool,
 }
 
@@ -82,6 +86,8 @@
 
 pub type NftWeightInfoOf<C> = <C as pallet_nft::Config>::WeightInfo;
 
+pub type AccountIdOf<C> = <C as SysConfig>::AccountId;
+
 impl<C: Config + pallet_contracts::Config> ChainExtension<C> for NFTExtension {
 	fn call<E: Ext>(func_id: u32, env: Environment<E, InitState>) -> Result<RetVal, DispatchError>
 	where
@@ -93,7 +99,7 @@
 		match func_id {
 			0 => {
 				let mut env = env.buf_in_buf_out();
-				let input: NFTExtTransfer<E> = env.read_as()?;
+				let input: NFTExtTransfer<AccountIdOf<C>> = env.read_as()?;
 				env.charge_weight(NftWeightInfoOf::<C>::transfer())?;
 
 				let collection = pallet_nft::Module::<C>::get_collection(input.collection_id)?;
@@ -106,13 +112,13 @@
 					input.amount,
 				)?;
 
-				pallet_nft::Module::<C>::submit_logs(collection)?;
+				collection.submit_logs()?;
 				Ok(RetVal::Converging(0))
 			}
 			1 => {
 				// Create Item
 				let mut env = env.buf_in_buf_out();
-				let input: NFTExtCreateItem<E> = env.read_as()?;
+				let input: NFTExtCreateItem<AccountIdOf<C>> = env.read_as()?;
 				env.charge_weight(NftWeightInfoOf::<C>::create_item(input.data.data_size()))?;
 
 				let collection = pallet_nft::Module::<C>::get_collection(input.collection_id)?;
@@ -124,13 +130,13 @@
 					input.data,
 				)?;
 
-				pallet_nft::Module::<C>::submit_logs(collection)?;
+				collection.submit_logs()?;
 				Ok(RetVal::Converging(0))
 			}
 			2 => {
 				// Create multiple items
 				let mut env = env.buf_in_buf_out();
-				let input: NFTExtCreateMultipleItems<E> = env.read_as()?;
+				let input: NFTExtCreateMultipleItems<AccountIdOf<C>> = env.read_as()?;
 				env.charge_weight(NftWeightInfoOf::<C>::create_item(
 					input.data.iter().map(|i| i.data_size()).sum(),
 				))?;
@@ -141,16 +147,16 @@
 					&C::CrossAccountId::from_sub(env.ext().address().clone()),
 					&collection,
 					&C::CrossAccountId::from_sub(input.owner),
-					input.data,
+					input.data.into_inner(),
 				)?;
 
-				pallet_nft::Module::<C>::submit_logs(collection)?;
+				collection.submit_logs()?;
 				Ok(RetVal::Converging(0))
 			}
 			3 => {
 				// Approve
 				let mut env = env.buf_in_buf_out();
-				let input: NFTExtApprove<E> = env.read_as()?;
+				let input: NFTExtApprove<AccountIdOf<C>> = env.read_as()?;
 				env.charge_weight(NftWeightInfoOf::<C>::approve())?;
 
 				let collection = pallet_nft::Module::<C>::get_collection(input.collection_id)?;
@@ -163,13 +169,13 @@
 					input.amount,
 				)?;
 
-				pallet_nft::Module::<C>::submit_logs(collection)?;
+				collection.submit_logs()?;
 				Ok(RetVal::Converging(0))
 			}
 			4 => {
 				// Transfer from
 				let mut env = env.buf_in_buf_out();
-				let input: NFTExtTransferFrom<E> = env.read_as()?;
+				let input: NFTExtTransferFrom<AccountIdOf<C>> = env.read_as()?;
 				env.charge_weight(NftWeightInfoOf::<C>::transfer_from())?;
 
 				let collection = pallet_nft::Module::<C>::get_collection(input.collection_id)?;
@@ -183,7 +189,7 @@
 					input.amount,
 				)?;
 
-				pallet_nft::Module::<C>::submit_logs(collection)?;
+				collection.submit_logs()?;
 				Ok(RetVal::Converging(0))
 			}
 			5 => {
@@ -198,16 +204,16 @@
 					&C::CrossAccountId::from_sub(env.ext().address().clone()),
 					&collection,
 					input.item_id,
-					input.data,
+					input.data.into_inner(),
 				)?;
 
-				pallet_nft::Module::<C>::submit_logs(collection)?;
+				collection.submit_logs()?;
 				Ok(RetVal::Converging(0))
 			}
 			6 => {
 				// Toggle whitelist
 				let mut env = env.buf_in_buf_out();
-				let input: NFTExtToggleWhiteList<E> = env.read_as()?;
+				let input: NFTExtToggleWhiteList<AccountIdOf<C>> = env.read_as()?;
 				env.charge_weight(NftWeightInfoOf::<C>::add_to_white_list())?;
 
 				let collection = pallet_nft::Module::<C>::get_collection(input.collection_id)?;
@@ -219,7 +225,7 @@
 					input.whitelisted,
 				)?;
 
-				pallet_nft::Module::<C>::submit_logs(collection)?;
+				collection.submit_logs()?;
 				Ok(RetVal::Converging(0))
 			}
 			_ => Err(DispatchError::Other("unknown chain_extension func_id")),
modifiedruntime/src/lib.rsdiffbeforeafterboth
--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -72,7 +72,6 @@
 use sp_runtime::{
 	traits::{Dispatchable},
 };
-// use pallet_contracts::chain_extension::UncheckedFrom;
 
 // pub use pallet_timestamp::Call as TimestampCall;
 pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
@@ -119,8 +118,6 @@
 
 /// Digest item type.
 pub type DigestItem = generic::DigestItem<Hash>;
-
-mod nft_weights;
 
 /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
 /// the specifics of the runtime. They can then be made to be agnostic over specific formats
@@ -163,6 +160,10 @@
 pub const HOURS: BlockNumber = MINUTES * 60;
 pub const DAYS: BlockNumber = HOURS * 24;
 
+parameter_types! {
+	pub const DefaultSponsoringRateLimit: BlockNumber = 1 * DAYS;
+}
+
 #[derive(codec::Encode, codec::Decode)]
 pub enum XCMPMessage<XAccountId, XBalance> {
 	/// Transfer tokens to the given account from the Parachain account.
@@ -248,10 +249,21 @@
 	type Precompiles = ();
 	type Currency = Balances;
 	type Event = Event;
-	type OnMethodCall = pallet_nft::NftErcSupport<Self>;
+	type OnMethodCall = (
+		pallet_evm_migration::OnMethodCall<Self>,
+		pallet_nft::NftErcSupport<Self>,
+		pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,
+	);
+	type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
 	type ChainId = ChainId;
 	type Runner = pallet_evm::runner::stack::Runner<Self>;
-	type OnChargeTransaction = ();
+	type OnChargeTransaction = pallet_evm_transaction_payment::OnChargeTransaction<Self>;
+	type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;
+	type FindAuthor = EthereumFindAuthor<Aura>;
+}
+
+impl pallet_evm_migration::Config for Runtime {
+	type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;
 }
 
 pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);
@@ -274,9 +286,8 @@
 
 impl pallet_ethereum::Config for Runtime {
 	type Event = Event;
-	type FindAuthor = EthereumFindAuthor<Aura>;
 	type StateRoot = pallet_ethereum::IntermediateStateRoot;
-	type EvmSubmitLog = pallet_evm::Pallet<Runtime>;
+	type EvmSubmitLog = pallet_evm::Pallet<Self>;
 }
 
 impl pallet_randomness_collective_flip::Config for Runtime {}
@@ -324,7 +335,7 @@
 	/// This is used as an identifier of the chain. 42 is the generic substrate prefix.
 	type SS58Prefix = SS58Prefix;
 	/// Weight information for the extrinsics of this pallet.
-	type SystemWeightInfo = system::weights::SubstrateWeight<Runtime>;
+	type SystemWeightInfo = system::weights::SubstrateWeight<Self>;
 	/// Version of the runtime.
 	type Version = Version;
 }
@@ -358,7 +369,7 @@
 	type DustRemoval = Treasury;
 	type ExistentialDeposit = ExistentialDeposit;
 	type AccountStore = System;
-	type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
+	type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;
 }
 
 pub const MICROUNIQUE: Balance = 1_000_000_000;
@@ -410,7 +421,7 @@
 	type DepositPerStorageItem = DepositPerStorageItem;
 	type RentFraction = RentFraction;
 	type SurchargeReward = SurchargeReward;
-	type WeightPrice = pallet_transaction_payment::Module<Self>;
+	type WeightPrice = pallet_transaction_payment::Pallet<Self>;
 	type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;
 	type ChainExtension = NFTExtension;
 	type DeletionQueueDepth = DeletionQueueDepth;
@@ -482,7 +493,7 @@
 	type Burn = Burn;
 	type BurnDestination = ();
 	type SpendFunds = ();
-	type WeightInfo = pallet_treasury::weights::SubstrateWeight<Runtime>;
+	type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;
 	type MaxApprovals = MaxApprovals;
 }
 
@@ -511,7 +522,7 @@
 impl cumulus_pallet_parachain_system::Config for Runtime {
 	type Event = Event;
 	type OnValidationData = ();
-	type SelfParaId = parachain_info::Pallet<Runtime>;
+	type SelfParaId = parachain_info::Pallet<Self>;
 	// type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<
 	// 	MaxDownwardMessageWeight,
 	// 	XcmExecutor<XcmConfig>,
@@ -637,6 +648,10 @@
 	XcmpQueue,
 );
 
+impl pallet_evm_coder_substrate::Config for Runtime {
+	type EthereumTransactionSender = pallet_ethereum::Module<Self>;
+}
+
 impl pallet_xcm::Config for Runtime {
 	type Event = Event;
 	type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
@@ -678,7 +693,7 @@
 /// Used for the pallet nft in `./nft.rs`
 impl pallet_nft::Config for Runtime {
 	type Event = Event;
-	type WeightInfo = nft_weights::WeightInfo;
+	type WeightInfo = pallet_nft::weights::SubstrateWeight<Self>;
 
 	type EvmBackwardsAddressMapping = pallet_nft::MapBackwardsAddressTruncated;
 	type EvmAddressMapping = HashedAddressMapping<Self::Hashing>;
@@ -687,9 +702,6 @@
 	type Currency = Balances;
 	type CollectionCreationPrice = CollectionCreationPrice;
 	type TreasuryAccountId = TreasuryAccountId;
-
-	type EthereumChainId = ChainId;
-	type EthereumTransactionSender = pallet_ethereum::Module<Runtime>;
 }
 
 parameter_types! {
@@ -741,50 +753,76 @@
 	type SponsorshipHandler = SponsorshipHandler;
 }
 
+impl pallet_evm_transaction_payment::Config for Runtime {
+	type SponsorshipHandler = (
+		pallet_nft::NftEthSponsorshipHandler<Self>,
+		pallet_evm_contract_helpers::HelpersContractSponsoring<Self>,
+	);
+	type Currency = Balances;
+}
+
 impl pallet_nft_charge_transaction::Config for Runtime {}
 
-// impl pallet_contract_helpers::Config for Runtime {}
+// impl pallet_contract_helpers::Config for Runtime {
+//	 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
+// }
+
+parameter_types! {
+	// 0x842899ECF380553E8a4de75bF534cdf6fBF64049
+	pub const HelpersContractAddress: H160 = H160([
+		0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,
+	]);
+}
 
+impl pallet_evm_contract_helpers::Config for Runtime {
+	type ContractAddress = HelpersContractAddress;
+	type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
+}
+
 construct_runtime!(
 	pub enum Runtime where
 		Block = Block,
 		NodeBlock = opaque::Block,
 		UncheckedExtrinsic = UncheckedExtrinsic
 	{
-		Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,
-		// Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>},
-		RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Call, Storage},
-		Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
-		TransactionPayment: pallet_transaction_payment::{Pallet, Storage},
-		Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>},
-		Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>},
-		System: system::{Pallet, Call, Storage, Config, Event<T>},
-		Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>},
-
-		ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,
+		ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event<T>} = 20,
 		ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,
 
-		Aura: pallet_aura::{Pallet, Config<T>},
-		AuraExt: cumulus_pallet_aura_ext::{Pallet, Config},
+		Aura: pallet_aura::{Pallet, Config<T>} = 22,
+		AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,
 
-		// Frontier
-		EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>},
-		Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, ValidateUnsigned},
+		Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,
+		RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,
+		Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,
+		TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,
+		Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,
+		Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,
+		System: system::{Pallet, Call, Storage, Config, Event<T>} = 36,
+		Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,
+		// Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,
 
 		// XCM helpers.
 		XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,
 		PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,
 		CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,
 		DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,
-
 
 		// Unique Pallets
-		Inflation: pallet_inflation::{Pallet, Call, Storage},
-		Nft: pallet_nft::{Pallet, Call, Config<T>, Storage, Event<T>},
-		Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event<T>},
-		NftPayment: pallet_nft_transaction_payment::{Pallet, Call, Storage},
-		Charging: pallet_nft_charge_transaction::{Pallet, Call, Storage },
-		// ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage},
+		Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,
+		Nft: pallet_nft::{Pallet, Call, Config<T>, Storage, Event<T>} = 61,
+		Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event<T>} = 62,
+		NftPayment: pallet_nft_transaction_payment::{Pallet, Call, Storage} = 63,
+		Charging: pallet_nft_charge_transaction::{Pallet, Call, Storage } = 64,
+		// ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,
+
+		// Frontier
+		EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,
+		Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, ValidateUnsigned} = 101,
+
+		EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,
+		EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,
+		EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,
+		EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,
 	}
 );
 
@@ -910,8 +948,9 @@
 		fn validate_transaction(
 			source: TransactionSource,
 			tx: <Block as BlockT>::Extrinsic,
+			hash: <Block as BlockT>::Hash,
 		) -> TransactionValidity {
-			Executive::validate_transaction(source, tx)
+			Executive::validate_transaction(source, tx, hash)
 		}
 	}
 
@@ -939,7 +978,7 @@
 		}
 
 		fn author() -> H160 {
-			<pallet_ethereum::Module<Runtime>>::find_author()
+			<pallet_evm::Module<Runtime>>::find_author()
 		}
 
 		fn storage_at(address: H160, index: U256) -> H256 {
@@ -1029,6 +1068,13 @@
 				Ethereum::current_transaction_statuses()
 			)
 		}
+
+		fn extrinsic_filter(xts: Vec<<Block as sp_api::BlockT>::Extrinsic>) -> Vec<pallet_ethereum::Transaction> {
+			xts.into_iter().filter_map(|xt| match xt.function {
+				Call::Ethereum(pallet_ethereum::Call::transact(t)) => Some(t),
+				_ => None
+			}).collect()
+		}
 	}
 
 	impl sp_session::SessionKeys<Block> for Runtime {
@@ -1138,6 +1184,7 @@
 			let mut batches = Vec::<BenchmarkBatch>::new();
 			let params = (&config, &whitelist);
 
+			add_benchmark!(params, batches, pallet_evm_migration, EvmMigration);
 			add_benchmark!(params, batches, pallet_nft, Nft);
 			add_benchmark!(params, batches, pallet_inflation, Inflation);
 
deletedruntime/src/nft_weights.rsdiffbeforeafterboth
--- a/runtime/src/nft_weights.rs
+++ /dev/null
@@ -1,161 +0,0 @@
-//
-// 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;
-impl pallet_nft::WeightInfo for WeightInfo {
-	fn create_collection() -> Weight {
-		70_000_000_u64
-			.saturating_add(DbWeight::get().reads(7_u64))
-			.saturating_add(DbWeight::get().writes(5_u64))
-	}
-	fn destroy_collection() -> Weight {
-		90_000_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(5_u64))
-	}
-	fn add_to_white_list() -> Weight {
-		30_000_000_u64
-			.saturating_add(DbWeight::get().reads(3_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn remove_from_white_list() -> Weight {
-		35_000_000_u64
-			.saturating_add(DbWeight::get().reads(3_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_public_access_mode() -> Weight {
-		27_000_000_u64
-			.saturating_add(DbWeight::get().reads(1_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_mint_permission() -> Weight {
-		27_000_000_u64
-			.saturating_add(DbWeight::get().reads(1_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn change_collection_owner() -> Weight {
-		27_000_000_u64
-			.saturating_add(DbWeight::get().reads(1_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn add_collection_admin() -> Weight {
-		32_000_000_u64
-			.saturating_add(DbWeight::get().reads(3_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn remove_collection_admin() -> Weight {
-		50_000_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_collection_sponsor() -> Weight {
-		32_000_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn confirm_sponsorship() -> Weight {
-		22_000_000_u64
-			.saturating_add(DbWeight::get().reads(1_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn remove_collection_sponsor() -> Weight {
-		24_000_000_u64
-			.saturating_add(DbWeight::get().reads(1_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn create_item(s: usize) -> Weight {
-		130_000_000_u64
-			.saturating_add(2135_u64.saturating_mul(s as Weight).saturating_mul(500_u64)) // 500 is temparary multiplier, fee for storage
-			.saturating_add(DbWeight::get().reads(10_u64))
-			.saturating_add(DbWeight::get().writes(8_u64))
-	}
-	fn burn_item() -> Weight {
-		170_000_000_u64
-			.saturating_add(DbWeight::get().reads(9_u64))
-			.saturating_add(DbWeight::get().writes(7_u64))
-	}
-	fn transfer() -> Weight {
-		125_000_000_u64
-			.saturating_add(DbWeight::get().reads(7_u64))
-			.saturating_add(DbWeight::get().writes(7_u64))
-	}
-	fn approve() -> Weight {
-		45_000_000_u64
-			.saturating_add(DbWeight::get().reads(3_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn transfer_from() -> Weight {
-		150_000_000_u64
-			.saturating_add(DbWeight::get().reads(9_u64))
-			.saturating_add(DbWeight::get().writes(8_u64))
-	}
-	fn set_offchain_schema() -> Weight {
-		33_000_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_const_on_chain_schema() -> Weight {
-		11_100_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_variable_on_chain_schema() -> Weight {
-		11_100_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_variable_meta_data() -> Weight {
-		17_500_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn enable_contract_sponsoring() -> Weight {
-		13_000_000_u64
-			.saturating_add(DbWeight::get().reads(1_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_schema_version() -> Weight {
-		8_500_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_chain_limits() -> Weight {
-		1_300_000_u64
-			.saturating_add(DbWeight::get().reads(0_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-	fn set_contract_sponsoring_rate_limit() -> Weight {
-		3_500_000_u64
-			.saturating_add(DbWeight::get().reads(0_u64))
-			.saturating_add(DbWeight::get().writes(2_u64))
-	}
-	fn set_variable_meta_data_sponsoring_rate_limit() -> Weight {
-		3_500_000_u64
-			.saturating_add(DbWeight::get().reads(1_u64))
-			.saturating_add(DbWeight::get().writes(2_u64))
-	}
-	fn toggle_contract_white_list() -> Weight {
-		3_000_000_u64
-			.saturating_add(DbWeight::get().reads(0_u64))
-			.saturating_add(DbWeight::get().writes(2_u64))
-	}
-	fn add_to_contract_white_list() -> Weight {
-		3_000_000_u64
-			.saturating_add(DbWeight::get().reads(0_u64))
-			.saturating_add(DbWeight::get().writes(2_u64))
-	}
-	fn remove_from_contract_white_list() -> Weight {
-		3_200_000_u64
-			.saturating_add(DbWeight::get().reads(0_u64))
-			.saturating_add(DbWeight::get().writes(2_u64))
-	}
-	fn set_collection_limits() -> Weight {
-		8_900_000_u64
-			.saturating_add(DbWeight::get().reads(2_u64))
-			.saturating_add(DbWeight::get().writes(1_u64))
-	}
-}
modifiedruntime_types.jsondiffbeforeafterboth
--- a/runtime_types.json
+++ b/runtime_types.json
@@ -63,7 +63,8 @@
       "Limits": "CollectionLimits",
       "VariableOnChainSchema": "Vec<u8>",
       "ConstOnChainSchema": "Vec<u8>",
-      "MetaUpdatePermission": "MetaUpdatePermission"
+      "MetaUpdatePermission": "MetaUpdatePermission",
+      "TransfersEnabled": "bool"
     },
     "RawData": "Vec<u8>",
     "Address": "MultiAddress",
modifiedtests/package.jsondiffbeforeafterboth
--- a/tests/package.json
+++ b/tests/package.json
@@ -4,28 +4,28 @@
   "description": "Substrate Nft tests",
   "main": "",
   "devDependencies": {
-    "@polkadot/dev": "0.62.43",
-    "@polkadot/ts": "0.3.89",
-    "@polkadot/typegen": "5.0.1",
+    "@polkadot/dev": "0.62.60",
+    "@polkadot/ts": "0.4.4",
+    "@polkadot/typegen": "5.5.1",
     "@types/chai": "^4.2.17",
     "@types/chai-as-promised": "^7.1.3",
     "@types/mocha": "^8.2.2",
+    "@types/node": "^14.14.12",
+    "@typescript-eslint/eslint-plugin": "^4.28.5",
+    "@typescript-eslint/parser": "^4.28.5",
     "chai": "^4.3.4",
+    "eslint": "^7.31.0",
     "mocha": "^8.3.2",
     "ts-node": "^9.1.1",
     "tslint": "^6.1.3",
-    "typescript": "^4.2.4",
-    "eslint": "^7.28.0",
-    "@types/node": "^14.14.12",
-    "@typescript-eslint/eslint-plugin": "^3.4.0",
-    "@typescript-eslint/parser": "^3.4.0"
+    "typescript": "^4.2.4"
   },
   "scripts": {
     "lint": "eslint --ext .ts,.js src/",
     "fix": "eslint --ext .ts,.js src/ --fix",
-    "test": "mocha --timeout 9999999 -r ts-node/register ./**/*.test.ts",
-    "testEth": "mocha --timeout 9999999 -r ts-node/register ./**/eth/**/*.test.ts",
-    "load": "mocha --timeout 9999999 -r ts-node/register ./**/*.load.ts",
+    "test": "mocha --timeout 9999999 -r ts-node/register './**/*.test.ts'",
+    "testEth": "mocha --timeout 9999999 -r ts-node/register './**/eth/**/*.test.ts'",
+    "load": "mocha --timeout 9999999 -r ts-node/register './**/*.load.ts'",
     "loadTransfer": "ts-node src/transfer.nload.ts",
     "testCollision": "mocha --timeout 9999999 -r ts-node/register ./src/collision-tests/*.test.ts",
     "testAddCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/addCollectionAdmin.test.ts",
@@ -59,16 +59,19 @@
     "testSetVariableMetadataSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setVariableMetadataSponsoringRateLimit.test.ts",
     "testInflation": "mocha --timeout 9999999 -r ts-node/register ./**/inflation.test.ts",
     "testPalletPresence": "mocha --timeout 9999999 -r ts-node/register ./**/pallet-presence.test.ts",
-    "testBlockProduction": "mocha --timeout 9999999 -r ts-node/register ./**/block-production.test.ts"
+    "testBlockProduction": "mocha --timeout 9999999 -r ts-node/register ./**/block-production.test.ts",
+    "testEnableDisableTransfers": "mocha --timeout 9999999 -r ts-node/register ./**/enableDisableTransfer.test.ts"
   },
   "author": "",
   "license": "SEE LICENSE IN ../LICENSE",
   "homepage": "",
   "dependencies": {
-    "@polkadot/api": "5.0.1",
-    "@polkadot/api-contract": "5.0.1",
+    "@polkadot/api": "5.5.1",
+    "@polkadot/api-contract": "5.5.1",
+    "@polkadot/util-crypto": "^7.2.1",
     "bignumber.js": "^9.0.1",
     "chai-as-promised": "^7.1.1",
+    "solc": "^0.8.6",
     "web3": "^1.3.5"
   },
   "standard": {
modifiedtests/src/addCollectionAdmin.test.tsdiffbeforeafterboth
--- a/tests/src/addCollectionAdmin.test.ts
+++ b/tests/src/addCollectionAdmin.test.ts
@@ -117,8 +117,7 @@
       ];
       const collectionId = await createCollectionExpectSuccess();
 
-      const chainLimit = await api.query.nft.chainLimit() as unknown as { CollectionAdminsLimit: BN };
-      const chainAdminLimit = chainLimit.CollectionAdminsLimit.toNumber();
+      const chainAdminLimit = (api.consts.nft.collectionAdminsLimit as any).toNumber();
       expect(chainAdminLimit).to.be.equal(5);
 
       for (let i = 0; i < chainAdminLimit; i++) {
modifiedtests/src/addToWhiteList.test.tsdiffbeforeafterboth
--- a/tests/src/addToWhiteList.test.ts
+++ b/tests/src/addToWhiteList.test.ts
@@ -16,6 +16,8 @@
   enablePublicMintingExpectSuccess,
   enableWhiteListExpectSuccess,
   normalizeAccountId,
+  addCollectionAdminExpectSuccess,
+  addToWhiteListExpectFail,
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -23,6 +25,7 @@
 
 let Alice: IKeyringPair;
 let Bob: IKeyringPair;
+let Charlie: IKeyringPair;
 
 describe('Integration Test ext. addToWhiteList()', () => {
 
@@ -85,3 +88,37 @@
   });
 
 });
+
+describe('Integration Test ext. addToWhiteList() with collection admin permissions:', () => {
+
+  before(async () => {
+    await usingApi(async () => {
+      Alice = privateKey('//Alice');
+      Bob = privateKey('//Bob');
+      Charlie = privateKey('//Charlie');
+    });
+  });
+
+  it('Negative. Add to the white list by regular user', async () => {
+    const collectionId = await createCollectionExpectSuccess();
+    await addToWhiteListExpectFail(Bob, collectionId, Charlie.address);
+  });
+
+  it('Execute the extrinsic with parameters: Collection ID and address to add to the white list', async () => {
+    const collectionId = await createCollectionExpectSuccess();
+    await addCollectionAdminExpectSuccess(Alice, collectionId, Bob);
+    await addToWhiteListExpectSuccess(Bob, collectionId, Charlie.address);
+  });
+
+  it('Whitelisted minting: list restrictions', async () => {
+    const collectionId = await createCollectionExpectSuccess();
+    await addCollectionAdminExpectSuccess(Alice, collectionId, Bob);
+    await addToWhiteListExpectSuccess(Bob, collectionId, Charlie.address);
+
+    // allowed only for collection owner
+    await enableWhiteListExpectSuccess(Alice, collectionId);
+    await enablePublicMintingExpectSuccess(Alice, collectionId);
+
+    await createItemExpectSuccess(Charlie, collectionId, 'NFT', Charlie.address);
+  });
+});
\ No newline at end of file
modifiedtests/src/approve.test.tsdiffbeforeafterboth
--- a/tests/src/approve.test.ts
+++ b/tests/src/approve.test.ts
@@ -16,6 +16,7 @@
   destroyCollectionExpectSuccess,
   setCollectionLimitsExpectSuccess,
   transferExpectSuccess,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -177,3 +178,25 @@
     await approveExpectFail(collectionId, itemId, Alice, Charlie);
   });
 });
+
+describe('Integration Test approve(spender, collection_id, item_id, amount) with collection admin permissions:', () => {
+  let Alice: IKeyringPair;
+  let Bob: IKeyringPair;
+  let Charlie: IKeyringPair;
+
+  before(async () => {
+    await usingApi(async () => {
+      Alice = privateKey('//Alice');
+      Bob = privateKey('//Bob');
+      Charlie = privateKey('//Charlie');
+    });
+  });
+
+  it('can be called by collection admin on non-owned item', async () => {
+    const collectionId = await createCollectionExpectSuccess();
+    const itemId = await createItemExpectSuccess(Alice, collectionId, 'NFT', Alice.address);
+
+    await addCollectionAdminExpectSuccess(Alice, collectionId, Bob);
+    await approveExpectSuccess(collectionId, itemId, Bob, Charlie);
+  });
+});
modifiedtests/src/burnItem.test.tsdiffbeforeafterboth
--- a/tests/src/burnItem.test.ts
+++ b/tests/src/burnItem.test.ts
@@ -12,6 +12,7 @@
   getGenericResult,
   destroyCollectionExpectSuccess,
   normalizeAccountId,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 
 import chai from 'chai';
@@ -48,8 +49,8 @@
       // tslint:disable-next-line:no-unused-expression
       expect(item).to.be.null;
     });
-
   });
+
   it('Burn item in Fungible collection', async () => {
     const createMode = 'Fungible';
     const collectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0 }});
@@ -70,8 +71,8 @@
       expect(balance).to.be.not.null;
       expect(balance.Value).to.be.equal(9);
     });
+  });
 
-  });
   it('Burn item in ReFungible collection', async () => {
     const createMode = 'ReFungible';
     const collectionId = await createCollectionExpectSuccess({mode: {type: createMode }});
@@ -89,7 +90,6 @@
       expect(result.success).to.be.true;
       expect(balance).to.be.null;
     });
-
   });
 
   it('Burn owned portion of item in ReFungible collection', async () => {
@@ -136,6 +136,36 @@
 
 });
 
+describe('integration test: ext. burnItem() with admin permissions:', () => {
+  before(async () => {
+    await usingApi(async () => {
+      const keyring = new Keyring({ type: 'sr25519' });
+      alice = keyring.addFromUri('//Alice');
+      bob = keyring.addFromUri('//Bob');
+    });
+  });
+
+  it('Burn item in NFT collection', async () => {
+    const createMode = 'NFT';
+    const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
+    const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
+    await addCollectionAdminExpectSuccess(alice, collectionId, bob);
+
+    await usingApi(async (api) => {
+      const tx = api.tx.nft.burnItem(collectionId, tokenId, 0);
+      const events = await submitTransactionAsync(bob, tx);
+      const result = getGenericResult(events);
+      // Get the item
+      const item: any = (await api.query.nft.nftItemList(collectionId, tokenId)).toJSON();
+      // What to expect
+      // tslint:disable-next-line:no-unused-expression
+      expect(result.success).to.be.true;
+      // tslint:disable-next-line:no-unused-expression
+      expect(item).to.be.null;
+    });
+  });
+});
+
 describe('Negative integration test: ext. burnItem():', () => {
   before(async () => {
     await usingApi(async () => {
modifiedtests/src/change-collection-owner.test.tsdiffbeforeafterboth
--- a/tests/src/change-collection-owner.test.ts
+++ b/tests/src/change-collection-owner.test.ts
@@ -7,7 +7,22 @@
 import chaiAsPromised from 'chai-as-promised';
 import privateKey from './substrate/privateKey';
 import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api';
-import { createCollectionExpectSuccess } from './util/helpers';
+import { createCollectionExpectSuccess, 
+  addCollectionAdminExpectSuccess,
+  setCollectionSponsorExpectSuccess,
+  confirmSponsorshipExpectSuccess,
+  removeCollectionSponsorExpectSuccess,
+  enableWhiteListExpectSuccess,
+  setMintPermissionExpectSuccess,
+  destroyCollectionExpectSuccess,
+  setCollectionSponsorExpectFailure,
+  confirmSponsorshipExpectFailure,
+  removeCollectionSponsorExpectFailure,
+  enableWhiteListExpectFail,
+  setMintPermissionExpectFailure,
+  destroyCollectionExpectFailure,
+  setPublicAccessModeExpectSuccess,
+} from './util/helpers';
 
 chai.use(chaiAsPromised);
 const expect = chai.expect;
@@ -31,6 +46,97 @@
   });
 });
 
+describe('Integration Test changeCollectionOwner(collection_id, new_owner) special checks for exOwner:', () => {
+  it('Changing the owner of the collection is not allowed for the former owner', async () => {
+    await usingApi(async api => {
+      const collectionId = await createCollectionExpectSuccess();
+      const alice = privateKey('//Alice');
+      const bob = privateKey('//Bob');
+
+      const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      expect(collection.Owner).to.be.deep.eq(alice.address);
+
+      const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
+      await submitTransactionAsync(alice, changeOwnerTx);
+
+      const badChangeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, alice.address);
+      await expect(submitTransactionExpectFailAsync(alice, badChangeOwnerTx)).to.be.rejected;
+
+      const collectionAfterOwnerChange: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      expect(collectionAfterOwnerChange.Owner).to.be.deep.eq(bob.address);
+    });
+  });
+
+  it('New collectionOwner has access to sponsorship management operations in the collection', async () => {
+    await usingApi(async api => {
+      const collectionId = await createCollectionExpectSuccess();
+      const alice = privateKey('//Alice');
+      const bob = privateKey('//Bob');
+      const charlie = privateKey('//Charlie');
+
+      const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      expect(collection.Owner).to.be.deep.eq(alice.address);
+
+      const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
+      await submitTransactionAsync(alice, changeOwnerTx);
+
+      const collectionAfterOwnerChange: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      expect(collectionAfterOwnerChange.Owner).to.be.deep.eq(bob.address);
+
+      // After changing the owner of the collection, all privileged methods are available to the new owner
+      // The new owner of the collection has access to sponsorship management operations in the collection
+      await setCollectionSponsorExpectSuccess(collectionId, charlie.address, '//Bob');
+      await confirmSponsorshipExpectSuccess(collectionId, '//Charlie');
+      await removeCollectionSponsorExpectSuccess(collectionId, '//Bob');
+
+      // The new owner of the collection has access to operations for managing the collection parameters
+      const collectionLimits = {
+        AccountTokenOwnershipLimit: 1,
+        SponsoredMintSize: 1,
+        TokenLimit: 1,
+        SponsorTimeout: 1,
+        OwnerCanTransfer: true,
+        OwnerCanDestroy: true,
+      };
+      const tx1 = api.tx.nft.setCollectionLimits(
+        collectionId,
+        collectionLimits,
+      );
+      await submitTransactionAsync(bob, tx1);
+
+      await setPublicAccessModeExpectSuccess(bob, collectionId, 'WhiteList');
+      await enableWhiteListExpectSuccess(bob, collectionId);
+      await setMintPermissionExpectSuccess(bob, collectionId, true);
+      await destroyCollectionExpectSuccess(collectionId, '//Bob');
+    });
+  });
+
+  it('New collectionOwner has access to changeCollectionOwner', async () => {
+    await usingApi(async api => {
+      const collectionId = await createCollectionExpectSuccess();
+      const alice = privateKey('//Alice');
+      const bob = privateKey('//Bob');
+      const charlie = privateKey('//Charlie');
+  
+      const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      expect(collection.Owner).to.be.deep.eq(alice.address);
+  
+      const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
+      await submitTransactionAsync(alice, changeOwnerTx);
+  
+      const collectionAfterOwnerChange: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      expect(collectionAfterOwnerChange.Owner).to.be.deep.eq(bob.address);
+
+      const changeOwnerTx2 = api.tx.nft.changeCollectionOwner(collectionId, charlie.address);
+      await submitTransactionAsync(bob, changeOwnerTx2);
+  
+      // ownership lost
+      const collectionAfterOwnerChange2: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      expect(collectionAfterOwnerChange2.Owner).to.be.deep.eq(charlie.address);
+    });
+  });
+});
+
 describe('Negative Integration Test changeCollectionOwner(collection_id, new_owner):', () => {
   it('Not owner can\'t change owner.', async () => {
     await usingApi(async api => {
@@ -48,6 +154,26 @@
       await createCollectionExpectSuccess();
     });
   });
+
+  it('Collection admin can\'t change owner.', async () => {
+    await usingApi(async api => {
+      const collectionId = await createCollectionExpectSuccess();
+      const alice = privateKey('//Alice');
+      const bob = privateKey('//Bob');
+
+      await addCollectionAdminExpectSuccess(alice, collectionId, bob);
+
+      const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
+      await expect(submitTransactionExpectFailAsync(bob, changeOwnerTx)).to.be.rejected;
+
+      const collectionAfterOwnerChange: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      expect(collectionAfterOwnerChange.Owner).to.be.deep.eq(alice.address);
+
+      // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
+      await createCollectionExpectSuccess();
+    });
+  });
+
   it('Can\'t change owner of a non-existing collection.', async () => {
     await usingApi(async api => {
       const collectionId = (1<<32) - 1;
@@ -61,4 +187,47 @@
       await createCollectionExpectSuccess();
     });
   });
+
+  it('Former collectionOwner not allowed to sponsorship management operations in the collection', async () => {
+    await usingApi(async api => {
+      const collectionId = await createCollectionExpectSuccess();
+      const alice = privateKey('//Alice');
+      const bob = privateKey('//Bob');
+      const charlie = privateKey('//Charlie');
+
+      const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      expect(collection.Owner).to.be.deep.eq(alice.address);
+
+      const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
+      await submitTransactionAsync(alice, changeOwnerTx);
+
+      const badChangeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, alice.address);
+      await expect(submitTransactionExpectFailAsync(alice, badChangeOwnerTx)).to.be.rejected;
+
+      const collectionAfterOwnerChange: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      expect(collectionAfterOwnerChange.Owner).to.be.deep.eq(bob.address);
+
+      await setCollectionSponsorExpectFailure(collectionId, charlie.address, '//Alice');
+      await confirmSponsorshipExpectFailure(collectionId, '//Alice');
+      await removeCollectionSponsorExpectFailure(collectionId, '//Alice');
+
+      const collectionLimits = {
+        AccountTokenOwnershipLimit: 1,
+        SponsoredMintSize: 1,
+        TokenLimit: 1,
+        SponsorTimeout: 1,
+        OwnerCanTransfer: true,
+        OwnerCanDestroy: true,
+      };
+      const tx1 = api.tx.nft.setCollectionLimits(
+        collectionId,
+        collectionLimits,
+      );
+      await expect(submitTransactionExpectFailAsync(alice, tx1)).to.be.rejected;
+
+      await enableWhiteListExpectFail(alice, collectionId);
+      await setMintPermissionExpectFailure(alice, collectionId, true);
+      await destroyCollectionExpectFailure(collectionId, '//Alice');
+    });
+  });
 });
modifiedtests/src/collision-tests/adminLimitsOff.test.tsdiffbeforeafterboth
--- a/tests/src/collision-tests/adminLimitsOff.test.ts
+++ b/tests/src/collision-tests/adminLimitsOff.test.ts
@@ -34,8 +34,7 @@
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
 
-      const chainLimit = await api.query.nft.chainLimit() as unknown as { CollectionAdminsLimit: BN };
-      const chainAdminLimit = chainLimit.CollectionAdminsLimit.toNumber();
+      const chainAdminLimit = (api.consts.nft.collectionAdminsLimit as any).toNumber();
       expect(chainAdminLimit).to.be.equal(5);
 
       const changeAdminTx1 = api.tx.nft.addCollectionAdmin(collectionId, Eve.address);
modifiedtests/src/config.tsdiffbeforeafterboth
--- a/tests/src/config.ts
+++ b/tests/src/config.ts
@@ -7,6 +7,7 @@
 
 const config = {
   substrateUrl: process.env.substrateUrl || 'ws://127.0.0.1:9944',
+  frontierUrl: process.env.frontierUrl || 'http://127.0.0.1:9933',
 };
 
 export default config;
\ No newline at end of file
modifiedtests/src/confirmSponsorship.test.tsdiffbeforeafterboth
--- a/tests/src/confirmSponsorship.test.ts
+++ b/tests/src/confirmSponsorship.test.ts
@@ -19,6 +19,7 @@
   enablePublicMintingExpectSuccess,
   addToWhiteListExpectSuccess,
   normalizeAccountId,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 import { Keyring } from '@polkadot/api';
 import { IKeyringPair } from '@polkadot/types/types';
@@ -365,6 +366,13 @@
     await confirmSponsorshipExpectFailure(collectionId, '//Alice');
   });
 
+  it('(!negative test!) Confirm sponsorship by collection admin', async () => {
+    const collectionId = await createCollectionExpectSuccess();
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await addCollectionAdminExpectSuccess(alice, collectionId, charlie);
+    await confirmSponsorshipExpectFailure(collectionId, '//Charlie');
+  });
+
   it('(!negative test!) Confirm sponsorship without sponsor being set with setCollectionSponsor', async () => {
     const collectionId = await createCollectionExpectSuccess();
     await confirmSponsorshipExpectFailure(collectionId, '//Bob');
modifiedtests/src/createItem.test.tsdiffbeforeafterboth
--- a/tests/src/createItem.test.ts
+++ b/tests/src/createItem.test.ts
@@ -4,20 +4,25 @@
 //
 
 import { default as usingApi } from './substrate/substrate-api';
+import chai from 'chai';
 import { Keyring } from '@polkadot/api';
 import { IKeyringPair } from '@polkadot/types/types';
 import { 
   createCollectionExpectSuccess, 
   createItemExpectSuccess,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 
+const expect = chai.expect;
 let alice: IKeyringPair;
+let bob: IKeyringPair;
 
 describe('integration test: ext. createItem():', () => {
   before(async () => {
     await usingApi(async () => {
       const keyring = new Keyring({ type: 'sr25519' });
       alice = keyring.addFromUri('//Alice');
+      bob = keyring.addFromUri('//Bob');
     });
   });
 
@@ -36,4 +41,48 @@
     const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
     await createItemExpectSuccess(alice, newCollectionID, createMode);
   });
+  it('Create new item in NFT collection with collection admin permissions', async () => {
+    const createMode = 'NFT';
+    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
+    await addCollectionAdminExpectSuccess(alice, newCollectionID, bob);
+    await createItemExpectSuccess(bob, newCollectionID, createMode);
+  });
+  it('Create new item in Fungible collection with collection admin permissions', async () => {
+    const createMode = 'Fungible';
+    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});
+    await addCollectionAdminExpectSuccess(alice, newCollectionID, bob);
+    await createItemExpectSuccess(bob, newCollectionID, createMode);
+  });
+  it('Create new item in ReFungible collection with collection admin permissions', async () => {
+    const createMode = 'ReFungible';
+    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
+    await addCollectionAdminExpectSuccess(alice, newCollectionID, bob);
+    await createItemExpectSuccess(bob, newCollectionID, createMode);
+  });
+});
+
+describe('Negative integration test: ext. createItem():', () => {
+  before(async () => {
+    await usingApi(async () => {
+      const keyring = new Keyring({ type: 'sr25519' });
+      alice = keyring.addFromUri('//Alice');
+      bob = keyring.addFromUri('//Bob');
+    });
+  });
+
+  it('Regular user cannot create new item in NFT collection', async () => {
+    const createMode = 'NFT';
+    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
+    await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;
+  });
+  it('Regular user cannot create new item in Fungible collection', async () => {
+    const createMode = 'Fungible';
+    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});
+    await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;
+  });
+  it('Regular user cannot create new item in ReFungible collection', async () => {
+    const createMode = 'ReFungible';
+    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
+    await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;
+  });
 });
modifiedtests/src/createMultipleItems.test.tsdiffbeforeafterboth
--- a/tests/src/createMultipleItems.test.ts
+++ b/tests/src/createMultipleItems.test.ts
@@ -3,6 +3,7 @@
 // file 'LICENSE', which is part of this source code package.
 //
 import { ApiPromise } from '@polkadot/api';
+import { IKeyringPair } from '@polkadot/types/types';
 import BN from 'bn.js';
 import chai from 'chai';
 import chaiAsPromised from 'chai-as-promised';
@@ -12,9 +13,11 @@
   createCollectionExpectSuccess,
   destroyCollectionExpectSuccess,
   getGenericResult,
+  IFungibleTokenDataType,
   IReFungibleTokenDataType,
   normalizeAccountId,
   setCollectionLimitsExpectSuccess,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -57,6 +60,26 @@
     });
   });
 
+  it('Create  0x01, 0x02, 0x03 items in active Fungible collection and verify tokens data in chain', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+      const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      expect(itemsListIndexBefore.toNumber()).to.be.equal(0);
+      const Alice = privateKey('//Alice');
+      const args = [
+        {fungible: { value: 1 }},
+        {fungible: { value: 2 }},
+        {fungible: { value: 3 }},
+      ];
+      const createMultipleItemsTx = api.tx.nft
+        .createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);
+      await submitTransactionAsync(Alice, createMultipleItemsTx);
+      const token1Data = (await api.query.nft.fungibleItemList(collectionId, Alice.address) as any).toJSON() as unknown as IFungibleTokenDataType;
+
+      expect(token1Data.Value).to.be.equal(6); // 1 + 2 + 3
+    });
+  });
+
   it('Create  0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {
     await usingApi(async (api: ApiPromise) => {
       const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
@@ -116,11 +139,167 @@
   });
 });
 
+describe('Integration Test createMultipleItems(collection_id, owner, items_data) with collection admin permissions:', () => {
+
+  let Alice: IKeyringPair;
+  let Bob: IKeyringPair;
+
+  before(async () => {
+    await usingApi(async () => {
+      Alice = privateKey('//Alice');
+      Bob = privateKey('//Bob');
+    });
+  });
+
+  it('Create  0x31, 0x32, 0x33 items in active NFT collection and verify tokens data in chain', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      expect(itemsListIndexBefore.toNumber()).to.be.equal(0);
+      await addCollectionAdminExpectSuccess(Alice, collectionId, Bob); 
+      const args = [{ nft: ['0x31', '0x31'] }, { nft: ['0x32', '0x32'] }, { nft: ['0x33', '0x33'] }];
+      const createMultipleItemsTx = api.tx.nft
+        .createMultipleItems(collectionId, normalizeAccountId(Bob.address), args);
+      await submitTransactionAsync(Bob, createMultipleItemsTx);
+      const itemsListIndexAfter = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      expect(itemsListIndexAfter.toNumber()).to.be.equal(3);
+      const token1Data = (await api.query.nft.nftItemList(collectionId, 1)).toJSON() as unknown as ITokenDataType;
+      const token2Data = (await api.query.nft.nftItemList(collectionId, 2)).toJSON() as unknown as ITokenDataType;
+      const token3Data = (await api.query.nft.nftItemList(collectionId, 3)).toJSON() as unknown as ITokenDataType;
+
+      expect(token1Data.Owner).to.be.deep.equal(normalizeAccountId(Bob.address));
+      expect(token2Data.Owner).to.be.deep.equal(normalizeAccountId(Bob.address));
+      expect(token3Data.Owner).to.be.deep.equal(normalizeAccountId(Bob.address));
+
+      expect(token1Data.ConstData.toString()).to.be.equal('0x31');
+      expect(token2Data.ConstData.toString()).to.be.equal('0x32');
+      expect(token3Data.ConstData.toString()).to.be.equal('0x33');
+
+      expect(token1Data.VariableData.toString()).to.be.equal('0x31');
+      expect(token2Data.VariableData.toString()).to.be.equal('0x32');
+      expect(token3Data.VariableData.toString()).to.be.equal('0x33');
+    });
+  });
+
+  it('Create  0x01, 0x02, 0x03 items in active Fungible collection and verify tokens data in chain', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+      const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      expect(itemsListIndexBefore.toNumber()).to.be.equal(0);
+      await addCollectionAdminExpectSuccess(Alice, collectionId, Bob); 
+      const args = [
+        {fungible: { value: 1 }},
+        {fungible: { value: 2 }},
+        {fungible: { value: 3 }},
+      ];
+      const createMultipleItemsTx = api.tx.nft
+        .createMultipleItems(collectionId, normalizeAccountId(Bob.address), args);
+      await submitTransactionAsync(Bob, createMultipleItemsTx);
+      const token1Data = (await api.query.nft.fungibleItemList(collectionId, Bob.address) as any).toJSON() as unknown as IFungibleTokenDataType;
+
+      expect(token1Data.Value).to.be.equal(6); // 1 + 2 + 3
+    });
+  });
+
+  it('Create  0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+      const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      expect(itemsListIndexBefore.toNumber()).to.be.equal(0);
+      await addCollectionAdminExpectSuccess(Alice, collectionId, Bob); 
+      const args = [
+        {refungible: {const_data: [0x31], variable_data: [0x31], pieces: 1}},
+        {refungible: {const_data: [0x32], variable_data: [0x32], pieces: 1}},
+        {refungible: {const_data: [0x33], variable_data: [0x33], pieces: 1}},
+      ];
+      const createMultipleItemsTx = api.tx.nft
+        .createMultipleItems(collectionId, normalizeAccountId(Bob.address), args);
+      await submitTransactionAsync(Bob, createMultipleItemsTx);
+      const itemsListIndexAfter = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      expect(itemsListIndexAfter.toNumber()).to.be.equal(3);
+      const token1Data = (await api.query.nft.reFungibleItemList(collectionId, 1) as any).toJSON() as unknown as IReFungibleTokenDataType;
+      const token2Data = (await api.query.nft.reFungibleItemList(collectionId, 2) as any).toJSON() as unknown as IReFungibleTokenDataType;
+      const token3Data = (await api.query.nft.reFungibleItemList(collectionId, 3) as any).toJSON() as unknown as IReFungibleTokenDataType;
+
+      expect(token1Data.Owner[0].Owner).to.be.deep.equal(normalizeAccountId(Bob.address));
+      expect(token1Data.Owner[0].Fraction).to.be.equal(1);
+
+      expect(token2Data.Owner[0].Owner).to.be.deep.equal(normalizeAccountId(Bob.address));
+      expect(token2Data.Owner[0].Fraction).to.be.equal(1);
+
+      expect(token3Data.Owner[0].Owner).to.be.deep.equal(normalizeAccountId(Bob.address));
+      expect(token3Data.Owner[0].Fraction).to.be.equal(1);
+
+      expect(token1Data.ConstData.toString()).to.be.equal('0x31');
+      expect(token2Data.ConstData.toString()).to.be.equal('0x32');
+      expect(token3Data.ConstData.toString()).to.be.equal('0x33');
+
+      expect(token1Data.VariableData.toString()).to.be.equal('0x31');
+      expect(token2Data.VariableData.toString()).to.be.equal('0x32');
+      expect(token3Data.VariableData.toString()).to.be.equal('0x33');
+    });
+  });
+});
+
 describe('Negative Integration Test createMultipleItems(collection_id, owner, items_data):', () => {
+
+  let Alice: IKeyringPair;
+  let Bob: IKeyringPair;
+
+  before(async () => {
+    await usingApi(async () => {
+      Alice = privateKey('//Alice');
+      Bob = privateKey('//Bob');
+    });
+  });
+
+  it('Regular user cannot create items in active NFT collection', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      expect(itemsListIndexBefore.toNumber()).to.be.equal(0);
+      const args = [{ nft: ['0x31', '0x31'] }, { nft: ['0x32', '0x32'] }, { nft: ['0x33', '0x33'] }];
+      const createMultipleItemsTx = api.tx.nft
+        .createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);
+      await expect(submitTransactionAsync(Bob, createMultipleItemsTx)).to.be.rejected;
+    });
+  });
+
+  it('Regular user cannot create items in active Fungible collection', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+      const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      expect(itemsListIndexBefore.toNumber()).to.be.equal(0);
+      const args = [
+        {fungible: { value: 1 }},
+        {fungible: { value: 2 }},
+        {fungible: { value: 3 }},
+      ];
+      const createMultipleItemsTx = api.tx.nft
+        .createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);
+      await expect(submitTransactionAsync(Bob, createMultipleItemsTx)).to.be.rejected;
+    });
+  });
+
+  it('Regular user cannot create items in active ReFungible collection', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+      const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      expect(itemsListIndexBefore.toNumber()).to.be.equal(0);
+      const args = [
+        {refungible: {const_data: [0x31], variable_data: [0x31], pieces: 1}},
+        {refungible: {const_data: [0x32], variable_data: [0x32], pieces: 1}},
+        {refungible: {const_data: [0x33], variable_data: [0x33], pieces: 1}},
+      ];
+      const createMultipleItemsTx = api.tx.nft
+        .createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);
+      await expect(submitTransactionAsync(Bob, createMultipleItemsTx)).to.be.rejected;
+    });
+  });
+
   it('Create token with not existing type', async () => {
     await usingApi(async (api: ApiPromise) => {
       const collectionId = await createCollectionExpectSuccess();
-      const Alice = privateKey('//Alice');
       try {
         const args = [{ invalid: null }, { invalid: null }, { invalid: null }];
         const createMultipleItemsTx = await api.tx.nft
@@ -136,7 +315,6 @@
   it('Create token in not existing collection', async () => {
     await usingApi(async (api: ApiPromise) => {
       const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;
-      const Alice = privateKey('//Alice');
       const createMultipleItemsTx = api.tx.nft
         .createMultipleItems(collectionId, normalizeAccountId(Alice.address), ['NFT', 'NFT', 'NFT']);
       await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;
@@ -174,7 +352,6 @@
   it('Create tokens with different types', async () => {
     await usingApi(async (api: ApiPromise) => {
       const collectionId = await createCollectionExpectSuccess();
-      const Alice = privateKey('//Alice');
       const createMultipleItemsTx = api.tx.nft
         .createMultipleItems(collectionId, normalizeAccountId(Alice.address), ['NFT', 'Fungible', 'ReFungible']);
       await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;
@@ -186,7 +363,6 @@
   it('Create tokens with different data limits <> maximum data limit', async () => {
     await usingApi(async (api: ApiPromise) => {
       const collectionId = await createCollectionExpectSuccess();
-      const Alice = privateKey('//Alice');
       const args = [
         { nft: ['A', 'A'] },
         { nft: ['B', 'B'.repeat(2049)] },
@@ -200,18 +376,17 @@
 
   it('Fails when minting tokens exceeds collectionLimits amount', async () => {
     await usingApi(async (api) => {
-      const alice = privateKey('//Alice');
 
       const collectionId = await createCollectionExpectSuccess();
-      await setCollectionLimitsExpectSuccess(alice, collectionId, {
+      await setCollectionLimitsExpectSuccess(Alice, collectionId, {
         TokenLimit: 1,
       });
       const args = [
         { nft: ['A', 'A'] },
         { nft: ['B', 'B'] },
       ];
-      const createMultipleItemsTx = api.tx.nft.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
-      await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;
+      const createMultipleItemsTx = api.tx.nft.createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);
+      await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;
     });
   });
 });
modifiedtests/src/destroyCollection.test.tsdiffbeforeafterboth
--- a/tests/src/destroyCollection.test.ts
+++ b/tests/src/destroyCollection.test.ts
@@ -8,7 +8,12 @@
 import chaiAsPromised from 'chai-as-promised';
 import privateKey from './substrate/privateKey';
 import { default as usingApi } from './substrate/substrate-api';
-import { createCollectionExpectSuccess, destroyCollectionExpectSuccess, destroyCollectionExpectFailure, setCollectionLimitsExpectSuccess } from './util/helpers';
+import { createCollectionExpectSuccess, 
+  destroyCollectionExpectSuccess, 
+  destroyCollectionExpectFailure, 
+  setCollectionLimitsExpectSuccess,
+  addCollectionAdminExpectSuccess,
+} from './util/helpers';
 
 chai.use(chaiAsPromised);
 
@@ -29,10 +34,12 @@
 
 describe('(!negative test!) integration test: ext. destroyCollection():', () => {
   let alice: IKeyringPair;
+  let bob: IKeyringPair;
 
   before(async () => {
     await usingApi(async () => {
       alice = privateKey('//Alice');
+      bob = privateKey('//Bob');
     });
   });
 
@@ -53,6 +60,11 @@
     await destroyCollectionExpectFailure(collectionId, '//Bob');
     await destroyCollectionExpectSuccess(collectionId, '//Alice');
   });
+  it('(!negative test!) Destroy a collection using collection admin account', async () => {
+    const collectionId = await createCollectionExpectSuccess();
+    await addCollectionAdminExpectSuccess(alice, collectionId, bob);
+    await destroyCollectionExpectFailure(collectionId, '//Bob');
+  });
   it('fails when OwnerCanDestroy == false', async () => {
     const collectionId = await createCollectionExpectSuccess();
     await setCollectionLimitsExpectSuccess(alice, collectionId, { OwnerCanDestroy: false });
addedtests/src/enableDisableTransfer.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/enableDisableTransfer.test.ts
@@ -0,0 +1,64 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import privateKey from './substrate/privateKey';
+import usingApi from './substrate/substrate-api';
+import {
+  createItemExpectSuccess,
+  createCollectionExpectSuccess,
+  transferExpectSuccess,
+  transferExpectFailure,
+  setTransferFlagExpectSuccess,
+  setTransferFlagExpectFailure,
+} from './util/helpers';
+
+chai.use(chaiAsPromised);
+
+describe('Enable/Disable Transfers', () => {
+  it('User can transfer token with enabled transfer flag', async () => {
+    await usingApi(async () => {
+      const Alice = privateKey('//Alice');
+      const Bob = privateKey('//Bob');
+      // nft
+      const nftCollectionId = await createCollectionExpectSuccess();
+      const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
+
+      // explicitely set transfer flag
+      await setTransferFlagExpectSuccess(Alice, nftCollectionId, true);
+
+      await transferExpectSuccess(nftCollectionId, newNftTokenId, Alice, Bob, 1);
+    });
+  });
+
+  it('User can\'n transfer token with disabled transfer flag', async () => {
+    await usingApi(async () => {
+      const Alice = privateKey('//Alice');
+      const Bob = privateKey('//Bob');
+      // nft
+      const nftCollectionId = await createCollectionExpectSuccess();
+      const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
+
+      // explicitely set transfer flag
+      await setTransferFlagExpectSuccess(Alice, nftCollectionId, false);
+
+      await transferExpectFailure(nftCollectionId, newNftTokenId, Alice, Bob, 1);
+    });
+  });
+});
+
+describe('Negative Enable/Disable Transfers', () => {
+  it('Non-owner cannot change transfer flag', async () => {
+    await usingApi(async () => {
+      const Bob = privateKey('//Bob');
+      // nft
+      const nftCollectionId = await createCollectionExpectSuccess();
+
+      // Change transfer flag
+      await setTransferFlagExpectFailure(Bob, nftCollectionId, false);
+    });
+  });
+});
addedtests/src/eth/allowlist.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/allowlist.test.ts
@@ -0,0 +1,61 @@
+import { expect } from 'chai';
+import waitNewBlocks from '../substrate/wait-new-blocks';
+import { contractHelpers, createEthAccount, createEthAccountWithBalance, deployFlipper, itWeb3, usingWeb3Http } from './util/helpers';
+
+describe('EVM allowlist', () => {
+  itWeb3('Contract allowlist can be toggled', async ({ api }) => {
+    await usingWeb3Http(async web3Http => {
+      const owner = await createEthAccountWithBalance(api, web3Http);
+      const flipper = await deployFlipper(web3Http, owner);
+      await waitNewBlocks(api, 1);
+      const randomUser = createEthAccount(web3Http);
+
+      const helpers = contractHelpers(web3Http, owner);
+
+      // Any user is allowed by default
+      expect(await helpers.methods.allowlistEnabled(flipper.options.address).call()).to.be.false;
+      expect(await helpers.methods.allowed(flipper.options.address, randomUser).call()).to.be.true;
+      await waitNewBlocks(api, 1);
+
+      // Enable
+      await helpers.methods.toggleAllowlist(flipper.options.address, true).send({ from: owner });
+      await waitNewBlocks(api, 1);
+      expect(await helpers.methods.allowlistEnabled(flipper.options.address).call()).to.be.true;
+      expect(await helpers.methods.allowed(flipper.options.address, randomUser).call()).to.be.false;
+
+      // Disable
+      await helpers.methods.toggleAllowlist(flipper.options.address, false).send({ from: owner });
+      await waitNewBlocks(api, 1);
+      expect(await helpers.methods.allowlistEnabled(flipper.options.address).call()).to.be.false;
+      expect(await helpers.methods.allowed(flipper.options.address, randomUser).call()).to.be.true;
+    });
+  });
+
+  itWeb3('Non-whitelisted user can\'t call contract with allowlist enabled', async ({ api }) => {
+    await usingWeb3Http(async web3Http => {
+      const owner = await createEthAccountWithBalance(api, web3Http);
+      const flipper = await deployFlipper(web3Http, owner);
+      await waitNewBlocks(api, 1);
+      const caller = await createEthAccountWithBalance(api, web3Http);
+
+      const helpers = contractHelpers(web3Http, owner);
+
+      // User can flip with allowlist disabled
+      await flipper.methods.flip().send({ from: caller });
+      await waitNewBlocks(api, 1);
+      expect(await flipper.methods.getValue().call()).to.be.true;
+
+      // Tx will be reverted if user is not in whitelist
+      await helpers.methods.toggleAllowlist(flipper.options.address, true).send({ from: owner });
+      await expect(flipper.methods.flip().send({ from: caller })).to.rejected;
+      await waitNewBlocks(api, 1);
+      expect(await flipper.methods.getValue().call()).to.be.true;
+
+      // Adding caller to allowlist will make contract callable again
+      await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});
+      await flipper.methods.flip().send({ from: caller });
+      await waitNewBlocks(api, 1);
+      expect(await flipper.methods.getValue().call()).to.be.false;
+    });
+  });
+});
\ No newline at end of file
addedtests/src/eth/api/ContractHelpers.soldiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/api/ContractHelpers.sol
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: OTHER
+// This code is automatically generated
+
+pragma solidity >=0.8.0 <0.9.0;
+
+// Common stubs holder
+interface Dummy {
+
+}
+
+interface ContractHelpers is Dummy {
+	function contractOwner(address contractAddress)
+		external
+		view
+		returns (address);
+
+	function sponsoringEnabled(address contractAddress)
+		external
+		view
+		returns (bool);
+
+	function toggleSponsoring(address contractAddress, bool enabled) external;
+
+	function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)
+		external;
+
+	function allowed(address contractAddress, address user)
+		external
+		view
+		returns (bool);
+
+	function allowlistEnabled(address contractAddress)
+		external
+		view
+		returns (bool);
+
+	function toggleAllowlist(address contractAddress, bool enabled) external;
+
+	function toggleAllowed(
+		address contractAddress,
+		address user,
+		bool allowed
+	) external;
+}
addedtests/src/eth/api/UniqueFungible.soldiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: OTHER
+// This code is automatically generated
+
+pragma solidity >=0.8.0 <0.9.0;
+
+// Common stubs holder
+interface Dummy {
+
+}
+
+// Inline
+interface ERC20Events {
+	event Transfer(address indexed from, address indexed to, uint256 value);
+	event Approval(
+		address indexed owner,
+		address indexed spender,
+		uint256 value
+	);
+}
+
+// Inline
+interface InlineNameSymbol is Dummy {
+	function name() external view returns (string memory);
+
+	function symbol() external view returns (string memory);
+}
+
+// Inline
+interface InlineTotalSupply is Dummy {
+	function totalSupply() external view returns (uint256);
+}
+
+interface ERC165 is Dummy {
+	function supportsInterface(uint32 interfaceId) external view returns (bool);
+}
+
+interface ERC20 is Dummy, InlineNameSymbol, InlineTotalSupply, ERC20Events {
+	function decimals() external view returns (uint8);
+
+	function balanceOf(address owner) external view returns (uint256);
+
+	function transfer(address to, uint256 amount) external returns (bool);
+
+	function transferFrom(
+		address from,
+		address to,
+		uint256 amount
+	) external returns (bool);
+
+	function approve(address spender, uint256 amount) external returns (bool);
+
+	function allowance(address owner, address spender)
+		external
+		view
+		returns (uint256);
+}
+
+interface UniqueFungible is Dummy, ERC165, ERC20 {}
addedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: OTHER
+// This code is automatically generated
+
+pragma solidity >=0.8.0 <0.9.0;
+
+// Common stubs holder
+interface Dummy {
+
+}
+
+// Inline
+interface ERC721Events {
+	event Transfer(
+		address indexed from,
+		address indexed to,
+		uint256 indexed tokenId
+	);
+	event Approval(
+		address indexed owner,
+		address indexed approved,
+		uint256 indexed tokenId
+	);
+	event ApprovalForAll(
+		address indexed owner,
+		address indexed operator,
+		bool approved
+	);
+}
+
+// Inline
+interface ERC721MintableEvents {
+	event MintingFinished();
+}
+
+// Inline
+interface InlineNameSymbol is Dummy {
+	function name() external view returns (string memory);
+
+	function symbol() external view returns (string memory);
+}
+
+// Inline
+interface InlineTotalSupply is Dummy {
+	function totalSupply() external view returns (uint256);
+}
+
+interface ERC165 is Dummy {
+	function supportsInterface(uint32 interfaceId) external view returns (bool);
+}
+
+interface ERC721 is Dummy, ERC165, ERC721Events {
+	function balanceOf(address owner) external view returns (uint256);
+
+	function ownerOf(uint256 tokenId) external view returns (address);
+
+	function safeTransferFromWithData(
+		address from,
+		address to,
+		uint256 tokenId,
+		bytes memory data
+	) external;
+
+	function safeTransferFrom(
+		address from,
+		address to,
+		uint256 tokenId
+	) external;
+
+	function transferFrom(
+		address from,
+		address to,
+		uint256 tokenId
+	) external;
+
+	function approve(address approved, uint256 tokenId) external;
+
+	function setApprovalForAll(address operator, bool approved) external;
+
+	function getApproved(uint256 tokenId) external view returns (address);
+
+	function isApprovedForAll(address owner, address operator)
+		external
+		view
+		returns (address);
+}
+
+interface ERC721Burnable is Dummy {
+	function burn(uint256 tokenId) external;
+}
+
+interface ERC721Enumerable is Dummy, InlineTotalSupply {
+	function tokenByIndex(uint256 index) external view returns (uint256);
+
+	function tokenOfOwnerByIndex(address owner, uint256 index)
+		external
+		view
+		returns (uint256);
+}
+
+interface ERC721Metadata is Dummy, InlineNameSymbol {
+	function tokenURI(uint256 tokenId) external view returns (string memory);
+}
+
+interface ERC721Mintable is Dummy, ERC721MintableEvents {
+	function mintingFinished() external view returns (bool);
+
+	function mint(address to, uint256 tokenId) external returns (bool);
+
+	function mintWithTokenURI(
+		address to,
+		uint256 tokenId,
+		string memory tokenUri
+	) external returns (bool);
+
+	function finishMinting() external returns (bool);
+}
+
+interface ERC721UniqueExtensions is Dummy {
+	function transfer(address to, uint256 tokenId) external;
+
+	function nextTokenId() external view returns (uint256);
+}
+
+interface UniqueNFT is
+	Dummy,
+	ERC165,
+	ERC721,
+	ERC721Metadata,
+	ERC721Enumerable,
+	ERC721UniqueExtensions,
+	ERC721Mintable,
+	ERC721Burnable
+{}
addedtests/src/eth/base.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/base.test.ts
@@ -0,0 +1,22 @@
+
+import { createEthAccount, createEthAccountWithBalance, deployFlipper, ethBalanceViaSub, GAS_ARGS, itWeb3, recordEthFee } from './util/helpers';
+import { expect } from 'chai';
+import { UNIQUE } from '../util/helpers';
+
+describe('Contract calls', () => {
+  itWeb3('Call of simple contract fee is less than 0.2 UNQ', async ({ web3, api }) => {
+    const deployer = await createEthAccountWithBalance(api, web3);
+    const flipper = await deployFlipper(web3 as any, deployer);
+
+    const cost = await recordEthFee(api, deployer, () => flipper.methods.flip().send({from: deployer}));
+    expect(cost < BigInt(0.2 * Number(UNIQUE))).to.be.true;
+  });
+
+  itWeb3('Balance transfer fee is less than 0.2 UNQ', async ({ web3, api }) => {
+    const userA = await createEthAccountWithBalance(api, web3);
+    const userB = createEthAccount(web3);
+
+    const cost = await recordEthFee(api, userA, () => web3.eth.sendTransaction({ from: userA, to: userB, value: '1000000', ...GAS_ARGS }));
+    expect(cost - await ethBalanceViaSub(api, userB) < BigInt(0.2 * Number(UNIQUE))).to.be.true;
+  });
+});
\ No newline at end of file
addedtests/src/eth/crossTransfer.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/crossTransfer.test.ts
@@ -0,0 +1,88 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import privateKey from '../substrate/privateKey';
+import { createCollectionExpectSuccess, 
+  createFungibleItemExpectSuccess, 
+  transferExpectSuccess, 
+  transferFromExpectSuccess, 
+  createItemExpectSuccess } from '../util/helpers';
+import { collectionIdToAddress, 
+  createEthAccountWithBalance, 
+  subToEth,
+  GAS_ARGS, itWeb3 } from './util/helpers';
+import fungibleAbi from './fungibleAbi.json';
+import nonFungibleAbi from './nonFungibleAbi.json';
+
+describe('Token transfer between substrate address and EVM address. Fungible', () => {
+  itWeb3('The private key X create a substrate address. Alice sends a token to the corresponding EVM address, and X can send it to Bob in the substrate', async () => {
+    const collection = await createCollectionExpectSuccess({
+      name: 'token name',
+      mode: { type: 'Fungible', decimalPoints: 0 },
+    });
+    const alice = privateKey('//Alice');
+    const bob = privateKey('//Bob');
+    const charlie = privateKey('//Charlie');
+    await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { substrate: alice.address });
+    await transferExpectSuccess(collection, 0, alice, {ethereum: subToEth(charlie.address)} , 200, 'Fungible');
+    await transferFromExpectSuccess(collection, 0, alice, {ethereum: subToEth(charlie.address)}, charlie, 50, 'Fungible');
+    await transferExpectSuccess(collection, 0, charlie, bob, 50, 'Fungible');
+  });
+
+  itWeb3('The private key X create a EVM address. Alice sends a token to the substrate address corresponding to this EVM address, and X can send it to Bob in the EVM', async ({ api, web3 }) => {
+    const collection = await createCollectionExpectSuccess({
+      name: 'token name',
+      mode: { type: 'Fungible', decimalPoints: 0 },
+    });
+    const alice = privateKey('//Alice');
+    const bob = privateKey('//Bob');
+    const bobProxy = await createEthAccountWithBalance(api, web3);
+    const aliceProxy = await createEthAccountWithBalance(api, web3);
+
+    await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, alice.address);
+    await transferExpectSuccess(collection, 0, alice, { ethereum: aliceProxy } , 200, 'Fungible');
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: aliceProxy, ...GAS_ARGS});
+
+    await contract.methods.transfer(bobProxy, 50).send({ from: aliceProxy });
+    await transferFromExpectSuccess(collection, 0, alice, {ethereum: bobProxy}, bob, 50, 'Fungible');
+    await transferExpectSuccess(collection, 0, bob, alice, 50, 'Fungible');
+  });
+});
+
+describe('Token transfer between substrate address and EVM address. NFT', () => {
+  itWeb3('The private key X create a substrate address. Alice sends a token to the corresponding EVM address, and X can send it to Bob in the substrate', async () => {
+    const collection = await createCollectionExpectSuccess({
+      name: 'token name',
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+    const bob = privateKey('//Bob');
+    const charlie = privateKey('//Charlie');
+    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { substrate: alice.address });
+    await transferExpectSuccess(collection, tokenId, alice, { ethereum: subToEth(charlie.address) }, 1, 'NFT');
+    await transferFromExpectSuccess(collection, tokenId, alice, {ethereum: subToEth(charlie.address)}, charlie, 1, 'NFT');
+    await transferExpectSuccess(collection, tokenId, charlie, bob, 1, 'NFT');
+  });
+
+  itWeb3('The private key X create a EVM address. Alice sends a token to the substrate address corresponding to this EVM address, and X can send it to Bob in the EVM', async ({ api, web3 }) => {
+    const collection = await createCollectionExpectSuccess({
+      name: 'token name',
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+    const bob = privateKey('//Bob');
+    const charlie = privateKey('//Charlie');
+    const bobProxy = await createEthAccountWithBalance(api, web3);
+    const aliceProxy = await createEthAccountWithBalance(api, web3);
+    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { substrate: alice.address });
+    await transferExpectSuccess(collection, tokenId, alice, { ethereum: aliceProxy } , 1, 'NFT');
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: aliceProxy, ...GAS_ARGS});
+    await contract.methods.transfer(bobProxy, 1).send({ from: aliceProxy });
+    await transferFromExpectSuccess(collection, tokenId, alice, {ethereum: bobProxy}, bob, 1, 'NFT');
+    await transferExpectSuccess(collection, tokenId, bob, charlie, 1, 'NFT');
+  });
+});
\ No newline at end of file
modifiedtests/src/eth/fungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/fungible.test.ts
+++ b/tests/src/eth/fungible.test.ts
@@ -4,48 +4,51 @@
 //
 
 import privateKey from '../substrate/privateKey';
-import { approveExpectSuccess, createCollectionExpectSuccess, createFungibleItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess } from '../util/helpers';
-import { collectionIdToAddress, createEthAccount, itWeb3, normalizeEvents, recordEvents, subToEth, transferBalanceToEth } from './util/helpers';
+import { approveExpectSuccess, createCollectionExpectSuccess, createFungibleItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE } from '../util/helpers';
+import { collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth } from './util/helpers';
 import fungibleAbi from './fungibleAbi.json';
 import { expect } from 'chai';
 
-describe('Information getting', () => {
-  itWeb3('totalSupply', async ({ web3 }) => {
+describe('Fungible: Information getting', () => {
+  itWeb3('totalSupply', async ({ api, web3 }) => {
     const collection = await createCollectionExpectSuccess({
       name: 'token name',
       mode: { type: 'Fungible', decimalPoints: 0 },
     });
     const alice = privateKey('//Alice');
 
+    const caller = await createEthAccountWithBalance(api, web3);
+  
     await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { substrate: alice.address });
 
     const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(fungibleAbi as any, address);
+    const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS});
     const totalSupply = await contract.methods.totalSupply().call();
 
     // FIXME: always equals to 0, because this method is not implemented
     expect(totalSupply).to.equal('0');
   });
 
-  itWeb3('balanceOf', async ({ web3 }) => {
+  itWeb3('balanceOf', async ({ api, web3 }) => {
     const collection = await createCollectionExpectSuccess({
       name: 'token name',
       mode: { type: 'Fungible', decimalPoints: 0 },
     });
     const alice = privateKey('//Alice');
 
-    const caller = createEthAccount(web3);
+    const caller = await createEthAccountWithBalance(api, web3);
+
     await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: caller });
 
     const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(fungibleAbi as any, address);
+    const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS});
     const balance = await contract.methods.balanceOf(caller).call();
 
     expect(balance).to.equal('200');
   });
 });
 
-describe('Plain calls', () => {
+describe('Fungible: Plain calls', () => {
   itWeb3('Can perform approve()', async ({ web3, api }) => {
     const collection = await createCollectionExpectSuccess({
       name: 'token name',
@@ -53,18 +56,17 @@
     });
     const alice = privateKey('//Alice');
 
-    const owner = createEthAccount(web3);
-    await transferBalanceToEth(api, alice, owner, 999999999999999);
+    const owner = await createEthAccountWithBalance(api, web3);
 
     await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: owner });
 
     const spender = createEthAccount(web3);
 
     const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(fungibleAbi as any, address);
+    const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});
 
     {
-      const result = await contract.methods.approve(spender, 100).send({ from: owner, gas: '0x1000000', gasPrice: '0x01' });
+      const result = await contract.methods.approve(spender, 100).send({from: owner});
       const events = normalizeEvents(result.events);
 
       expect(events).to.be.deep.equal([
@@ -104,12 +106,12 @@
     const receiver = createEthAccount(web3);
 
     const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(fungibleAbi as any, address);
+    const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});
 
-    await contract.methods.approve(spender, 100).send({ from: owner, gas: '0x1000000', gasPrice: '0x01' });
+    await contract.methods.approve(spender, 100).send();
 
     {
-      const result = await contract.methods.transferFrom(owner, receiver, 49).send({ from: spender, gas: '0x1000000', gasPrice: '0x01' });
+      const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: spender});
       const events = normalizeEvents(result.events);
       expect(events).to.be.deep.equal([
         {
@@ -160,10 +162,10 @@
     await transferBalanceToEth(api, alice, receiver, 999999999999999);
 
     const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(fungibleAbi as any, address);
+    const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});
 
     {
-      const result = await contract.methods.transfer(receiver, 50).send({ from: owner, gas: '0x1000000', gasPrice: '0x01' });
+      const result = await contract.methods.transfer(receiver, 50).send({ from: owner});
       const events = normalizeEvents(result.events);
       expect(events).to.be.deep.equal([
         {
@@ -190,7 +192,65 @@
   });
 });
 
-describe('Substrate calls', () => {
+describe('Fungible: Fees', () => {
+  itWeb3('approve() call fee is less than 0.2UNQ', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'Fungible', decimalPoints: 0 },
+    });
+    const alice = privateKey('//Alice');
+
+    const owner = await createEthAccountWithBalance(api, web3);
+    const spender = createEthAccount(web3);
+
+    await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: owner });
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(fungibleAbi as any, address, { from: owner, ...GAS_ARGS });
+
+    const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, 100).send({ from: owner }));
+    expect(cost < BigInt(0.2 * Number(UNIQUE)));
+  });
+
+  itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: {type: 'Fungible', decimalPoints: 0},
+    });
+    const alice = privateKey('//Alice');
+  
+    const owner = await createEthAccountWithBalance(api, web3);
+    const spender = await createEthAccountWithBalance(api, web3);
+
+    await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: owner });
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(fungibleAbi as any, address, { from: owner, ...GAS_ARGS });
+
+    await contract.methods.approve(spender, 100).send({ from: owner });
+
+    const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, 100).send({ from: spender }));
+    expect(cost < BigInt(0.2 * Number(UNIQUE)));
+  });
+
+  itWeb3('transfer() call fee is less than 0.2UNQ', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'Fungible', decimalPoints: 0 },
+    });
+    const alice = privateKey('//Alice');
+
+    const owner = await createEthAccountWithBalance(api, web3);
+    const receiver = createEthAccount(web3);
+
+    await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: owner });
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(fungibleAbi as any, address, { from: owner, ...GAS_ARGS });
+
+    const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, 100).send({ from: owner }));
+    expect(cost < BigInt(0.2 * Number(UNIQUE)));
+  });
+});
+
+describe('Fungible: Substrate calls', () => {
   itWeb3('Events emitted for approve()', async ({ web3 }) => {
     const collection = await createCollectionExpectSuccess({
       mode: { type: 'Fungible', decimalPoints: 0 },
addedtests/src/eth/helpersSmoke.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/helpersSmoke.test.ts
@@ -0,0 +1,25 @@
+import { expect } from 'chai';
+import waitNewBlocks from '../substrate/wait-new-blocks';
+import { createEthAccountWithBalance, deployFlipper, itWeb3, contractHelpers } from './util/helpers';
+
+describe('Helpers sanity check', () => {
+  itWeb3('Contract owner is recorded', async ({ api, web3 }) => {
+    const owner = await createEthAccountWithBalance(api, web3);
+
+    const flipper = await deployFlipper(web3, owner);
+    await waitNewBlocks(api, 1);
+
+    expect(await contractHelpers(web3, owner).methods.contractOwner(flipper.options.address).call()).to.be.equal(owner);
+  });
+
+  itWeb3('Flipper is working', async ({ api, web3 }) => {
+    const owner = await createEthAccountWithBalance(api, web3);
+    const flipper = await deployFlipper(web3, owner);
+    await waitNewBlocks(api, 1);
+
+    expect(await flipper.methods.getValue().call()).to.be.false;
+    await flipper.methods.flip().send({ from: owner });
+    await waitNewBlocks(api, 1);
+    expect(await flipper.methods.getValue().call()).to.be.true;
+  });
+});
\ No newline at end of file
addedtests/src/eth/marketplace/MarketPlaceKSM.abidiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/marketplace/MarketPlaceKSM.abi
@@ -0,0 +1 @@
+[{"inputs":[{"internalType":"address","name":"_escrow","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"asks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"asksbySeller","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"balanceKSM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"}],"name":"buy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_currencyCode","type":"uint256"},{"internalType":"address","name":"_sender","type":"address"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_currencyCode","type":"uint256"},{"internalType":"address","name":"_sender","type":"address"}],"name":"escrowBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"offers","outputs":[{"internalType":"uint256","name":"idNFT","type":"uint256"},{"internalType":"uint256","name":"currencyCode","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"address","name":"idCollection","type":"address"},{"internalType":"address","name":"userAddr","type":"address"},{"internalType":"uint8","name":"flagActive","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"uint256","name":"_currencyCode","type":"uint256"},{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"},{"internalType":"uint8","name":"_active","type":"uint8"}],"name":"setAsk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newEscrow","type":"address"}],"name":"setEscrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newEscrow","type":"address"}],"name":"setowner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_currencyCode","type":"uint256"},{"internalType":"address","name":"_sender","type":"address"}],"name":"withdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
\ No newline at end of file
addedtests/src/eth/marketplace/MarketPlaceKSM.bindiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/marketplace/MarketPlaceKSM.bin
@@ -0,0 +1 @@
+608060405234801561001057600080fd5b50604051610e27380380610e2783398101604081905261002f9161005d565b600480546001600160a01b039092166001600160a01b0319928316179055600580549091163317905561008d565b60006020828403121561006f57600080fd5b81516001600160a01b038116811461008657600080fd5b9392505050565b610d8b8061009c6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c806399f2d4eb1161007157806399f2d4eb1461018e5780639df55f52146101a1578063c10c35461461010f578063cce7ec13146101b4578063db87db52146101c7578063e22d4f7d146101fa57600080fd5b80630ad58d2f146100ae57806310a5ff17146100d6578063592bd7051461010f5780638a72ea6a146101245780638dbdbe6d1461017b575b600080fd5b6100c16100bc366004610c4d565b610225565b60405190151581526020015b60405180910390f35b6101016100e4366004610bd8565b600160209081526000928352604080842090915290825290205481565b6040519081526020016100cd565b61012261011d366004610b97565b6102d8565b005b610137610132366004610c04565b610345565b6040805197885260208801969096529486019390935260608501919091526001600160a01b0390811660808501521660a083015260ff1660c082015260e0016100cd565b610122610189366004610c4d565b6103a4565b61010161019c366004610bd8565b610449565b6101226101af366004610c86565b61047a565b6101226101c2366004610bd8565b610984565b6101016101d5366004610c1d565b6001600160a01b03166000908152600160209081526040808320938352929052205490565b610101610208366004610bd8565b600260209081526000928352604080842090915290825290205481565b6004546000906001600160a01b031633146102795760405162461bcd60e51b815260206004820152600f60248201526e27b7363c9032b9b1b937bb9031b0b760891b60448201526064015b60405180910390fd5b6001600160a01b03821660009081526001602090815260408083208684529091529020546102a8908590610cfa565b6001600160a01b039290921660009081526001602081815260408084209684529590529390209190915550919050565b6005546001600160a01b031633146103235760405162461bcd60e51b815260206004820152600e60248201526d27b7363c9037bbb732b91031b0b760911b6044820152606401610270565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6000818154811061035557600080fd5b6000918252602090912060069091020180546001820154600283015460038401546004850154600590950154939550919390926001600160a01b0391821691811690600160a01b900460ff1687565b6004546001600160a01b031633146103f05760405162461bcd60e51b815260206004820152600f60248201526e27b7363c9032b9b1b937bb9031b0b760891b6044820152606401610270565b6001600160a01b038116600090815260016020908152604080832085845290915290205461041f908490610ce2565b6001600160a01b039091166000908152600160209081526040808320948352939052919091205550565b6003602052816000526040600020818154811061046557600080fd5b90600052602060002001600091509150505481565b6040516331a9108f60e11b81526004810183905233906001600160a01b03851690636352211e9060240160206040518083038186803b1580156104bc57600080fd5b505afa1580156104d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f49190610bbb565b6001600160a01b0316146105425760405162461bcd60e51b81526020600482015260156024820152742737ba103934b3b43a103a37b5b2b71037bbb732b960591b6044820152606401610270565b6001600160a01b0383166000908152600260209081526040808320858452909152812054905415806105ac575060006001600160a01b03166000828154811061058d5761058d610d27565b60009182526020909120600460069092020101546001600160a01b0316145b15610793576040805160e0810182528481526020810187815291810188815242606083019081526001600160a01b03808916608085019081523360a0860190815260ff808a1660c088019081526000805460018181018355828052995160069091027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56381019190915599517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5648b015596517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5658a015594517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56689015591517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567880180549185166001600160a01b0319909216919091179055517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56890960180549351909116600160a01b026001600160a81b031990931695909116949094171790925590546107399190610cfa565b6001600160a01b038516600090815260026020908152604080832087845282528083209390935533825260039052908120905461077890600190610cfa565b81546001810183556000928352602090922090910155610916565b6040805160e0810182526001600160a01b03861660009081526002602090815283822087835290529182205482549192839290919081106107d6576107d6610d27565b60009182526020808320600690920290910154835282810189905260408084018b90524260608501526001600160a01b0389168352600282528083208884529091528120548154608090930192811061083157610831610d27565b60009182526020808320600460069093020191909101546001600160a01b039081168452338483015260ff871660409485015288168252600281528282208783529052908120548154811061088857610888610d27565b60009182526020918290208351600690920201908155908201516001820155604082015160028201556060820151600382015560808201516004820180546001600160a01b039283166001600160a01b031990911617905560a08301516005909201805460c09094015160ff16600160a01b026001600160a81b031990941692909116919091179190911790555b6040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b038516906323b872dd90606401600060405180830381600087803b15801561096457600080fd5b505af1158015610978573d6000803e3d6000fd5b50505050505050505050565b6001600160a01b0382166000908152600260209081526040808320848452909152812054815482919081106109bb576109bb610d27565b600091825260208083206040805160e0810182526006949094029091018054845260018082015485850190815260028301548685018190526003840154606088015260048401546001600160a01b03908116608089015260059094015493841660a0880152600160a01b90930460ff1660c08701523387529084528286209051865290925290922054909250610a519190610cfa565b33600090815260016020818152604080842086830180518652908352818520959095558581015160a08701516001600160a01b031685529282528084209451845293905291902054610aa39190610ce2565b60a08201516001600160a01b0390811660009081526001602090815260408083208287015184528252808320949094559186168152600282528281208582529091529081205481548291908110610afc57610afc610d27565b60009182526020909120600560069092020101805460ff92909216600160a01b0260ff60a01b199092169190911790556040516323b872dd60e01b8152306004820152336024820152604481018390526001600160a01b038416906323b872dd90606401600060405180830381600087803b158015610b7a57600080fd5b505af1158015610b8e573d6000803e3d6000fd5b50505050505050565b600060208284031215610ba957600080fd5b8135610bb481610d3d565b9392505050565b600060208284031215610bcd57600080fd5b8151610bb481610d3d565b60008060408385031215610beb57600080fd5b8235610bf681610d3d565b946020939093013593505050565b600060208284031215610c1657600080fd5b5035919050565b60008060408385031215610c3057600080fd5b823591506020830135610c4281610d3d565b809150509250929050565b600080600060608486031215610c6257600080fd5b83359250602084013591506040840135610c7b81610d3d565b809150509250925092565b600080600080600060a08688031215610c9e57600080fd5b85359450602086013593506040860135610cb781610d3d565b925060608601359150608086013560ff81168114610cd457600080fd5b809150509295509295909350565b60008219821115610cf557610cf5610d11565b500190565b600082821015610d0c57610d0c610d11565b500390565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0381168114610d5257600080fd5b5056fea2646970667358221220d098ae4e0cc7bdbb7de1061c03402a667836f903122c1c606ca2c65db1ab78e964736f6c63430008070033
\ No newline at end of file
addedtests/src/eth/marketplace/MarketPlaceKSM.soldiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/marketplace/MarketPlaceKSM.sol
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier:  Apache License
+pragma solidity >=0.8.0;
+
+interface IERC721 {
+    event Transfer(
+        address indexed from,
+        address indexed to,
+        uint256 indexed tokenId
+    );
+    event Approval(
+        address indexed owner,
+        address indexed approved,
+        uint256 indexed tokenId
+    );
+
+    function ownerOf(uint256 tokenId) external view returns (address owner);
+
+    function transferFrom(
+        address from,
+        address to,
+        uint256 tokenId
+    ) external;
+
+    function debug(string memory value) external;
+}
+
+interface IERC20 {
+    event Transfer(address indexed from, address indexed to, uint256 value);
+    event Approval(
+        address indexed owner,
+        address indexed spender,
+        uint256 value
+    );
+
+    function transfer(address recipient, uint256 amount)
+        external
+        returns (bool);
+
+    function transferFrom(
+        address sender,
+        address recipient,
+        uint256 amount
+    ) external returns (bool);
+}
+
+contract MarketPlaceKSM {
+    struct Offer {
+        uint256 idNFT;
+        uint256 currencyCode;
+        uint256 price;
+        uint256 time;
+        address idCollection;
+        address userAddr;
+        uint8 flagActive;
+    }
+    Offer[] public offers;
+
+    mapping(address => mapping(uint256 => uint256)) public balanceKSM; //  [userAddr] => [KSMs]
+    mapping(address => mapping(uint256 => uint256)) public asks; // [buyer][idCollection][idNFT] => idOffer
+
+    mapping(address => uint256[]) public asksbySeller; // [addressSeller] =>idOffer
+
+    address escrow;
+    address owner;
+
+    constructor(address _escrow) {
+        escrow = _escrow;
+        owner = msg.sender;
+    }
+
+    function setowner(address _newEscrow) public onlyOwner {
+        escrow = _newEscrow;
+    }
+
+    function setEscrow(address _newEscrow) public onlyOwner {
+        escrow = _newEscrow;
+    }
+
+    modifier onlyEscrow() {
+        require(msg.sender == escrow, "Only escrow can");
+        _;
+    }
+
+    modifier onlyOwner() {
+        require(msg.sender == owner, "Only owner can");
+        _;
+    }
+
+    /**
+     * Make bids (offers) to sell NFTs
+     */
+    function setAsk(
+        uint256 _price,
+        uint256 _currencyCode,
+        address _idCollection,
+        uint256 _idNFT,
+        uint8 _active
+    ) public {
+        require(
+            IERC721(_idCollection).ownerOf(_idNFT) == msg.sender,
+            "Not right token owner"
+        );
+        uint256 offerID = asks[_idCollection][_idNFT];
+        if (offers.length == 0 || offers[offerID].idCollection == address(0)) {
+            offers.push(
+                Offer(
+                    _idNFT,
+                    _currencyCode,
+                    _price,
+                    block.timestamp,
+                    _idCollection,
+                    msg.sender,
+                    _active
+                )
+            );
+            asks[_idCollection][_idNFT] = offers.length - 1;
+            asksbySeller[msg.sender].push(offers.length - 1);
+        }
+        //edit existing offer
+        else {
+            offers[asks[_idCollection][_idNFT]] = Offer(
+                offers[asks[_idCollection][_idNFT]].idNFT,
+                _currencyCode,
+                _price,
+                block.timestamp,
+                offers[asks[_idCollection][_idNFT]].idCollection,
+                msg.sender,
+                _active
+            );
+        }
+
+        IERC721(_idCollection).transferFrom(msg.sender, address(this), _idNFT);
+    }
+
+    function deposit(
+        uint256 _amount,
+        uint256 _currencyCode,
+        address _sender
+    ) public onlyEscrow {
+        balanceKSM[_sender][_currencyCode] =
+            balanceKSM[_sender][_currencyCode] +
+            _amount;
+    }
+
+    function buy(address _idCollection, uint256 _idNFT) public {
+        Offer memory offer = offers[asks[_idCollection][_idNFT]];
+        // 1. reduce balance
+        balanceKSM[msg.sender][offer.currencyCode] =
+            balanceKSM[msg.sender][offer.currencyCode] -
+            offer.price;
+        // 2. increase balance
+        balanceKSM[offer.userAddr][offer.currencyCode] =
+            balanceKSM[offer.userAddr][offer.currencyCode] +
+            offer.price;
+        // 3. close offer
+        offers[asks[_idCollection][_idNFT]].flagActive = 0;
+        // 4. transfer NFT to buyer
+        IERC721(_idCollection).transferFrom(address(this), msg.sender, _idNFT);
+    }
+
+    function withdraw(
+        uint256 _amount,
+        uint256 _currencyCode,
+        address _sender
+    ) public onlyEscrow returns (bool) {
+        balanceKSM[_sender][_currencyCode] =
+            balanceKSM[_sender][_currencyCode] -
+            _amount;
+        return true;
+    }
+
+    function escrowBalance(uint256 _currencyCode, address _sender)
+        public
+        view
+        returns (uint256)
+    {
+        return balanceKSM[_sender][_currencyCode];
+    }
+}
addedtests/src/eth/marketplace/MarketPlaceUNQ.abidiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/marketplace/MarketPlaceUNQ.abi
@@ -0,0 +1 @@
+[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"asks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"asksbySeller","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"},{"internalType":"address","name":"_currencyCode","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"buy","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"}],"name":"buy","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"offers","outputs":[{"internalType":"uint256","name":"idNFT","type":"uint256"},{"internalType":"address","name":"currencyCode","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"address","name":"idCollection","type":"address"},{"internalType":"address","name":"userAddr","type":"address"},{"internalType":"uint8","name":"flagActive","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"},{"internalType":"address","name":"_currencyCode","type":"address"},{"internalType":"address","name":"_idCollection","type":"address"},{"internalType":"uint256","name":"_idNFT","type":"uint256"},{"internalType":"uint8","name":"_active","type":"uint8"}],"name":"setAsk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"setowner","outputs":[],"stateMutability":"nonpayable","type":"function"}]
\ No newline at end of file
addedtests/src/eth/marketplace/MarketPlaceUNQ.bindiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/marketplace/MarketPlaceUNQ.bin
@@ -0,0 +1 @@
+608060405234801561001057600080fd5b50600380546001600160a01b03191633179055610f2d806100326000396000f3fe6080604052600436106100705760003560e01c806399f2d4eb1161004e57806399f2d4eb14610120578063b3ffb7601461014e578063cce7ec1314610161578063e22d4f7d1461017457600080fd5b8063592bd705146100755780637b1d6001146100975780638a72ea6a146100b7575b600080fd5b34801561008157600080fd5b50610095610090366004610d2b565b6101ac565b005b3480156100a357600080fd5b506100956100b2366004610e1b565b61021e565b3480156100c357600080fd5b506100d76100d2366004610e02565b61073d565b604080519788526001600160a01b03968716602089015287019490945260608601929092528316608085015290911660a083015260ff1660c082015260e0015b60405180910390f35b34801561012c57600080fd5b5061014061013b366004610d6c565b6107a0565b604051908152602001610117565b61009561015c366004610d98565b6107d1565b61009561016f366004610d6c565b610b0b565b34801561018057600080fd5b5061014061018f366004610d6c565b600160209081526000928352604080842090915290825290205481565b6003546001600160a01b031633146101fc5760405162461bcd60e51b815260206004820152600e60248201526d27b7363c9037bbb732b91031b0b760911b60448201526064015b60405180910390fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6040516331a9108f60e11b81526004810183905233906001600160a01b03851690636352211e9060240160206040518083038186803b15801561026057600080fd5b505afa158015610274573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102989190610d4f565b6001600160a01b0316146102e65760405162461bcd60e51b81526020600482015260156024820152742737ba103934b3b43a103a37b5b2b71037bbb732b960591b60448201526064016101f3565b6001600160a01b038316600090815260016020908152604080832085845290915281205490541580610350575060006001600160a01b03166000828154811061033157610331610ec9565b60009182526020909120600460069092020101546001600160a01b0316145b15610542576040805160e0810182528481526001600160a01b03878116602083019081529282018981524260608401908152888316608085019081523360a0860190815260ff89811660c08801908152600080546001808201835582805299517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56360069092029182015599517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5648b0180546001600160a01b0319908116928b1692909217905596517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5658b015594517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5668a015592517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5678901805490961690871617909455517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56890960180549151969094166001600160a81b031990911617600160a01b959092169490940217905590546104e99190610ea4565b6001600160a01b0385166000908152600160208181526040808420888552825280842094909455338352600290529181209054909161052791610ea4565b815460018101835560009283526020909220909101556106d3565b6040805160e0810182526001600160a01b038616600090815260016020908152838220878352905291822054825491928392909190811061058557610585610ec9565b6000918252602080832060069092029091015483526001600160a01b03808a168483015260408085018c9052426060860152908916835260018252808320888452909152812054815460809093019281106105e2576105e2610ec9565b60009182526020808320600460069093020191909101546001600160a01b039081168452338483015260ff871660409485015288168252600181528282208783529052908120548154811061063957610639610ec9565b60009182526020918290208351600690920201908155908201516001820180546001600160a01b039283166001600160a01b031991821617909155604084015160028401556060840151600384015560808401516004840180549184169190921617905560a08301516005909201805460c09094015160ff16600160a01b026001600160a81b031990941692909116919091179190911790555b6040516323b872dd60e01b81526001600160a01b038516906323b872dd9061070390339030908890600401610e80565b600060405180830381600087803b15801561071d57600080fd5b505af1158015610731573d6000803e3d6000fd5b50505050505050505050565b6000818154811061074d57600080fd5b60009182526020909120600690910201805460018201546002830154600384015460048501546005909501549395506001600160a01b03928316949193909291821691811690600160a01b900460ff1687565b600260205281600052604060002081815481106107bc57600080fd5b90600052602060002001600091509150505481565b6001600160a01b03841660009081526001602090815260408083208684529091528120548154829190811061080857610808610ec9565b60009182526020918290206040805160e0810182526006939093029091018054835260018101546001600160a01b03908116948401949094526002810154918301829052600381015460608401526004810154841660808401526005015492831660a0830152600160a01b90920460ff1660c08201529150821480156108a35750826001600160a01b031681602001516001600160a01b0316145b6109245760405162461bcd60e51b815260206004820152604660248201527f4e6f7420726967687420616d6f756e74206f722063757272656e63792073656e60448201527f742c206861766520746f20626520657175616c2063757272656e637920616e6460648201526520707269636560d01b608482015260a4016101f3565b80602001516001600160a01b03166323b872dd333084604001516040518463ffffffff1660e01b815260040161095c93929190610e80565b602060405180830381600087803b15801561097657600080fd5b505af115801561098a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ae9190610de0565b50602081015160a0820151604080840151905163a9059cbb60e01b81526001600160a01b039283166004820152602481019190915291169063a9059cbb90604401602060405180830381600087803b158015610a0957600080fd5b505af1158015610a1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a419190610de0565b506001600160a01b038516600090815260016020908152604080832087845290915281205481548291908110610a7957610a79610ec9565b906000526020600020906006020160050160146101000a81548160ff021916908360ff160217905550846001600160a01b03166323b872dd3033876040518463ffffffff1660e01b8152600401610ad293929190610e80565b600060405180830381600087803b158015610aec57600080fd5b505af1158015610b00573d6000803e3d6000fd5b505050505050505050565b6001600160a01b038216600090815260016020908152604080832084845290915281205481548291908110610b4257610b42610ec9565b60009182526020918290206040805160e0810182526006939093029091018054835260018101546001600160a01b03908116948401949094526002810154918301829052600381015460608401526004810154841660808401526005015492831660a0830152600160a01b90920460ff1660c082015291503414610c225760405162461bcd60e51b815260206004820152603160248201527f4e6f7420726967687420616d6f756e7420554e512073656e742c206861766520604482015270746f20626520657175616c20707269636560781b60648201526084016101f3565b8060a001516001600160a01b03166108fc82604001519081150290604051600060405180830381858888f19350505050158015610c63573d6000803e3d6000fd5b506001600160a01b038316600090815260016020908152604080832085845290915281205481548291908110610c9b57610c9b610ec9565b906000526020600020906006020160050160146101000a81548160ff021916908360ff160217905550826001600160a01b03166323b872dd3033856040518463ffffffff1660e01b8152600401610cf493929190610e80565b600060405180830381600087803b158015610d0e57600080fd5b505af1158015610d22573d6000803e3d6000fd5b50505050505050565b600060208284031215610d3d57600080fd5b8135610d4881610edf565b9392505050565b600060208284031215610d6157600080fd5b8151610d4881610edf565b60008060408385031215610d7f57600080fd5b8235610d8a81610edf565b946020939093013593505050565b60008060008060808587031215610dae57600080fd5b8435610db981610edf565b9350602085013592506040850135610dd081610edf565b9396929550929360600135925050565b600060208284031215610df257600080fd5b81518015158114610d4857600080fd5b600060208284031215610e1457600080fd5b5035919050565b600080600080600060a08688031215610e3357600080fd5b853594506020860135610e4581610edf565b93506040860135610e5581610edf565b925060608601359150608086013560ff81168114610e7257600080fd5b809150509295509295909350565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600082821015610ec457634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0381168114610ef457600080fd5b5056fea2646970667358221220fbf33eb1e471c428b86ad6d948b8699fd08a127b923d5fe27ec1e1ec5f59627564736f6c63430008070033
\ No newline at end of file
addedtests/src/eth/marketplace/MarketPlaceUNQ.soldiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/marketplace/MarketPlaceUNQ.sol
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier:  Apache License
+pragma solidity >=0.8.0;
+
+interface IERC721 {
+    event Transfer(
+        address indexed from,
+        address indexed to,
+        uint256 indexed tokenId
+    );
+    event Approval(
+        address indexed owner,
+        address indexed approved,
+        uint256 indexed tokenId
+    );
+
+    function ownerOf(uint256 tokenId) external view returns (address owner);
+
+    function transferFrom(
+        address from,
+        address to,
+        uint256 tokenId
+    ) external;
+
+    function debug(string memory value) external;
+}
+
+interface IERC20 {
+    event Transfer(address indexed from, address indexed to, uint256 value);
+    event Approval(
+        address indexed owner,
+        address indexed spender,
+        uint256 value
+    );
+
+    function transfer(address recipient, uint256 amount)
+        external
+        returns (bool);
+
+    function transferFrom(
+        address sender,
+        address recipient,
+        uint256 amount
+    ) external returns (bool);
+}
+
+contract MarketPlaceUNQ {
+    struct Offer {
+        uint256 idNFT;
+        address currencyCode; //address of currency  token, = address(0) for UNQ
+        uint256 price;
+        uint256 time;
+        address idCollection;
+        address userAddr;
+        uint8 flagActive;
+    }
+    Offer[] public offers;
+
+    mapping(address => mapping(uint256 => uint256)) public asks; // [idCollection][idNFT] => idOffer
+
+    mapping(address => uint256[]) public asksbySeller; // [addressSeller] =>idOffer
+
+    address owner;
+
+    constructor() {
+        owner = msg.sender;
+    }
+
+    function setowner(address _newOwner) public onlyOwner {
+        owner = _newOwner;
+    }
+
+    modifier onlyOwner() {
+        require(msg.sender == owner, "Only owner can");
+        _;
+    }
+
+    /**
+     * Make bids (offers) to sell NFTs
+     */
+    function setAsk(
+        uint256 _price,
+        address _currencyCode,
+        address _idCollection,
+        uint256 _idNFT,
+        uint8 _active
+    ) public {
+        require(
+            IERC721(_idCollection).ownerOf(_idNFT) == msg.sender,
+            "Not right token owner"
+        );
+        uint256 offerID = asks[_idCollection][_idNFT];
+        if (offers.length == 0 || offers[offerID].idCollection == address(0)) {
+            offers.push(
+                Offer(
+                    _idNFT,
+                    _currencyCode,
+                    _price,
+                    block.timestamp,
+                    _idCollection,
+                    msg.sender,
+                    _active
+                )
+            );
+            asks[_idCollection][_idNFT] = offers.length - 1;
+            asksbySeller[msg.sender].push(offers.length - 1);
+        }
+        //edit existing offer
+        else {
+            offers[asks[_idCollection][_idNFT]] = Offer(
+                offers[asks[_idCollection][_idNFT]].idNFT,
+                _currencyCode,
+                _price,
+                block.timestamp,
+                offers[asks[_idCollection][_idNFT]].idCollection,
+                msg.sender,
+                _active
+            );
+        }
+
+        IERC721(_idCollection).transferFrom(msg.sender, address(this), _idNFT);
+    }
+
+    function buy(address _idCollection, uint256 _idNFT) public payable {
+        //buing for UNQ like as ethers
+        Offer memory offer = offers[asks[_idCollection][_idNFT]];
+        //1. check sent amount and send to seller
+        require(
+            msg.value == offer.price,
+            "Not right amount UNQ sent, have to be equal price"
+        );
+        payable(offer.userAddr).transfer(offer.price);
+        // 2. close offer
+        offers[asks[_idCollection][_idNFT]].flagActive = 0;
+        // 3. transfer NFT to buyer
+        IERC721(_idCollection).transferFrom(address(this), msg.sender, _idNFT);
+    }
+
+    function buy(
+        address _idCollection,
+        uint256 _idNFT,
+        address _currencyCode,
+        uint256 _amount
+    ) public payable {
+        Offer memory offer = offers[asks[_idCollection][_idNFT]];
+        //1. check sent amount and transfer from buyer to seller
+        require(
+            offer.price == _amount && offer.currencyCode == _currencyCode,
+            "Not right amount or currency sent, have to be equal currency and price"
+        );
+        // !!! transfer have to be approved to marketplace!
+        IERC20(offer.currencyCode).transferFrom(
+            msg.sender,
+            address(this),
+            offer.price
+        );
+        //to not disclojure buyer's address
+        IERC20(offer.currencyCode).transfer(offer.userAddr, offer.price);
+        // 2. close offer
+        offers[asks[_idCollection][_idNFT]].flagActive = 0;
+        // 3. transfer NFT to buyer
+        IERC721(_idCollection).transferFrom(address(this), msg.sender, _idNFT);
+    }
+}
addedtests/src/eth/marketplace/marketplace.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/marketplace/marketplace.test.ts
@@ -0,0 +1,198 @@
+import { readFile } from 'fs/promises';
+import { getBalanceSingle, transferBalanceExpectSuccess } from '../../substrate/get-balance';
+import privateKey from '../../substrate/privateKey';
+import { createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, queryNftOwner, transferExpectSuccess, transferFromExpectSuccess } from '../../util/helpers';
+import { collectionIdToAddress, createEthAccountWithBalance, executeEthTxOnSub, GAS_ARGS, itWeb3, subToEth, subToEthLowercase } from '../util/helpers';
+import { evmToAddress } from '@polkadot/util-crypto';
+import nonFungibleAbi from '../nonFungibleAbi.json';
+import fungibleAbi from '../fungibleAbi.json';
+import waitNewBlocks from '../../substrate/wait-new-blocks';
+import { expect } from 'chai';
+
+const PRICE = 2000n;
+
+describe('Matcher contract usage', () => {
+  itWeb3('With UNQ', async ({api, web3}) => {
+    const matcherOwner = await createEthAccountWithBalance(api, web3);
+    const Matcher = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlaceUNQ.abi`)).toString()), undefined, {
+      from: matcherOwner,
+      ...GAS_ARGS,
+    });
+    const matcher = await Matcher.deploy({ data: (await readFile(`${__dirname}/MarketPlaceUNQ.bin`)).toString() }).send({ from: matcherOwner });
+
+    const alice = privateKey('//Alice');
+    const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
+    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), { from: matcherOwner });
+
+    const seller = privateKey('//Bob');
+  
+    const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);
+
+    // To transfer item to matcher it first needs to be transfered to EVM account of bob
+    await transferExpectSuccess(collectionId, tokenId, seller, {ethereum: subToEth(seller.address)});
+    // Fees will be paid from EVM account, so we should have some balance here
+    await transferBalanceExpectSuccess(api, seller, evmToAddress(subToEth(seller.address)), 10n ** 18n);
+    await transferBalanceExpectSuccess(api, alice, evmToAddress(subToEth(alice.address)), 10n ** 18n);
+    await waitNewBlocks(api, 1);
+
+    // Token is owned by seller initially
+    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: subToEthLowercase(seller.address) });
+
+    // Ask
+    {
+      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));
+      await executeEthTxOnSub(api, seller, matcher, m => m.setAsk(PRICE, '0x0000000000000000000000000000000000000000', evmCollection.options.address, tokenId, 1));
+    }
+      
+    // Token is transferred to matcher
+    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: matcher.options.address.toLowerCase() });
+
+    // Buy
+    {
+      const sellerBalanceBeforePurchase = await getBalanceSingle(api, seller.address);
+      // There is two functions named 'buy', so we should provide full signature
+      await executeEthTxOnSub(api, alice, matcher, m => m['buy(address,uint256)'](evmCollection.options.address, tokenId), { value: PRICE });
+      expect(await getBalanceSingle(api, seller.address) - sellerBalanceBeforePurchase === PRICE);
+    }
+
+    // Token is transferred to evm account of alice
+    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: subToEthLowercase(alice.address) });
+
+  
+    // Transfer token to substrate side of alice
+    await transferFromExpectSuccess(collectionId, tokenId, alice, { ethereum: subToEth(alice.address) }, { substrate: alice.address });
+    
+    // Token is transferred to substrate account of alice, seller received funds
+    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ substrate: alice.address });
+  });
+
+  itWeb3('With custom ERC20', async ({api, web3}) => {
+    const matcherOwner = await createEthAccountWithBalance(api, web3);
+    const Matcher = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlaceUNQ.abi`)).toString()), undefined, {
+      from: matcherOwner,
+      ...GAS_ARGS,
+    });
+    const matcher = await Matcher.deploy({ data: (await readFile(`${__dirname}/MarketPlaceUNQ.bin`)).toString() }).send({ from: matcherOwner });
+
+    const alice = privateKey('//Alice');
+    const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
+    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), { from: matcherOwner });
+
+    const fungibleId = await createCollectionExpectSuccess({ mode: { type: 'Fungible', decimalPoints: 0 } });
+    const evmFungible = new web3.eth.Contract(fungibleAbi as any, collectionIdToAddress(fungibleId), { from: matcherOwner, ...GAS_ARGS });
+    await createFungibleItemExpectSuccess(alice, fungibleId, { Value: PRICE }, { ethereum: subToEth(alice.address) });
+
+    const seller = privateKey('//Bob');
+  
+    const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);
+
+    // To transfer item to matcher it first needs to be transfered to EVM account of bob
+    await transferExpectSuccess(collectionId, tokenId, seller, {ethereum: subToEth(seller.address)});
+    // Fees will be paid from EVM account, so we should have some balance here
+    await transferBalanceExpectSuccess(api, seller, evmToAddress(subToEth(seller.address)), 10n ** 18n);
+    await transferBalanceExpectSuccess(api, alice, evmToAddress(subToEth(alice.address)), 10n ** 18n);
+    await waitNewBlocks(api, 1);
+
+    // Token is owned by seller initially
+    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: subToEthLowercase(seller.address) });
+
+    // Ask
+    {
+      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));
+      await executeEthTxOnSub(api, seller, matcher, m => m.setAsk(PRICE, evmFungible.options.address, evmCollection.options.address, tokenId, 1));
+    }
+      
+    // Token is transferred to matcher
+    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: matcher.options.address.toLowerCase() });
+
+    // Buy
+    {
+      const sellerBalanceBeforePurchase = BigInt(await evmFungible.methods.balanceOf(subToEth(seller.address)).call());
+      const buyerBalanceBeforePurchase = BigInt(await evmFungible.methods.balanceOf(subToEth(alice.address)).call());
+
+      await executeEthTxOnSub(api, alice, evmFungible, m => m.approve(matcher.options.address, PRICE));
+      // There is two functions named 'buy', so we should provide full signature
+      await executeEthTxOnSub(api, alice, matcher, m =>
+        m['buy(address,uint256,address,uint256)'](evmCollection.options.address, tokenId, evmFungible.options.address, PRICE));
+
+      // Approved price is removed from buyer balance, and added to seller
+      expect(BigInt(await evmFungible.methods.balanceOf(subToEth(seller.address)).call()) - sellerBalanceBeforePurchase === PRICE);
+      expect(buyerBalanceBeforePurchase - BigInt(await evmFungible.methods.balanceOf(subToEth(alice.address)).call()) === PRICE);
+    }
+
+    // Token is transferred to evm account of alice
+    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: subToEthLowercase(alice.address) });
+
+  
+    // Transfer token to substrate side of alice
+    await transferFromExpectSuccess(collectionId, tokenId, alice, { ethereum: subToEth(alice.address) }, { substrate: alice.address });
+    
+    // Token is transferred to substrate account of alice
+    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ substrate: alice.address });
+  });
+
+  itWeb3('With escrow', async ({ api, web3 }) => {
+    const matcherOwner = await createEthAccountWithBalance(api, web3);
+    const escrow = await createEthAccountWithBalance(api, web3);
+    const Matcher = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlaceKSM.abi`)).toString()), undefined, {
+      from: matcherOwner,
+      ...GAS_ARGS,
+    });
+    const matcher = await Matcher.deploy({ data: (await readFile(`${__dirname}/MarketPlaceKSM.bin`)).toString(), arguments: [escrow] }).send({ from: matcherOwner });
+    
+    const ksmToken = 11;
+
+    const alice = privateKey('//Alice');
+    const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
+    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), { from: matcherOwner });
+
+    const seller = privateKey('//Bob');
+  
+    const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);
+
+    // To transfer item to matcher it first needs to be transfered to EVM account of bob
+    await transferExpectSuccess(collectionId, tokenId, seller, {ethereum: subToEth(seller.address)});
+    // Fees will be paid from EVM account, so we should have some balance here
+    await transferBalanceExpectSuccess(api, seller, evmToAddress(subToEth(seller.address)), 10n ** 18n);
+    await transferBalanceExpectSuccess(api, alice, evmToAddress(subToEth(alice.address)), 10n ** 18n);
+    await waitNewBlocks(api, 1);
+
+    // Token is owned by seller initially
+    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: subToEthLowercase(seller.address) });
+
+    // Ask
+    {
+      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));
+      await executeEthTxOnSub(api, seller, matcher, m => m.setAsk(PRICE, ksmToken, evmCollection.options.address, tokenId, 1));
+    }
+      
+    // Token is transferred to matcher
+    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: matcher.options.address.toLowerCase() });
+
+    // Give buyer KSM
+    await matcher.methods.deposit(PRICE, ksmToken, subToEth(alice.address)).send({ from: escrow });
+    await waitNewBlocks(api, 1);
+  
+    // Buy
+    {
+      expect(await matcher.methods.escrowBalance(ksmToken, subToEth(seller.address)).call()).to.be.equal('0');
+      expect(await matcher.methods.escrowBalance(ksmToken, subToEth(alice.address)).call()).to.be.equal(PRICE.toString());
+
+      await executeEthTxOnSub(api, alice, matcher, m => m.buy(evmCollection.options.address, tokenId));
+      await waitNewBlocks(api, 1);
+
+      // Price is removed from buyer balance, and added to seller
+      expect(await matcher.methods.escrowBalance(ksmToken, subToEth(alice.address)).call()).to.be.equal('0');
+      expect(await matcher.methods.escrowBalance(ksmToken, subToEth(seller.address)).call()).to.be.equal(PRICE.toString());
+    }
+
+    // Token is transferred to evm account of alice
+    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: subToEthLowercase(alice.address) });
+  
+    // Transfer token to substrate side of alice
+    await transferFromExpectSuccess(collectionId, tokenId, alice, { ethereum: subToEth(alice.address) }, { substrate: alice.address });
+    
+    // Token is transferred to substrate account of alice, seller received funds
+    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ substrate: alice.address });
+  });
+});
modifiedtests/src/eth/metadata.test.tsdiffbeforeafterboth
--- a/tests/src/eth/metadata.test.ts
+++ b/tests/src/eth/metadata.test.ts
@@ -4,9 +4,8 @@
 //
 
 import { expect } from 'chai';
-import privateKey from '../substrate/privateKey';
 import { createCollectionExpectSuccess } from '../util/helpers';
-import { collectionIdToAddress, createEthAccount, itWeb3, transferBalanceToEth } from './util/helpers';
+import { collectionIdToAddress, createEthAccountWithBalance, GAS_ARGS, itWeb3 } from './util/helpers';
 import fungibleMetadataAbi from './fungibleMetadataAbi.json';
 
 describe('Common metadata', () => {
@@ -15,12 +14,11 @@
       name: 'token name',
       mode: { type: 'NFT' },
     });
-    const caller = createEthAccount(web3);
-    await transferBalanceToEth(api, privateKey('//Alice'), caller, 999999);
+    const caller = await createEthAccountWithBalance(api, web3);
 
     const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(fungibleMetadataAbi as any, address);
-    const name = await contract.methods.name().call({ from: caller });
+    const contract = new web3.eth.Contract(fungibleMetadataAbi as any, address, { from: caller, ...GAS_ARGS });
+    const name = await contract.methods.name().call();
 
     expect(name).to.equal('token name');
   });
@@ -30,12 +28,11 @@
       tokenPrefix: 'TOK',
       mode: { type: 'NFT' },
     });
-    const caller = createEthAccount(web3);
-    await transferBalanceToEth(api, privateKey('//Alice'), caller, 999999);
+    const caller = await createEthAccountWithBalance(api, web3);
 
     const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(fungibleMetadataAbi as any, address);
-    const symbol = await contract.methods.symbol().call({ from: caller });
+    const contract = new web3.eth.Contract(fungibleMetadataAbi as any, address, { from: caller, ...GAS_ARGS });
+    const symbol = await contract.methods.symbol().call();
 
     expect(symbol).to.equal('TOK');
   });
@@ -46,12 +43,11 @@
     const collection = await createCollectionExpectSuccess({
       mode: { type: 'Fungible', decimalPoints: 6 },
     });
-    const caller = createEthAccount(web3);
-    await transferBalanceToEth(api, privateKey('//Alice'), caller, 999999);
+    const caller = await createEthAccountWithBalance(api, web3);
 
     const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(fungibleMetadataAbi as any, address);
-    const decimals = await contract.methods.decimals().call({ from: caller });
+    const contract = new web3.eth.Contract(fungibleMetadataAbi as any, address, { from: caller, ...GAS_ARGS });
+    const decimals = await contract.methods.decimals().call();
 
     expect(+decimals).to.equal(6);
   });
addedtests/src/eth/migration.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/migration.test.ts
@@ -0,0 +1,82 @@
+import { expect } from 'chai';
+import privateKey from '../substrate/privateKey';
+import { submitTransactionAsync } from '../substrate/substrate-api';
+import { createEthAccountWithBalance, GAS_ARGS, itWeb3 } from './util/helpers';
+
+describe('EVM Migrations', () => {
+  itWeb3('Deploy contract saved state', async ({ web3, api }) => {
+    /*
+      contract StatefulContract {
+        uint counter;
+        mapping (uint => uint) kv;
+
+        function inc() public {
+          counter = counter + 1;
+        }
+        function counterValue() public view returns (uint) {
+          return counter;
+        }
+
+        function set(uint key, uint value) public {
+          kv[key] = value;
+        }
+
+        function get(uint key) public view returns (uint) {
+          return kv[key];
+        }
+      }
+    */
+    const ADDRESS = '0x4956bf52ef9ed8789f21bc600e915e0d961079f6';
+    const CODE = '0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80631ab06ee514610051578063371303c01461006d5780637bfdec3b146100775780639507d39a14610095575b600080fd5b61006b60048036038101906100669190610160565b6100c5565b005b6100756100e1565b005b61007f6100f8565b60405161008c91906101af565b60405180910390f35b6100af60048036038101906100aa9190610133565b610101565b6040516100bc91906101af565b60405180910390f35b8060016000848152602001908152602001600020819055505050565b60016000546100f091906101ca565b600081905550565b60008054905090565b600060016000838152602001908152602001600020549050919050565b60008135905061012d8161025e565b92915050565b60006020828403121561014957610148610259565b5b60006101578482850161011e565b91505092915050565b6000806040838503121561017757610176610259565b5b60006101858582860161011e565b92505060206101968582860161011e565b9150509250929050565b6101a981610220565b82525050565b60006020820190506101c460008301846101a0565b92915050565b60006101d582610220565b91506101e083610220565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156102155761021461022a565b5b828201905092915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b61026781610220565b811461027257600080fd5b5056fea26469706673582212206a02d2fb5c244105ab884961479c1aee3b4c1011e4b5530ab483eb22344a865664736f6c63430008060033';
+    const DATA = [
+      // counter = 10
+      ['0x0000000000000000000000000000000000000000000000000000000000000000', '0x000000000000000000000000000000000000000000000000000000000000000a'],
+      // kv = {1: 1, 2: 2, 3: 3, 4: 4},
+      ['0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f', '0x0000000000000000000000000000000000000000000000000000000000000001'],
+      ['0xd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f', '0x0000000000000000000000000000000000000000000000000000000000000002'],
+      ['0x7dfe757ecd65cbd7922a9c0161e935dd7fdbcc0e999689c7d31633896b1fc60b', '0x0000000000000000000000000000000000000000000000000000000000000003'],
+      ['0xedc95719e9a3b28dd8e80877cb5880a9be7de1a13fc8b05e7999683b6b567643', '0x0000000000000000000000000000000000000000000000000000000000000004'],
+    ];
+
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+
+    await submitTransactionAsync(alice, api.tx.sudo.sudo(api.tx.evmMigration.begin(ADDRESS)));
+    await submitTransactionAsync(alice, api.tx.sudo.sudo(api.tx.evmMigration.setData(ADDRESS, DATA)));
+    await submitTransactionAsync(alice, api.tx.sudo.sudo(api.tx.evmMigration.finish(ADDRESS, CODE)));
+
+    const contract = new web3.eth.Contract([
+      {
+        inputs: [],
+        name: 'counterValue',
+        outputs: [{
+          internalType: 'uint256',
+          name: '',
+          type: 'uint256',
+        }],
+        stateMutability: 'view',
+        type: 'function',
+      },
+      {
+        inputs: [{
+          internalType: 'uint256',
+          name: 'key',
+          type: 'uint256',
+        }],
+        name: 'get',
+        outputs: [{
+          internalType: 'uint256',
+          name: '',
+          type: 'uint256',
+        }],
+        stateMutability: 'view',
+        type: 'function',
+      },
+    ], ADDRESS, { from: caller, ...GAS_ARGS });
+    
+    expect(await contract.methods.counterValue().call()).to.be.equal('10');
+    for (let i = 1; i <= 4; i++) {
+      expect(await contract.methods.get(i).call()).to.be.equal(i.toString());
+    }
+  });
+});
\ No newline at end of file
modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/nonFungible.test.ts
+++ b/tests/src/eth/nonFungible.test.ts
@@ -4,64 +4,140 @@
 //
 
 import privateKey from '../substrate/privateKey';
-import { approveExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess } from '../util/helpers';
-import { collectionIdToAddress, createEthAccount, itWeb3, normalizeEvents, recordEvents, subToEth, transferBalanceToEth } from './util/helpers';
+import { approveExpectSuccess, burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE } from '../util/helpers';
+import { collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth } from './util/helpers';
+import { evmToAddress } from '@polkadot/util-crypto';
 import nonFungibleAbi from './nonFungibleAbi.json';
 import { expect } from 'chai';
+import waitNewBlocks from '../substrate/wait-new-blocks';
+import { submitTransactionAsync } from '../substrate/substrate-api';
 
-describe('Information getting', () => {
-  itWeb3('totalSupply', async ({ web3 }) => {
+describe('NFT: Information getting', () => {
+  itWeb3('totalSupply', async ({ api, web3 }) => {
     const collection = await createCollectionExpectSuccess({
       mode: { type: 'NFT' },
     });
     const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
 
     await createItemExpectSuccess(alice, collection, 'NFT', { substrate: alice.address });
 
     const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
     const totalSupply = await contract.methods.totalSupply().call();
 
     // FIXME: always equals to 0, because this method is not implemented
     expect(totalSupply).to.equal('0');
   });
 
-  itWeb3('balanceOf', async ({ web3 }) => {
+  itWeb3('balanceOf', async ({ api, web3 }) => {
     const collection = await createCollectionExpectSuccess({
       mode: { type: 'NFT' },
     });
     const alice = privateKey('//Alice');
 
-    const caller = createEthAccount(web3);
+    const caller = await createEthAccountWithBalance(api, web3);
     await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });
     await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });
     await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });
 
     const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
     const balance = await contract.methods.balanceOf(caller).call();
 
     expect(balance).to.equal('3');
   });
 
-  itWeb3('ownerOf', async ({ web3 }) => {
+  itWeb3('ownerOf', async ({ api, web3 }) => {
     const collection = await createCollectionExpectSuccess({
       mode: { type: 'NFT' },
     });
     const alice = privateKey('//Alice');
 
-    const caller = createEthAccount(web3);
+    const caller = await createEthAccountWithBalance(api, web3);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });
 
     const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
     const owner = await contract.methods.ownerOf(tokenId).call();
 
     expect(owner).to.equal(caller);
   });
 });
 
-describe('Plain calls', () => {
+describe('NFT: Plain calls', () => {
+  itWeb3('Can perform mint()', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+
+    const caller = await createEthAccountWithBalance(api, web3);
+    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, { ethereum: caller });
+    await submitTransactionAsync(alice, changeAdminTx);
+    const receiver = createEthAccount(web3);
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+
+    {
+      const nextTokenId = await contract.methods.nextTokenId().call();
+      expect(nextTokenId).to.be.equal('1');
+      const result = await contract.methods.mintWithTokenURI(
+        receiver,
+        nextTokenId,
+        'Test URI',
+      ).send({from: caller});
+      const events = normalizeEvents(result.events);
+
+      expect(events).to.be.deep.equal([
+        {
+          address,
+          event: 'Transfer',
+          args: {
+            from: '0x0000000000000000000000000000000000000000',
+            to: receiver,
+            tokenId: nextTokenId,
+          },
+        },
+      ]);
+
+      await waitNewBlocks(api, 1);
+      expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
+    }
+  });
+
+  itWeb3('Can perform burn()', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: {type: 'NFT'},
+    });
+    const alice = privateKey('//Alice');
+
+    const owner = await createEthAccountWithBalance(api, web3);
+
+    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });
+    
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});
+
+    {
+      const result = await contract.methods.burn(tokenId).send({ from: owner });
+      const events = normalizeEvents(result.events);
+      
+      expect(events).to.be.deep.equal([
+        {
+          address,
+          event: 'Transfer',
+          args: {
+            from: owner,
+            to: '0x0000000000000000000000000000000000000000',
+            tokenId: tokenId.toString(),
+          },
+        },
+      ]);
+    }
+  });
+
   itWeb3('Can perform approve()', async ({ web3, api }) => {
     const collection = await createCollectionExpectSuccess({
       mode: { type: 'NFT' },
@@ -113,12 +189,12 @@
     const receiver = createEthAccount(web3);
 
     const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});
 
-    await contract.methods.approve(spender, tokenId).send({ from: owner, gas: '0x1000000', gasPrice: '0x01' });
+    await contract.methods.approve(spender, tokenId).send({ from: owner });
 
     {
-      const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({ from: spender, gas: '0x1000000', gasPrice: '0x01' });
+      const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({ from: spender });
       const events = normalizeEvents(result.events);
       expect(events).to.be.deep.equal([
         {
@@ -159,11 +235,11 @@
     await transferBalanceToEth(api, alice, receiver, 999999999999999);
 
     const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});
 
     {
-      const result = await contract.methods.transfer(receiver, tokenId).send({ from: owner, gas: '0x1000000', gasPrice: '0x01' });
-      console.log(result);
+      const result = await contract.methods.transfer(receiver, tokenId).send({ from: owner });
+      await waitNewBlocks(api, 1);
       const events = normalizeEvents(result.events);
       expect(events).to.be.deep.equal([
         {
@@ -190,7 +266,119 @@
   });
 });
 
-describe('Substrate calls', () => {
+describe('NFT: Fees', () => {
+  itWeb3('approve() call fee is less than 0.2UNQ', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+
+    const owner = await createEthAccountWithBalance(api, web3);
+    const spender = createEthAccount(web3);
+
+    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, { from: owner, ...GAS_ARGS });
+
+    const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, tokenId).send({ from: owner }));
+    expect(cost < BigInt(0.2 * Number(UNIQUE)));
+  });
+
+  itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+  
+    const owner = await createEthAccountWithBalance(api, web3);
+    const spender = await createEthAccountWithBalance(api, web3);
+
+    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, { from: owner, ...GAS_ARGS });
+
+    await contract.methods.approve(spender, tokenId).send({ from: owner });
+
+    const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, tokenId).send({ from: spender }));
+    expect(cost < BigInt(0.2 * Number(UNIQUE)));
+  });
+
+  itWeb3('transfer() call fee is less than 0.2UNQ', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+
+    const owner = await createEthAccountWithBalance(api, web3);
+    const receiver = createEthAccount(web3);
+
+    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, { from: owner, ...GAS_ARGS });
+
+    const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, tokenId).send({ from: owner }));
+    expect(cost < BigInt(0.2 * Number(UNIQUE)));
+  });
+});
+
+describe('NFT: Substrate calls', () => {
+  itWeb3('Events emitted for mint()', async ({ web3 }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+
+    let tokenId: number;
+    const events = await recordEvents(contract, async () => {
+      tokenId = await createItemExpectSuccess(alice, collection, 'NFT');
+    });
+
+    expect(events).to.be.deep.equal([
+      {
+        address,
+        event: 'Transfer',
+        args: {
+          from: '0x0000000000000000000000000000000000000000',
+          to: subToEth(alice.address),
+          tokenId: tokenId!.toString(),
+        },
+      },
+    ]);
+  });
+
+  itWeb3('Events emitted for burn()', async ({ web3 }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+
+    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');
+    const events = await recordEvents(contract, async () => {
+      await burnItemExpectSuccess(alice, collection, tokenId);
+    });
+
+    expect(events).to.be.deep.equal([
+      {
+        address,
+        event: 'Transfer',
+        args: {
+          from: subToEth(alice.address),
+          to: '0x0000000000000000000000000000000000000000',
+          tokenId: tokenId.toString(),
+        },
+      },
+    ]);
+  });
+
   itWeb3('Events emitted for approve()', async ({ web3 }) => {
     const collection = await createCollectionExpectSuccess({
       mode: { type: 'NFT' },
@@ -282,4 +470,4 @@
       },
     ]);
   });
-});
\ No newline at end of file
+});
modifiedtests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth
--- a/tests/src/eth/nonFungibleAbi.json
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -50,6 +50,12 @@
         "type": "event"
     },
     {
+        "anonymous": true,
+        "inputs": [],
+        "name": "MintingFinished",
+        "type": "event"
+    },
+    {
         "anonymous": false,
         "inputs": [
             {
@@ -89,7 +95,7 @@
         ],
         "name": "approve",
         "outputs": [],
-        "stateMutability": "payable",
+        "stateMutability": "nonpayable",
         "type": "function"
     },
     {
@@ -119,6 +125,32 @@
                 "type": "uint256"
             }
         ],
+        "name": "burn",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "finishMinting",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "uint256",
+                "name": "tokenId",
+                "type": "uint256"
+            }
+        ],
         "name": "getApproved",
         "outputs": [
             {
@@ -146,11 +178,77 @@
         "name": "isApprovedForAll",
         "outputs": [
             {
+                "internalType": "address",
+                "name": "",
+                "type": "address"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "to",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "tokenId",
+                "type": "uint256"
+            }
+        ],
+        "name": "mint",
+        "outputs": [
+            {
                 "internalType": "bool",
                 "name": "",
                 "type": "bool"
             }
         ],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "to",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "tokenId",
+                "type": "uint256"
+            },
+            {
+                "internalType": "string",
+                "name": "tokenURI",
+                "type": "string"
+            }
+        ],
+        "name": "mintWithTokenURI",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "mintingFinished",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
         "stateMutability": "view",
         "type": "function"
     },
@@ -160,7 +258,7 @@
         "outputs": [
             {
                 "internalType": "string",
-                "name": "res_name",
+                "name": "",
                 "type": "string"
             }
         ],
@@ -168,6 +266,19 @@
         "type": "function"
     },
     {
+        "inputs": [],
+        "name": "nextTokenId",
+        "outputs": [
+            {
+                "internalType": "uint256",
+                "name": "",
+                "type": "uint256"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
         "inputs": [
             {
                 "internalType": "uint256",
@@ -206,7 +317,7 @@
         ],
         "name": "safeTransferFrom",
         "outputs": [],
-        "stateMutability": "payable",
+        "stateMutability": "nonpayable",
         "type": "function"
     },
     {
@@ -232,9 +343,9 @@
                 "type": "bytes"
             }
         ],
-        "name": "safeTransferFrom",
+        "name": "safeTransferFromWithData",
         "outputs": [],
-        "stateMutability": "payable",
+        "stateMutability": "nonpayable",
         "type": "function"
     },
     {
@@ -258,9 +369,9 @@
     {
         "inputs": [
             {
-                "internalType": "bytes4",
-                "name": "interfaceID",
-                "type": "bytes4"
+                "internalType": "uint32",
+                "name": "interfaceId",
+                "type": "uint32"
             }
         ],
         "name": "supportsInterface",
@@ -271,7 +382,7 @@
                 "type": "bool"
             }
         ],
-        "stateMutability": "pure",
+        "stateMutability": "view",
         "type": "function"
     },
     {
@@ -280,7 +391,7 @@
         "outputs": [
             {
                 "internalType": "string",
-                "name": "res_symbol",
+                "name": "",
                 "type": "string"
             }
         ],
@@ -366,11 +477,6 @@
         "inputs": [
             {
                 "internalType": "address",
-                "name": "from",
-                "type": "address"
-            },
-            {
-                "internalType": "address",
                 "name": "to",
                 "type": "address"
             },
@@ -380,15 +486,20 @@
                 "type": "uint256"
             }
         ],
-        "name": "transferFrom",
+        "name": "transfer",
         "outputs": [],
-        "stateMutability": "payable",
+        "stateMutability": "nonpayable",
         "type": "function"
     },
     {
         "inputs": [
             {
                 "internalType": "address",
+                "name": "from",
+                "type": "address"
+            },
+            {
+                "internalType": "address",
                 "name": "to",
                 "type": "address"
             },
@@ -398,9 +509,9 @@
                 "type": "uint256"
             }
         ],
-        "name": "transfer",
+        "name": "transferFrom",
         "outputs": [],
-        "stateMutability": "payable",
+        "stateMutability": "nonpayable",
         "type": "function"
     }
 ]
\ No newline at end of file
addedtests/src/eth/payable.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/payable.test.ts
@@ -0,0 +1,98 @@
+import { expect } from 'chai';
+import privateKey from '../substrate/privateKey';
+import { submitTransactionAsync } from '../substrate/substrate-api';
+import waitNewBlocks from '../substrate/wait-new-blocks';
+import { createEthAccountWithBalance, deployCollector, GAS_ARGS, itWeb3, subToEth } from './util/helpers';
+import {evmToAddress} from '@polkadot/util-crypto';
+import { getGenericResult } from '../util/helpers';
+import { getBalanceSingle, transferBalanceExpectSuccess } from '../substrate/get-balance';
+
+describe('EVM payable contracts', ()=>{
+  itWeb3('Evm contract can receive wei from eth account', async ({api, web3}) => {
+    const deployer = await createEthAccountWithBalance(api, web3);
+    const contract = await deployCollector(web3, deployer);
+
+    await web3.eth.sendTransaction({from: deployer, to: contract.options.address, value: '10000', ...GAS_ARGS});
+    await waitNewBlocks(api, 1);
+
+    expect(await contract.methods.getCollected().call()).to.be.equal('10000');
+  });
+
+  itWeb3('Evm contract can receive wei from substrate account', async ({api, web3}) => {
+    const deployer = await createEthAccountWithBalance(api, web3);
+    const contract = await deployCollector(web3, deployer);
+    const alice = privateKey('//Alice');
+
+    // Transaction fee/value will be payed from subToEth(sender) evm balance,
+    // which is backed by evmToAddress(subToEth(sender)) substrate balance
+    await transferBalanceExpectSuccess(api, alice, evmToAddress(subToEth(alice.address)), '1000000000000');
+
+    {
+      const tx = api.tx.evm.call(
+        subToEth(alice.address),
+        contract.options.address,
+        contract.methods.giveMoney().encodeABI(),
+        '10000',
+        GAS_ARGS.gas,
+        GAS_ARGS.gasPrice,
+        null,
+      );
+      const events = await submitTransactionAsync(alice, tx);
+      const result = getGenericResult(events);
+      expect(result.success).to.be.true;
+    }
+
+    expect(await contract.methods.getCollected().call()).to.be.equal('10000');
+  });
+
+  // We can't handle sending balance to backing storage of evm balance, because evmToAddress operation is irreversible
+  itWeb3('Wei sent directly to backing storage of evm contract balance is unaccounted', async({api, web3}) => {
+    const deployer = await createEthAccountWithBalance(api, web3);
+    const contract = await deployCollector(web3, deployer);
+    const alice = privateKey('//Alice');
+
+    await transferBalanceExpectSuccess(api, alice, evmToAddress(contract.options.address), '10000');
+  
+    expect(await contract.methods.getUnaccounted().call()).to.be.equal('10000');
+  });
+
+  itWeb3('Balance can be retrieved from evm contract', async({api, web3}) => {
+    const FEE_BALANCE = 10n ** 18n;
+    const CONTRACT_BALANCE = 10n ** 14n;
+
+    const deployer = await createEthAccountWithBalance(api, web3);
+    const contract = await deployCollector(web3, deployer);
+    const alice = privateKey('//Alice');
+
+    await web3.eth.sendTransaction({from: deployer, to: contract.options.address, value: CONTRACT_BALANCE.toString(), ...GAS_ARGS});
+    await waitNewBlocks(api, 1);
+
+    const receiver = privateKey(`//Receiver${Date.now()}`);
+
+    // First receive balance on eth balance of bob
+    {
+      const ethReceiver = subToEth(receiver.address);
+      expect(await web3.eth.getBalance(ethReceiver)).to.be.equal('0');
+      await contract.methods.withdraw(ethReceiver).send({from: deployer});
+      expect(await web3.eth.getBalance(ethReceiver)).to.be.equal(CONTRACT_BALANCE.toString());
+    }
+
+    // Some balance is required to pay fee for evm.withdraw call
+    await transferBalanceExpectSuccess(api, alice, receiver.address, FEE_BALANCE.toString());
+
+    // Withdraw balance from eth to substrate
+    {
+      const initialReceiverBalance = await getBalanceSingle(api, receiver.address);
+      const tx = api.tx.evm.withdraw(
+        subToEth(receiver.address),
+        CONTRACT_BALANCE.toString(),
+      );
+      const events = await submitTransactionAsync(receiver, tx);
+      const result = getGenericResult(events);
+      expect(result.success).to.be.true;
+      const finalReceiverBalance = await getBalanceSingle(api, receiver.address);
+
+      expect(finalReceiverBalance > initialReceiverBalance).to.be.true;
+    }
+  });
+});
\ No newline at end of file
addedtests/src/eth/proxy/UniqueFungibleProxy.abidiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/proxy/UniqueFungibleProxy.abi
@@ -0,0 +1 @@
+[{"inputs":[{"internalType":"address","name":"_proxied","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"interfaceId","type":"uint32"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
\ No newline at end of file
addedtests/src/eth/proxy/UniqueFungibleProxy.bindiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/proxy/UniqueFungibleProxy.bin
@@ -0,0 +1 @@
+608060405234801561001057600080fd5b5060405161098038038061098083398101604081905261002f91610054565b600080546001600160a01b0319166001600160a01b0392909216919091179055610084565b60006020828403121561006657600080fd5b81516001600160a01b038116811461007d57600080fd5b9392505050565b6108ed806100936000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c806370a082311161006657806370a082311461012757806395d89b411461013a578063a9059cbb14610142578063dd62ed3e14610155578063f4f4b5001461016857600080fd5b806306fdde03146100a3578063095ea7b3146100c157806318160ddd146100e457806323b872dd146100fa578063313ce5671461010d575b600080fd5b6100ab61017b565b6040516100b8919061083e565b60405180910390f35b6100d46100cf3660046106e3565b610200565b60405190151581526020016100b8565b6100ec61028f565b6040519081526020016100b8565b6100d46101083660046106a7565b610316565b6101156103ad565b60405160ff90911681526020016100b8565b6100ec610135366004610659565b610434565b6100ab6104b8565b6100d46101503660046106e3565b6104fc565b6100ec610163366004610674565b610536565b6100d46101763660046107f5565b6105bc565b60008054604080516306fdde0360e01b815290516060936001600160a01b03909316926306fdde039260048082019391829003018186803b1580156101bf57600080fd5b505afa1580156101d3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101fb919081019061072f565b905090565b6000805460405163095ea7b360e01b81526001600160a01b038581166004830152602482018590529091169063095ea7b3906044015b602060405180830381600087803b15801561025057600080fd5b505af1158015610264573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610288919061070d565b9392505050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156102de57600080fd5b505afa1580156102f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fb91906107dc565b600080546040516323b872dd60e01b81526001600160a01b038681166004830152858116602483015260448201859052909116906323b872dd90606401602060405180830381600087803b15801561036d57600080fd5b505af1158015610381573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a5919061070d565b949350505050565b60008060009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156103fc57600080fd5b505afa158015610410573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fb919061081b565b600080546040516370a0823160e01b81526001600160a01b038481166004830152909116906370a082319060240160206040518083038186803b15801561047a57600080fd5b505afa15801561048e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b291906107dc565b92915050565b60008054604080516395d89b4160e01b815290516060936001600160a01b03909316926395d89b419260048082019391829003018186803b1580156101bf57600080fd5b6000805460405163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529091169063a9059cbb90604401610236565b60008054604051636eb1769f60e11b81526001600160a01b03858116600483015284811660248301529091169063dd62ed3e9060440160206040518083038186803b15801561058457600080fd5b505afa158015610598573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061028891906107dc565b6000805460405162f4f4b560e81b815263ffffffff841660048201526001600160a01b039091169063f4f4b5009060240160206040518083038186803b15801561060557600080fd5b505afa158015610619573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b2919061070d565b80356001600160a01b038116811461065457600080fd5b919050565b60006020828403121561066b57600080fd5b6102888261063d565b6000806040838503121561068757600080fd5b6106908361063d565b915061069e6020840161063d565b90509250929050565b6000806000606084860312156106bc57600080fd5b6106c58461063d565b92506106d36020850161063d565b9150604084013590509250925092565b600080604083850312156106f657600080fd5b6106ff8361063d565b946020939093013593505050565b60006020828403121561071f57600080fd5b8151801515811461028857600080fd5b60006020828403121561074157600080fd5b815167ffffffffffffffff8082111561075957600080fd5b818401915084601f83011261076d57600080fd5b81518181111561077f5761077f6108a1565b604051601f8201601f19908116603f011681019083821181831017156107a7576107a76108a1565b816040528281528760208487010111156107c057600080fd5b6107d1836020830160208801610871565b979650505050505050565b6000602082840312156107ee57600080fd5b5051919050565b60006020828403121561080757600080fd5b813563ffffffff8116811461028857600080fd5b60006020828403121561082d57600080fd5b815160ff8116811461028857600080fd5b602081526000825180602084015261085d816040850160208701610871565b601f01601f19169190910160400192915050565b60005b8381101561088c578181015183820152602001610874565b8381111561089b576000848401525b50505050565b634e487b7160e01b600052604160045260246000fdfea2646970667358221220c05e4cb7ab439b86c0b6ac8a84eec6a230b592fa63d1ab2e3a7f1474c27338f364736f6c63430008070033
\ No newline at end of file
addedtests/src/eth/proxy/UniqueFungibleProxy.soldiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/proxy/UniqueFungibleProxy.sol
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: OTHER
+
+pragma solidity >=0.8.0 <0.9.0;
+
+import "../api/UniqueFungible.sol";
+
+contract UniqueFungibleProxy is UniqueFungible {
+    UniqueFungible proxied;
+
+    constructor(address _proxied) UniqueFungible() {
+        proxied = UniqueFungible(_proxied);
+    }
+
+    function name() external view override returns (string memory) {
+        return proxied.name();
+    }
+
+    function symbol() external view override returns (string memory) {
+        return proxied.symbol();
+    }
+
+    function totalSupply() external view override returns (uint256) {
+        return proxied.totalSupply();
+    }
+
+    function supportsInterface(uint32 interfaceId)
+        external
+        view
+        override
+        returns (bool)
+    {
+        return proxied.supportsInterface(interfaceId);
+    }
+
+    function decimals() external view override returns (uint8) {
+        return proxied.decimals();
+    }
+
+    function balanceOf(address owner) external view override returns (uint256) {
+        return proxied.balanceOf(owner);
+    }
+
+    function transfer(address to, uint256 amount)
+        external
+        override
+        returns (bool)
+    {
+        return proxied.transfer(to, amount);
+    }
+
+    function transferFrom(
+        address from,
+        address to,
+        uint256 amount
+    ) external override returns (bool) {
+        return proxied.transferFrom(from, to, amount);
+    }
+
+    function approve(address spender, uint256 amount)
+        external
+        override
+        returns (bool)
+    {
+        return proxied.approve(spender, amount);
+    }
+
+    function allowance(address owner, address spender)
+        external
+        view
+        override
+        returns (uint256)
+    {
+        return proxied.allowance(owner, spender);
+    }
+}
addedtests/src/eth/proxy/UniqueNFTProxy.abidiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/proxy/UniqueNFTProxy.abi
@@ -0,0 +1 @@
+[{"inputs":[{"internalType":"address","name":"_proxied","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[],"name":"MintingFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"approved","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finishMinting","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"tokenUri","type":"string"}],"name":"mintWithTokenURI","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintingFinished","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFromWithData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"interfaceId","type":"uint32"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]
\ No newline at end of file
addedtests/src/eth/proxy/UniqueNFTProxy.bindiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/proxy/UniqueNFTProxy.bin
@@ -0,0 +1 @@
+608060405234801561001057600080fd5b506040516111e03803806111e083398101604081905261002f91610054565b600080546001600160a01b0319166001600160a01b0392909216919091179055610084565b60006020828403121561006657600080fd5b81516001600160a01b038116811461007d57600080fd5b9392505050565b61114d806100936000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c806350bb4e7f116100c357806395d89b411161007c57806395d89b41146102a8578063a22cb465146102b0578063a9059cbb146102c3578063c87b56dd146102d6578063e985e9c5146102e9578063f4f4b500146102fc57600080fd5b806350bb4e7f1461024c57806360a116721461025f5780636352211e1461027257806370a082311461028557806375794a3c146102985780637d64bcb4146102a057600080fd5b806323b872dd1161011557806323b872dd146101da5780632f745c59146101ed57806340c10f191461020057806342842e0e1461021357806342966c68146102265780634f6ccce71461023957600080fd5b806305d2035b1461015257806306fdde031461016f578063081812fc14610184578063095ea7b3146101af57806318160ddd146101c4575b600080fd5b61015a61030f565b60405190151581526020015b60405180910390f35b61017761039b565b6040516101669190611043565b610197610192366004610f5b565b61041b565b6040516001600160a01b039091168152602001610166565b6101c26101bd366004610e2e565b61049f565b005b6101cc61050a565b604051908152602001610166565b6101c26101e8366004610d3f565b610591565b6101cc6101fb366004610e2e565b610605565b61015a61020e366004610e2e565b610691565b6101c2610221366004610d3f565b610718565b6101c2610234366004610f5b565b610759565b6101cc610247366004610f5b565b6107ba565b61015a61025a366004610e5a565b610838565b6101c261026d366004610d80565b6108c7565b610197610280366004610f5b565b610936565b6101cc610293366004610ccc565b610968565b6101cc61099b565b61015a6109ea565b610177610a4f565b6101c26102be366004610e00565b610a93565b6101c26102d1366004610e2e565b610acd565b6101776102e4366004610f5b565b610b06565b6101976102f7366004610d06565b610b87565b61015a61030a366004610f8d565b610c0d565b60008060009054906101000a90046001600160a01b03166001600160a01b03166305d2035b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561035e57600080fd5b505afa158015610372573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103969190610ec7565b905090565b60008054604080516306fdde0360e01b815290516060936001600160a01b03909316926306fdde039260048082019391829003018186803b1580156103df57600080fd5b505afa1580156103f3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103969190810190610ee4565b6000805460405163020604bf60e21b8152600481018490526001600160a01b039091169063081812fc906024015b60206040518083038186803b15801561046157600080fd5b505afa158015610475573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104999190610ce9565b92915050565b60005460405163095ea7b360e01b81526001600160a01b038481166004830152602482018490529091169063095ea7b3906044015b600060405180830381600087803b1580156104ee57600080fd5b505af1158015610502573d6000803e3d6000fd5b505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561055957600080fd5b505afa15801561056d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103969190610f74565b6000546040516323b872dd60e01b81526001600160a01b038581166004830152848116602483015260448201849052909116906323b872dd906064015b600060405180830381600087803b1580156105e857600080fd5b505af11580156105fc573d6000803e3d6000fd5b50505050505050565b60008054604051632f745c5960e01b81526001600160a01b0385811660048301526024820185905290911690632f745c599060440160206040518083038186803b15801561065257600080fd5b505afa158015610666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068a9190610f74565b9392505050565b600080546040516340c10f1960e01b81526001600160a01b03858116600483015260248201859052909116906340c10f1990604401602060405180830381600087803b1580156106e057600080fd5b505af11580156106f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068a9190610ec7565b600054604051632142170760e11b81526001600160a01b038581166004830152848116602483015260448201849052909116906342842e0e906064016105ce565b600054604051630852cd8d60e31b8152600481018390526001600160a01b03909116906342966c6890602401600060405180830381600087803b15801561079f57600080fd5b505af11580156107b3573d6000803e3d6000fd5b5050505050565b60008054604051634f6ccce760e01b8152600481018490526001600160a01b0390911690634f6ccce7906024015b60206040518083038186803b15801561080057600080fd5b505afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104999190610f74565b600080546040516350bb4e7f60e01b81526001600160a01b03909116906350bb4e7f9061086d9087908790879060040161101c565b602060405180830381600087803b15801561088757600080fd5b505af115801561089b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108bf9190610ec7565b949350505050565b6000546040516330508b3960e11b81526001600160a01b03909116906360a11672906108fd908790879087908790600401610fdf565b600060405180830381600087803b15801561091757600080fd5b505af115801561092b573d6000803e3d6000fd5b505050505b50505050565b600080546040516331a9108f60e11b8152600481018490526001600160a01b0390911690636352211e90602401610449565b600080546040516370a0823160e01b81526001600160a01b038481166004830152909116906370a08231906024016107e8565b60008060009054906101000a90046001600160a01b03166001600160a01b03166375794a3c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561055957600080fd5b60008060009054906101000a90046001600160a01b03166001600160a01b0316637d64bcb46040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610a3b57600080fd5b505af1158015610372573d6000803e3d6000fd5b60008054604080516395d89b4160e01b815290516060936001600160a01b03909316926395d89b419260048082019391829003018186803b1580156103df57600080fd5b60005460405163a22cb46560e01b81526001600160a01b03848116600483015283151560248301529091169063a22cb465906044016104d4565b60005460405163a9059cbb60e01b81526001600160a01b038481166004830152602482018490529091169063a9059cbb906044016104d4565b60005460405163c87b56dd60e01b8152600481018390526060916001600160a01b03169063c87b56dd9060240160006040518083038186803b158015610b4b57600080fd5b505afa158015610b5f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104999190810190610ee4565b6000805460405163e985e9c560e01b81526001600160a01b03858116600483015284811660248301529091169063e985e9c59060440160206040518083038186803b158015610bd557600080fd5b505afa158015610be9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068a9190610ce9565b6000805460405162f4f4b560e81b815263ffffffff841660048201526001600160a01b039091169063f4f4b5009060240160206040518083038186803b158015610c5657600080fd5b505afa158015610c6a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104999190610ec7565b6000610ca1610c9c84611087565b611056565b9050828152838383011115610cb557600080fd5b828260208301376000602084830101529392505050565b600060208284031215610cde57600080fd5b813561068a816110f1565b600060208284031215610cfb57600080fd5b815161068a816110f1565b60008060408385031215610d1957600080fd5b8235610d24816110f1565b91506020830135610d34816110f1565b809150509250929050565b600080600060608486031215610d5457600080fd5b8335610d5f816110f1565b92506020840135610d6f816110f1565b929592945050506040919091013590565b60008060008060808587031215610d9657600080fd5b8435610da1816110f1565b93506020850135610db1816110f1565b925060408501359150606085013567ffffffffffffffff811115610dd457600080fd5b8501601f81018713610de557600080fd5b610df487823560208401610c8e565b91505092959194509250565b60008060408385031215610e1357600080fd5b8235610e1e816110f1565b91506020830135610d3481611109565b60008060408385031215610e4157600080fd5b8235610e4c816110f1565b946020939093013593505050565b600080600060608486031215610e6f57600080fd5b8335610e7a816110f1565b925060208401359150604084013567ffffffffffffffff811115610e9d57600080fd5b8401601f81018613610eae57600080fd5b610ebd86823560208401610c8e565b9150509250925092565b600060208284031215610ed957600080fd5b815161068a81611109565b600060208284031215610ef657600080fd5b815167ffffffffffffffff811115610f0d57600080fd5b8201601f81018413610f1e57600080fd5b8051610f2c610c9c82611087565b818152856020838501011115610f4157600080fd5b610f528260208301602086016110af565b95945050505050565b600060208284031215610f6d57600080fd5b5035919050565b600060208284031215610f8657600080fd5b5051919050565b600060208284031215610f9f57600080fd5b813563ffffffff8116811461068a57600080fd5b60008151808452610fcb8160208601602086016110af565b601f01601f19169290920160200192915050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061101290830184610fb3565b9695505050505050565b60018060a01b0384168152826020820152606060408201526000610f526060830184610fb3565b60208152600061068a6020830184610fb3565b604051601f8201601f1916810167ffffffffffffffff8111828210171561107f5761107f6110db565b604052919050565b600067ffffffffffffffff8211156110a1576110a16110db565b50601f01601f191660200190565b60005b838110156110ca5781810151838201526020016110b2565b838111156109305750506000910152565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461110657600080fd5b50565b801515811461110657600080fdfea2646970667358221220cd50bb20b48b73eddb390585af8699a01cd5f49b79ab50aa532df41df639f36764736f6c63430008070033
\ No newline at end of file
addedtests/src/eth/proxy/UniqueNFTProxy.soldiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/proxy/UniqueNFTProxy.sol
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: OTHER
+
+pragma solidity >=0.8.0 <0.9.0;
+
+import "../api/UniqueNFT.sol";
+
+contract UniqueNFTProxy is UniqueNFT {
+    UniqueNFT proxied;
+
+    constructor(address _proxied) UniqueNFT() {
+        proxied = UniqueNFT(_proxied);
+    }
+
+    function name() external view override returns (string memory) {
+        return proxied.name();
+    }
+
+    function symbol() external view override returns (string memory) {
+        return proxied.symbol();
+    }
+
+    function totalSupply() external view override returns (uint256) {
+        return proxied.totalSupply();
+    }
+
+    function balanceOf(address owner) external view override returns (uint256) {
+        return proxied.balanceOf(owner);
+    }
+
+    function ownerOf(uint256 tokenId) external view override returns (address) {
+        return proxied.ownerOf(tokenId);
+    }
+
+    function safeTransferFromWithData(
+        address from,
+        address to,
+        uint256 tokenId,
+        bytes memory data
+    ) external override {
+        return proxied.safeTransferFromWithData(from, to, tokenId, data);
+    }
+
+    function safeTransferFrom(
+        address from,
+        address to,
+        uint256 tokenId
+    ) external override {
+        return proxied.safeTransferFrom(from, to, tokenId);
+    }
+
+    function transferFrom(
+        address from,
+        address to,
+        uint256 tokenId
+    ) external override {
+        return proxied.transferFrom(from, to, tokenId);
+    }
+
+    function approve(address approved, uint256 tokenId) external override {
+        return proxied.approve(approved, tokenId);
+    }
+
+    function setApprovalForAll(address operator, bool approved)
+        external
+        override
+    {
+        return proxied.setApprovalForAll(operator, approved);
+    }
+
+    function getApproved(uint256 tokenId)
+        external
+        view
+        override
+        returns (address)
+    {
+        return proxied.getApproved(tokenId);
+    }
+
+    function isApprovedForAll(address owner, address operator)
+        external
+        view
+        override
+        returns (address)
+    {
+        return proxied.isApprovedForAll(owner, operator);
+    }
+
+    function burn(uint256 tokenId) external override {
+        return proxied.burn(tokenId);
+    }
+
+    function tokenByIndex(uint256 index)
+        external
+        view
+        override
+        returns (uint256)
+    {
+        return proxied.tokenByIndex(index);
+    }
+
+    function tokenOfOwnerByIndex(address owner, uint256 index)
+        external
+        view
+        override
+        returns (uint256)
+    {
+        return proxied.tokenOfOwnerByIndex(owner, index);
+    }
+
+    function tokenURI(uint256 tokenId)
+        external
+        view
+        override
+        returns (string memory)
+    {
+        return proxied.tokenURI(tokenId);
+    }
+
+    function mintingFinished() external view override returns (bool) {
+        return proxied.mintingFinished();
+    }
+
+    function mint(address to, uint256 tokenId)
+        external
+        override
+        returns (bool)
+    {
+        return proxied.mint(to, tokenId);
+    }
+
+    function mintWithTokenURI(
+        address to,
+        uint256 tokenId,
+        string memory tokenUri
+    ) external override returns (bool) {
+        return proxied.mintWithTokenURI(to, tokenId, tokenUri);
+    }
+
+    function finishMinting() external override returns (bool) {
+        return proxied.finishMinting();
+    }
+
+    function transfer(address to, uint256 tokenId) external override {
+        return proxied.transfer(to, tokenId);
+    }
+
+    function nextTokenId() external view override returns (uint256) {
+        return proxied.nextTokenId();
+    }
+
+    function supportsInterface(uint32 interfaceId)
+        external
+        view
+        override
+        returns (bool)
+    {
+        return proxied.supportsInterface(interfaceId);
+    }
+}
addedtests/src/eth/proxy/fungibleProxy.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/proxy/fungibleProxy.test.ts
@@ -0,0 +1,194 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import privateKey from '../../substrate/privateKey';
+import { createCollectionExpectSuccess, createFungibleItemExpectSuccess } from '../../util/helpers';
+import { collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents } from '../util/helpers';
+import fungibleAbi from '../fungibleAbi.json';
+import { expect } from 'chai';
+import { ApiPromise } from '@polkadot/api';
+import Web3 from 'web3';
+import { readFile } from 'fs/promises';
+
+async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any) {
+  // Proxy owner has no special privilegies, we don't need to reuse them
+  const owner = await createEthAccountWithBalance(api, web3);
+  const Proxy = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueFungibleProxy.abi`)).toString()), undefined, {
+    from: owner,
+    ...GAS_ARGS,
+  });
+  const proxy = await Proxy.deploy({ data: (await readFile(`${__dirname}/UniqueFungibleProxy.bin`)).toString(), arguments: [wrapped.options.address] }).send({ from: owner });
+  return proxy;
+}
+
+describe('Fungible (Via EVM proxy): Information getting', () => {
+  itWeb3('totalSupply', async ({ api, web3 }) => {
+    const collection = await createCollectionExpectSuccess({
+      name: 'token name',
+      mode: { type: 'Fungible', decimalPoints: 0 },
+    });
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+  
+    await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { substrate: alice.address });
+
+    const address = collectionIdToAddress(collection);
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const totalSupply = await contract.methods.totalSupply().call();
+
+    // FIXME: always equals to 0, because this method is not implemented
+    expect(totalSupply).to.equal('0');
+  });
+
+  itWeb3('balanceOf', async ({ api, web3 }) => {
+    const collection = await createCollectionExpectSuccess({
+      name: 'token name',
+      mode: { type: 'Fungible', decimalPoints: 0 },
+    });
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+
+    await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: caller });
+
+    const address = collectionIdToAddress(collection);
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const balance = await contract.methods.balanceOf(caller).call();
+
+    expect(balance).to.equal('200');
+  });
+});
+
+describe('Fungible (Via EVM proxy): Plain calls', () => {
+  itWeb3('Can perform approve()', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      name: 'token name',
+      mode: { type: 'Fungible', decimalPoints: 0 },
+    });
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+    const spender = createEthAccount(web3);
+
+    const address = collectionIdToAddress(collection);
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: contract.options.address });
+
+    {
+      const result = await contract.methods.approve(spender, 100).send({from: caller});
+      const events = normalizeEvents(result.events);
+
+      expect(events).to.be.deep.equal([
+        {
+          address,
+          event: 'Approval',
+          args: {
+            owner: contract.options.address,
+            spender,
+            value: '100',
+          },
+        },
+      ]);
+    }
+
+    {
+      const allowance = await contract.methods.allowance(contract.options.address, spender).call();
+      expect(+allowance).to.equal(100);
+    }
+  });
+
+  itWeb3('Can perform transferFrom()', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      name: 'token name',
+      mode: { type: 'Fungible', decimalPoints: 0 },
+    });
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3);
+
+    await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: owner });
+
+    const receiver = createEthAccount(web3);
+
+    const address = collectionIdToAddress(collection);
+    const evmCollection = new web3.eth.Contract(fungibleAbi as any, address, { from: caller, ...GAS_ARGS });
+    const contract = await proxyWrap(api, web3, evmCollection);
+
+    await evmCollection.methods.approve(contract.options.address, 100).send({from: owner});
+
+    {
+      const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: caller});
+      const events = normalizeEvents(result.events);
+      expect(events).to.be.deep.equal([
+        {
+          address,
+          event: 'Transfer',
+          args: {
+            from: owner,
+            to: receiver,
+            value: '49',
+          },
+        },
+        {
+          address,
+          event: 'Approval',
+          args: {
+            owner,
+            spender: contract.options.address,
+            value: '51',
+          },
+        },
+      ]);
+    }
+
+    {
+      const balance = await contract.methods.balanceOf(receiver).call();
+      expect(+balance).to.equal(49);
+    }
+
+    {
+      const balance = await contract.methods.balanceOf(owner).call();
+      expect(+balance).to.equal(151);
+    }
+  });
+
+  itWeb3('Can perform transfer()', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      name: 'token name',
+      mode: { type: 'Fungible', decimalPoints: 0 },
+    });
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+    const receiver = await createEthAccountWithBalance(api, web3);
+
+    const address = collectionIdToAddress(collection);
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: contract.options.address });
+
+    {
+      const result = await contract.methods.transfer(receiver, 50).send({ from: caller});
+      const events = normalizeEvents(result.events);
+      expect(events).to.be.deep.equal([
+        {
+          address,
+          event: 'Transfer',
+          args: {
+            from: contract.options.address,
+            to: receiver,
+            value: '50',
+          },
+        },
+      ]);
+    }
+
+    {
+      const balance = await contract.methods.balanceOf(contract.options.address).call();
+      expect(+balance).to.equal(150);
+    }
+
+    {
+      const balance = await contract.methods.balanceOf(receiver).call();
+      expect(+balance).to.equal(50);
+    }
+  });
+});
addedtests/src/eth/proxy/nonFungibleProxy.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/proxy/nonFungibleProxy.test.ts
@@ -0,0 +1,270 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import privateKey from '../../substrate/privateKey';
+import { createCollectionExpectSuccess, createItemExpectSuccess } from '../../util/helpers';
+import { collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents } from '../util/helpers';
+import nonFungibleAbi from '../nonFungibleAbi.json';
+import { expect } from 'chai';
+import waitNewBlocks from '../../substrate/wait-new-blocks';
+import { submitTransactionAsync } from '../../substrate/substrate-api';
+import Web3 from 'web3';
+import { readFile } from 'fs/promises';
+import { ApiPromise } from '@polkadot/api';
+
+async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any) {
+  // Proxy owner has no special privilegies, we don't need to reuse them
+  const owner = await createEthAccountWithBalance(api, web3);
+  const Proxy = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueNFTProxy.abi`)).toString()), undefined, {
+    from: owner,
+    ...GAS_ARGS,
+  });
+  const proxy = await Proxy.deploy({ data: (await readFile(`${__dirname}/UniqueNFTProxy.bin`)).toString(), arguments: [wrapped.options.address] }).send({ from: owner });
+  return proxy;
+}
+
+describe('NFT (Via EVM proxy): Information getting', () => {
+  itWeb3('totalSupply', async ({ api, web3 }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+
+    await createItemExpectSuccess(alice, collection, 'NFT', { substrate: alice.address });
+
+    const address = collectionIdToAddress(collection);
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const totalSupply = await contract.methods.totalSupply().call();
+
+    // FIXME: always equals to 0, because this method is not implemented
+    expect(totalSupply).to.equal('0');
+  });
+
+  itWeb3('balanceOf', async ({ api, web3 }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+
+    const caller = await createEthAccountWithBalance(api, web3);
+    await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });
+    await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });
+    await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });
+
+    const address = collectionIdToAddress(collection);
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const balance = await contract.methods.balanceOf(caller).call();
+
+    expect(balance).to.equal('3');
+  });
+
+  itWeb3('ownerOf', async ({ api, web3 }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+
+    const caller = await createEthAccountWithBalance(api, web3);
+    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });
+
+    const address = collectionIdToAddress(collection);
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const owner = await contract.methods.ownerOf(tokenId).call();
+
+    expect(owner).to.equal(caller);
+  });
+});
+
+describe('NFT (Via EVM proxy): Plain calls', () => {
+  itWeb3('Can perform mint()', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+    const receiver = createEthAccount(web3);
+
+    const address = collectionIdToAddress(collection);
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, { from: caller, ...GAS_ARGS }));
+
+    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, { ethereum: contract.options.address });
+    await submitTransactionAsync(alice, changeAdminTx);
+
+    {
+      const nextTokenId = await contract.methods.nextTokenId().call();
+      expect(nextTokenId).to.be.equal('1');
+      console.log('Before mint');
+      const result = await contract.methods.mintWithTokenURI(
+        receiver,
+        nextTokenId,
+        'Test URI',
+      ).send({ from: caller });
+      console.log('After mint');
+      const events = normalizeEvents(result.events);
+
+      expect(events).to.be.deep.equal([
+        {
+          address,
+          event: 'Transfer',
+          args: {
+            from: '0x0000000000000000000000000000000000000000',
+            to: receiver,
+            tokenId: nextTokenId,
+          },
+        },
+      ]);
+
+      await waitNewBlocks(api, 1);
+      expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
+    }
+  });
+
+  itWeb3('Can perform burn()', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: {type: 'NFT'},
+    });
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+    
+    const address = collectionIdToAddress(collection);
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: contract.options.address });
+
+    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, { ethereum: contract.options.address });
+    await submitTransactionAsync(alice, changeAdminTx);
+
+    {
+      const result = await contract.methods.burn(tokenId).send({ from: caller });
+      const events = normalizeEvents(result.events);
+      
+      expect(events).to.be.deep.equal([
+        {
+          address,
+          event: 'Transfer',
+          args: {
+            from: contract.options.address,
+            to: '0x0000000000000000000000000000000000000000',
+            tokenId: tokenId.toString(),
+          },
+        },
+      ]);
+    }
+  });
+
+  itWeb3('Can perform approve()', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+    const spender = createEthAccount(web3);
+
+    const address = collectionIdToAddress(collection);
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address));
+    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: contract.options.address });
+
+    {
+      const result = await contract.methods.approve(spender, tokenId).send({ from: caller, gas: '0x1000000', gasPrice: '0x01' });
+      const events = normalizeEvents(result.events);
+
+      expect(events).to.be.deep.equal([
+        {
+          address,
+          event: 'Approval',
+          args: {
+            owner: contract.options.address,
+            approved: spender,
+            tokenId: tokenId.toString(),
+          },
+        },
+      ]);
+    }
+  });
+
+  itWeb3('Can perform transferFrom()', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3);
+
+    const receiver = createEthAccount(web3);
+
+    const address = collectionIdToAddress(collection);
+    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, address, { from: caller, ...GAS_ARGS });
+    const contract = await proxyWrap(api, web3, evmCollection);
+    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });
+
+    await evmCollection.methods.approve(contract.options.address, tokenId).send({ from: owner });
+
+    {
+      const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({ from: caller });
+      const events = normalizeEvents(result.events);
+      expect(events).to.be.deep.equal([
+        {
+          address,
+          event: 'Transfer',
+          args: {
+            from: owner,
+            to: receiver,
+            tokenId: tokenId.toString(),
+          },
+        },
+      ]);
+    }
+
+    {
+      const balance = await contract.methods.balanceOf(receiver).call();
+      expect(+balance).to.equal(1);
+    }
+
+    {
+      const balance = await contract.methods.balanceOf(contract.options.address).call();
+      expect(+balance).to.equal(0);
+    }
+  });
+
+  itWeb3('Can perform transfer()', async ({ web3, api }) => {
+    const collection = await createCollectionExpectSuccess({
+      mode: { type: 'NFT' },
+    });
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+    const receiver = createEthAccount(web3);
+
+    const address = collectionIdToAddress(collection);
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: contract.options.address });
+
+    {
+      const result = await contract.methods.transfer(receiver, tokenId).send({ from: caller });
+      await waitNewBlocks(api, 1);
+      const events = normalizeEvents(result.events);
+      expect(events).to.be.deep.equal([
+        {
+          address,
+          event: 'Transfer',
+          args: {
+            from: contract.options.address,
+            to: receiver,
+            tokenId: tokenId.toString(),
+          },
+        },
+      ]);
+    }
+
+    {
+      const balance = await contract.methods.balanceOf(contract.options.address).call();
+      expect(+balance).to.equal(0);
+    }
+
+    {
+      const balance = await contract.methods.balanceOf(receiver).call();
+      expect(+balance).to.equal(1);
+    }
+  });
+});
addedtests/src/eth/sponsoring.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/sponsoring.test.ts
@@ -0,0 +1,88 @@
+import { expect } from 'chai';
+import privateKey from '../substrate/privateKey';
+import waitNewBlocks from '../substrate/wait-new-blocks';
+import { contractHelpers, createEthAccount, createEthAccountWithBalance, deployCollector, deployFlipper, itWeb3, transferBalanceToEth, usingWeb3Http } from './util/helpers';
+
+describe('EVM sponsoring', () => {
+  itWeb3('Fee is deducted from contract if sponsoring is enabled', async ({api, web3}) => {
+    await usingWeb3Http(async web3Http => {
+      const alice = privateKey('//Alice');
+
+      const owner = await createEthAccountWithBalance(api, web3Http);
+      const caller = createEthAccount(web3Http);
+      const originalCallerBalance = await web3.eth.getBalance(caller);
+      expect(originalCallerBalance).to.be.equal('0');
+
+      const flipper = await deployFlipper(web3Http, owner);
+      await waitNewBlocks(api, 1);
+      
+      const helpers = contractHelpers(web3Http, owner);
+      await helpers.methods.toggleAllowlist(flipper.options.address, true).send({ from: owner });
+      await waitNewBlocks(api, 1);
+      await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({ from: owner });
+      await waitNewBlocks(api, 1);
+
+      expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
+      await helpers.methods.toggleSponsoring(flipper.options.address, true).send({from: owner});
+      await waitNewBlocks(api, 1);
+      await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});
+      await waitNewBlocks(api, 1);
+      expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
+
+      await transferBalanceToEth(api, alice, flipper.options.address);
+      await waitNewBlocks(api, 2);
+
+      const originalFlipperBalance = await web3.eth.getBalance(flipper.options.address);
+      expect(originalFlipperBalance).to.be.not.equal('0');
+
+      await flipper.methods.flip().send({ from: caller });
+      await waitNewBlocks(api, 1);
+      expect(await flipper.methods.getValue().call()).to.be.true;
+
+      // Balance should be taken from flipper instead of caller
+      expect(await web3.eth.getBalance(caller)).to.be.equals(originalCallerBalance);
+      expect(await web3.eth.getBalance(flipper.options.address)).to.be.not.equals(originalFlipperBalance);
+    });
+  });
+  itWeb3('...but this doesn\'t applies to payable value', async ({api, web3}) => {
+    await usingWeb3Http(async web3Http => {
+      const alice = privateKey('//Alice');
+
+      const owner = await createEthAccountWithBalance(api, web3Http);
+      const caller = await createEthAccountWithBalance(api, web3Http);
+      await waitNewBlocks(api, 1);
+      const originalCallerBalance = await web3.eth.getBalance(caller);
+      expect(originalCallerBalance).to.be.not.equal('0');
+
+      const collector = await deployCollector(web3Http, owner);
+      await waitNewBlocks(api, 1);
+     
+      const helpers = contractHelpers(web3Http, owner);
+      await helpers.methods.toggleAllowlist(collector.options.address, true).send({ from: owner });
+      await waitNewBlocks(api, 1);
+      await helpers.methods.toggleAllowed(collector.options.address, caller, true).send({ from: owner });
+      await waitNewBlocks(api, 1);
+
+      expect(await helpers.methods.sponsoringEnabled(collector.options.address).call()).to.be.false;
+      await helpers.methods.toggleSponsoring(collector.options.address, true).send({ from: owner });
+      await waitNewBlocks(api, 1);
+      await helpers.methods.setSponsoringRateLimit(collector.options.address, 0).send({ from: owner });
+      await waitNewBlocks(api, 1);
+      expect(await helpers.methods.sponsoringEnabled(collector.options.address).call()).to.be.true;
+
+      await transferBalanceToEth(api, alice, collector.options.address);
+      await waitNewBlocks(api, 2);
+
+      const originalCollectorBalance = await web3.eth.getBalance(collector.options.address);
+      expect(originalCollectorBalance).to.be.not.equal('0');
+
+      await collector.methods.giveMoney().send({ from: caller, value: '10000' });
+      await waitNewBlocks(api, 1);
+
+      // Balance will be taken from both caller (value) and from collector (fee)
+      expect(await web3.eth.getBalance(caller)).to.be.equals((BigInt(originalCallerBalance) - 10000n).toString());
+      expect(await web3.eth.getBalance(collector.options.address)).to.be.not.equals(originalCollectorBalance);
+      expect(await collector.methods.getCollected().call()).to.be.equal('10000');
+    });
+  });
+});
\ No newline at end of file
addedtests/src/eth/util/contractHelpersAbi.jsondiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/util/contractHelpersAbi.json
@@ -0,0 +1,160 @@
+[
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "contract",
+                "type": "address"
+            }
+        ],
+        "name": "allowlistEnabled",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "target",
+                "type": "address"
+            },
+            {
+                "internalType": "address",
+                "name": "caller",
+                "type": "address"
+            }
+        ],
+        "name": "allowed",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "target",
+                "type": "address"
+            }
+        ],
+        "name": "contractOwner",
+        "outputs": [
+            {
+                "internalType": "address",
+                "name": "",
+                "type": "address"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "target",
+                "type": "address"
+            }
+        ],
+        "name": "sponsoringEnabled",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "target",
+                "type": "address"
+            },
+            {
+                "internalType": "address",
+                "name": "user",
+                "type": "address"
+            },
+            {
+                "internalType": "bool",
+                "name": "isAllowed",
+                "type": "bool"
+            }
+        ],
+        "name": "toggleAllowed",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "target",
+                "type": "address"
+            },
+            {
+                "internalType": "bool",
+                "name": "enabled",
+                "type": "bool"
+            }
+        ],
+        "name": "toggleAllowlist",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "target",
+                "type": "address"
+            },
+            {
+                "internalType": "bool",
+                "name": "enabled",
+                "type": "bool"
+            }
+        ],
+        "name": "toggleSponsoring",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "target",
+                "type": "address"
+            },
+            {
+                "internalType": "uint32",
+                "name": "limit",
+                "type": "uint32"
+            }
+        ],
+        "name": "setSponsoringRateLimit",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    }
+]
\ No newline at end of file
addedtests/src/eth/util/helpers.d.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/util/helpers.d.ts
@@ -0,0 +1 @@
+declare module 'solc';
\ No newline at end of file
modifiedtests/src/eth/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/eth/util/helpers.ts
+++ b/tests/src/eth/util/helpers.ts
@@ -3,6 +3,9 @@
 // file 'LICENSE', which is part of this source code package.
 //
 
+// eslint-disable-next-line @typescript-eslint/triple-slash-reference
+/// <reference path="helpers.d.ts" />
+
 import { ApiPromise } from '@polkadot/api';
 import { addressToEvm, evmToAddress } from '@polkadot/util-crypto';
 import Web3 from 'web3';
@@ -10,13 +13,21 @@
 import { IKeyringPair } from '@polkadot/types/types';
 import { expect } from 'chai';
 import { getGenericResult } from '../../util/helpers';
+import * as solc from 'solc';
+import config from '../../config';
+import privateKey from '../../substrate/privateKey';
+import contractHelpersAbi from './contractHelpersAbi.json';
+import getBalance from '../../substrate/get-balance';
+import waitNewBlocks from '../../substrate/wait-new-blocks';
+
+export const GAS_ARGS = { gas: 0x1000000, gasPrice: '0x01' };
 
 let web3Connected = false;
 export async function usingWeb3<T>(cb: (web3: Web3) => Promise<T> | T): Promise<T> {
   if (web3Connected) throw new Error('do not nest usingWeb3 calls');
   web3Connected = true;
 
-  const provider = new Web3.providers.WebsocketProvider('http://localhost:9944');
+  const provider = new Web3.providers.WebsocketProvider(config.substrateUrl);
   const web3 = new Web3(provider);
 
   try {
@@ -28,6 +39,16 @@
   }
 }
 
+/**
+ * @deprecated Web3 update solved issue with deployment over ws provider
+ */
+export async function usingWeb3Http<T>(cb: (web3: Web3) => Promise<T> | T): Promise<T> {
+  const provider = new Web3.providers.HttpProvider(config.frontierUrl);
+  const web3: Web3 = new Web3(provider);
+
+  return await cb(web3);
+}
+
 export function collectionIdToAddress(address: number): string {
   if (address >= 0xffffffff || address < 0) throw new Error('id overflow');
   const buf = Buffer.from([0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,
@@ -45,7 +66,15 @@
   return account.address;
 }
 
-export async function transferBalanceToEth(api: ApiPromise, source: IKeyringPair, target: string, amount: number) {
+export async function createEthAccountWithBalance(api: ApiPromise, web3: Web3) {
+  const alice = privateKey('//Alice');
+  const account = createEthAccount(web3);
+  await transferBalanceToEth(api, alice, account);
+
+  return account;
+}
+
+export async function transferBalanceToEth(api: ApiPromise, source: IKeyringPair, target: string, amount = 999999999999999) {
   const tx = api.tx.balances.transfer(evmToAddress(target), amount);
   const events = await submitTransactionAsync(source, tx);
   const result = getGenericResult(events);
@@ -114,8 +143,130 @@
   return normalizeEvents(out);
 }
 
+export function subToEthLowercase(eth: string): string {
+  const bytes = addressToEvm(eth);
+  return '0x' + Buffer.from(bytes).toString('hex');
+}
+
 export function subToEth(eth: string): string {
-  const bytes = addressToEvm(eth);
-  const string = '0x' + Buffer.from(bytes).toString('hex');
-  return Web3.utils.toChecksumAddress(string);
+  return Web3.utils.toChecksumAddress(subToEthLowercase(eth));
+}
+
+export function compileContract(name: string, src: string) {
+  const out = JSON.parse(solc.compile(JSON.stringify({
+    language: 'Solidity',
+    sources: {
+      [`${name}.sol`]: {
+        content: `
+          // SPDX-License-Identifier: UNLICENSED
+          pragma solidity ^0.8.6;
+
+          ${src}
+        `,
+      },
+    },
+    settings: {
+      outputSelection: {
+        '*': {
+          '*': ['*'],
+        },
+      },
+    },
+  }))).contracts[`${name}.sol`][name];
+
+  return {
+    abi: out.abi,
+    object: '0x' + out.evm.bytecode.object,
+  };
+}
+
+export async function deployFlipper(web3: Web3, deployer: string) {
+  const compiled = compileContract('Flipper', `
+    contract Flipper {
+      bool value = false;
+      function flip() public {
+        value = !value;
+      }
+      function getValue() public view returns (bool) {
+        return value;
+      }
+    }
+  `);
+  const Flipper = new web3.eth.Contract(compiled.abi, undefined, {
+    data: compiled.object,
+    from: deployer,
+    ...GAS_ARGS,
+  });
+  const flipper = await Flipper.deploy({ data: compiled.object }).send({from: deployer});
+
+  return flipper;
+}
+
+export async function deployCollector(web3: Web3, deployer: string) {
+  const compiled = compileContract('Collector', `
+    contract Collector {
+      uint256 collected;
+      fallback() external payable {
+        giveMoney();
+      }
+      function giveMoney() public payable {
+        collected += msg.value;
+      }
+      function getCollected() public view returns (uint256) {
+        return collected;
+      }
+      function getUnaccounted() public view returns (uint256) {
+        return address(this).balance - collected;
+      }
+
+      function withdraw(address payable target) public {
+        target.transfer(collected);
+        collected = 0;
+      }
+    }
+  `);
+  const Collector = new web3.eth.Contract(compiled.abi, undefined, {
+    data: compiled.object,
+    from: deployer,
+    ...GAS_ARGS,
+  });
+  const collector = await Collector.deploy({ data: compiled.object }).send({ from: deployer });
+
+  return collector;
+}
+
+export function contractHelpers(web3: Web3, caller: string) {
+  return new web3.eth.Contract(contractHelpersAbi as any, '0x842899ECF380553E8a4de75bF534cdf6fBF64049', {from: caller, ...GAS_ARGS});
+}
+
+export async function executeEthTxOnSub(api: ApiPromise, from: IKeyringPair, to: any, mkTx: (methods: any) => any, { value = 0 }: {value?: bigint | number} = { }) {
+  const tx = api.tx.evm.call(
+    subToEth(from.address),
+    to.options.address,
+    mkTx(to.methods).encodeABI(),
+    value,
+    GAS_ARGS.gas,
+    GAS_ARGS.gasPrice,
+    null,
+  );
+  const events = await submitTransactionAsync(from, tx);
+  expect(events.find(({ event: {section, method}})=>section === 'evm' && method === 'Executed')).to.be.not.undefined;
+}
+
+export async function ethBalanceViaSub(api: ApiPromise, address: string): Promise<bigint> {
+  return (await getBalance(api, [evmToAddress(address)]))[0];
+}
+
+export async function recordEthFee(api: ApiPromise, user: string, call: () => Promise<any>): Promise<bigint> {
+  const before = await ethBalanceViaSub(api, user);
+
+  await call();
+  await waitNewBlocks(api, 1);
+
+  const after = await ethBalanceViaSub(api, user);
+
+  // Can't use .to.be.less, because chai doesn't supports bigint
+  expect(after < before).to.be.true;
+
+  return before - after;
 }
\ 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
@@ -23,6 +23,9 @@
   'parachainsystem',
   'parachaininfo',
   'evm',
+  'evmcodersubstrate',
+  'evmcontracthelpers',
+  'evmtransactionpayment',
   'ethereum',
   'xcmpqueue',
   'polkadotxcm',
@@ -59,7 +62,7 @@
   });
   it('No extra pallets are included', async () => {
     await usingApi(async api => {
-      expect(getModuleNames(api).length).to.be.equal(requiredPallets.length + consensusPallets.length);
+      expect(getModuleNames(api).sort()).to.be.deep.equal([...requiredPallets, ...consensusPallets].sort());
     });
   });
 });
modifiedtests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth
--- a/tests/src/removeCollectionAdmin.test.ts
+++ b/tests/src/removeCollectionAdmin.test.ts
@@ -37,6 +37,33 @@
     });
   });
 
+  it('Remove collection admin by admin.', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const Alice = privateKey('//Alice');
+      const Bob = privateKey('//Bob');
+      const Charlie = privateKey('//Charlie');
+      const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      expect(collection.Owner).to.be.deep.eq(Alice.address);
+      // first - add collection admin Bob
+      const addAdminTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
+      await submitTransactionAsync(Alice, addAdminTx);
+
+      const addAdminTx2 = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Charlie.address));
+      await submitTransactionAsync(Alice, addAdminTx2);
+
+      const adminListAfterAddAdmin: any = (await api.query.nft.adminList(collectionId)).toJSON();
+      expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(Bob.address));
+
+      // then remove bob from admins of collection
+      const removeAdminTx = api.tx.nft.removeCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
+      await submitTransactionAsync(Charlie, removeAdminTx);
+
+      const adminListAfterRemoveAdmin: any = (await api.query.nft.adminList(collectionId)).toJSON;
+      expect(adminListAfterRemoveAdmin).not.to.be.deep.contains(normalizeAccountId(Bob.address));
+    });
+  });
+
   it('Remove admin from collection that has no admins', async () => {
     await usingApi(async (api: ApiPromise) => {
       const Alice = privateKey('//Alice');
@@ -83,4 +110,22 @@
       await createCollectionExpectSuccess();
     });
   });
+
+  it('Regular user Can\'t remove collection admin', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const Alice = privateKey('//Alice');
+      const Bob = privateKey('//Bob');
+      const Charlie = privateKey('//Charlie');
+
+      const addAdminTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
+      await submitTransactionAsync(Alice, addAdminTx);
+
+      const changeOwnerTx = api.tx.nft.removeCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
+      await expect(submitTransactionExpectFailAsync(Charlie, changeOwnerTx)).to.be.rejected;
+
+      // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
+      await createCollectionExpectSuccess();
+    });
+  });
 });
modifiedtests/src/removeCollectionSponsor.test.tsdiffbeforeafterboth
--- a/tests/src/removeCollectionSponsor.test.ts
+++ b/tests/src/removeCollectionSponsor.test.ts
@@ -17,6 +17,7 @@
   removeCollectionSponsorExpectSuccess,
   removeCollectionSponsorExpectFailure,
   normalizeAccountId,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 import { Keyring } from '@polkadot/api';
 import { IKeyringPair } from '@polkadot/types/types';
@@ -104,6 +105,19 @@
     await removeCollectionSponsorExpectFailure(collectionId);
   });
 
+  it('(!negative test!) Remove sponsor for a collection with collection admin permissions', async () => {
+    const collectionId = await createCollectionExpectSuccess();
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await addCollectionAdminExpectSuccess(alice, collectionId, bob);
+    await removeCollectionSponsorExpectFailure(collectionId, '//Bob');
+  });
+
+  it('(!negative test!) Remove sponsor for a collection by regular user', async () => {
+    const collectionId = await createCollectionExpectSuccess();
+    await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+    await removeCollectionSponsorExpectFailure(collectionId, '//Bob');
+  });
+
   it('(!negative test!) Remove sponsor in a destroyed collection', async () => {
     const collectionId = await createCollectionExpectSuccess();
     await setCollectionSponsorExpectSuccess(collectionId, bob.address);
modifiedtests/src/removeFromWhiteList.test.tsdiffbeforeafterboth
--- a/tests/src/removeFromWhiteList.test.ts
+++ b/tests/src/removeFromWhiteList.test.ts
@@ -17,6 +17,7 @@
   removeFromWhiteListExpectFailure,
   disableWhiteListExpectSuccess,
   normalizeAccountId,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 import { IKeyringPair } from '@polkadot/types/types';
 import privateKey from './substrate/privateKey';
@@ -88,3 +89,48 @@
     });
   });
 });
+
+describe('Integration Test removeFromWhiteList with collection admin permissions', () => {
+  let alice: IKeyringPair;
+  let bob: IKeyringPair;
+  let charlie: IKeyringPair;
+
+  before(async () => {
+    await usingApi(async () => {
+      alice = privateKey('//Alice');
+      bob = privateKey('//Bob');
+      charlie = privateKey('//Charlie');
+    });
+  });
+
+  it('ensure address is not in whitelist after removal', async () => {
+    await usingApi(async () => {
+      const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+      await enableWhiteListExpectSuccess(alice, collectionId);
+      await addCollectionAdminExpectSuccess(alice, collectionId, bob);
+      await addToWhiteListExpectSuccess(alice, collectionId, charlie.address);
+      await removeFromWhiteListExpectSuccess(bob, collectionId, normalizeAccountId(charlie.address));
+      expect(await isWhitelisted(collectionId, charlie.address)).to.be.false;
+    });
+  });
+
+  it('Collection admin allowed to remove from whitelist with unset whitelist status', async () => {
+    await usingApi(async () => {
+      const collectionWithoutWhitelistId = await createCollectionExpectSuccess();
+      await enableWhiteListExpectSuccess(alice, collectionWithoutWhitelistId);
+      await addCollectionAdminExpectSuccess(alice, collectionWithoutWhitelistId, bob);
+      await addToWhiteListExpectSuccess(alice, collectionWithoutWhitelistId, charlie.address);
+      await disableWhiteListExpectSuccess(alice, collectionWithoutWhitelistId);
+      await removeFromWhiteListExpectSuccess(bob, collectionWithoutWhitelistId, normalizeAccountId(charlie.address));
+    });
+  });
+
+  it('Regular user can`t remove from whitelist', async () => {
+    await usingApi(async () => {
+      const collectionWithoutWhitelistId = await createCollectionExpectSuccess();
+      await enableWhiteListExpectSuccess(alice, collectionWithoutWhitelistId);
+      await addToWhiteListExpectSuccess(alice, collectionWithoutWhitelistId, charlie.address);
+      await removeFromWhiteListExpectFailure(bob, collectionWithoutWhitelistId, normalizeAccountId(charlie.address));
+    });
+  });
+});
\ No newline at end of file
addedtests/src/setChainLimits.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/setChainLimits.test.ts
@@ -0,0 +1,56 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { IKeyringPair } from '@polkadot/types/types';
+import privateKey from './substrate/privateKey';
+import usingApi from './substrate/substrate-api';
+import {
+  createCollectionExpectSuccess,
+  addCollectionAdminExpectSuccess,
+  setChainLimitsExpectFailure,
+  IChainLimits,
+} from './util/helpers';
+
+describe('Negative Integration Test setChainLimits', () => {
+  let alice: IKeyringPair;
+  let bob: IKeyringPair;
+  let dave: IKeyringPair;
+  let limits: IChainLimits;
+
+  before(async () => {
+    await usingApi(async () => {
+      alice = privateKey('//Alice');
+      bob = privateKey('//Bob');
+      dave = privateKey('//Dave');
+      limits = {
+        CollectionNumbersLimit : 1,
+        AccountTokenOwnershipLimit: 1,
+        CollectionsAdminsLimit: 1,
+        CustomDataLimit: 1,
+        NftSponsorTransferTimeout: 1,
+        FungibleSponsorTransferTimeout: 1,
+        RefungibleSponsorTransferTimeout: 1,
+        OffchainSchemaLimit: 1,
+        VariableOnChainSchemaLimit: 1,
+        ConstOnChainSchemaLimit: 1,
+      };
+    });
+  });
+
+  it('Collection owner cannot set chain limits', async () => {
+    await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+    await setChainLimitsExpectFailure(alice, limits);
+  });
+
+  it('Collection admin cannot set chain limits', async () => {
+    const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+    await addCollectionAdminExpectSuccess(alice, collectionId, bob);
+    await setChainLimitsExpectFailure(bob, limits);
+  });
+  
+  it('Regular user cannot set chain limits', async () => {
+    await setChainLimitsExpectFailure(dave, limits);
+  });
+});
modifiedtests/src/setCollectionLimits.test.tsdiffbeforeafterboth
--- a/tests/src/setCollectionLimits.test.ts
+++ b/tests/src/setCollectionLimits.test.ts
@@ -16,6 +16,7 @@
   getDetailedCollectionInfo,
   setCollectionLimitsExpectFailure,
   setCollectionLimitsExpectSuccess,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -150,6 +151,21 @@
       await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected;
     });
   });
+  it('execute setCollectionLimits from admin collection', async () => {
+    await addCollectionAdminExpectSuccess(alice, collectionIdForTesting, bob);
+    await usingApi(async (api: ApiPromise) => {
+      tx = api.tx.nft.setCollectionLimits(
+        collectionIdForTesting,
+        {
+          accountTokenOwnershipLimit,
+          sponsoredDataSize,
+          sponsoredMintSize,
+          tokenLimit,
+        },
+      );
+      await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected;
+    });
+  });
   it('execute setCollectionLimits with incorrect limits', async () => {
     await usingApi(async (api: ApiPromise) => {
       tx = api.tx.nft.setCollectionLimits(
modifiedtests/src/setCollectionSponsor.test.tsdiffbeforeafterboth
--- a/tests/src/setCollectionSponsor.test.ts
+++ b/tests/src/setCollectionSponsor.test.ts
@@ -6,19 +6,27 @@
 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 { createCollectionExpectSuccess, 
+  setCollectionSponsorExpectSuccess, 
+  destroyCollectionExpectSuccess, 
+  setCollectionSponsorExpectFailure,
+  addCollectionAdminExpectSuccess,
+} from './util/helpers';
 import { Keyring } from '@polkadot/api';
 import { IKeyringPair } from '@polkadot/types/types';
 
 chai.use(chaiAsPromised);
 
+let alice: IKeyringPair;
 let bob: IKeyringPair;
+let charlie: IKeyringPair;
 
 describe('integration test: ext. setCollectionSponsor():', () => {
 
   before(async () => {
     await usingApi(async () => {
       const keyring = new Keyring({ type: 'sr25519' });
+      alice = keyring.addFromUri('//Alice');
       bob = keyring.addFromUri('//Bob');
     });
   });
@@ -55,7 +63,9 @@
   before(async () => {
     await usingApi(async () => {
       const keyring = new Keyring({ type: 'sr25519' });
+      alice = keyring.addFromUri('//Alice');
       bob = keyring.addFromUri('//Bob');
+      charlie = keyring.addFromUri('//Charlie');
     });
   });
 
@@ -77,4 +87,9 @@
     await destroyCollectionExpectSuccess(collectionId);
     await setCollectionSponsorExpectFailure(collectionId, bob.address);
   });
+  it('(!negative test!) Collection admin add sponsor', async () => {
+    const collectionId = await createCollectionExpectSuccess();
+    await addCollectionAdminExpectSuccess(alice, collectionId, bob);
+    await setCollectionSponsorExpectFailure(collectionId, charlie.address, '//Bob');
+  });
 });
modifiedtests/src/setConstOnChainSchema.test.tsdiffbeforeafterboth
--- a/tests/src/setConstOnChainSchema.test.ts
+++ b/tests/src/setConstOnChainSchema.test.ts
@@ -11,6 +11,7 @@
 import {
   createCollectionExpectSuccess,
   destroyCollectionExpectSuccess,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -43,6 +44,17 @@
     });
   });
 
+  it('Collection admin can set the scheme', async () => {
+    await usingApi(async (api) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      expect(collection.Owner).to.be.eq(Alice.address);
+      await addCollectionAdminExpectSuccess(Alice, collectionId, Bob);
+      const setShema = api.tx.nft.setConstOnChainSchema(collectionId, Shema);
+      await submitTransactionAsync(Bob, setShema);
+    });
+  });
+
   it('Checking collection data using the ConstOnChainSchema parameter', async () => {
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
modifiedtests/src/setMintPermission.test.tsdiffbeforeafterboth
--- a/tests/src/setMintPermission.test.ts
+++ b/tests/src/setMintPermission.test.ts
@@ -16,6 +16,7 @@
   findNotExistingCollection,
   setMintPermissionExpectFailure,
   setMintPermissionExpectSuccess,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 
 describe('Integration Test setMintPermission', () => {
@@ -91,6 +92,14 @@
     await setMintPermissionExpectFailure(bob, collectionId, true);
   });
 
+  it('Collection admin fails on set', async () => {
+    await usingApi(async () => {
+      const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+      await addCollectionAdminExpectSuccess(alice, collectionId, bob);
+      await setMintPermissionExpectFailure(bob, collectionId, true);
+    });
+  });
+
   it('ensure non-white-listed non-privileged address can\'t mint tokens', async () => {
     await usingApi(async () => {
       const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
modifiedtests/src/setOffchainSchema.test.tsdiffbeforeafterboth
--- a/tests/src/setOffchainSchema.test.ts
+++ b/tests/src/setOffchainSchema.test.ts
@@ -15,6 +15,7 @@
   queryCollectionExpectSuccess,
   setOffchainSchemaExpectFailure,
   setOffchainSchemaExpectSuccess,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -24,10 +25,12 @@
 
 describe('Integration Test setOffchainSchema', () => {
   let alice: IKeyringPair;
+  let bob: IKeyringPair;
 
   before(async () => {
     await usingApi(async () => {
       alice = privateKey('//Alice');
+      bob = privateKey('//Bob');
     });
   });
 
@@ -38,6 +41,15 @@
 
     expect(collection.OffchainSchema).to.be.equal('0x' + Buffer.from(DATA).toString('hex'));
   });
+
+  it('execute setOffchainSchema (collection admin), verify data was set', async () => {
+    const collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+    await addCollectionAdminExpectSuccess(alice, collectionId, bob);
+    await setOffchainSchemaExpectSuccess(bob, collectionId, DATA);
+    const collection = await queryCollectionExpectSuccess(collectionId);
+
+    expect(collection.OffchainSchema).to.be.equal('0x' + Buffer.from(DATA).toString('hex'));
+  });
 });
 
 describe('Negative Integration Test setOffchainSchema', () => {
modifiedtests/src/setPublicAccessMode.test.tsdiffbeforeafterboth
--- a/tests/src/setPublicAccessMode.test.ts
+++ b/tests/src/setPublicAccessMode.test.ts
@@ -18,6 +18,7 @@
   enablePublicMintingExpectSuccess,
   enableWhiteListExpectSuccess,
   normalizeAccountId,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -92,3 +93,21 @@
     });
   });
 });
+
+describe('Negative Integration Test ext. collection admin setPublicAccessMode(): ', () => {
+  before(async () => {
+    await usingApi(async () => {
+      Alice = privateKey('//Alice');
+      Bob = privateKey('//Bob');
+    });
+  });
+  it('setPublicAccessMode by collection admin', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      // tslint:disable-next-line: no-bitwise
+      const collectionId = await createCollectionExpectSuccess();
+      await addCollectionAdminExpectSuccess(Alice, collectionId, Bob);
+      const tx = api.tx.nft.setPublicAccessMode(collectionId, 'WhiteList');
+      await expect(submitTransactionExpectFailAsync(Bob, tx)).to.be.rejected;
+    });
+  });
+});
modifiedtests/src/setSchemaVersion.test.tsdiffbeforeafterboth
--- a/tests/src/setSchemaVersion.test.ts
+++ b/tests/src/setSchemaVersion.test.ts
@@ -16,12 +16,15 @@
   getCreatedCollectionCount,
   getCreateItemResult,
   getDetailedCollectionInfo,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
 const expect = chai.expect;
 
 let alice: IKeyringPair;
+let bob: IKeyringPair;
+let charlie: IKeyringPair;
 let collectionIdForTesting: number;
 
 /*
@@ -66,11 +69,37 @@
       expect(collectionInfo ? collectionInfo.SchemaVersion.toString() : '').to.be.equal('Unique');
     });
   });
+});
+
+describe('Collection admin setSchemaVersion positive', () => {
+  let tx;
+  before(async () => {
+    await usingApi(async () => {
+      const keyring = new Keyring({ type: 'sr25519' });
+      alice = keyring.addFromUri('//Alice');
+      bob = keyring.addFromUri('//Bob');
+      await addCollectionAdminExpectSuccess(alice, collectionIdForTesting, bob);
+    });
+  });
+  it('execute setSchemaVersion with image url and unique ', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      tx = api.tx.nft.setSchemaVersion(collectionIdForTesting, 'Unique');
+      const events = await submitTransactionAsync(bob, tx);
+      const result = getCreateItemResult(events);
+      const collectionInfo = await getDetailedCollectionInfo(api, collectionIdForTesting) as ICollectionInterface;
+      // tslint:disable-next-line:no-unused-expression
+      expect(result.success).to.be.true;
+      // tslint:disable-next-line:no-unused-expression
+      expect(collectionInfo).to.be.exist;
+      // tslint:disable-next-line:no-unused-expression
+      expect(collectionInfo ? collectionInfo.SchemaVersion.toString() : '').to.be.equal('Unique');
+    });
+  });
 
   it('validate schema version with just entered data', async () => {
     await usingApi(async (api: ApiPromise) => {
       tx = api.tx.nft.setSchemaVersion(collectionIdForTesting, 'ImageURL');
-      const events = await submitTransactionAsync(alice, tx);
+      const events = await submitTransactionAsync(bob, tx);
       const result = getCreateItemResult(events);
       const collectionInfo = await getDetailedCollectionInfo(api, collectionIdForTesting) as ICollectionInterface;
       // tslint:disable-next-line:no-unused-expression
@@ -89,6 +118,7 @@
     await usingApi(async () => {
       const keyring = new Keyring({ type: 'sr25519' });
       alice = keyring.addFromUri('//Alice');
+      charlie = keyring.addFromUri('//Charlie');
     });
   });
   it('execute setSchemaVersion for not exists collection', async () => {
@@ -99,7 +129,6 @@
       await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;
     });
   });
-
   it('execute setSchemaVersion with not correct schema version', async () => {
     await usingApi(async (api: ApiPromise) => {
       const consoleError = console.error;
@@ -115,7 +144,6 @@
       }
     });
   });
-
   it('execute setSchemaVersion for deleted collection', async () => {
     await usingApi(async (api: ApiPromise) => {
       await destroyCollectionExpectSuccess(collectionIdForTesting);
@@ -123,4 +151,10 @@
       await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;
     });
   });
+  it('Regular user can`t execute setSchemaVersion with image url and unique ', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      tx = api.tx.nft.setSchemaVersion(collectionIdForTesting, 'Unique');
+      await expect(submitTransactionAsync(charlie, tx)).to.be.rejected;
+    });
+  });
 });
modifiedtests/src/setVariableMetaData.test.tsdiffbeforeafterboth
--- a/tests/src/setVariableMetaData.test.ts
+++ b/tests/src/setVariableMetaData.test.ts
@@ -16,6 +16,7 @@
   findNotExistingCollection,
   setVariableMetaDataExpectFailure,
   setVariableMetaDataExpectSuccess,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -48,6 +49,36 @@
   });
 });
 
+describe('Integration Test collection admin setVariableMetaData', () => {
+  const data = [1, 2, 254, 255];
+
+  let alice: IKeyringPair;
+  let bob: IKeyringPair;
+  let collectionId: number;
+  let tokenId: number;
+  before(async () => {
+    await usingApi(async () => {
+      alice = privateKey('//Alice');
+      bob = privateKey('//Bob');
+      collectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+      tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');
+      await addCollectionAdminExpectSuccess(alice, collectionId, bob);
+    });
+  });
+
+  it('execute setVariableMetaData', async () => {
+    await setVariableMetaDataExpectSuccess(bob, collectionId, tokenId, data);
+  });
+
+  it('verify data was set', async () => {
+    await usingApi(async api => {
+      const item: any = (await api.query.nft.nftItemList(collectionId, tokenId) as any).unwrap();
+
+      expect(Array.from(item.VariableData)).to.deep.equal(Array.from(data));
+    });
+  });
+});
+
 describe('Negative Integration Test setVariableMetaData', () => {
   const data = [1];
 
modifiedtests/src/setVariableOnChainSchema.test.tsdiffbeforeafterboth
--- a/tests/src/setVariableOnChainSchema.test.ts
+++ b/tests/src/setVariableOnChainSchema.test.ts
@@ -11,6 +11,7 @@
 import {
   createCollectionExpectSuccess,
   destroyCollectionExpectSuccess,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -55,6 +56,32 @@
   });
 });
 
+describe('Integration Test ext. collection admin setVariableOnChainSchema()', () => {
+
+  it('Run extrinsic with parameters of the collection id, set the scheme', async () => {
+    await usingApi(async (api) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      expect(collection.Owner).to.be.eq(Alice.address);
+      await addCollectionAdminExpectSuccess(Alice, collectionId, Bob);
+      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
+      await submitTransactionAsync(Bob, setSchema);
+    });
+  });
+
+  it('Checking collection data using the setVariableOnChainSchema parameter', async () => {
+    await usingApi(async (api) => {
+      const collectionId = await createCollectionExpectSuccess();
+      await addCollectionAdminExpectSuccess(Alice, collectionId, Bob);
+      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
+      await submitTransactionAsync(Bob, setSchema);
+      const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      expect(collection.VariableOnChainSchema.toString()).to.be.eq(Schema);
+
+    });
+  });
+});
+
 describe('Negative Integration Test ext. setVariableOnChainSchema()', () => {
 
   it('Set a non-existent collection', async () => {
modifiedtests/src/substrate/get-balance.tsdiffbeforeafterboth
--- a/tests/src/substrate/get-balance.ts
+++ b/tests/src/substrate/get-balance.ts
@@ -6,9 +6,24 @@
 import { ApiPromise } from '@polkadot/api';
 import {AccountInfo} from '@polkadot/types/interfaces/system';
 import promisifySubstrate from './promisify-substrate';
+import { IKeyringPair } from '@polkadot/types/types';
+import { submitTransactionAsync } from './substrate-api';
+import { getGenericResult } from '../util/helpers';
+import { expect } from 'chai';
 
 export default async function getBalance(api: ApiPromise, accounts: string[]): Promise<Array<bigint>> {
   const balance = promisifySubstrate(api, (acc: string[]) => api.query.system.account.multi(acc));
   const responce = await balance(accounts) as unknown as AccountInfo[];
   return responce.map((r) => r.data.free.toBigInt().valueOf());
 }
+
+export async function getBalanceSingle(api: ApiPromise, account: string): Promise<bigint> {
+  return (await getBalance(api, [account]))[0];
+}
+
+export async function transferBalanceExpectSuccess(api: ApiPromise, from: IKeyringPair, to: string, amount: bigint | string) {
+  const tx = api.tx.balances.transfer(to, amount);
+  const events = await submitTransactionAsync(from, tx);
+  const result = getGenericResult(events);
+  expect(result.success).to.be.true;
+}
\ No newline at end of file
modifiedtests/src/substrate/substrate-api.tsdiffbeforeafterboth
--- a/tests/src/substrate/substrate-api.ts
+++ b/tests/src/substrate/substrate-api.ts
@@ -37,6 +37,10 @@
   const consoleWarn = console.warn;
 
   const outFn = (message: string) => {
+    if (typeof message !== 'string') {
+      consoleErr(message);
+      return;
+    }
     if (!message.includes('StorageChangeSet:: WebSocket is not connected') && 
         !message.includes('2021-') &&
         !message.includes('StorageChangeSet:: Normal connection closure'))
modifiedtests/src/transfer.test.tsdiffbeforeafterboth
--- a/tests/src/transfer.test.ts
+++ b/tests/src/transfer.test.ts
@@ -18,6 +18,7 @@
   getCreateItemResult,
   transferExpectFailure,
   transferExpectSuccess,
+  addCollectionAdminExpectSuccess,
 } from './util/helpers';
 
 let Alice: IKeyringPair;
@@ -89,6 +90,35 @@
       );
     });
   });
+
+  it('Collection admin can transfer owned token', async () => {
+    await usingApi(async () => {
+      const Alice = privateKey('//Alice');
+      const Bob = privateKey('//Bob');
+      // nft
+      const nftCollectionId = await createCollectionExpectSuccess();
+      await addCollectionAdminExpectSuccess(Alice, nftCollectionId, Bob);
+      const newNftTokenId = await createItemExpectSuccess(Bob, nftCollectionId, 'NFT', Bob.address);
+      await transferExpectSuccess(nftCollectionId, newNftTokenId, Bob, Alice, 1, 'NFT');
+      // fungible
+      const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+      await addCollectionAdminExpectSuccess(Alice, fungibleCollectionId, Bob);
+      const newFungibleTokenId = await createItemExpectSuccess(Alice, fungibleCollectionId, 'Fungible', Bob.address);
+      await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, Bob, Alice, 1, 'Fungible');
+      // reFungible
+      const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+      await addCollectionAdminExpectSuccess(Alice, reFungibleCollectionId, Bob);
+      const newReFungibleTokenId = await createItemExpectSuccess(Bob, reFungibleCollectionId, 'ReFungible', Bob.address);
+      await transferExpectSuccess(
+        reFungibleCollectionId,
+        newReFungibleTokenId,
+        Bob,
+        Alice,
+        100,
+        'ReFungible',
+      );
+    });
+  });
 });
 
 describe('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => {
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -53,6 +53,11 @@
 
 export const U128_MAX = (1n << 128n) - 1n;
 
+const MICROUNIQUE = 1_000_000_000n;
+const MILLIUNIQUE = 1_000n * MICROUNIQUE;
+const CENTIUNIQUE = 10n * MILLIUNIQUE;
+export const UNIQUE = 100n * CENTIUNIQUE;
+
 type GenericResult = {
   success: boolean,
 };
@@ -95,6 +100,23 @@
   checkMsgSysMethod: string;
 }
 
+export interface IFungibleTokenDataType {
+  Value: number;
+}
+
+export interface IChainLimits {
+  CollectionNumbersLimit: number;
+	AccountTokenOwnershipLimit: number;
+	CollectionsAdminsLimit: number;
+	CustomDataLimit: number;
+	NftSponsorTransferTimeout: number;
+	FungibleSponsorTransferTimeout: number;
+	RefungibleSponsorTransferTimeout: number;
+	OffchainSchemaLimit: number;
+	VariableOnChainSchemaLimit: number;
+	ConstOnChainSchemaLimit: number;
+}
+
 export interface IReFungibleTokenDataType {
   Owner: IReFungibleOwner[];
   ConstData: number[];
@@ -414,13 +436,13 @@
   });
 }
 
-export async function setCollectionSponsorExpectSuccess(collectionId: number, sponsor: string) {
+export async function setCollectionSponsorExpectSuccess(collectionId: number, sponsor: string, sender = '//Alice') {
   await usingApi(async (api) => {
 
     // Run the transaction
-    const alicePrivateKey = privateKey('//Alice');
+    const senderPrivateKey = privateKey(sender);
     const tx = api.tx.nft.setCollectionSponsor(collectionId, sponsor);
-    const events = await submitTransactionAsync(alicePrivateKey, tx);
+    const events = await submitTransactionAsync(senderPrivateKey, tx);
     const result = getGenericResult(events);
 
     // Get the collection
@@ -434,11 +456,11 @@
   });
 }
 
-export async function removeCollectionSponsorExpectSuccess(collectionId: number) {
+export async function removeCollectionSponsorExpectSuccess(collectionId: number, sender = '//Alice') {
   await usingApi(async (api) => {
 
     // Run the transaction
-    const alicePrivateKey = privateKey('//Alice');
+    const alicePrivateKey = privateKey(sender);
     const tx = api.tx.nft.removeCollectionSponsor(collectionId);
     const events = await submitTransactionAsync(alicePrivateKey, tx);
     const result = getGenericResult(events);
@@ -452,11 +474,11 @@
   });
 }
 
-export async function removeCollectionSponsorExpectFailure(collectionId: number) {
+export async function removeCollectionSponsorExpectFailure(collectionId: number, senderSeed = '//Alice') {
   await usingApi(async (api) => {
 
     // Run the transaction
-    const alicePrivateKey = privateKey('//Alice');
+    const alicePrivateKey = privateKey(senderSeed);
     const tx = api.tx.nft.removeCollectionSponsor(collectionId);
     await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;
   });
@@ -545,6 +567,30 @@
   });
 }
 
+export async function setTransferFlagExpectSuccess(sender: IKeyringPair, collectionId: number, enabled: boolean) {
+
+  await usingApi(async (api) => {
+
+    const tx = api.tx.nft.setTransfersEnabledFlag (collectionId, enabled);
+    const events = await submitTransactionAsync(sender, tx);
+    const result = getGenericResult(events);
+
+    expect(result.success).to.be.true;
+  }); 
+}
+
+export async function setTransferFlagExpectFailure(sender: IKeyringPair, collectionId: number, enabled: boolean) {
+
+  await usingApi(async (api) => {
+
+    const tx = api.tx.nft.setTransfersEnabledFlag (collectionId, enabled);
+    const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
+    const result = getGenericResult(events);
+
+    expect(result.success).to.be.false;
+  }); 
+}
+
 export async function setContractSponsoringRateLimitExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, rateLimit: number) {
   await usingApi(async (api) => {
     const tx = api.tx.nft.setContractSponsoringRateLimit(contractAddress, rateLimit);
@@ -763,6 +809,15 @@
   });
 }
 
+export async function addCollectionAdminExpectSuccess(sender: IKeyringPair, collectionId: number, address: IKeyringPair) {
+  await usingApi(async (api) => {
+    const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(address.address));
+    const events = await submitTransactionAsync(sender, changeAdminTx);
+    const result = getCreateCollectionResult(events);
+    expect(result.success).to.be.true;
+  });
+}
+
 export async function
 scheduleTransferExpectSuccess(
   collectionId: number,
@@ -978,10 +1033,31 @@
   });
 }
 
+export async function setPublicAccessModeExpectFail(
+  sender: IKeyringPair, collectionId: number,
+  accessMode: 'Normal' | 'WhiteList',
+) {
+  await usingApi(async (api) => {
+
+    // Run the transaction
+    const tx = api.tx.nft.setPublicAccessMode(collectionId, accessMode);
+    const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
+    const result = getGenericResult(events);
+
+    // What to expect
+    // tslint:disable-next-line:no-unused-expression
+    expect(result.success).to.be.false;
+  });
+}
+
 export async function enableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) {
   await setPublicAccessModeExpectSuccess(sender, collectionId, 'WhiteList');
 }
 
+export async function enableWhiteListExpectFail(sender: IKeyringPair, collectionId: number) {
+  await setPublicAccessModeExpectFail(sender, collectionId, 'WhiteList');
+}
+
 export async function disableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) {
   await setPublicAccessModeExpectSuccess(sender, collectionId, 'Normal');
 }
@@ -1028,6 +1104,17 @@
   });
 }
 
+export async function setChainLimitsExpectFailure(sender: IKeyringPair, limits: IChainLimits) {
+  await usingApi(async (api) => {
+    // Run the transaction
+    const tx = api.tx.nft.setChainLimits(limits);
+    const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
+    const result = getCreateCollectionResult(events);
+    // tslint:disable-next-line:no-unused-expression
+    expect(result.success).to.be.false;
+  });
+}
+
 export async function isWhitelisted(collectionId: number, address: string) {
   let whitelisted = false;
   await usingApi(async (api) => {
@@ -1058,6 +1145,19 @@
   });
 }
 
+export async function addToWhiteListExpectFail(sender: IKeyringPair, collectionId: number, address: string | AccountId) {
+  await usingApi(async (api) => {
+    // Run the transaction
+    const tx = api.tx.nft.addToWhiteList(collectionId, normalizeAccountId(address));
+    const events = await expect(submitTransactionAsync(sender, tx)).to.be.rejected;
+    const result = getGenericResult(events);
+
+    // What to expect
+    // tslint:disable-next-line:no-unused-expression
+    expect(result.success).to.be.false;
+  });
+}
+
 export async function removeFromWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number, address: CrossAccountId) {
   await usingApi(async (api) => {
     // Run the transaction
@@ -1099,3 +1199,7 @@
     return (await api.query.nft.collectionById(collectionId)).toJSON() as unknown as ICollectionInterface;
   });
 }
+
+export async function queryNftOwner(api: ApiPromise, collectionId: number, tokenId: number): Promise<CrossAccountId> {
+  return normalizeAccountId((await api.query.nft.nftItemList(collectionId, tokenId) as any).toJSON().Owner);
+}
\ No newline at end of file
modifiedtests/yarn.lockdiffbeforeafterboth
--- a/tests/yarn.lock
+++ b/tests/yarn.lock
@@ -2,10 +2,10 @@
 # yarn lockfile v1
 
 
-"@babel/cli@^7.14.5":
-  version "7.14.5"
-  resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.14.5.tgz#9551b194f02360729de6060785bbdcce52c69f0a"
-  integrity sha512-poegjhRvXHWO0EAsnYajwYZuqcz7gyfxwfaecUESxDujrqOivf3zrjFbub8IJkrqEaz3fvJWh001EzxBub54fg==
+"@babel/cli@^7.14.8":
+  version "7.14.8"
+  resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.14.8.tgz#fac73c0e2328a8af9fd3560c06b096bfa3730933"
+  integrity sha512-lcy6Lymft9Rpfqmrqdd4oTDdUx9ZwaAhAfywVrHG4771Pa6PPT0danJ1kDHBXYqh4HHSmIdA+nlmfxfxSDPtBg==
   dependencies:
     commander "^4.0.1"
     convert-source-map "^1.1.0"
@@ -42,7 +42,12 @@
   resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.14.7.tgz#7b047d7a3a89a67d2258dc61f604f098f1bc7e08"
   integrity sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==
 
-"@babel/core@^7.1.0", "@babel/core@^7.14.6", "@babel/core@^7.7.2", "@babel/core@^7.7.5":
+"@babel/compat-data@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176"
+  integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==
+
+"@babel/core@^7.1.0", "@babel/core@^7.7.2", "@babel/core@^7.7.5":
   version "7.14.6"
   resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.14.6.tgz#e0814ec1a950032ff16c13a2721de39a8416fcab"
   integrity sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA==
@@ -63,6 +68,27 @@
     semver "^6.3.0"
     source-map "^0.5.0"
 
+"@babel/core@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.0.tgz#749e57c68778b73ad8082775561f67f5196aafa8"
+  integrity sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==
+  dependencies:
+    "@babel/code-frame" "^7.14.5"
+    "@babel/generator" "^7.15.0"
+    "@babel/helper-compilation-targets" "^7.15.0"
+    "@babel/helper-module-transforms" "^7.15.0"
+    "@babel/helpers" "^7.14.8"
+    "@babel/parser" "^7.15.0"
+    "@babel/template" "^7.14.5"
+    "@babel/traverse" "^7.15.0"
+    "@babel/types" "^7.15.0"
+    convert-source-map "^1.7.0"
+    debug "^4.1.0"
+    gensync "^1.0.0-beta.2"
+    json5 "^2.1.2"
+    semver "^6.3.0"
+    source-map "^0.5.0"
+
 "@babel/generator@^7.14.5", "@babel/generator@^7.7.2":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.5.tgz#848d7b9f031caca9d0cd0af01b063f226f52d785"
@@ -72,6 +98,15 @@
     jsesc "^2.5.1"
     source-map "^0.5.0"
 
+"@babel/generator@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.0.tgz#a7d0c172e0d814974bad5aa77ace543b97917f15"
+  integrity sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==
+  dependencies:
+    "@babel/types" "^7.15.0"
+    jsesc "^2.5.1"
+    source-map "^0.5.0"
+
 "@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.14.5":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz#7bf478ec3b71726d56a8ca5775b046fc29879e61"
@@ -97,7 +132,17 @@
     browserslist "^4.16.6"
     semver "^6.3.0"
 
-"@babel/helper-create-class-features-plugin@^7.14.5", "@babel/helper-create-class-features-plugin@^7.14.6":
+"@babel/helper-compilation-targets@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz#973df8cbd025515f3ff25db0c05efc704fa79818"
+  integrity sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A==
+  dependencies:
+    "@babel/compat-data" "^7.15.0"
+    "@babel/helper-validator-option" "^7.14.5"
+    browserslist "^4.16.6"
+    semver "^6.3.0"
+
+"@babel/helper-create-class-features-plugin@^7.14.5":
   version "7.14.6"
   resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz#f114469b6c06f8b5c59c6c4e74621f5085362542"
   integrity sha512-Z6gsfGofTxH/+LQXqYEK45kxmcensbzmk/oi8DmaQytlQCgqNZt9XQF8iqlI/SeXWVjaMNxvYvzaYw+kh42mDg==
@@ -109,6 +154,18 @@
     "@babel/helper-replace-supers" "^7.14.5"
     "@babel/helper-split-export-declaration" "^7.14.5"
 
+"@babel/helper-create-class-features-plugin@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.0.tgz#c9a137a4d137b2d0e2c649acf536d7ba1a76c0f7"
+  integrity sha512-MdmDXgvTIi4heDVX/e9EFfeGpugqm9fobBVg/iioE8kueXrOHdRDe36FAY7SnE9xXLVeYCoJR/gdrBEIHRC83Q==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.14.5"
+    "@babel/helper-function-name" "^7.14.5"
+    "@babel/helper-member-expression-to-functions" "^7.15.0"
+    "@babel/helper-optimise-call-expression" "^7.14.5"
+    "@babel/helper-replace-supers" "^7.15.0"
+    "@babel/helper-split-export-declaration" "^7.14.5"
+
 "@babel/helper-create-regexp-features-plugin@^7.14.5":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz#c7d5ac5e9cf621c26057722fb7a8a4c5889358c4"
@@ -168,6 +225,13 @@
   dependencies:
     "@babel/types" "^7.14.5"
 
+"@babel/helper-member-expression-to-functions@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz#0ddaf5299c8179f27f37327936553e9bba60990b"
+  integrity sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg==
+  dependencies:
+    "@babel/types" "^7.15.0"
+
 "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.14.5":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz#6d1a44df6a38c957aa7c312da076429f11b422f3"
@@ -189,6 +253,20 @@
     "@babel/traverse" "^7.14.5"
     "@babel/types" "^7.14.5"
 
+"@babel/helper-module-transforms@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz#679275581ea056373eddbe360e1419ef23783b08"
+  integrity sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==
+  dependencies:
+    "@babel/helper-module-imports" "^7.14.5"
+    "@babel/helper-replace-supers" "^7.15.0"
+    "@babel/helper-simple-access" "^7.14.8"
+    "@babel/helper-split-export-declaration" "^7.14.5"
+    "@babel/helper-validator-identifier" "^7.14.9"
+    "@babel/template" "^7.14.5"
+    "@babel/traverse" "^7.15.0"
+    "@babel/types" "^7.15.0"
+
 "@babel/helper-optimise-call-expression@^7.14.5":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz#f27395a8619e0665b3f0364cddb41c25d71b499c"
@@ -220,6 +298,16 @@
     "@babel/traverse" "^7.14.5"
     "@babel/types" "^7.14.5"
 
+"@babel/helper-replace-supers@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz#ace07708f5bf746bf2e6ba99572cce79b5d4e7f4"
+  integrity sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA==
+  dependencies:
+    "@babel/helper-member-expression-to-functions" "^7.15.0"
+    "@babel/helper-optimise-call-expression" "^7.14.5"
+    "@babel/traverse" "^7.15.0"
+    "@babel/types" "^7.15.0"
+
 "@babel/helper-simple-access@^7.14.5":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz#66ea85cf53ba0b4e588ba77fc813f53abcaa41c4"
@@ -227,6 +315,13 @@
   dependencies:
     "@babel/types" "^7.14.5"
 
+"@babel/helper-simple-access@^7.14.8":
+  version "7.14.8"
+  resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz#82e1fec0644a7e775c74d305f212c39f8fe73924"
+  integrity sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg==
+  dependencies:
+    "@babel/types" "^7.14.8"
+
 "@babel/helper-skip-transparent-expression-wrappers@^7.14.5":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz#96f486ac050ca9f44b009fbe5b7d394cab3a0ee4"
@@ -246,6 +341,11 @@
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8"
   integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==
 
+"@babel/helper-validator-identifier@^7.14.9":
+  version "7.14.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48"
+  integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==
+
 "@babel/helper-validator-option@^7.14.5":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3"
@@ -270,6 +370,15 @@
     "@babel/traverse" "^7.14.5"
     "@babel/types" "^7.14.5"
 
+"@babel/helpers@^7.14.8":
+  version "7.15.3"
+  resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.15.3.tgz#c96838b752b95dcd525b4e741ed40bb1dc2a1357"
+  integrity sha512-HwJiz52XaS96lX+28Tnbu31VeFSQJGOeKHJeaEPQlTl7PnlhFElWPj8tUXtqFIzeN86XxXoBr+WFAyK2PPVz6g==
+  dependencies:
+    "@babel/template" "^7.14.5"
+    "@babel/traverse" "^7.15.0"
+    "@babel/types" "^7.15.0"
+
 "@babel/highlight@^7.10.4", "@babel/highlight@^7.14.5":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9"
@@ -284,6 +393,11 @@
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.6.tgz#d85cc68ca3cac84eae384c06f032921f5227f4b2"
   integrity sha512-oG0ej7efjEXxb4UgE+klVx+3j4MVo+A2vCzm7OUN4CLo6WhQ+vSOD2yJ8m7B+DghObxtLxt3EfgMWpq+AsWehQ==
 
+"@babel/parser@^7.15.0":
+  version "7.15.3"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.3.tgz#3416d9bea748052cfcb63dbcc27368105b1ed862"
+  integrity sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==
+
 "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.14.5":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz#4b467302e1548ed3b1be43beae2cc9cf45e0bb7e"
@@ -293,10 +407,10 @@
     "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5"
     "@babel/plugin-proposal-optional-chaining" "^7.14.5"
 
-"@babel/plugin-proposal-async-generator-functions@^7.14.7":
-  version "7.14.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz#784a48c3d8ed073f65adcf30b57bcbf6c8119ace"
-  integrity sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==
+"@babel/plugin-proposal-async-generator-functions@^7.14.9":
+  version "7.14.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.9.tgz#7028dc4fa21dc199bbacf98b39bab1267d0eaf9a"
+  integrity sha512-d1lnh+ZnKrFKwtTYdw320+sQWCTwgkB9fmUhNXRADA4akR6wLjaruSGnIEUjpt9HCOwTr4ynFTKu19b7rFRpmw==
   dependencies:
     "@babel/helper-plugin-utils" "^7.14.5"
     "@babel/helper-remap-async-to-generator" "^7.14.5"
@@ -577,10 +691,10 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-classes@^7.14.5":
-  version "7.14.5"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.5.tgz#0e98e82097b38550b03b483f9b51a78de0acb2cf"
-  integrity sha512-J4VxKAMykM06K/64z9rwiL6xnBHgB1+FVspqvlgCdwD1KUbQNfszeKVVOMh59w3sztHYIZDgnhOC4WbdEfHFDA==
+"@babel/plugin-transform-classes@^7.14.9":
+  version "7.14.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.9.tgz#2a391ffb1e5292710b00f2e2c210e1435e7d449f"
+  integrity sha512-NfZpTcxU3foGWbl4wxmZ35mTsYJy8oQocbeIMoDAGGFarAmSQlL+LWMkDx/tj6pNotpbX3rltIA4dprgAPOq5A==
   dependencies:
     "@babel/helper-annotate-as-pure" "^7.14.5"
     "@babel/helper-function-name" "^7.14.5"
@@ -665,14 +779,14 @@
     "@babel/helper-plugin-utils" "^7.14.5"
     babel-plugin-dynamic-import-node "^2.3.3"
 
-"@babel/plugin-transform-modules-commonjs@^7.14.5":
-  version "7.14.5"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz#7aaee0ea98283de94da98b28f8c35701429dad97"
-  integrity sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A==
+"@babel/plugin-transform-modules-commonjs@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.0.tgz#3305896e5835f953b5cdb363acd9e8c2219a5281"
+  integrity sha512-3H/R9s8cXcOGE8kgMlmjYYC9nqr5ELiPkJn4q0mypBrjhYQoc+5/Maq69vV4xRPWnkzZuwJPf5rArxpB/35Cig==
   dependencies:
-    "@babel/helper-module-transforms" "^7.14.5"
+    "@babel/helper-module-transforms" "^7.15.0"
     "@babel/helper-plugin-utils" "^7.14.5"
-    "@babel/helper-simple-access" "^7.14.5"
+    "@babel/helper-simple-access" "^7.14.8"
     babel-plugin-dynamic-import-node "^2.3.3"
 
 "@babel/plugin-transform-modules-systemjs@^7.14.5":
@@ -694,10 +808,10 @@
     "@babel/helper-module-transforms" "^7.14.5"
     "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-named-capturing-groups-regex@^7.14.7":
-  version "7.14.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz#60c06892acf9df231e256c24464bfecb0908fd4e"
-  integrity sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==
+"@babel/plugin-transform-named-capturing-groups-regex@^7.14.9":
+  version "7.14.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz#c68f5c5d12d2ebaba3762e57c2c4f6347a46e7b2"
+  integrity sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA==
   dependencies:
     "@babel/helper-create-regexp-features-plugin" "^7.14.5"
 
@@ -777,10 +891,10 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-runtime@^7.14.5":
-  version "7.14.5"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.14.5.tgz#30491dad49c6059f8f8fa5ee8896a0089e987523"
-  integrity sha512-fPMBhh1AV8ZyneiCIA+wYYUH1arzlXR1UMcApjvchDhfKxhy2r2lReJv8uHEyihi4IFIGlr1Pdx7S5fkESDQsg==
+"@babel/plugin-transform-runtime@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.0.tgz#d3aa650d11678ca76ce294071fda53d7804183b3"
+  integrity sha512-sfHYkLGjhzWTq6xsuQ01oEsUYjkHRux9fW1iUA68dC7Qd8BS1Unq4aZ8itmQp95zUzIcyR2EbNMTzAicFj+guw==
   dependencies:
     "@babel/helper-module-imports" "^7.14.5"
     "@babel/helper-plugin-utils" "^7.14.5"
@@ -825,12 +939,12 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-transform-typescript@^7.14.5":
-  version "7.14.6"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.14.6.tgz#6e9c2d98da2507ebe0a883b100cde3c7279df36c"
-  integrity sha512-XlTdBq7Awr4FYIzqhmYY80WN0V0azF74DMPyFqVHBvf81ZUgc4X7ZOpx6O8eLDK6iM5cCQzeyJw0ynTaefixRA==
+"@babel/plugin-transform-typescript@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.0.tgz#553f230b9d5385018716586fc48db10dd228eb7e"
+  integrity sha512-WIIEazmngMEEHDaPTx0IZY48SaAmjVWe3TRSX7cmJXn0bEv9midFzAjxiruOWYIVf5iQ10vFx7ASDpgEO08L5w==
   dependencies:
-    "@babel/helper-create-class-features-plugin" "^7.14.6"
+    "@babel/helper-create-class-features-plugin" "^7.15.0"
     "@babel/helper-plugin-utils" "^7.14.5"
     "@babel/plugin-syntax-typescript" "^7.14.5"
 
@@ -849,17 +963,17 @@
     "@babel/helper-create-regexp-features-plugin" "^7.14.5"
     "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/preset-env@^7.14.7":
-  version "7.14.7"
-  resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.14.7.tgz#5c70b22d4c2d893b03d8c886a5c17422502b932a"
-  integrity sha512-itOGqCKLsSUl0Y+1nSfhbuuOlTs0MJk2Iv7iSH+XT/mR8U1zRLO7NjWlYXB47yhK4J/7j+HYty/EhFZDYKa/VA==
+"@babel/preset-env@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.15.0.tgz#e2165bf16594c9c05e52517a194bf6187d6fe464"
+  integrity sha512-FhEpCNFCcWW3iZLg0L2NPE9UerdtsCR6ZcsGHUX6Om6kbCQeL5QZDqFDmeNHC6/fy6UH3jEge7K4qG5uC9In0Q==
   dependencies:
-    "@babel/compat-data" "^7.14.7"
-    "@babel/helper-compilation-targets" "^7.14.5"
+    "@babel/compat-data" "^7.15.0"
+    "@babel/helper-compilation-targets" "^7.15.0"
     "@babel/helper-plugin-utils" "^7.14.5"
     "@babel/helper-validator-option" "^7.14.5"
     "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.14.5"
-    "@babel/plugin-proposal-async-generator-functions" "^7.14.7"
+    "@babel/plugin-proposal-async-generator-functions" "^7.14.9"
     "@babel/plugin-proposal-class-properties" "^7.14.5"
     "@babel/plugin-proposal-class-static-block" "^7.14.5"
     "@babel/plugin-proposal-dynamic-import" "^7.14.5"
@@ -892,7 +1006,7 @@
     "@babel/plugin-transform-async-to-generator" "^7.14.5"
     "@babel/plugin-transform-block-scoped-functions" "^7.14.5"
     "@babel/plugin-transform-block-scoping" "^7.14.5"
-    "@babel/plugin-transform-classes" "^7.14.5"
+    "@babel/plugin-transform-classes" "^7.14.9"
     "@babel/plugin-transform-computed-properties" "^7.14.5"
     "@babel/plugin-transform-destructuring" "^7.14.7"
     "@babel/plugin-transform-dotall-regex" "^7.14.5"
@@ -903,10 +1017,10 @@
     "@babel/plugin-transform-literals" "^7.14.5"
     "@babel/plugin-transform-member-expression-literals" "^7.14.5"
     "@babel/plugin-transform-modules-amd" "^7.14.5"
-    "@babel/plugin-transform-modules-commonjs" "^7.14.5"
+    "@babel/plugin-transform-modules-commonjs" "^7.15.0"
     "@babel/plugin-transform-modules-systemjs" "^7.14.5"
     "@babel/plugin-transform-modules-umd" "^7.14.5"
-    "@babel/plugin-transform-named-capturing-groups-regex" "^7.14.7"
+    "@babel/plugin-transform-named-capturing-groups-regex" "^7.14.9"
     "@babel/plugin-transform-new-target" "^7.14.5"
     "@babel/plugin-transform-object-super" "^7.14.5"
     "@babel/plugin-transform-parameters" "^7.14.5"
@@ -921,11 +1035,11 @@
     "@babel/plugin-transform-unicode-escapes" "^7.14.5"
     "@babel/plugin-transform-unicode-regex" "^7.14.5"
     "@babel/preset-modules" "^0.1.4"
-    "@babel/types" "^7.14.5"
+    "@babel/types" "^7.15.0"
     babel-plugin-polyfill-corejs2 "^0.2.2"
     babel-plugin-polyfill-corejs3 "^0.2.2"
     babel-plugin-polyfill-regenerator "^0.2.2"
-    core-js-compat "^3.15.0"
+    core-js-compat "^3.16.0"
     semver "^6.3.0"
 
 "@babel/preset-modules@^0.1.4":
@@ -951,19 +1065,19 @@
     "@babel/plugin-transform-react-jsx-development" "^7.14.5"
     "@babel/plugin-transform-react-pure-annotations" "^7.14.5"
 
-"@babel/preset-typescript@^7.14.5":
-  version "7.14.5"
-  resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.14.5.tgz#aa98de119cf9852b79511f19e7f44a2d379bcce0"
-  integrity sha512-u4zO6CdbRKbS9TypMqrlGH7sd2TAJppZwn3c/ZRLeO/wGsbddxgbPDUZVNrie3JWYLQ9vpineKlsrWFvO6Pwkw==
+"@babel/preset-typescript@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.15.0.tgz#e8fca638a1a0f64f14e1119f7fe4500277840945"
+  integrity sha512-lt0Y/8V3y06Wq/8H/u0WakrqciZ7Fz7mwPDHWUJAXlABL5hiUG42BNlRXiELNjeWjO5rWmnNKlx+yzJvxezHow==
   dependencies:
     "@babel/helper-plugin-utils" "^7.14.5"
     "@babel/helper-validator-option" "^7.14.5"
-    "@babel/plugin-transform-typescript" "^7.14.5"
+    "@babel/plugin-transform-typescript" "^7.15.0"
 
-"@babel/register@^7.14.5":
-  version "7.14.5"
-  resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.14.5.tgz#d0eac615065d9c2f1995842f85d6e56c345f3233"
-  integrity sha512-TjJpGz/aDjFGWsItRBQMOFTrmTI9tr79CHOK+KIvLeCkbxuOAk2M5QHjvruIMGoo9OuccMh5euplPzc5FjAKGg==
+"@babel/register@^7.15.3":
+  version "7.15.3"
+  resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.15.3.tgz#6b40a549e06ec06c885b2ec42c3dd711f55fe752"
+  integrity sha512-mj4IY1ZJkorClxKTImccn4T81+UKTo4Ux0+OFSV9hME1ooqS9UV+pJ6BjD0qXPK4T3XW/KNa79XByjeEMZz+fw==
   dependencies:
     clone-deep "^4.0.1"
     find-cache-dir "^2.0.0"
@@ -978,6 +1092,13 @@
   dependencies:
     regenerator-runtime "^0.13.4"
 
+"@babel/runtime@^7.15.3":
+  version "7.15.3"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz#2e1c2880ca118e5b2f9988322bd8a7656a32502b"
+  integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==
+  dependencies:
+    regenerator-runtime "^0.13.4"
+
 "@babel/template@^7.14.5", "@babel/template@^7.3.3":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4"
@@ -1002,6 +1123,21 @@
     debug "^4.1.0"
     globals "^11.1.0"
 
+"@babel/traverse@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.0.tgz#4cca838fd1b2a03283c1f38e141f639d60b3fc98"
+  integrity sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==
+  dependencies:
+    "@babel/code-frame" "^7.14.5"
+    "@babel/generator" "^7.15.0"
+    "@babel/helper-function-name" "^7.14.5"
+    "@babel/helper-hoist-variables" "^7.14.5"
+    "@babel/helper-split-export-declaration" "^7.14.5"
+    "@babel/parser" "^7.15.0"
+    "@babel/types" "^7.15.0"
+    debug "^4.1.0"
+    globals "^11.1.0"
+
 "@babel/types@^7.0.0", "@babel/types@^7.14.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.5.tgz#3bb997ba829a2104cedb20689c4a5b8121d383ff"
@@ -1010,15 +1146,23 @@
     "@babel/helper-validator-identifier" "^7.14.5"
     to-fast-properties "^2.0.0"
 
+"@babel/types@^7.14.8", "@babel/types@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.0.tgz#61af11f2286c4e9c69ca8deb5f4375a73c72dcbd"
+  integrity sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.14.9"
+    to-fast-properties "^2.0.0"
+
 "@bcoe/v8-coverage@^0.2.3":
   version "0.2.3"
   resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
   integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
 
-"@eslint/eslintrc@^0.4.2":
-  version "0.4.2"
-  resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.2.tgz#f63d0ef06f5c0c57d76c4ab5f63d3835c51b0179"
-  integrity sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==
+"@eslint/eslintrc@^0.4.3":
+  version "0.4.3"
+  resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
+  integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==
   dependencies:
     ajv "^6.12.4"
     debug "^4.1.1"
@@ -1236,94 +1380,94 @@
   resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98"
   integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==
 
-"@jest/console@^27.0.2":
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.0.2.tgz#b8eeff8f21ac51d224c851e1729d2630c18631e6"
-  integrity sha512-/zYigssuHLImGeMAACkjI4VLAiiJznHgAl3xnFT19iWyct2LhrH3KXOjHRmxBGTkiPLZKKAJAgaPpiU9EZ9K+w==
+"@jest/console@^27.0.6":
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.0.6.tgz#3eb72ea80897495c3d73dd97aab7f26770e2260f"
+  integrity sha512-fMlIBocSHPZ3JxgWiDNW/KPj6s+YRd0hicb33IrmelCcjXo/pXPwvuiKFmZz+XuqI/1u7nbUK10zSsWL/1aegg==
   dependencies:
-    "@jest/types" "^27.0.2"
+    "@jest/types" "^27.0.6"
     "@types/node" "*"
     chalk "^4.0.0"
-    jest-message-util "^27.0.2"
-    jest-util "^27.0.2"
+    jest-message-util "^27.0.6"
+    jest-util "^27.0.6"
     slash "^3.0.0"
 
-"@jest/core@^27.0.5":
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.0.5.tgz#59e9e69e7374d65dbb22e3fc1bd52e80991eae72"
-  integrity sha512-g73//jF0VwsOIrWUC9Cqg03lU3QoAMFxVjsm6n6yNmwZcQPN/o8w+gLWODw5VfKNFZT38otXHWxc6b8eGDUpEA==
+"@jest/core@^27.0.6":
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.0.6.tgz#c5f642727a0b3bf0f37c4b46c675372d0978d4a1"
+  integrity sha512-SsYBm3yhqOn5ZLJCtccaBcvD/ccTLCeuDv8U41WJH/V1MW5eKUkeMHT9U+Pw/v1m1AIWlnIW/eM2XzQr0rEmow==
   dependencies:
-    "@jest/console" "^27.0.2"
-    "@jest/reporters" "^27.0.5"
-    "@jest/test-result" "^27.0.2"
-    "@jest/transform" "^27.0.5"
-    "@jest/types" "^27.0.2"
+    "@jest/console" "^27.0.6"
+    "@jest/reporters" "^27.0.6"
+    "@jest/test-result" "^27.0.6"
+    "@jest/transform" "^27.0.6"
+    "@jest/types" "^27.0.6"
     "@types/node" "*"
     ansi-escapes "^4.2.1"
     chalk "^4.0.0"
     emittery "^0.8.1"
     exit "^0.1.2"
     graceful-fs "^4.2.4"
-    jest-changed-files "^27.0.2"
-    jest-config "^27.0.5"
-    jest-haste-map "^27.0.5"
-    jest-message-util "^27.0.2"
-    jest-regex-util "^27.0.1"
-    jest-resolve "^27.0.5"
-    jest-resolve-dependencies "^27.0.5"
-    jest-runner "^27.0.5"
-    jest-runtime "^27.0.5"
-    jest-snapshot "^27.0.5"
-    jest-util "^27.0.2"
-    jest-validate "^27.0.2"
-    jest-watcher "^27.0.2"
+    jest-changed-files "^27.0.6"
+    jest-config "^27.0.6"
+    jest-haste-map "^27.0.6"
+    jest-message-util "^27.0.6"
+    jest-regex-util "^27.0.6"
+    jest-resolve "^27.0.6"
+    jest-resolve-dependencies "^27.0.6"
+    jest-runner "^27.0.6"
+    jest-runtime "^27.0.6"
+    jest-snapshot "^27.0.6"
+    jest-util "^27.0.6"
+    jest-validate "^27.0.6"
+    jest-watcher "^27.0.6"
     micromatch "^4.0.4"
     p-each-series "^2.1.0"
     rimraf "^3.0.0"
     slash "^3.0.0"
     strip-ansi "^6.0.0"
 
-"@jest/environment@^27.0.5":
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.0.5.tgz#a294ad4acda2e250f789fb98dc667aad33d3adc9"
-  integrity sha512-IAkJPOT7bqn0GiX5LPio6/e1YpcmLbrd8O5EFYpAOZ6V+9xJDsXjdgN2vgv9WOKIs/uA1kf5WeD96HhlBYO+FA==
+"@jest/environment@^27.0.6":
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.0.6.tgz#ee293fe996db01d7d663b8108fa0e1ff436219d2"
+  integrity sha512-4XywtdhwZwCpPJ/qfAkqExRsERW+UaoSRStSHCCiQTUpoYdLukj+YJbQSFrZjhlUDRZeNiU9SFH0u7iNimdiIg==
   dependencies:
-    "@jest/fake-timers" "^27.0.5"
-    "@jest/types" "^27.0.2"
+    "@jest/fake-timers" "^27.0.6"
+    "@jest/types" "^27.0.6"
     "@types/node" "*"
-    jest-mock "^27.0.3"
+    jest-mock "^27.0.6"
 
-"@jest/fake-timers@^27.0.5":
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.0.5.tgz#304d5aedadf4c75cff3696995460b39d6c6e72f6"
-  integrity sha512-d6Tyf7iDoKqeUdwUKrOBV/GvEZRF67m7lpuWI0+SCD9D3aaejiOQZxAOxwH2EH/W18gnfYaBPLi0VeTGBHtQBg==
+"@jest/fake-timers@^27.0.6":
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.0.6.tgz#cbad52f3fe6abe30e7acb8cd5fa3466b9588e3df"
+  integrity sha512-sqd+xTWtZ94l3yWDKnRTdvTeZ+A/V7SSKrxsrOKSqdyddb9CeNRF8fbhAU0D7ZJBpTTW2nbp6MftmKJDZfW2LQ==
   dependencies:
-    "@jest/types" "^27.0.2"
+    "@jest/types" "^27.0.6"
     "@sinonjs/fake-timers" "^7.0.2"
     "@types/node" "*"
-    jest-message-util "^27.0.2"
-    jest-mock "^27.0.3"
-    jest-util "^27.0.2"
+    jest-message-util "^27.0.6"
+    jest-mock "^27.0.6"
+    jest-util "^27.0.6"
 
-"@jest/globals@^27.0.5":
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.0.5.tgz#f63b8bfa6ea3716f8df50f6a604b5c15b36ffd20"
-  integrity sha512-qqKyjDXUaZwDuccpbMMKCCMBftvrbXzigtIsikAH/9ca+kaae8InP2MDf+Y/PdCSMuAsSpHS6q6M25irBBUh+Q==
+"@jest/globals@^27.0.6":
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.0.6.tgz#48e3903f99a4650673d8657334d13c9caf0e8f82"
+  integrity sha512-DdTGCP606rh9bjkdQ7VvChV18iS7q0IMJVP1piwTWyWskol4iqcVwthZmoJEf7obE1nc34OpIyoVGPeqLC+ryw==
   dependencies:
-    "@jest/environment" "^27.0.5"
-    "@jest/types" "^27.0.2"
-    expect "^27.0.2"
+    "@jest/environment" "^27.0.6"
+    "@jest/types" "^27.0.6"
+    expect "^27.0.6"
 
-"@jest/reporters@^27.0.5":
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.0.5.tgz#cd730b77d9667b8ff700ad66d4edc293bb09716a"
-  integrity sha512-4uNg5+0eIfRafnpgu3jCZws3NNcFzhu5JdRd1mKQ4/53+vkIqwB6vfZ4gn5BdGqOaLtYhlOsPaL5ATkKzyBrJw==
+"@jest/reporters@^27.0.6":
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.0.6.tgz#91e7f2d98c002ad5df94d5b5167c1eb0b9fd5b00"
+  integrity sha512-TIkBt09Cb2gptji3yJXb3EE+eVltW6BjO7frO7NEfjI9vSIYoISi5R3aI3KpEDXlB1xwB+97NXIqz84qYeYsfA==
   dependencies:
     "@bcoe/v8-coverage" "^0.2.3"
-    "@jest/console" "^27.0.2"
-    "@jest/test-result" "^27.0.2"
-    "@jest/transform" "^27.0.5"
-    "@jest/types" "^27.0.2"
+    "@jest/console" "^27.0.6"
+    "@jest/test-result" "^27.0.6"
+    "@jest/transform" "^27.0.6"
+    "@jest/types" "^27.0.6"
     chalk "^4.0.0"
     collect-v8-coverage "^1.0.0"
     exit "^0.1.2"
@@ -1334,70 +1478,70 @@
     istanbul-lib-report "^3.0.0"
     istanbul-lib-source-maps "^4.0.0"
     istanbul-reports "^3.0.2"
-    jest-haste-map "^27.0.5"
-    jest-resolve "^27.0.5"
-    jest-util "^27.0.2"
-    jest-worker "^27.0.2"
+    jest-haste-map "^27.0.6"
+    jest-resolve "^27.0.6"
+    jest-util "^27.0.6"
+    jest-worker "^27.0.6"
     slash "^3.0.0"
     source-map "^0.6.0"
     string-length "^4.0.1"
     terminal-link "^2.0.0"
     v8-to-istanbul "^8.0.0"
 
-"@jest/source-map@^27.0.1":
-  version "27.0.1"
-  resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.0.1.tgz#2afbf73ddbaddcb920a8e62d0238a0a9e0a8d3e4"
-  integrity sha512-yMgkF0f+6WJtDMdDYNavmqvbHtiSpwRN2U/W+6uztgfqgkq/PXdKPqjBTUF1RD/feth4rH5N3NW0T5+wIuln1A==
+"@jest/source-map@^27.0.6":
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.0.6.tgz#be9e9b93565d49b0548b86e232092491fb60551f"
+  integrity sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g==
   dependencies:
     callsites "^3.0.0"
     graceful-fs "^4.2.4"
     source-map "^0.6.0"
 
-"@jest/test-result@^27.0.2":
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.0.2.tgz#0451049e32ceb609b636004ccc27c8fa22263f10"
-  integrity sha512-gcdWwL3yP5VaIadzwQtbZyZMgpmes8ryBAJp70tuxghiA8qL4imJyZex+i+USQH2H4jeLVVszhwntgdQ97fccA==
+"@jest/test-result@^27.0.6":
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.0.6.tgz#3fa42015a14e4fdede6acd042ce98c7f36627051"
+  integrity sha512-ja/pBOMTufjX4JLEauLxE3LQBPaI2YjGFtXexRAjt1I/MbfNlMx0sytSX3tn5hSLzQsR3Qy2rd0hc1BWojtj9w==
   dependencies:
-    "@jest/console" "^27.0.2"
-    "@jest/types" "^27.0.2"
+    "@jest/console" "^27.0.6"
+    "@jest/types" "^27.0.6"
     "@types/istanbul-lib-coverage" "^2.0.0"
     collect-v8-coverage "^1.0.0"
 
-"@jest/test-sequencer@^27.0.5":
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.0.5.tgz#c58b21db49afc36c0e3921d7ddf1fb7954abfded"
-  integrity sha512-opztnGs+cXzZ5txFG2+omBaV5ge/0yuJNKbhE3DREMiXE0YxBuzyEa6pNv3kk2JuucIlH2Xvgmn9kEEHSNt/SA==
+"@jest/test-sequencer@^27.0.6":
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.0.6.tgz#80a913ed7a1130545b1cd777ff2735dd3af5d34b"
+  integrity sha512-bISzNIApazYOlTHDum9PwW22NOyDa6VI31n6JucpjTVM0jD6JDgqEZ9+yn575nDdPF0+4csYDxNNW13NvFQGZA==
   dependencies:
-    "@jest/test-result" "^27.0.2"
+    "@jest/test-result" "^27.0.6"
     graceful-fs "^4.2.4"
-    jest-haste-map "^27.0.5"
-    jest-runtime "^27.0.5"
+    jest-haste-map "^27.0.6"
+    jest-runtime "^27.0.6"
 
-"@jest/transform@^27.0.5":
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.0.5.tgz#2dcb78953708af713941ac845b06078bc74ed873"
-  integrity sha512-lBD6OwKXSc6JJECBNk4mVxtSVuJSBsQrJ9WCBisfJs7EZuYq4K6vM9HmoB7hmPiLIDGeyaerw3feBV/bC4z8tg==
+"@jest/transform@^27.0.6":
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.0.6.tgz#189ad7107413208f7600f4719f81dd2f7278cc95"
+  integrity sha512-rj5Dw+mtIcntAUnMlW/Vju5mr73u8yg+irnHwzgtgoeI6cCPOvUwQ0D1uQtc/APmWgvRweEb1g05pkUpxH3iCA==
   dependencies:
     "@babel/core" "^7.1.0"
-    "@jest/types" "^27.0.2"
+    "@jest/types" "^27.0.6"
     babel-plugin-istanbul "^6.0.0"
     chalk "^4.0.0"
     convert-source-map "^1.4.0"
     fast-json-stable-stringify "^2.0.0"
     graceful-fs "^4.2.4"
-    jest-haste-map "^27.0.5"
-    jest-regex-util "^27.0.1"
-    jest-util "^27.0.2"
+    jest-haste-map "^27.0.6"
+    jest-regex-util "^27.0.6"
+    jest-util "^27.0.6"
     micromatch "^4.0.4"
     pirates "^4.0.1"
     slash "^3.0.0"
     source-map "^0.6.1"
     write-file-atomic "^3.0.0"
 
-"@jest/types@^27.0.2":
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.0.2.tgz#e153d6c46bda0f2589f0702b071f9898c7bbd37e"
-  integrity sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==
+"@jest/types@^27.0.6":
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.0.6.tgz#9a992bc517e0c49f035938b8549719c2de40706b"
+  integrity sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==
   dependencies:
     "@types/istanbul-lib-coverage" "^2.0.0"
     "@types/istanbul-reports" "^3.0.0"
@@ -1544,54 +1688,54 @@
   dependencies:
     "@octokit/openapi-types" "^7.3.2"
 
-"@polkadot/api-contract@5.0.1":
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/api-contract/-/api-contract-5.0.1.tgz#520a7b3cd990a76374b79e12eca5bf629cc565a1"
-  integrity sha512-qZ2wnXHDyU2c1/V9GKpbcZKBfVua4YFsU/LHKevZLkJfnGFBgNRdwAuKgVe5h2FCt2W2/pt618WgxG0UDWwjcw==
+"@polkadot/api-contract@5.5.1":
+  version "5.5.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/api-contract/-/api-contract-5.5.1.tgz#4cdd0d6f4352050c58464d5958bdb779770bd2dc"
+  integrity sha512-/1O1AnpCu+LM2EKhRY83r36blG8KOr0JCVFeSfT0u52tM4wMdLlUy1XV/XTZayuCucdJ6I0pjUudCljm92aiGw==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/api" "5.0.1"
-    "@polkadot/types" "5.0.1"
-    "@polkadot/util" "^7.0.1"
-    rxjs "^7.2.0"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/api" "5.5.1"
+    "@polkadot/types" "5.5.1"
+    "@polkadot/util" "^7.2.1"
+    rxjs "^7.3.0"
 
-"@polkadot/api-derive@5.0.1":
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-5.0.1.tgz#08064c10ed159826ffd07013dcdde1d8b63186a0"
-  integrity sha512-JZpH1JVLu3PvX4+A71iDLtNr6LL103dAFou61DxyJF4obyTmS2lzigG3xXqUFShiPDb19ywxQpsE4gAOP6emuQ==
+"@polkadot/api-derive@5.5.1":
+  version "5.5.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-5.5.1.tgz#6fdba748d90024f2fcdeb7827d178ff8d0ad308e"
+  integrity sha512-dkpl3CnroBYAlLx571KoyjI72TqRweWI61z7tzNeR8qwniNyWDEILTErUfzy5jYAO7XrZpW1Gn4WMMH+kEcqZQ==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/api" "5.0.1"
-    "@polkadot/rpc-core" "5.0.1"
-    "@polkadot/types" "5.0.1"
-    "@polkadot/util" "^7.0.1"
-    "@polkadot/util-crypto" "^7.0.1"
-    rxjs "^7.2.0"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/api" "5.5.1"
+    "@polkadot/rpc-core" "5.5.1"
+    "@polkadot/types" "5.5.1"
+    "@polkadot/util" "^7.2.1"
+    "@polkadot/util-crypto" "^7.2.1"
+    rxjs "^7.3.0"
 
-"@polkadot/api@5.0.1":
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-5.0.1.tgz#9607b53009322f9264f7dcc8705c466bd33aa516"
-  integrity sha512-5JDpM2Fjc80gHBju1B/rMBGDfAvY8UiU4XVlivJRk+mTVD3OTwbtTro4nmwJOub05xQCJvD/bnCuxG8eFSoq+Q==
+"@polkadot/api@5.5.1":
+  version "5.5.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-5.5.1.tgz#0298c6d883c2264a68ae93a3b59b98263aed53d3"
+  integrity sha512-GS/MoRc7NB61jz7TzwX0WAA3JS7DSj3xH4ac39LcuPHXu0VMQw6LgT/5KIzYxTx+79Iwth62bKelW/Mgk23wUg==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/api-derive" "5.0.1"
-    "@polkadot/keyring" "^7.0.1"
-    "@polkadot/rpc-core" "5.0.1"
-    "@polkadot/rpc-provider" "5.0.1"
-    "@polkadot/types" "5.0.1"
-    "@polkadot/types-known" "5.0.1"
-    "@polkadot/util" "^7.0.1"
-    "@polkadot/util-crypto" "^7.0.1"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/api-derive" "5.5.1"
+    "@polkadot/keyring" "^7.2.1"
+    "@polkadot/rpc-core" "5.5.1"
+    "@polkadot/rpc-provider" "5.5.1"
+    "@polkadot/types" "5.5.1"
+    "@polkadot/types-known" "5.5.1"
+    "@polkadot/util" "^7.2.1"
+    "@polkadot/util-crypto" "^7.2.1"
     eventemitter3 "^4.0.7"
-    rxjs "^7.2.0"
+    rxjs "^7.3.0"
 
-"@polkadot/dev@0.62.43":
-  version "0.62.43"
-  resolved "https://registry.yarnpkg.com/@polkadot/dev/-/dev-0.62.43.tgz#567591bf3c38dded4b4c1f3ec8bf3d3198a23b6d"
-  integrity sha512-ZSgYUbC6A+WtRSY5nq7yeGYW+wv3g8cds2zndL4GeClIdVHksgEW6+ch3Hx6LMkE3y4q9Kjvs50oHeemBDut4Q==
+"@polkadot/dev@0.62.60":
+  version "0.62.60"
+  resolved "https://registry.yarnpkg.com/@polkadot/dev/-/dev-0.62.60.tgz#450007c189a8433d8627bcc1fc01d2ffb1becfc3"
+  integrity sha512-VHZ4d/hhRSNFe0RXp3L/ZcAk1t2JQ1/lsznONAz4I9SZ2pn5kAQrWRF6eukgfQscrlqCH5njDAxwgXe6ODNVRw==
   dependencies:
-    "@babel/cli" "^7.14.5"
-    "@babel/core" "^7.14.6"
+    "@babel/cli" "^7.14.8"
+    "@babel/core" "^7.15.0"
     "@babel/plugin-proposal-class-properties" "^7.14.5"
     "@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5"
     "@babel/plugin-proposal-numeric-separator" "^7.14.5"
@@ -1603,28 +1747,34 @@
     "@babel/plugin-syntax-import-meta" "^7.10.4"
     "@babel/plugin-syntax-top-level-await" "^7.14.5"
     "@babel/plugin-transform-regenerator" "^7.14.5"
-    "@babel/plugin-transform-runtime" "^7.14.5"
-    "@babel/preset-env" "^7.14.7"
+    "@babel/plugin-transform-runtime" "^7.15.0"
+    "@babel/preset-env" "^7.15.0"
     "@babel/preset-react" "^7.14.5"
-    "@babel/preset-typescript" "^7.14.5"
-    "@babel/register" "^7.14.5"
-    "@babel/runtime" "^7.14.6"
+    "@babel/preset-typescript" "^7.15.0"
+    "@babel/register" "^7.15.3"
+    "@babel/runtime" "^7.15.3"
+    "@rollup/plugin-alias" "^3.1.5"
+    "@rollup/plugin-commonjs" "^19.0.2"
+    "@rollup/plugin-inject" "^4.0.2"
+    "@rollup/plugin-json" "^4.1.0"
+    "@rollup/plugin-node-resolve" "^13.0.4"
     "@rushstack/eslint-patch" "^1.0.6"
-    "@typescript-eslint/eslint-plugin" "4.28.0"
-    "@typescript-eslint/parser" "4.28.0"
+    "@typescript-eslint/eslint-plugin" "4.29.2"
+    "@typescript-eslint/parser" "4.29.2"
     "@vue/component-compiler-utils" "^3.2.2"
-    babel-jest "^27.0.5"
+    babel-jest "^27.0.6"
     babel-plugin-module-extension-resolver "^1.0.0-rc.2"
     babel-plugin-module-resolver "^4.1.0"
-    babel-plugin-styled-components "^1.12.0"
-    browserslist "^4.16.6"
-    chalk "^4.1.1"
-    coveralls "^3.1.0"
-    eslint "^7.29.0"
+    babel-plugin-styled-components "^1.13.2"
+    browserslist "^4.16.7"
+    chalk "^4.1.2"
+    coveralls "^3.1.1"
+    eslint "^7.32.0"
     eslint-config-standard "^16.0.3"
-    eslint-import-resolver-node "^0.3.4"
+    eslint-import-resolver-node "^0.3.6"
     eslint-plugin-header "^3.1.1"
-    eslint-plugin-import "^2.23.4"
+    eslint-plugin-import "^2.24.0"
+    eslint-plugin-import-newlines "^1.1.4"
     eslint-plugin-node "^11.1.0"
     eslint-plugin-promise "^5.1.0"
     eslint-plugin-react "^7.24.0"
@@ -1636,118 +1786,129 @@
     gh-release "^6.0.0"
     glob "^7.1.7"
     glob2base "^0.0.12"
-    jest "^27.0.5"
-    jest-cli "^27.0.5"
-    jest-config "^27.0.5"
-    jest-haste-map "^27.0.5"
-    jest-resolve "^27.0.5"
+    jest "^27.0.6"
+    jest-cli "^27.0.6"
+    jest-config "^27.0.6"
+    jest-haste-map "^27.0.6"
+    jest-resolve "^27.0.6"
     madge "^4.0.2"
     minimatch "^3.0.4"
     mkdirp "^1.0.4"
-    prettier "^2.3.1"
+    prettier "^2.3.2"
     rimraf "^3.0.2"
-    typescript "^4.3.4"
-    yargs "^17.0.1"
+    rollup "^2.56.2"
+    typescript "^4.3.5"
+    yargs "^17.1.1"
 
-"@polkadot/keyring@^7.0.1":
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-7.0.1.tgz#666e903661b98279dc16d512be69f5ace4b58d8d"
-  integrity sha512-eSvG8Q4gUTRDFWj2lqTY/9NekGP8dtp+W6WmouKh0DDwHRawaVeDaq6UJYQv6XoBG1i+ZGPvErRQeGMPOn/mUQ==
+"@polkadot/keyring@^7.2.1":
+  version "7.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-7.2.1.tgz#5ed8e6c0edc61e3dd99ee647a227b9e3d955e8e6"
+  integrity sha512-WmiTsHKELX16uZWLvebDBckZIAXeJFfbcOM6m/VbMOjSV5C6xIKqiV3232Mn8ZuPKgsOf25Q78/IwJW1Dq53Qg==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/util" "7.0.1"
-    "@polkadot/util-crypto" "7.0.1"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/util" "7.2.1"
+    "@polkadot/util-crypto" "7.2.1"
 
-"@polkadot/networks@7.0.1", "@polkadot/networks@^7.0.1":
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-7.0.1.tgz#e07c4b88e25711433e76d24fce4c7273c25dd38b"
-  integrity sha512-bJSvI7UgEpxmBKS8TMh+I1mfmCMwhClGdSs29kwU+K61IjBTKTt3yQJ/SflYIQV7QftGbz3oMfSkGbQbRHZqvQ==
+"@polkadot/networks@7.2.1", "@polkadot/networks@^7.2.1":
+  version "7.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-7.2.1.tgz#20c8d81fba4b48162bf360759d8d54c55d30128b"
+  integrity sha512-YX8oQ7QQ2oq3YowwOiv/C82l849V0ZEzpR26YrPgKSXbYFbasho3Akf0zalndZJZV1Bb8EiOkzGoJ3ffogSPxA==
   dependencies:
-    "@babel/runtime" "^7.14.6"
+    "@babel/runtime" "^7.15.3"
 
-"@polkadot/rpc-core@5.0.1":
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-5.0.1.tgz#8460287532fe61c31505564df53e92ef6feba875"
-  integrity sha512-JMNOVQijjyJZNu9B8CJwIrQzGYzAp03uCBSbqYfzWBFnYVLKh7JmvOlkLnODM8uUYq0gVN4BaDUSPc39GpELAQ==
+"@polkadot/rpc-core@5.5.1":
+  version "5.5.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-5.5.1.tgz#4ce0646becabe7736dfb81eb902e5933158646c8"
+  integrity sha512-hP7a55iSpgZVqxAIpK+v63eV/nD14Tm7C1rUmfKIS6gGJFJf+sQbTmp6d7+fuKxvYfFqBrFLU8IraOhLOQ5W3Q==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/rpc-provider" "5.0.1"
-    "@polkadot/types" "5.0.1"
-    "@polkadot/util" "^7.0.1"
-    rxjs "^7.2.0"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/rpc-provider" "5.5.1"
+    "@polkadot/types" "5.5.1"
+    "@polkadot/util" "^7.2.1"
+    rxjs "^7.3.0"
 
-"@polkadot/rpc-provider@5.0.1":
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-5.0.1.tgz#ef022a123eb9073634b59c6e0f6e1705e96066a5"
-  integrity sha512-t+VKhMtQfQVgkZDqYnP/44KlBDmcCVo1/MvJ+DoNd7RUWUIBJt3v71G5gDSNeGMTyvxn0KK0qL4j+Nqr6c4FUQ==
+"@polkadot/rpc-provider@5.5.1":
+  version "5.5.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-5.5.1.tgz#633f4a48605623092fb9017433f2b3cd70cd96bc"
+  integrity sha512-wOCKeeyUa7Dw3nxKkQntnfOO471icdzqT2V7bwloBOo+G2MX8nHImO0mW3QMfJygn4qoARF1PBo1PLbDUEDgog==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/types" "5.0.1"
-    "@polkadot/util" "^7.0.1"
-    "@polkadot/util-crypto" "^7.0.1"
-    "@polkadot/x-fetch" "^7.0.1"
-    "@polkadot/x-global" "^7.0.1"
-    "@polkadot/x-ws" "^7.0.1"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/types" "5.5.1"
+    "@polkadot/util" "^7.2.1"
+    "@polkadot/util-crypto" "^7.2.1"
+    "@polkadot/x-fetch" "^7.2.1"
+    "@polkadot/x-global" "^7.2.1"
+    "@polkadot/x-ws" "^7.2.1"
     eventemitter3 "^4.0.7"
 
-"@polkadot/ts@0.3.89":
-  version "0.3.89"
-  resolved "https://registry.yarnpkg.com/@polkadot/ts/-/ts-0.3.89.tgz#c7a704ea284d04fcf4d581f5df156d5945480033"
-  integrity sha512-GC0H8wmVKebkieN2MHScjDDonzigIzkjl1Q4V1OhoRcfQbeZZ7vijeiVwP8Hw3wIw4GLKxxXeDrkKPWl/bcaHw==
+"@polkadot/ts@0.4.4":
+  version "0.4.4"
+  resolved "https://registry.yarnpkg.com/@polkadot/ts/-/ts-0.4.4.tgz#e86aa47c2bcbc70ac8385b31014c81927c4b0a88"
+  integrity sha512-lzB8lg8GfdJlA7RdeoOJVFopecN4i++JndbUs6jW7AgRz+joeXQIIRomVgCNE52nW1uWpXMELnlvEP812v7sVw==
   dependencies:
-    "@types/chrome" "^0.0.144"
+    "@types/chrome" "^0.0.145"
 
-"@polkadot/typegen@5.0.1":
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/typegen/-/typegen-5.0.1.tgz#718b517f4f1578441911096603577bd0a2a968e0"
-  integrity sha512-iFLJoWgIkn+J6MDw3AUWveP9qxVn1C+VeLJbpZ21St5WyeE148Tml0BmYnKLSXlaPMhZEwB+/IV3jpQ35dH4bw==
+"@polkadot/typegen@5.5.1":
+  version "5.5.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/typegen/-/typegen-5.5.1.tgz#b31010716a142290d12f48ead6166851599055d0"
+  integrity sha512-ua55CVqT3+Y5fX9stpYUO+UhiJJ1RDTZ6vM2/Lndmsuda4lHQnUDrCnMmxKhM5OcyIlJlY5mF9dyO0kl5mTm+w==
   dependencies:
-    "@babel/core" "^7.14.6"
-    "@babel/register" "^7.14.5"
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/api" "5.0.1"
-    "@polkadot/rpc-provider" "5.0.1"
-    "@polkadot/types" "5.0.1"
-    "@polkadot/util" "^7.0.1"
+    "@babel/core" "^7.15.0"
+    "@babel/register" "^7.15.3"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/api" "5.5.1"
+    "@polkadot/rpc-provider" "5.5.1"
+    "@polkadot/types" "5.5.1"
+    "@polkadot/types-support" "5.5.1"
+    "@polkadot/util" "^7.2.1"
     handlebars "^4.7.7"
     websocket "^1.0.34"
-    yargs "^17.0.1"
+    yargs "^17.1.0"
 
-"@polkadot/types-known@5.0.1":
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-5.0.1.tgz#21feb327fc4323733bf027c8d874a2aa3014b21f"
-  integrity sha512-AIhPlN4r14ZW4wdwHZD2nIe1DE61ZO9PsyrCyAU3ysl6Cw6TI+txDCN3aS/8XYuC7wDLEgLB9vJv2sVWdCzqJg==
+"@polkadot/types-known@5.5.1":
+  version "5.5.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-5.5.1.tgz#b00b0d45cbd07b4e0c3199f8ba00d10a1bd3f63d"
+  integrity sha512-bxBRmZ0a3lwEyWkWOKqmDJfpNKh3cp9xo6IidrQU2S5OPMjFFercB+HwJjkNE1cMtShwBYTvDheUImNkdm+FXA==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/networks" "^7.0.1"
-    "@polkadot/types" "5.0.1"
-    "@polkadot/util" "^7.0.1"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/networks" "^7.2.1"
+    "@polkadot/types" "5.5.1"
+    "@polkadot/util" "^7.2.1"
 
-"@polkadot/types@5.0.1":
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-5.0.1.tgz#2a4e23e452f999eeae175b595470df0e426a930d"
-  integrity sha512-aN6JKeF7ZYi5irYAaUoDqth6qlOlB15C5vhlDOojEorYLfRs/R+GCrO+lPSs+bKmSxh7BSRh500ikI/xD4nx5A==
+"@polkadot/types-support@5.5.1":
+  version "5.5.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/types-support/-/types-support-5.5.1.tgz#15556c2f31e79f0a6a821c7723f702757cb89462"
+  integrity sha512-57i1SdK8B+miGTAlDNdvbBuN6FguTnwzv2UPE2Zv3iQznTSZBkQZN16tIK/yMkQfhtO4ZzPcAnnSPZMncqh/Mg==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/util" "^7.0.1"
-    "@polkadot/util-crypto" "^7.0.1"
-    rxjs "^7.2.0"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/util" "^7.2.1"
 
-"@polkadot/util-crypto@7.0.1", "@polkadot/util-crypto@^7.0.1":
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-7.0.1.tgz#03109dc11323dad174fb2214d395855495def16a"
-  integrity sha512-dbvdsICoyOVw/K45RmHOP7wXE/7vj+NzEKGcKbiDt39nglHm6g2BTJ947PwwyNusTTAx82Q2iJ9vIZ1Kl0xG+g==
+"@polkadot/types@5.5.1":
+  version "5.5.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-5.5.1.tgz#057e8f0fc2369c0741c0f9b0224418e8f25a6938"
+  integrity sha512-+Cm7Y6D/98WqL8ofONyZrVvE2CxzK3/z18bATIQIWhG2w9ir9PdWaFMZ3fLCRw2Ggaq88AknguK6kXeEPcKPrA==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/networks" "7.0.1"
-    "@polkadot/util" "7.0.1"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/util" "^7.2.1"
+    "@polkadot/util-crypto" "^7.2.1"
+    rxjs "^7.3.0"
+
+"@polkadot/util-crypto@7.2.1", "@polkadot/util-crypto@^7.2.1":
+  version "7.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-7.2.1.tgz#7f1bbf031dac75090699083fc9e825c22e5d5f61"
+  integrity sha512-X3iGba/1JTL/0MNzMNEIlO9DNyKlwFV839jfGLDKhPbCuDmWp0NdQjF3mBmbvNwkXvn07WmhE7g3q9n5iTzqvQ==
+  dependencies:
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/networks" "7.2.1"
+    "@polkadot/util" "7.2.1"
     "@polkadot/wasm-crypto" "^4.1.2"
-    "@polkadot/x-randomvalues" "7.0.1"
+    "@polkadot/x-randomvalues" "7.2.1"
     base-x "^3.0.8"
     base64-js "^1.5.1"
     blakejs "^1.1.1"
     bn.js "^4.11.9"
     create-hash "^1.2.0"
+    ed2curve "^0.3.0"
     elliptic "^6.5.4"
     hash.js "^1.1.7"
     js-sha3 "^0.8.0"
@@ -1755,14 +1916,14 @@
     tweetnacl "^1.0.3"
     xxhashjs "^0.2.2"
 
-"@polkadot/util@7.0.1", "@polkadot/util@^7.0.1":
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-7.0.1.tgz#79afd40473016876f51d65ebb9900a20108fe0a4"
-  integrity sha512-EtQlZL6ok0Ep+zRz2QHMUoJo/b3kFHVN2qqyD2+9sdqg0FGLmkzNFM+K6dasCMLXieJ1l0HoFsQppSo/leUeaA==
+"@polkadot/util@7.2.1", "@polkadot/util@^7.2.1":
+  version "7.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-7.2.1.tgz#abcad49f884534ff042c37480f63b9750c69341d"
+  integrity sha512-GilFg3i5dmu0H6dHEyh5bUw3yywmnFpEHfxFmKghL1ABDEr4qD0d/XAJ9UrzLFCBKbdTZsR0MDjgjVI2N84J1A==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/x-textdecoder" "7.0.1"
-    "@polkadot/x-textencoder" "7.0.1"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/x-textdecoder" "7.2.1"
+    "@polkadot/x-textencoder" "7.2.1"
     "@types/bn.js" "^4.11.6"
     bn.js "^4.11.9"
     camelcase "^5.3.1"
@@ -1791,57 +1952,114 @@
     "@polkadot/wasm-crypto-asmjs" "^4.1.2"
     "@polkadot/wasm-crypto-wasm" "^4.1.2"
 
-"@polkadot/x-fetch@^7.0.1":
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-7.0.1.tgz#2db6fa19f4f4d9b2f4cf50ba78bf3aa947d7b982"
-  integrity sha512-9R38FjtlJcvdpEA7tVGmTmH4aiBCTABuLJdVSn3cYkgWfxDHeFMqjdFzTJ6Asa5cY0Ds3ZKsh9uccTQBQzV/HQ==
+"@polkadot/x-fetch@^7.2.1":
+  version "7.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-7.2.1.tgz#c9bee0316d31cd150b2cb6646ccdb77c6dc3d42d"
+  integrity sha512-osdZNPfrB50d7tfjVs4QRjfsb6xqC09JEeYzbUl24hUXPwtkQE8/379jayu1usPe9/JI2wKYGscdf/nRl4pBkA==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/x-global" "7.0.1"
-    "@types/node-fetch" "^2.5.11"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/x-global" "7.2.1"
+    "@types/node-fetch" "^2.5.12"
     node-fetch "^2.6.1"
 
-"@polkadot/x-global@7.0.1", "@polkadot/x-global@^7.0.1":
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-7.0.1.tgz#44fb248d3aaea557753318327149772969e96bff"
-  integrity sha512-gVVACSdRhHYRJejLEAL0mM9BZfY8N50VT2+15A7ALD1tVqwS4tz3P9vRW3Go7ZjfyAc83aEmh0PiQ8Nm1R+2Cg==
+"@polkadot/x-global@7.2.1", "@polkadot/x-global@^7.2.1":
+  version "7.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-7.2.1.tgz#32207936b7f939a21da608f82ca20535f9148cda"
+  integrity sha512-VNW+76TxEPqvBy3XMNV05mJRPRGZcYh3k5HjW4+asYeFunMahH4zjmCulhtD9SRI/TqdfHTiqDOqKNKe2xJcVg==
   dependencies:
-    "@babel/runtime" "^7.14.6"
+    "@babel/runtime" "^7.15.3"
 
-"@polkadot/x-randomvalues@7.0.1":
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-7.0.1.tgz#32036ae5d48645a062f6a1c3ebbf227236c806b8"
-  integrity sha512-UNoIFaz1xJPozruT+lo8BTeT8A3NM3PgWuru7Vs8OsIz0Phkg7lUWlpHu9PZHyQCyKlUryvkOA692IlVlNYy2Q==
+"@polkadot/x-randomvalues@7.2.1":
+  version "7.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-7.2.1.tgz#708b7a54bd90ec091ab54e125d8b52e0853ea86b"
+  integrity sha512-B4sjwX+gFweZ1YM1Cg/S9hAEx9E/gV/vqLW89PJB6+hyvsPS9eiVvfVpaOsohc7AgmuINm/bSQbNZvtC+BbbKw==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/x-global" "7.0.1"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/x-global" "7.2.1"
 
-"@polkadot/x-textdecoder@7.0.1":
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-7.0.1.tgz#bb9bba94b2eb1612dd35c299f43ab74515db74d9"
-  integrity sha512-CFRnpI0cp1h2N1+ec551BLVLwV6OHG6Gj62EYcIOXR+o/SX/6MXm3Qcehm2YvfTKqktyIUSWmTwbWjGjuqPrpA==
+"@polkadot/x-textdecoder@7.2.1":
+  version "7.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-7.2.1.tgz#c52074dba9943a12583f3f8672a49399f10e00f3"
+  integrity sha512-yXSZ0P/D/8HT8gbkdTjw/1AKZIVbX3+mIfiDiN3VqUBzruV7ak5hA+D01I0woBGDqxWISoLQFtGrxPAQ8pwAcg==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/x-global" "7.0.1"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/x-global" "7.2.1"
 
-"@polkadot/x-textencoder@7.0.1":
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-7.0.1.tgz#181d403c5dc1d94fd1e2147fd1c5c528d30d8805"
-  integrity sha512-m+QL1HNiu5GMz6cfr/udSA6fUTv3RyIybJb7v43EQCxqlj/L0J3cUHapFd6tqH9PElD6jPkH1pXcgYN8e7dWTQ==
+"@polkadot/x-textencoder@7.2.1":
+  version "7.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-7.2.1.tgz#2326b3b7f9a5e445d7e560c438effbe800e2b1f6"
+  integrity sha512-1aqfxmfKSOWeOxmGBmk+RYrpqGtWywS6t0y/R3FI+k+s8NfIfGdcjMcupKq7khPh92PvVGkur+CnM/y6chn4XA==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/x-global" "7.0.1"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/x-global" "7.2.1"
 
-"@polkadot/x-ws@^7.0.1":
-  version "7.0.1"
-  resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-7.0.1.tgz#8c22a61c0dd9b82865c7631e22ac147c2b73b118"
-  integrity sha512-VUn/6sCJUpvW9WhUK+DKo1uDrw4yO84twRcy5JSzvSiBTaSplhU9Q4qGFl2Atr3WIzAYYx1jQSm/j6AhPRji1w==
+"@polkadot/x-ws@^7.2.1":
+  version "7.2.1"
+  resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-7.2.1.tgz#5971ab630911cdecd0a46db6fb899e9086954e58"
+  integrity sha512-sYnOF0qNdMuGFiRGWAtpkQQYIP44JFzGywap0CskhNEyCc+zDBi4l/ta3qHjeGta+h9rdVjDeYk2J86EsKlkSw==
   dependencies:
-    "@babel/runtime" "^7.14.6"
-    "@polkadot/x-global" "7.0.1"
-    "@types/websocket" "^1.0.3"
+    "@babel/runtime" "^7.15.3"
+    "@polkadot/x-global" "7.2.1"
+    "@types/websocket" "^1.0.4"
     websocket "^1.0.34"
 
+"@rollup/plugin-alias@^3.1.5":
+  version "3.1.5"
+  resolved "https://registry.yarnpkg.com/@rollup/plugin-alias/-/plugin-alias-3.1.5.tgz#73356a3a1eab2e1e2fd952f9f53cd89fc740d952"
+  integrity sha512-yzUaSvCC/LJPbl9rnzX3HN7vy0tq7EzHoEiQl1ofh4n5r2Rd5bj/+zcJgaGA76xbw95/JjWQyvHg9rOJp2y0oQ==
+  dependencies:
+    slash "^3.0.0"
+
+"@rollup/plugin-commonjs@^19.0.2":
+  version "19.0.2"
+  resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-19.0.2.tgz#1ccc3d63878d1bc9846f8969f09dd3b3e4ecc244"
+  integrity sha512-gBjarfqlC7qs0AutpRW/hrFNm+cd2/QKxhwyFa+srbg1oX7rDsEU3l+W7LAUhsAp9mPJMAkXDhLbQaVwEaE8bA==
+  dependencies:
+    "@rollup/pluginutils" "^3.1.0"
+    commondir "^1.0.1"
+    estree-walker "^2.0.1"
+    glob "^7.1.6"
+    is-reference "^1.2.1"
+    magic-string "^0.25.7"
+    resolve "^1.17.0"
+
+"@rollup/plugin-inject@^4.0.2":
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/@rollup/plugin-inject/-/plugin-inject-4.0.2.tgz#55b21bb244a07675f7fdde577db929c82fc17395"
+  integrity sha512-TSLMA8waJ7Dmgmoc8JfPnwUwVZgLjjIAM6MqeIFqPO2ODK36JqE0Cf2F54UTgCUuW8da93Mvoj75a6KAVWgylw==
+  dependencies:
+    "@rollup/pluginutils" "^3.0.4"
+    estree-walker "^1.0.1"
+    magic-string "^0.25.5"
+
+"@rollup/plugin-json@^4.1.0":
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.1.0.tgz#54e09867ae6963c593844d8bd7a9c718294496f3"
+  integrity sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==
+  dependencies:
+    "@rollup/pluginutils" "^3.0.8"
+
+"@rollup/plugin-node-resolve@^13.0.4":
+  version "13.0.4"
+  resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.0.4.tgz#b10222f4145a019740acb7738402130d848660c0"
+  integrity sha512-eYq4TFy40O8hjeDs+sIxEH/jc9lyuI2k9DM557WN6rO5OpnC2qXMBNj4IKH1oHrnAazL49C5p0tgP0/VpqJ+/w==
+  dependencies:
+    "@rollup/pluginutils" "^3.1.0"
+    "@types/resolve" "1.17.1"
+    builtin-modules "^3.1.0"
+    deepmerge "^4.2.2"
+    is-module "^1.0.0"
+    resolve "^1.19.0"
+
+"@rollup/pluginutils@^3.0.4", "@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0":
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
+  integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==
+  dependencies:
+    "@types/estree" "0.0.39"
+    estree-walker "^1.0.1"
+    picomatch "^2.2.2"
+
 "@rushstack/eslint-patch@^1.0.6":
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.0.6.tgz#023d72a5c4531b4ce204528971700a78a85a0c50"
@@ -1930,18 +2148,23 @@
   resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.18.tgz#0c8e298dbff8205e2266606c1ea5fbdba29b46e4"
   integrity sha512-rS27+EkB/RE1Iz3u0XtVL5q36MGDWbgYe7zWiodyKNUnthxY0rukK5V36eiUCtCisB7NN8zKYH6DO2M37qxFEQ==
 
-"@types/chrome@^0.0.144":
-  version "0.0.144"
-  resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.144.tgz#7dd9188e355aa17e3ad397f50b5cd3ad12caf788"
-  integrity sha512-BgoiO7/KP9hRNrCR2Wq+aKWT5Dh9bTofuWaRtcqPcj8YKhZojQgb6sSdIqvds2C+eO63BwaR9KHVMYYgZdGGBg==
+"@types/chrome@^0.0.145":
+  version "0.0.145"
+  resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.145.tgz#6c53ae0af5f25350b07bfd24cf459b5fe65cd9b8"
+  integrity sha512-vLvTMmfc8mvwOZzkmn2UwlWSNu0t0txBkyuIv8NgihRkvFCe6XJX65YZAgAP/RdBit3enhU2GTxCr+prn4uZmA==
   dependencies:
     "@types/filesystem" "*"
     "@types/har-format" "*"
 
-"@types/eslint-visitor-keys@^1.0.0":
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
-  integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==
+"@types/estree@*":
+  version "0.0.50"
+  resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83"
+  integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==
+
+"@types/estree@0.0.39":
+  version "0.0.39"
+  resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
+  integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
 
 "@types/filesystem@*":
   version "0.0.30"
@@ -1985,11 +2208,6 @@
   integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==
   dependencies:
     "@types/istanbul-lib-report" "*"
-
-"@types/json-schema@^7.0.3":
-  version "7.0.8"
-  resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.8.tgz#edf1bf1dbf4e04413ca8e5b17b3b7d7d54b59818"
-  integrity sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==
 
 "@types/json-schema@^7.0.7":
   version "7.0.7"
@@ -2006,10 +2224,10 @@
   resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.2.tgz#91daa226eb8c2ff261e6a8cbf8c7304641e095e0"
   integrity sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==
 
-"@types/node-fetch@^2.5.11":
-  version "2.5.11"
-  resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.11.tgz#ce22a2e65fc8999f4dbdb7ddbbcf187d755169e4"
-  integrity sha512-2upCKaqVZETDRb8A2VTaRymqFBEgH8u6yr96b/u3+1uQEPDRo3mJLEiPk7vdXBHRtjwkjqzFYMJXrt0Z9QsYjQ==
+"@types/node-fetch@^2.5.12":
+  version "2.5.12"
+  resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.12.tgz#8a6f779b1d4e60b7a57fb6fd48d84fb545b9cc66"
+  integrity sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==
   dependencies:
     "@types/node" "*"
     form-data "^3.0.0"
@@ -2041,6 +2259,13 @@
   resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.0.tgz#2e8332cc7363f887d32ec5496b207d26ba8052bb"
   integrity sha512-hkc1DATxFLQo4VxPDpMH1gCkPpBbpOoJ/4nhuXw4n63/0R6bCpQECj4+K226UJ4JO/eJQz+1mC2I7JsWanAdQw==
 
+"@types/resolve@1.17.1":
+  version "1.17.1"
+  resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6"
+  integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==
+  dependencies:
+    "@types/node" "*"
+
 "@types/secp256k1@^4.0.1":
   version "4.0.2"
   resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.2.tgz#20c29a87149d980f64464e56539bf4810fdb5d1d"
@@ -2053,10 +2278,10 @@
   resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff"
   integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==
 
-"@types/websocket@^1.0.3":
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.3.tgz#49e09f939afd0ccdee4f7108d4712ec9feb0f153"
-  integrity sha512-ZdoTSwmDsKR7l1I8fpfQtmTI/hUwlOvE3q0iyJsp4tXU0MkdrYowimDzwxjhQvxU4qjhHLd3a6ig0OXRbLgIdw==
+"@types/websocket@^1.0.4":
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.4.tgz#1dc497280d8049a5450854dd698ee7e6ea9e60b8"
+  integrity sha512-qn1LkcFEKK8RPp459jkjzsfpbsx36BBt3oC3pITYtkoBw/aVX+EZFa5j3ThCRTNpLFvIMr5dSTD4RaMdilIOpA==
   dependencies:
     "@types/node" "*"
 
@@ -2072,119 +2297,127 @@
   dependencies:
     "@types/yargs-parser" "*"
 
-"@typescript-eslint/eslint-plugin@4.28.0":
-  version "4.28.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.0.tgz#1a66f03b264844387beb7dc85e1f1d403bd1803f"
-  integrity sha512-KcF6p3zWhf1f8xO84tuBailV5cN92vhS+VT7UJsPzGBm9VnQqfI9AsiMUFUCYHTYPg1uCCo+HyiDnpDuvkAMfQ==
+"@typescript-eslint/eslint-plugin@4.29.2":
+  version "4.29.2"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.2.tgz#f54dc0a32b8f61c6024ab8755da05363b733838d"
+  integrity sha512-x4EMgn4BTfVd9+Z+r+6rmWxoAzBaapt4QFqE+d8L8sUtYZYLDTK6VG/y/SMMWA5t1/BVU5Kf+20rX4PtWzUYZg==
   dependencies:
-    "@typescript-eslint/experimental-utils" "4.28.0"
-    "@typescript-eslint/scope-manager" "4.28.0"
+    "@typescript-eslint/experimental-utils" "4.29.2"
+    "@typescript-eslint/scope-manager" "4.29.2"
     debug "^4.3.1"
     functional-red-black-tree "^1.0.1"
     regexpp "^3.1.0"
     semver "^7.3.5"
     tsutils "^3.21.0"
 
-"@typescript-eslint/eslint-plugin@^3.4.0":
-  version "3.10.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz#7e061338a1383f59edc204c605899f93dc2e2c8f"
-  integrity sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ==
+"@typescript-eslint/eslint-plugin@^4.28.5":
+  version "4.28.5"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.5.tgz#8197f1473e7da8218c6a37ff308d695707835684"
+  integrity sha512-m31cPEnbuCqXtEZQJOXAHsHvtoDi9OVaeL5wZnO2KZTnkvELk+u6J6jHg+NzvWQxk+87Zjbc4lJS4NHmgImz6Q==
   dependencies:
-    "@typescript-eslint/experimental-utils" "3.10.1"
-    debug "^4.1.1"
+    "@typescript-eslint/experimental-utils" "4.28.5"
+    "@typescript-eslint/scope-manager" "4.28.5"
+    debug "^4.3.1"
     functional-red-black-tree "^1.0.1"
-    regexpp "^3.0.0"
-    semver "^7.3.2"
-    tsutils "^3.17.1"
+    regexpp "^3.1.0"
+    semver "^7.3.5"
+    tsutils "^3.21.0"
 
-"@typescript-eslint/experimental-utils@3.10.1":
-  version "3.10.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686"
-  integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==
+"@typescript-eslint/experimental-utils@4.28.5":
+  version "4.28.5"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.5.tgz#66c28bef115b417cf9d80812a713e0e46bb42a64"
+  integrity sha512-bGPLCOJAa+j49hsynTaAtQIWg6uZd8VLiPcyDe4QPULsvQwLHGLSGKKcBN8/lBxIX14F74UEMK2zNDI8r0okwA==
   dependencies:
-    "@types/json-schema" "^7.0.3"
-    "@typescript-eslint/types" "3.10.1"
-    "@typescript-eslint/typescript-estree" "3.10.1"
-    eslint-scope "^5.0.0"
-    eslint-utils "^2.0.0"
+    "@types/json-schema" "^7.0.7"
+    "@typescript-eslint/scope-manager" "4.28.5"
+    "@typescript-eslint/types" "4.28.5"
+    "@typescript-eslint/typescript-estree" "4.28.5"
+    eslint-scope "^5.1.1"
+    eslint-utils "^3.0.0"
 
-"@typescript-eslint/experimental-utils@4.28.0":
-  version "4.28.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.0.tgz#13167ed991320684bdc23588135ae62115b30ee0"
-  integrity sha512-9XD9s7mt3QWMk82GoyUpc/Ji03vz4T5AYlHF9DcoFNfJ/y3UAclRsfGiE2gLfXtyC+JRA3trR7cR296TEb1oiQ==
+"@typescript-eslint/experimental-utils@4.29.2":
+  version "4.29.2"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.2.tgz#5f67fb5c5757ef2cb3be64817468ba35c9d4e3b7"
+  integrity sha512-P6mn4pqObhftBBPAv4GQtEK7Yos1fz/MlpT7+YjH9fTxZcALbiiPKuSIfYP/j13CeOjfq8/fr9Thr2glM9ub7A==
   dependencies:
     "@types/json-schema" "^7.0.7"
-    "@typescript-eslint/scope-manager" "4.28.0"
-    "@typescript-eslint/types" "4.28.0"
-    "@typescript-eslint/typescript-estree" "4.28.0"
+    "@typescript-eslint/scope-manager" "4.29.2"
+    "@typescript-eslint/types" "4.29.2"
+    "@typescript-eslint/typescript-estree" "4.29.2"
     eslint-scope "^5.1.1"
     eslint-utils "^3.0.0"
 
-"@typescript-eslint/parser@4.28.0":
-  version "4.28.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.28.0.tgz#2404c16751a28616ef3abab77c8e51d680a12caa"
-  integrity sha512-7x4D22oPY8fDaOCvkuXtYYTQ6mTMmkivwEzS+7iml9F9VkHGbbZ3x4fHRwxAb5KeuSkLqfnYjs46tGx2Nour4A==
+"@typescript-eslint/parser@4.29.2":
+  version "4.29.2"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.29.2.tgz#1c7744f4c27aeb74610c955d3dce9250e95c370a"
+  integrity sha512-WQ6BPf+lNuwteUuyk1jD/aHKqMQ9jrdCn7Gxt9vvBnzbpj7aWEf+aZsJ1zvTjx5zFxGCt000lsbD9tQPEL8u6g==
   dependencies:
-    "@typescript-eslint/scope-manager" "4.28.0"
-    "@typescript-eslint/types" "4.28.0"
-    "@typescript-eslint/typescript-estree" "4.28.0"
+    "@typescript-eslint/scope-manager" "4.29.2"
+    "@typescript-eslint/types" "4.29.2"
+    "@typescript-eslint/typescript-estree" "4.29.2"
     debug "^4.3.1"
 
-"@typescript-eslint/parser@^3.4.0":
-  version "3.10.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467"
-  integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==
+"@typescript-eslint/parser@^4.28.5":
+  version "4.28.5"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.28.5.tgz#9c971668f86d1b5c552266c47788a87488a47d1c"
+  integrity sha512-NPCOGhTnkXGMqTznqgVbA5LqVsnw+i3+XA1UKLnAb+MG1Y1rP4ZSK9GX0kJBmAZTMIktf+dTwXToT6kFwyimbw==
   dependencies:
-    "@types/eslint-visitor-keys" "^1.0.0"
-    "@typescript-eslint/experimental-utils" "3.10.1"
-    "@typescript-eslint/types" "3.10.1"
-    "@typescript-eslint/typescript-estree" "3.10.1"
-    eslint-visitor-keys "^1.1.0"
+    "@typescript-eslint/scope-manager" "4.28.5"
+    "@typescript-eslint/types" "4.28.5"
+    "@typescript-eslint/typescript-estree" "4.28.5"
+    debug "^4.3.1"
 
-"@typescript-eslint/scope-manager@4.28.0":
-  version "4.28.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.28.0.tgz#6a3009d2ab64a30fc8a1e257a1a320067f36a0ce"
-  integrity sha512-eCALCeScs5P/EYjwo6se9bdjtrh8ByWjtHzOkC4Tia6QQWtQr3PHovxh3TdYTuFcurkYI4rmFsRFpucADIkseg==
+"@typescript-eslint/scope-manager@4.28.5":
+  version "4.28.5"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.28.5.tgz#3a1b70c50c1535ac33322786ea99ebe403d3b923"
+  integrity sha512-PHLq6n9nTMrLYcVcIZ7v0VY1X7dK309NM8ya9oL/yG8syFINIMHxyr2GzGoBYUdv3NUfCOqtuqps0ZmcgnZTfQ==
   dependencies:
-    "@typescript-eslint/types" "4.28.0"
-    "@typescript-eslint/visitor-keys" "4.28.0"
+    "@typescript-eslint/types" "4.28.5"
+    "@typescript-eslint/visitor-keys" "4.28.5"
 
-"@typescript-eslint/types@3.10.1":
-  version "3.10.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727"
-  integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==
+"@typescript-eslint/scope-manager@4.29.2":
+  version "4.29.2"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.29.2.tgz#442b0f029d981fa402942715b1718ac7fcd5aa1b"
+  integrity sha512-mfHmvlQxmfkU8D55CkZO2sQOueTxLqGvzV+mG6S/6fIunDiD2ouwsAoiYCZYDDK73QCibYjIZmGhpvKwAB5BOA==
+  dependencies:
+    "@typescript-eslint/types" "4.29.2"
+    "@typescript-eslint/visitor-keys" "4.29.2"
 
 "@typescript-eslint/types@4.27.0":
   version "4.27.0"
   resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.27.0.tgz#712b408519ed699baff69086bc59cd2fc13df8d8"
   integrity sha512-I4ps3SCPFCKclRcvnsVA/7sWzh7naaM/b4pBO2hVxnM3wrU51Lveybdw5WoIktU/V4KfXrTt94V9b065b/0+wA==
 
-"@typescript-eslint/types@4.28.0":
-  version "4.28.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.0.tgz#a33504e1ce7ac51fc39035f5fe6f15079d4dafb0"
-  integrity sha512-p16xMNKKoiJCVZY5PW/AfILw2xe1LfruTcfAKBj3a+wgNYP5I9ZEKNDOItoRt53p4EiPV6iRSICy8EPanG9ZVA==
+"@typescript-eslint/types@4.28.5":
+  version "4.28.5"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.5.tgz#d33edf8e429f0c0930a7c3d44e9b010354c422e9"
+  integrity sha512-MruOu4ZaDOLOhw4f/6iudyks/obuvvZUAHBDSW80Trnc5+ovmViLT2ZMDXhUV66ozcl6z0LJfKs1Usldgi/WCA==
+
+"@typescript-eslint/types@4.29.2":
+  version "4.29.2"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.29.2.tgz#fc0489c6b89773f99109fb0aa0aaddff21f52fcd"
+  integrity sha512-K6ApnEXId+WTGxqnda8z4LhNMa/pZmbTFkDxEBLQAbhLZL50DjeY0VIDCml/0Y3FlcbqXZrABqrcKxq+n0LwzQ==
 
-"@typescript-eslint/typescript-estree@3.10.1":
-  version "3.10.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853"
-  integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==
+"@typescript-eslint/typescript-estree@4.28.5":
+  version "4.28.5"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.5.tgz#4906d343de693cf3d8dcc301383ed638e0441cd1"
+  integrity sha512-FzJUKsBX8poCCdve7iV7ShirP8V+ys2t1fvamVeD1rWpiAnIm550a+BX/fmTHrjEpQJ7ZAn+Z7ZZwJjytk9rZw==
   dependencies:
-    "@typescript-eslint/types" "3.10.1"
-    "@typescript-eslint/visitor-keys" "3.10.1"
-    debug "^4.1.1"
-    glob "^7.1.6"
+    "@typescript-eslint/types" "4.28.5"
+    "@typescript-eslint/visitor-keys" "4.28.5"
+    debug "^4.3.1"
+    globby "^11.0.3"
     is-glob "^4.0.1"
-    lodash "^4.17.15"
-    semver "^7.3.2"
-    tsutils "^3.17.1"
+    semver "^7.3.5"
+    tsutils "^3.21.0"
 
-"@typescript-eslint/typescript-estree@4.28.0":
-  version "4.28.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.0.tgz#e66d4e5aa2ede66fec8af434898fe61af10c71cf"
-  integrity sha512-m19UQTRtxMzKAm8QxfKpvh6OwQSXaW1CdZPoCaQuLwAq7VZMNuhJmZR4g5281s2ECt658sldnJfdpSZZaxUGMQ==
+"@typescript-eslint/typescript-estree@4.29.2":
+  version "4.29.2"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.2.tgz#a0ea8b98b274adbb2577100ba545ddf8bf7dc219"
+  integrity sha512-TJ0/hEnYxapYn9SGn3dCnETO0r+MjaxtlWZ2xU+EvytF0g4CqTpZL48SqSNn2hXsPolnewF30pdzR9a5Lj3DNg==
   dependencies:
-    "@typescript-eslint/types" "4.28.0"
-    "@typescript-eslint/visitor-keys" "4.28.0"
+    "@typescript-eslint/types" "4.29.2"
+    "@typescript-eslint/visitor-keys" "4.29.2"
     debug "^4.3.1"
     globby "^11.0.3"
     is-glob "^4.0.1"
@@ -2204,13 +2437,6 @@
     semver "^7.3.5"
     tsutils "^3.21.0"
 
-"@typescript-eslint/visitor-keys@3.10.1":
-  version "3.10.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931"
-  integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==
-  dependencies:
-    eslint-visitor-keys "^1.1.0"
-
 "@typescript-eslint/visitor-keys@4.27.0":
   version "4.27.0"
   resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.27.0.tgz#f56138b993ec822793e7ebcfac6ffdce0a60cb81"
@@ -2219,14 +2445,22 @@
     "@typescript-eslint/types" "4.27.0"
     eslint-visitor-keys "^2.0.0"
 
-"@typescript-eslint/visitor-keys@4.28.0":
-  version "4.28.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.0.tgz#255c67c966ec294104169a6939d96f91c8a89434"
-  integrity sha512-PjJyTWwrlrvM5jazxYF5ZPs/nl0kHDZMVbuIcbpawVXaDPelp3+S9zpOz5RmVUfS/fD5l5+ZXNKnWhNYjPzCvw==
+"@typescript-eslint/visitor-keys@4.28.5":
+  version "4.28.5"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.5.tgz#ffee2c602762ed6893405ee7c1144d9cc0a29675"
+  integrity sha512-dva/7Rr+EkxNWdJWau26xU/0slnFlkh88v3TsyTgRS/IIYFi5iIfpCFM4ikw0vQTFUR9FYSSyqgK4w64gsgxhg==
   dependencies:
-    "@typescript-eslint/types" "4.28.0"
+    "@typescript-eslint/types" "4.28.5"
     eslint-visitor-keys "^2.0.0"
 
+"@typescript-eslint/visitor-keys@4.29.2":
+  version "4.29.2"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.2.tgz#d2da7341f3519486f50655159f4e5ecdcb2cd1df"
+  integrity sha512-bDgJLQ86oWHJoZ1ai4TZdgXzJxsea3Ee9u9wsTAvjChdj2WLcVsgWYAPeY7RQMn16tKrlQaBnpKv7KBfs4EQag==
+  dependencies:
+    "@typescript-eslint/types" "4.29.2"
+    eslint-visitor-keys "^2.0.0"
+
 "@ungap/promise-all-settled@1.1.2":
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
@@ -2592,16 +2826,16 @@
   resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
   integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
 
-babel-jest@^27.0.5:
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.0.5.tgz#cd34c033ada05d1362211e5152391fd7a88080c8"
-  integrity sha512-bTMAbpCX7ldtfbca2llYLeSFsDM257aspyAOpsdrdSrBqoLkWCy4HPYTXtXWaSLgFPjrJGACL65rzzr4RFGadw==
+babel-jest@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.0.6.tgz#e99c6e0577da2655118e3608b68761a5a69bd0d8"
+  integrity sha512-iTJyYLNc4wRofASmofpOc5NK9QunwMk+TLFgGXsTFS8uEqmd8wdI7sga0FPe2oVH3b5Agt/EAK1QjPEuKL8VfA==
   dependencies:
-    "@jest/transform" "^27.0.5"
-    "@jest/types" "^27.0.2"
+    "@jest/transform" "^27.0.6"
+    "@jest/types" "^27.0.6"
     "@types/babel__core" "^7.1.14"
     babel-plugin-istanbul "^6.0.0"
-    babel-preset-jest "^27.0.1"
+    babel-preset-jest "^27.0.6"
     chalk "^4.0.0"
     graceful-fs "^4.2.4"
     slash "^3.0.0"
@@ -2624,10 +2858,10 @@
     istanbul-lib-instrument "^4.0.0"
     test-exclude "^6.0.0"
 
-babel-plugin-jest-hoist@^27.0.1:
-  version "27.0.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.0.1.tgz#a6d10e484c93abff0f4e95f437dad26e5736ea11"
-  integrity sha512-sqBF0owAcCDBVEDtxqfYr2F36eSHdx7lAVGyYuOBRnKdD6gzcy0I0XrAYCZgOA3CRrLhmR+Uae9nogPzmAtOfQ==
+babel-plugin-jest-hoist@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.0.6.tgz#f7c6b3d764af21cb4a2a1ab6870117dbde15b456"
+  integrity sha512-CewFeM9Vv2gM7Yr9n5eyyLVPRSiBnk6lKZRjgwYnGKSl9M14TMn2vkN02wTF04OGuSDLEzlWiMzvjXuW9mB6Gw==
   dependencies:
     "@babel/template" "^7.3.3"
     "@babel/types" "^7.3.3"
@@ -2674,10 +2908,10 @@
   dependencies:
     "@babel/helper-define-polyfill-provider" "^0.2.2"
 
-babel-plugin-styled-components@^1.12.0:
-  version "1.12.0"
-  resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.12.0.tgz#1dec1676512177de6b827211e9eda5a30db4f9b9"
-  integrity sha512-FEiD7l5ZABdJPpLssKXjBUJMYqzbcNzBowfXDCdJhOpbhWiewapUaY+LZGT8R4Jg2TwOjGjG4RKeyrO5p9sBkA==
+babel-plugin-styled-components@^1.13.2:
+  version "1.13.2"
+  resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.13.2.tgz#ebe0e6deff51d7f93fceda1819e9b96aeb88278d"
+  integrity sha512-Vb1R3d4g+MUfPQPVDMCGjm3cDocJEUTR7Xq7QS95JWWeksN1wdFRYpD2kulDgI3Huuaf1CZd+NK4KQmqUFh5dA==
   dependencies:
     "@babel/helper-annotate-as-pure" "^7.0.0"
     "@babel/helper-module-imports" "^7.0.0"
@@ -2707,12 +2941,12 @@
     "@babel/plugin-syntax-optional-chaining" "^7.8.3"
     "@babel/plugin-syntax-top-level-await" "^7.8.3"
 
-babel-preset-jest@^27.0.1:
-  version "27.0.1"
-  resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.0.1.tgz#7a50c75d16647c23a2cf5158d5bb9eb206b10e20"
-  integrity sha512-nIBIqCEpuiyhvjQs2mVNwTxQQa2xk70p9Dd/0obQGBf8FBzbnI8QhQKzLsWMN2i6q+5B0OcWDtrboBX5gmOLyA==
+babel-preset-jest@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.0.6.tgz#909ef08e9f24a4679768be2f60a3df0856843f9d"
+  integrity sha512-WObA0/Biw2LrVVwZkF/2GqbOdzhKD6Fkdwhoy9ASIrOWr/zodcSpQh72JOkEn6NWyjmnPDjNSqaGN4KnpKzhXw==
   dependencies:
-    babel-plugin-jest-hoist "^27.0.1"
+    babel-plugin-jest-hoist "^27.0.6"
     babel-preset-current-node-syntax "^1.0.0"
 
 balanced-match@^1.0.0:
@@ -2952,6 +3186,17 @@
     escalade "^3.1.1"
     node-releases "^1.1.71"
 
+browserslist@^4.16.7:
+  version "4.16.7"
+  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.7.tgz#108b0d1ef33c4af1b587c54f390e7041178e4335"
+  integrity sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==
+  dependencies:
+    caniuse-lite "^1.0.30001248"
+    colorette "^1.2.2"
+    electron-to-chromium "^1.3.793"
+    escalade "^3.1.1"
+    node-releases "^1.1.73"
+
 bs58@^4.0.0:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a"
@@ -3010,6 +3255,11 @@
   resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
   integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
 
+builtin-modules@^3.1.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887"
+  integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==
+
 bytes@3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
@@ -3071,6 +3321,11 @@
   resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001238.tgz#e6a8b45455c5de601718736d0242feef0ecdda15"
   integrity sha512-bZGam2MxEt7YNsa2VwshqWQMwrYs5tR5WZQRYSuFxsBQunWjBuXhN4cS9nV5FFb1Z9y+DoQcQ0COyQbv6A+CKw==
 
+caniuse-lite@^1.0.30001248:
+  version "1.0.30001251"
+  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz#6853a606ec50893115db660f82c094d18f096d85"
+  integrity sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==
+
 caseless@~0.12.0:
   version "0.12.0"
   resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
@@ -3120,6 +3375,14 @@
     ansi-styles "^4.1.0"
     supports-color "^7.1.0"
 
+chalk@^4.1.2:
+  version "4.1.2"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+  integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+  dependencies:
+    ansi-styles "^4.1.0"
+    supports-color "^7.1.0"
+
 changelog-parser@^2.0.0:
   version "2.8.0"
   resolved "https://registry.yarnpkg.com/changelog-parser/-/changelog-parser-2.8.0.tgz#c14293e3e8fab797913c722de965480198650108"
@@ -3338,6 +3601,16 @@
   dependencies:
     delayed-stream "~1.0.0"
 
+command-exists@^1.2.8:
+  version "1.2.9"
+  resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69"
+  integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==
+
+commander@3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e"
+  integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==
+
 commander@^2.12.1, commander@^2.16.0, commander@^2.18.0, commander@^2.20.3, commander@^2.8.1:
   version "2.20.3"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@@ -3448,12 +3721,12 @@
     browserslist "^4.16.6"
     semver "7.0.0"
 
-core-js-compat@^3.15.0:
-  version "3.15.1"
-  resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.15.1.tgz#1afe233716d37ee021956ef097594071b2b585a7"
-  integrity sha512-xGhzYMX6y7oEGQGAJmP2TmtBLvR4nZmRGEcFa3ubHOq5YEp51gGN9AovVa0AoujGZIq+Wm6dISiYyGNfdflYww==
+core-js-compat@^3.16.0:
+  version "3.16.1"
+  resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.16.1.tgz#c44b7caa2dcb94b673a98f27eee1c8312f55bc2d"
+  integrity sha512-NHXQXvRbd4nxp9TEmooTJLUf94ySUG6+DSsscBpTftN1lQLQ4LjnWvc7AoIo4UjDsFF3hB8Uh5LLCRRdaiT5MQ==
   dependencies:
-    browserslist "^4.16.6"
+    browserslist "^4.16.7"
     semver "7.0.0"
 
 core-util-is@1.0.2, core-util-is@~1.0.0:
@@ -3469,10 +3742,10 @@
     object-assign "^4"
     vary "^1"
 
-coveralls@^3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.0.tgz#13c754d5e7a2dd8b44fe5269e21ca394fb4d615b"
-  integrity sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ==
+coveralls@^3.1.1:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.1.tgz#f5d4431d8b5ae69c5079c8f8ca00d64ac77cf081"
+  integrity sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==
   dependencies:
     js-yaml "^3.13.1"
     lcov-parse "^1.0.0"
@@ -3859,10 +4132,10 @@
     node-source-walk "^4.2.0"
     typescript "^3.9.7"
 
-diff-sequences@^27.0.1:
-  version "27.0.1"
-  resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.0.1.tgz#9c9801d52ed5f576ff0a20e3022a13ee6e297e7c"
-  integrity sha512-XPLijkfJUh/PIBnfkcSHgvD6tlYixmcMAn3osTk6jt+H0v/mgURto1XUiD9DKuGX5NDoVS6dSlA23gd9FUaCFg==
+diff-sequences@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.0.6.tgz#3305cb2e55a033924054695cc66019fd7f8e5723"
+  integrity sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==
 
 diff@5.0.0:
   version "5.0.0"
@@ -3946,6 +4219,13 @@
     jsbn "~0.1.0"
     safer-buffer "^2.1.0"
 
+ed2curve@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/ed2curve/-/ed2curve-0.3.0.tgz#322b575152a45305429d546b071823a93129a05d"
+  integrity sha512-8w2fmmq3hv9rCrcI7g9hms2pMunQr1JINfcjwR9tAyZqhtyaMN991lF/ZfHfr5tzZQ8c7y7aBgZbjfbd0fjFwQ==
+  dependencies:
+    tweetnacl "1.x.x"
+
 ee-first@1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -3956,6 +4236,11 @@
   resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.752.tgz#0728587f1b9b970ec9ffad932496429aef750d09"
   integrity sha512-2Tg+7jSl3oPxgsBsWKh5H83QazTkmWG/cnNwJplmyZc7KcN61+I10oUgaXSVk/NwfvN3BdkKDR4FYuRBQQ2v0A==
 
+electron-to-chromium@^1.3.793:
+  version "1.3.807"
+  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.807.tgz#c2eb803f4f094869b1a24151184ffbbdbf688b1f"
+  integrity sha512-p8uxxg2a23zRsvQ2uwA/OOI+O4BQxzaR7YKMIGGGQCpYmkFX2CVF5f0/hxLMV7yCr7nnJViCwHLhPfs52rIYCA==
+
 elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4:
   version "6.5.4"
   resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
@@ -4127,18 +4412,18 @@
   resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz#6c8761e544e96c531ff92642eeb87842b8488516"
   integrity sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg==
 
-eslint-import-resolver-node@^0.3.4:
-  version "0.3.4"
-  resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717"
-  integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==
+eslint-import-resolver-node@^0.3.5, eslint-import-resolver-node@^0.3.6:
+  version "0.3.6"
+  resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd"
+  integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==
   dependencies:
-    debug "^2.6.9"
-    resolve "^1.13.1"
+    debug "^3.2.7"
+    resolve "^1.20.0"
 
-eslint-module-utils@^2.6.1:
-  version "2.6.1"
-  resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz#b51be1e473dd0de1c5ea638e22429c2490ea8233"
-  integrity sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==
+eslint-module-utils@^2.6.2:
+  version "2.6.2"
+  resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz#94e5540dd15fe1522e8ffa3ec8db3b7fa7e7a534"
+  integrity sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==
   dependencies:
     debug "^3.2.7"
     pkg-dir "^2.0.0"
@@ -4156,17 +4441,22 @@
   resolved "https://registry.yarnpkg.com/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz#6ce512432d57675265fac47292b50d1eff11acd6"
   integrity sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg==
 
-eslint-plugin-import@^2.23.4:
-  version "2.23.4"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz#8dceb1ed6b73e46e50ec9a5bb2411b645e7d3d97"
-  integrity sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==
+eslint-plugin-import-newlines@^1.1.4:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-import-newlines/-/eslint-plugin-import-newlines-1.1.4.tgz#d69d03fe512b2f54bc781d1dfc51a4ad99df7a52"
+  integrity sha512-GCIM+524XQOFcEPinEyrvktQHkQq+k+kYCwbRrIioGBVGnk3RGDFWv5BPqBQCDci6SNZCVgIOi3/FmtDetbxvA==
+
+eslint-plugin-import@^2.24.0:
+  version "2.24.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.24.0.tgz#697ffd263e24da5e84e03b282f5fb62251777177"
+  integrity sha512-Kc6xqT9hiYi2cgybOc0I2vC9OgAYga5o/rAFinam/yF/t5uBqxQbauNPMC6fgb640T/89P0gFoO27FOilJ/Cqg==
   dependencies:
     array-includes "^3.1.3"
     array.prototype.flat "^1.2.4"
     debug "^2.6.9"
     doctrine "^2.1.0"
-    eslint-import-resolver-node "^0.3.4"
-    eslint-module-utils "^2.6.1"
+    eslint-import-resolver-node "^0.3.5"
+    eslint-module-utils "^2.6.2"
     find-up "^2.0.0"
     has "^1.0.3"
     is-core-module "^2.4.0"
@@ -4229,7 +4519,7 @@
   dependencies:
     natural-compare-lite "^1.4.0"
 
-eslint-scope@^5.0.0, eslint-scope@^5.1.1:
+eslint-scope@^5.1.1:
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
   integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
@@ -4261,13 +4551,13 @@
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
   integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
 
-eslint@^7.28.0:
-  version "7.30.0"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.30.0.tgz#6d34ab51aaa56112fd97166226c9a97f505474f8"
-  integrity sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg==
+eslint@^7.31.0:
+  version "7.31.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.31.0.tgz#f972b539424bf2604907a970860732c5d99d3aca"
+  integrity sha512-vafgJpSh2ia8tnTkNUkwxGmnumgckLh5aAbLa1xRmIn9+owi8qBNGKL+B881kNKNTy7FFqTEkpNkUvmw0n6PkA==
   dependencies:
     "@babel/code-frame" "7.12.11"
-    "@eslint/eslintrc" "^0.4.2"
+    "@eslint/eslintrc" "^0.4.3"
     "@humanwhocodes/config-array" "^0.5.0"
     ajv "^6.10.0"
     chalk "^4.0.0"
@@ -4307,13 +4597,14 @@
     text-table "^0.2.0"
     v8-compile-cache "^2.0.3"
 
-eslint@^7.29.0:
-  version "7.29.0"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.29.0.tgz#ee2a7648f2e729485e4d0bd6383ec1deabc8b3c0"
-  integrity sha512-82G/JToB9qIy/ArBzIWG9xvvwL3R86AlCjtGw+A29OMZDqhTybz/MByORSukGxeI+YPCR4coYyITKk8BFH9nDA==
+eslint@^7.32.0:
+  version "7.32.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d"
+  integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==
   dependencies:
     "@babel/code-frame" "7.12.11"
-    "@eslint/eslintrc" "^0.4.2"
+    "@eslint/eslintrc" "^0.4.3"
+    "@humanwhocodes/config-array" "^0.5.0"
     ajv "^6.10.0"
     chalk "^4.0.0"
     cross-spawn "^7.0.2"
@@ -4390,6 +4681,16 @@
   resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880"
   integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==
 
+estree-walker@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700"
+  integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==
+
+estree-walker@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
+  integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
+
 esutils@^2.0.2:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
@@ -4550,17 +4851,17 @@
     snapdragon "^0.8.1"
     to-regex "^3.0.1"
 
-expect@^27.0.2:
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/expect/-/expect-27.0.2.tgz#e66ca3a4c9592f1c019fa1d46459a9d2084f3422"
-  integrity sha512-YJFNJe2+P2DqH+ZrXy+ydRQYO87oxRUonZImpDodR1G7qo3NYd3pL+NQ9Keqpez3cehczYwZDBC3A7xk3n7M/w==
+expect@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/expect/-/expect-27.0.6.tgz#a4d74fbe27222c718fff68ef49d78e26a8fd4c05"
+  integrity sha512-psNLt8j2kwg42jGBDSfAlU49CEZxejN1f1PlANWDZqIhBOVU/c2Pm888FcjWJzFewhIsNWfZJeLjUjtKGiPuSw==
   dependencies:
-    "@jest/types" "^27.0.2"
+    "@jest/types" "^27.0.6"
     ansi-styles "^5.0.0"
-    jest-get-type "^27.0.1"
-    jest-matcher-utils "^27.0.2"
-    jest-message-util "^27.0.2"
-    jest-regex-util "^27.0.1"
+    jest-get-type "^27.0.6"
+    jest-matcher-utils "^27.0.6"
+    jest-message-util "^27.0.6"
+    jest-regex-util "^27.0.6"
 
 express@^4.14.0:
   version "4.17.1"
@@ -4860,6 +5161,11 @@
   resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b"
   integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==
 
+follow-redirects@^1.12.1:
+  version "1.14.1"
+  resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43"
+  integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==
+
 for-in@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@@ -4910,6 +5216,17 @@
   resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
   integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
 
+fs-extra@^0.30.0:
+  version "0.30.0"
+  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0"
+  integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=
+  dependencies:
+    graceful-fs "^4.1.2"
+    jsonfile "^2.1.0"
+    klaw "^1.0.0"
+    path-is-absolute "^1.0.0"
+    rimraf "^2.2.8"
+
 fs-extra@^10.0.0:
   version "10.0.0"
   resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1"
@@ -5253,7 +5570,7 @@
     url-parse-lax "^1.0.0"
     url-to-options "^1.0.1"
 
-graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
   version "4.2.6"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
   integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
@@ -5817,6 +6134,11 @@
   resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
   integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
 
+is-module@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
+  integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=
+
 is-negative-zero@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
@@ -5891,6 +6213,13 @@
   resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
   integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
 
+is-reference@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7"
+  integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==
+  dependencies:
+    "@types/estree" "*"
+
 is-regex@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.3.tgz#d029f9aff6448b93ebbe3f33dac71511fdcbef9f"
@@ -6048,226 +6377,226 @@
     has-to-string-tag-x "^1.2.0"
     is-object "^1.0.1"
 
-jest-changed-files@^27.0.2:
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.0.2.tgz#997253042b4a032950fc5f56abf3c5d1f8560801"
-  integrity sha512-eMeb1Pn7w7x3wue5/vF73LPCJ7DKQuC9wQUR5ebP9hDPpk5hzcT/3Hmz3Q5BOFpR3tgbmaWhJcMTVgC8Z1NuMw==
+jest-changed-files@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.0.6.tgz#bed6183fcdea8a285482e3b50a9a7712d49a7a8b"
+  integrity sha512-BuL/ZDauaq5dumYh5y20sn4IISnf1P9A0TDswTxUi84ORGtVa86ApuBHqICL0vepqAnZiY6a7xeSPWv2/yy4eA==
   dependencies:
-    "@jest/types" "^27.0.2"
+    "@jest/types" "^27.0.6"
     execa "^5.0.0"
     throat "^6.0.1"
 
-jest-circus@^27.0.5:
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.0.5.tgz#b5e327f1d6857c8485126f8e364aefa4378debaa"
-  integrity sha512-p5rO90o1RTh8LPOG6l0Fc9qgp5YGv+8M5CFixhMh7gGHtGSobD1AxX9cjFZujILgY8t30QZ7WVvxlnuG31r8TA==
+jest-circus@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.0.6.tgz#dd4df17c4697db6a2c232aaad4e9cec666926668"
+  integrity sha512-OJlsz6BBeX9qR+7O9lXefWoc2m9ZqcZ5Ohlzz0pTEAG4xMiZUJoacY8f4YDHxgk0oKYxj277AfOk9w6hZYvi1Q==
   dependencies:
-    "@jest/environment" "^27.0.5"
-    "@jest/test-result" "^27.0.2"
-    "@jest/types" "^27.0.2"
+    "@jest/environment" "^27.0.6"
+    "@jest/test-result" "^27.0.6"
+    "@jest/types" "^27.0.6"
     "@types/node" "*"
     chalk "^4.0.0"
     co "^4.6.0"
     dedent "^0.7.0"
-    expect "^27.0.2"
+    expect "^27.0.6"
     is-generator-fn "^2.0.0"
-    jest-each "^27.0.2"
-    jest-matcher-utils "^27.0.2"
-    jest-message-util "^27.0.2"
-    jest-runtime "^27.0.5"
-    jest-snapshot "^27.0.5"
-    jest-util "^27.0.2"
-    pretty-format "^27.0.2"
+    jest-each "^27.0.6"
+    jest-matcher-utils "^27.0.6"
+    jest-message-util "^27.0.6"
+    jest-runtime "^27.0.6"
+    jest-snapshot "^27.0.6"
+    jest-util "^27.0.6"
+    pretty-format "^27.0.6"
     slash "^3.0.0"
     stack-utils "^2.0.3"
     throat "^6.0.1"
 
-jest-cli@^27.0.5:
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.0.5.tgz#f359ba042624cffb96b713010a94bffb7498a37c"
-  integrity sha512-kZqY020QFOFQKVE2knFHirTBElw3/Q0kUbDc3nMfy/x+RQ7zUY89SUuzpHHJoSX1kX7Lq569ncvjNqU3Td/FCA==
+jest-cli@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.0.6.tgz#d021e5f4d86d6a212450d4c7b86cb219f1e6864f"
+  integrity sha512-qUUVlGb9fdKir3RDE+B10ULI+LQrz+MCflEH2UJyoUjoHHCbxDrMxSzjQAPUMsic4SncI62ofYCcAvW6+6rhhg==
   dependencies:
-    "@jest/core" "^27.0.5"
-    "@jest/test-result" "^27.0.2"
-    "@jest/types" "^27.0.2"
+    "@jest/core" "^27.0.6"
+    "@jest/test-result" "^27.0.6"
+    "@jest/types" "^27.0.6"
     chalk "^4.0.0"
     exit "^0.1.2"
     graceful-fs "^4.2.4"
     import-local "^3.0.2"
-    jest-config "^27.0.5"
-    jest-util "^27.0.2"
-    jest-validate "^27.0.2"
+    jest-config "^27.0.6"
+    jest-util "^27.0.6"
+    jest-validate "^27.0.6"
     prompts "^2.0.1"
     yargs "^16.0.3"
 
-jest-config@^27.0.5:
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.0.5.tgz#683da3b0d8237675c29c817f6e3aba1481028e19"
-  integrity sha512-zCUIXag7QIXKEVN4kUKbDBDi9Q53dV5o3eNhGqe+5zAbt1vLs4VE3ceWaYrOub0L4Y7E9pGfM84TX/0ARcE+Qw==
+jest-config@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.0.6.tgz#119fb10f149ba63d9c50621baa4f1f179500277f"
+  integrity sha512-JZRR3I1Plr2YxPBhgqRspDE2S5zprbga3swYNrvY3HfQGu7p/GjyLOqwrYad97tX3U3mzT53TPHVmozacfP/3w==
   dependencies:
     "@babel/core" "^7.1.0"
-    "@jest/test-sequencer" "^27.0.5"
-    "@jest/types" "^27.0.2"
-    babel-jest "^27.0.5"
+    "@jest/test-sequencer" "^27.0.6"
+    "@jest/types" "^27.0.6"
+    babel-jest "^27.0.6"
     chalk "^4.0.0"
     deepmerge "^4.2.2"
     glob "^7.1.1"
     graceful-fs "^4.2.4"
     is-ci "^3.0.0"
-    jest-circus "^27.0.5"
-    jest-environment-jsdom "^27.0.5"
-    jest-environment-node "^27.0.5"
-    jest-get-type "^27.0.1"
-    jest-jasmine2 "^27.0.5"
-    jest-regex-util "^27.0.1"
-    jest-resolve "^27.0.5"
-    jest-runner "^27.0.5"
-    jest-util "^27.0.2"
-    jest-validate "^27.0.2"
+    jest-circus "^27.0.6"
+    jest-environment-jsdom "^27.0.6"
+    jest-environment-node "^27.0.6"
+    jest-get-type "^27.0.6"
+    jest-jasmine2 "^27.0.6"
+    jest-regex-util "^27.0.6"
+    jest-resolve "^27.0.6"
+    jest-runner "^27.0.6"
+    jest-util "^27.0.6"
+    jest-validate "^27.0.6"
     micromatch "^4.0.4"
-    pretty-format "^27.0.2"
+    pretty-format "^27.0.6"
 
-jest-diff@^27.0.2:
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.0.2.tgz#f315b87cee5dc134cf42c2708ab27375cc3f5a7e"
-  integrity sha512-BFIdRb0LqfV1hBt8crQmw6gGQHVDhM87SpMIZ45FPYKReZYG5er1+5pIn2zKqvrJp6WNox0ylR8571Iwk2Dmgw==
+jest-diff@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.0.6.tgz#4a7a19ee6f04ad70e0e3388f35829394a44c7b5e"
+  integrity sha512-Z1mqgkTCSYaFgwTlP/NUiRzdqgxmmhzHY1Tq17zL94morOHfHu3K4bgSgl+CR4GLhpV8VxkuOYuIWnQ9LnFqmg==
   dependencies:
     chalk "^4.0.0"
-    diff-sequences "^27.0.1"
-    jest-get-type "^27.0.1"
-    pretty-format "^27.0.2"
+    diff-sequences "^27.0.6"
+    jest-get-type "^27.0.6"
+    pretty-format "^27.0.6"
 
-jest-docblock@^27.0.1:
-  version "27.0.1"
-  resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.0.1.tgz#bd9752819b49fa4fab1a50b73eb58c653b962e8b"
-  integrity sha512-TA4+21s3oebURc7VgFV4r7ltdIJ5rtBH1E3Tbovcg7AV+oLfD5DcJ2V2vJ5zFA9sL5CFd/d2D6IpsAeSheEdrA==
+jest-docblock@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.0.6.tgz#cc78266acf7fe693ca462cbbda0ea4e639e4e5f3"
+  integrity sha512-Fid6dPcjwepTFraz0YxIMCi7dejjJ/KL9FBjPYhBp4Sv1Y9PdhImlKZqYU555BlN4TQKaTc+F2Av1z+anVyGkA==
   dependencies:
     detect-newline "^3.0.0"
 
-jest-each@^27.0.2:
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.0.2.tgz#865ddb4367476ced752167926b656fa0dcecd8c7"
-  integrity sha512-OLMBZBZ6JkoXgUenDtseFRWA43wVl2BwmZYIWQws7eS7pqsIvePqj/jJmEnfq91ALk3LNphgwNK/PRFBYi7ITQ==
+jest-each@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.0.6.tgz#cee117071b04060158dc8d9a66dc50ad40ef453b"
+  integrity sha512-m6yKcV3bkSWrUIjxkE9OC0mhBZZdhovIW5ergBYirqnkLXkyEn3oUUF/QZgyecA1cF1QFyTE8bRRl8Tfg1pfLA==
   dependencies:
-    "@jest/types" "^27.0.2"
+    "@jest/types" "^27.0.6"
     chalk "^4.0.0"
-    jest-get-type "^27.0.1"
-    jest-util "^27.0.2"
-    pretty-format "^27.0.2"
+    jest-get-type "^27.0.6"
+    jest-util "^27.0.6"
+    pretty-format "^27.0.6"
 
-jest-environment-jsdom@^27.0.5:
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.0.5.tgz#c36771977cf4490a9216a70473b39161d193c212"
-  integrity sha512-ToWhViIoTl5738oRaajTMgYhdQL73UWPoV4GqHGk2DPhs+olv8OLq5KoQW8Yf+HtRao52XLqPWvl46dPI88PdA==
+jest-environment-jsdom@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.0.6.tgz#f66426c4c9950807d0a9f209c590ce544f73291f"
+  integrity sha512-FvetXg7lnXL9+78H+xUAsra3IeZRTiegA3An01cWeXBspKXUhAwMM9ycIJ4yBaR0L7HkoMPaZsozCLHh4T8fuw==
   dependencies:
-    "@jest/environment" "^27.0.5"
-    "@jest/fake-timers" "^27.0.5"
-    "@jest/types" "^27.0.2"
+    "@jest/environment" "^27.0.6"
+    "@jest/fake-timers" "^27.0.6"
+    "@jest/types" "^27.0.6"
     "@types/node" "*"
-    jest-mock "^27.0.3"
-    jest-util "^27.0.2"
+    jest-mock "^27.0.6"
+    jest-util "^27.0.6"
     jsdom "^16.6.0"
 
-jest-environment-node@^27.0.5:
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.0.5.tgz#b7238fc2b61ef2fb9563a3b7653a95fa009a6a54"
-  integrity sha512-47qqScV/WMVz5OKF5TWpAeQ1neZKqM3ySwNveEnLyd+yaE/KT6lSMx/0SOx60+ZUcVxPiESYS+Kt2JS9y4PpkQ==
+jest-environment-node@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.0.6.tgz#a6699b7ceb52e8d68138b9808b0c404e505f3e07"
+  integrity sha512-+Vi6yLrPg/qC81jfXx3IBlVnDTI6kmRr08iVa2hFCWmJt4zha0XW7ucQltCAPhSR0FEKEoJ3i+W4E6T0s9is0w==
   dependencies:
-    "@jest/environment" "^27.0.5"
-    "@jest/fake-timers" "^27.0.5"
-    "@jest/types" "^27.0.2"
+    "@jest/environment" "^27.0.6"
+    "@jest/fake-timers" "^27.0.6"
+    "@jest/types" "^27.0.6"
     "@types/node" "*"
-    jest-mock "^27.0.3"
-    jest-util "^27.0.2"
+    jest-mock "^27.0.6"
+    jest-util "^27.0.6"
 
-jest-get-type@^27.0.1:
-  version "27.0.1"
-  resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.0.1.tgz#34951e2b08c8801eb28559d7eb732b04bbcf7815"
-  integrity sha512-9Tggo9zZbu0sHKebiAijyt1NM77Z0uO4tuWOxUCujAiSeXv30Vb5D4xVF4UR4YWNapcftj+PbByU54lKD7/xMg==
+jest-get-type@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.0.6.tgz#0eb5c7f755854279ce9b68a9f1a4122f69047cfe"
+  integrity sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg==
 
-jest-haste-map@^27.0.5:
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.0.5.tgz#2e1e55073b5328410a2c0d74b334e513d71f3470"
-  integrity sha512-3LFryGSHxwPFHzKIs6W0BGA2xr6g1MvzSjR3h3D8K8Uqy4vbRm/grpGHzbPtIbOPLC6wFoViRrNEmd116QWSkw==
+jest-haste-map@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.0.6.tgz#4683a4e68f6ecaa74231679dca237279562c8dc7"
+  integrity sha512-4ldjPXX9h8doB2JlRzg9oAZ2p6/GpQUNAeiYXqcpmrKbP0Qev0wdZlxSMOmz8mPOEnt4h6qIzXFLDi8RScX/1w==
   dependencies:
-    "@jest/types" "^27.0.2"
+    "@jest/types" "^27.0.6"
     "@types/graceful-fs" "^4.1.2"
     "@types/node" "*"
     anymatch "^3.0.3"
     fb-watchman "^2.0.0"
     graceful-fs "^4.2.4"
-    jest-regex-util "^27.0.1"
-    jest-serializer "^27.0.1"
-    jest-util "^27.0.2"
-    jest-worker "^27.0.2"
+    jest-regex-util "^27.0.6"
+    jest-serializer "^27.0.6"
+    jest-util "^27.0.6"
+    jest-worker "^27.0.6"
     micromatch "^4.0.4"
     walker "^1.0.7"
   optionalDependencies:
     fsevents "^2.3.2"
 
-jest-jasmine2@^27.0.5:
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.0.5.tgz#8a6eb2a685cdec3af13881145c77553e4e197776"
-  integrity sha512-m3TojR19sFmTn79QoaGy1nOHBcLvtLso6Zh7u+gYxZWGcza4rRPVqwk1hciA5ZOWWZIJOukAcore8JRX992FaA==
+jest-jasmine2@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.0.6.tgz#fd509a9ed3d92bd6edb68a779f4738b100655b37"
+  integrity sha512-cjpH2sBy+t6dvCeKBsHpW41mjHzXgsavaFMp+VWRf0eR4EW8xASk1acqmljFtK2DgyIECMv2yCdY41r2l1+4iA==
   dependencies:
     "@babel/traverse" "^7.1.0"
-    "@jest/environment" "^27.0.5"
-    "@jest/source-map" "^27.0.1"
-    "@jest/test-result" "^27.0.2"
-    "@jest/types" "^27.0.2"
+    "@jest/environment" "^27.0.6"
+    "@jest/source-map" "^27.0.6"
+    "@jest/test-result" "^27.0.6"
+    "@jest/types" "^27.0.6"
     "@types/node" "*"
     chalk "^4.0.0"
     co "^4.6.0"
-    expect "^27.0.2"
+    expect "^27.0.6"
     is-generator-fn "^2.0.0"
-    jest-each "^27.0.2"
-    jest-matcher-utils "^27.0.2"
-    jest-message-util "^27.0.2"
-    jest-runtime "^27.0.5"
-    jest-snapshot "^27.0.5"
-    jest-util "^27.0.2"
-    pretty-format "^27.0.2"
+    jest-each "^27.0.6"
+    jest-matcher-utils "^27.0.6"
+    jest-message-util "^27.0.6"
+    jest-runtime "^27.0.6"
+    jest-snapshot "^27.0.6"
+    jest-util "^27.0.6"
+    pretty-format "^27.0.6"
     throat "^6.0.1"
 
-jest-leak-detector@^27.0.2:
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.0.2.tgz#ce19aa9dbcf7a72a9d58907a970427506f624e69"
-  integrity sha512-TZA3DmCOfe8YZFIMD1GxFqXUkQnIoOGQyy4hFCA2mlHtnAaf+FeOMxi0fZmfB41ZL+QbFG6BVaZF5IeFIVy53Q==
+jest-leak-detector@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.0.6.tgz#545854275f85450d4ef4b8fe305ca2a26450450f"
+  integrity sha512-2/d6n2wlH5zEcdctX4zdbgX8oM61tb67PQt4Xh8JFAIy6LRKUnX528HulkaG6nD5qDl5vRV1NXejCe1XRCH5gQ==
   dependencies:
-    jest-get-type "^27.0.1"
-    pretty-format "^27.0.2"
+    jest-get-type "^27.0.6"
+    pretty-format "^27.0.6"
 
-jest-matcher-utils@^27.0.2:
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.0.2.tgz#f14c060605a95a466cdc759acc546c6f4cbfc4f0"
-  integrity sha512-Qczi5xnTNjkhcIB0Yy75Txt+Ez51xdhOxsukN7awzq2auZQGPHcQrJ623PZj0ECDEMOk2soxWx05EXdXGd1CbA==
+jest-matcher-utils@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.0.6.tgz#2a8da1e86c620b39459f4352eaa255f0d43e39a9"
+  integrity sha512-OFgF2VCQx9vdPSYTHWJ9MzFCehs20TsyFi6bIHbk5V1u52zJOnvF0Y/65z3GLZHKRuTgVPY4Z6LVePNahaQ+tA==
   dependencies:
     chalk "^4.0.0"
-    jest-diff "^27.0.2"
-    jest-get-type "^27.0.1"
-    pretty-format "^27.0.2"
+    jest-diff "^27.0.6"
+    jest-get-type "^27.0.6"
+    pretty-format "^27.0.6"
 
-jest-message-util@^27.0.2:
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.0.2.tgz#181c9b67dff504d8f4ad15cba10d8b80f272048c"
-  integrity sha512-rTqWUX42ec2LdMkoUPOzrEd1Tcm+R1KfLOmFK+OVNo4MnLsEaxO5zPDb2BbdSmthdM/IfXxOZU60P/WbWF8BTw==
+jest-message-util@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.0.6.tgz#158bcdf4785706492d164a39abca6a14da5ab8b5"
+  integrity sha512-rBxIs2XK7rGy+zGxgi+UJKP6WqQ+KrBbD1YMj517HYN3v2BG66t3Xan3FWqYHKZwjdB700KiAJ+iES9a0M+ixw==
   dependencies:
     "@babel/code-frame" "^7.12.13"
-    "@jest/types" "^27.0.2"
+    "@jest/types" "^27.0.6"
     "@types/stack-utils" "^2.0.0"
     chalk "^4.0.0"
     graceful-fs "^4.2.4"
     micromatch "^4.0.4"
-    pretty-format "^27.0.2"
+    pretty-format "^27.0.6"
     slash "^3.0.0"
     stack-utils "^2.0.3"
 
-jest-mock@^27.0.3:
-  version "27.0.3"
-  resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.0.3.tgz#5591844f9192b3335c0dca38e8e45ed297d4d23d"
-  integrity sha512-O5FZn5XDzEp+Xg28mUz4ovVcdwBBPfAhW9+zJLO0Efn2qNbYcDaJvSlRiQ6BCZUCVOJjALicuJQI9mRFjv1o9Q==
+jest-mock@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.0.6.tgz#0efdd40851398307ba16778728f6d34d583e3467"
+  integrity sha512-lzBETUoK8cSxts2NYXSBWT+EJNzmUVtVVwS1sU9GwE1DLCfGsngg+ZVSIe0yd0ZSm+y791esiuo+WSwpXJQ5Bw==
   dependencies:
-    "@jest/types" "^27.0.2"
+    "@jest/types" "^27.0.6"
     "@types/node" "*"
 
 jest-pnp-resolver@^1.2.2:
@@ -6275,76 +6604,76 @@
   resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c"
   integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==
 
-jest-regex-util@^27.0.1:
-  version "27.0.1"
-  resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.0.1.tgz#69d4b1bf5b690faa3490113c47486ed85dd45b68"
-  integrity sha512-6nY6QVcpTgEKQy1L41P4pr3aOddneK17kn3HJw6SdwGiKfgCGTvH02hVXL0GU8GEKtPH83eD2DIDgxHXOxVohQ==
+jest-regex-util@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.0.6.tgz#02e112082935ae949ce5d13b2675db3d8c87d9c5"
+  integrity sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==
 
-jest-resolve-dependencies@^27.0.5:
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.0.5.tgz#819ccdddd909c65acddb063aac3a49e4ba1ed569"
-  integrity sha512-xUj2dPoEEd59P+nuih4XwNa4nJ/zRd/g4rMvjHrZPEBWeWRq/aJnnM6mug+B+Nx+ILXGtfWHzQvh7TqNV/WbuA==
+jest-resolve-dependencies@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.0.6.tgz#3e619e0ef391c3ecfcf6ef4056207a3d2be3269f"
+  integrity sha512-mg9x9DS3BPAREWKCAoyg3QucCr0n6S8HEEsqRCKSPjPcu9HzRILzhdzY3imsLoZWeosEbJZz6TKasveczzpJZA==
   dependencies:
-    "@jest/types" "^27.0.2"
-    jest-regex-util "^27.0.1"
-    jest-snapshot "^27.0.5"
+    "@jest/types" "^27.0.6"
+    jest-regex-util "^27.0.6"
+    jest-snapshot "^27.0.6"
 
-jest-resolve@^27.0.5:
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.0.5.tgz#937535a5b481ad58e7121eaea46d1424a1e0c507"
-  integrity sha512-Md65pngRh8cRuWVdWznXBB5eDt391OJpdBaJMxfjfuXCvOhM3qQBtLMCMTykhuUKiBMmy5BhqCW7AVOKmPrW+Q==
+jest-resolve@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.0.6.tgz#e90f436dd4f8fbf53f58a91c42344864f8e55bff"
+  integrity sha512-yKmIgw2LgTh7uAJtzv8UFHGF7Dm7XfvOe/LQ3Txv101fLM8cx2h1QVwtSJ51Q/SCxpIiKfVn6G2jYYMDNHZteA==
   dependencies:
-    "@jest/types" "^27.0.2"
+    "@jest/types" "^27.0.6"
     chalk "^4.0.0"
     escalade "^3.1.1"
     graceful-fs "^4.2.4"
     jest-pnp-resolver "^1.2.2"
-    jest-util "^27.0.2"
-    jest-validate "^27.0.2"
+    jest-util "^27.0.6"
+    jest-validate "^27.0.6"
     resolve "^1.20.0"
     slash "^3.0.0"
 
-jest-runner@^27.0.5:
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.0.5.tgz#b6fdc587e1a5056339205914294555c554efc08a"
-  integrity sha512-HNhOtrhfKPArcECgBTcWOc+8OSL8GoFoa7RsHGnfZR1C1dFohxy9eLtpYBS+koybAHlJLZzNCx2Y/Ic3iEtJpQ==
+jest-runner@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.0.6.tgz#1325f45055539222bbc7256a6976e993ad2f9520"
+  integrity sha512-W3Bz5qAgaSChuivLn+nKOgjqNxM7O/9JOJoKDCqThPIg2sH/d4A/lzyiaFgnb9V1/w29Le11NpzTJSzga1vyYQ==
   dependencies:
-    "@jest/console" "^27.0.2"
-    "@jest/environment" "^27.0.5"
-    "@jest/test-result" "^27.0.2"
-    "@jest/transform" "^27.0.5"
-    "@jest/types" "^27.0.2"
+    "@jest/console" "^27.0.6"
+    "@jest/environment" "^27.0.6"
+    "@jest/test-result" "^27.0.6"
+    "@jest/transform" "^27.0.6"
+    "@jest/types" "^27.0.6"
     "@types/node" "*"
     chalk "^4.0.0"
     emittery "^0.8.1"
     exit "^0.1.2"
     graceful-fs "^4.2.4"
-    jest-docblock "^27.0.1"
-    jest-environment-jsdom "^27.0.5"
-    jest-environment-node "^27.0.5"
-    jest-haste-map "^27.0.5"
-    jest-leak-detector "^27.0.2"
-    jest-message-util "^27.0.2"
-    jest-resolve "^27.0.5"
-    jest-runtime "^27.0.5"
-    jest-util "^27.0.2"
-    jest-worker "^27.0.2"
+    jest-docblock "^27.0.6"
+    jest-environment-jsdom "^27.0.6"
+    jest-environment-node "^27.0.6"
+    jest-haste-map "^27.0.6"
+    jest-leak-detector "^27.0.6"
+    jest-message-util "^27.0.6"
+    jest-resolve "^27.0.6"
+    jest-runtime "^27.0.6"
+    jest-util "^27.0.6"
+    jest-worker "^27.0.6"
     source-map-support "^0.5.6"
     throat "^6.0.1"
 
-jest-runtime@^27.0.5:
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.0.5.tgz#cd5d1aa9754d30ddf9f13038b3cb7b95b46f552d"
-  integrity sha512-V/w/+VasowPESbmhXn5AsBGPfb35T7jZPGZybYTHxZdP7Gwaa+A0EXE6rx30DshHKA98lVCODbCO8KZpEW3hiQ==
+jest-runtime@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.0.6.tgz#45877cfcd386afdd4f317def551fc369794c27c9"
+  integrity sha512-BhvHLRVfKibYyqqEFkybsznKwhrsu7AWx2F3y9G9L95VSIN3/ZZ9vBpm/XCS2bS+BWz3sSeNGLzI3TVQ0uL85Q==
   dependencies:
-    "@jest/console" "^27.0.2"
-    "@jest/environment" "^27.0.5"
-    "@jest/fake-timers" "^27.0.5"
-    "@jest/globals" "^27.0.5"
-    "@jest/source-map" "^27.0.1"
-    "@jest/test-result" "^27.0.2"
-    "@jest/transform" "^27.0.5"
-    "@jest/types" "^27.0.2"
+    "@jest/console" "^27.0.6"
+    "@jest/environment" "^27.0.6"
+    "@jest/fake-timers" "^27.0.6"
+    "@jest/globals" "^27.0.6"
+    "@jest/source-map" "^27.0.6"
+    "@jest/test-result" "^27.0.6"
+    "@jest/transform" "^27.0.6"
+    "@jest/types" "^27.0.6"
     "@types/yargs" "^16.0.0"
     chalk "^4.0.0"
     cjs-module-lexer "^1.0.0"
@@ -6352,30 +6681,30 @@
     exit "^0.1.2"
     glob "^7.1.3"
     graceful-fs "^4.2.4"
-    jest-haste-map "^27.0.5"
-    jest-message-util "^27.0.2"
-    jest-mock "^27.0.3"
-    jest-regex-util "^27.0.1"
-    jest-resolve "^27.0.5"
-    jest-snapshot "^27.0.5"
-    jest-util "^27.0.2"
-    jest-validate "^27.0.2"
+    jest-haste-map "^27.0.6"
+    jest-message-util "^27.0.6"
+    jest-mock "^27.0.6"
+    jest-regex-util "^27.0.6"
+    jest-resolve "^27.0.6"
+    jest-snapshot "^27.0.6"
+    jest-util "^27.0.6"
+    jest-validate "^27.0.6"
     slash "^3.0.0"
     strip-bom "^4.0.0"
     yargs "^16.0.3"
 
-jest-serializer@^27.0.1:
-  version "27.0.1"
-  resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.0.1.tgz#2464d04dcc33fb71dc80b7c82e3c5e8a08cb1020"
-  integrity sha512-svy//5IH6bfQvAbkAEg1s7xhhgHTtXu0li0I2fdKHDsLP2P2MOiscPQIENQep8oU2g2B3jqLyxKKzotZOz4CwQ==
+jest-serializer@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.0.6.tgz#93a6c74e0132b81a2d54623251c46c498bb5bec1"
+  integrity sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA==
   dependencies:
     "@types/node" "*"
     graceful-fs "^4.2.4"
 
-jest-snapshot@^27.0.5:
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.0.5.tgz#6e3b9e8e193685372baff771ba34af631fe4d4d5"
-  integrity sha512-H1yFYdgnL1vXvDqMrnDStH6yHFdMEuzYQYc71SnC/IJnuuhW6J16w8GWG1P+qGd3Ag3sQHjbRr0TcwEo/vGS+g==
+jest-snapshot@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.0.6.tgz#f4e6b208bd2e92e888344d78f0f650bcff05a4bf"
+  integrity sha512-NTHaz8He+ATUagUgE7C/UtFcRoHqR2Gc+KDfhQIyx+VFgwbeEMjeP+ILpUTLosZn/ZtbNdCF5LkVnN/l+V751A==
   dependencies:
     "@babel/core" "^7.7.2"
     "@babel/generator" "^7.7.2"
@@ -6383,86 +6712,86 @@
     "@babel/plugin-syntax-typescript" "^7.7.2"
     "@babel/traverse" "^7.7.2"
     "@babel/types" "^7.0.0"
-    "@jest/transform" "^27.0.5"
-    "@jest/types" "^27.0.2"
+    "@jest/transform" "^27.0.6"
+    "@jest/types" "^27.0.6"
     "@types/babel__traverse" "^7.0.4"
     "@types/prettier" "^2.1.5"
     babel-preset-current-node-syntax "^1.0.0"
     chalk "^4.0.0"
-    expect "^27.0.2"
+    expect "^27.0.6"
     graceful-fs "^4.2.4"
-    jest-diff "^27.0.2"
-    jest-get-type "^27.0.1"
-    jest-haste-map "^27.0.5"
-    jest-matcher-utils "^27.0.2"
-    jest-message-util "^27.0.2"
-    jest-resolve "^27.0.5"
-    jest-util "^27.0.2"
+    jest-diff "^27.0.6"
+    jest-get-type "^27.0.6"
+    jest-haste-map "^27.0.6"
+    jest-matcher-utils "^27.0.6"
+    jest-message-util "^27.0.6"
+    jest-resolve "^27.0.6"
+    jest-util "^27.0.6"
     natural-compare "^1.4.0"
-    pretty-format "^27.0.2"
+    pretty-format "^27.0.6"
     semver "^7.3.2"
 
-jest-util@^27.0.2:
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.0.2.tgz#fc2c7ace3c75ae561cf1e5fdb643bf685a5be7c7"
-  integrity sha512-1d9uH3a00OFGGWSibpNYr+jojZ6AckOMCXV2Z4K3YXDnzpkAaXQyIpY14FOJPiUmil7CD+A6Qs+lnnh6ctRbIA==
+jest-util@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.0.6.tgz#e8e04eec159de2f4d5f57f795df9cdc091e50297"
+  integrity sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ==
   dependencies:
-    "@jest/types" "^27.0.2"
+    "@jest/types" "^27.0.6"
     "@types/node" "*"
     chalk "^4.0.0"
     graceful-fs "^4.2.4"
     is-ci "^3.0.0"
     picomatch "^2.2.3"
 
-jest-validate@^27.0.2:
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.0.2.tgz#7fe2c100089449cd5cbb47a5b0b6cb7cda5beee5"
-  integrity sha512-UgBF6/oVu1ofd1XbaSotXKihi8nZhg0Prm8twQ9uCuAfo59vlxCXMPI/RKmrZEVgi3Nd9dS0I8A0wzWU48pOvg==
+jest-validate@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.0.6.tgz#930a527c7a951927df269f43b2dc23262457e2a6"
+  integrity sha512-yhZZOaMH3Zg6DC83n60pLmdU1DQE46DW+KLozPiPbSbPhlXXaiUTDlhHQhHFpaqIFRrInko1FHXjTRpjWRuWfA==
   dependencies:
-    "@jest/types" "^27.0.2"
+    "@jest/types" "^27.0.6"
     camelcase "^6.2.0"
     chalk "^4.0.0"
-    jest-get-type "^27.0.1"
+    jest-get-type "^27.0.6"
     leven "^3.1.0"
-    pretty-format "^27.0.2"
+    pretty-format "^27.0.6"
 
-jest-watcher@^27.0.2:
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.0.2.tgz#dab5f9443e2d7f52597186480731a8c6335c5deb"
-  integrity sha512-8nuf0PGuTxWj/Ytfw5fyvNn/R80iXY8QhIT0ofyImUvdnoaBdT6kob0GmhXR+wO+ALYVnh8bQxN4Tjfez0JgkA==
+jest-watcher@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.0.6.tgz#89526f7f9edf1eac4e4be989bcb6dec6b8878d9c"
+  integrity sha512-/jIoKBhAP00/iMGnTwUBLgvxkn7vsOweDrOTSPzc7X9uOyUtJIDthQBTI1EXz90bdkrxorUZVhJwiB69gcHtYQ==
   dependencies:
-    "@jest/test-result" "^27.0.2"
-    "@jest/types" "^27.0.2"
+    "@jest/test-result" "^27.0.6"
+    "@jest/types" "^27.0.6"
     "@types/node" "*"
     ansi-escapes "^4.2.1"
     chalk "^4.0.0"
-    jest-util "^27.0.2"
+    jest-util "^27.0.6"
     string-length "^4.0.1"
 
-jest-worker@^27.0.2:
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.2.tgz#4ebeb56cef48b3e7514552f80d0d80c0129f0b05"
-  integrity sha512-EoBdilOTTyOgmHXtw/cPc+ZrCA0KJMrkXzkrPGNwLmnvvlN1nj7MPrxpT7m+otSv2e1TLaVffzDnE/LB14zJMg==
+jest-worker@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.6.tgz#a5fdb1e14ad34eb228cfe162d9f729cdbfa28aed"
+  integrity sha512-qupxcj/dRuA3xHPMUd40gr2EaAurFbkwzOh7wfPaeE9id7hyjURRQoqNfHifHK3XjJU6YJJUQKILGUnwGPEOCA==
   dependencies:
     "@types/node" "*"
     merge-stream "^2.0.0"
     supports-color "^8.0.0"
 
-jest@^27.0.5:
-  version "27.0.5"
-  resolved "https://registry.yarnpkg.com/jest/-/jest-27.0.5.tgz#141825e105514a834cc8d6e44670509e8d74c5f2"
-  integrity sha512-4NlVMS29gE+JOZvgmSAsz3eOjkSsHqjTajlIsah/4MVSmKvf3zFP/TvgcLoWe2UVHiE9KF741sReqhF0p4mqbQ==
+jest@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/jest/-/jest-27.0.6.tgz#10517b2a628f0409087fbf473db44777d7a04505"
+  integrity sha512-EjV8aETrsD0wHl7CKMibKwQNQc3gIRBXlTikBmmHUeVMKaPFxdcUIBfoDqTSXDoGJIivAYGqCWVlzCSaVjPQsA==
   dependencies:
-    "@jest/core" "^27.0.5"
+    "@jest/core" "^27.0.6"
     import-local "^3.0.2"
-    jest-cli "^27.0.5"
+    jest-cli "^27.0.6"
 
 js-sha3@0.5.7, js-sha3@^0.5.7:
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7"
   integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=
 
-js-sha3@^0.8.0:
+js-sha3@0.8.0, js-sha3@^0.8.0:
   version "0.8.0"
   resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
   integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
@@ -6594,6 +6923,13 @@
   dependencies:
     minimist "^1.2.5"
 
+jsonfile@^2.1.0:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8"
+  integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug=
+  optionalDependencies:
+    graceful-fs "^4.1.6"
+
 jsonfile@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
@@ -6667,6 +7003,13 @@
   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
   integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
 
+klaw@^1.0.0:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439"
+  integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk=
+  optionalDependencies:
+    graceful-fs "^4.1.9"
+
 kleur@^3.0.3:
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
@@ -6785,7 +7128,7 @@
   resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
   integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
 
-lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21, lodash@^4.7.0:
+lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.21, lodash@^4.7.0:
   version "4.17.21"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
   integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -6877,6 +7220,13 @@
     typescript "^3.9.5"
     walkdir "^0.4.1"
 
+magic-string@^0.25.5, magic-string@^0.25.7:
+  version "0.25.7"
+  resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
+  integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==
+  dependencies:
+    sourcemap-codec "^1.4.4"
+
 make-dir@^2.0.0, make-dir@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
@@ -6930,6 +7280,11 @@
   resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
   integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
 
+memorystream@^0.3.1:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2"
+  integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI=
+
 merge-descriptors@1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
@@ -7307,6 +7662,11 @@
   resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20"
   integrity sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==
 
+node-releases@^1.1.73:
+  version "1.1.74"
+  resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.74.tgz#e5866488080ebaa70a93b91144ccde06f3c3463e"
+  integrity sha512-caJBVempXZPepZoZAPCWRTNxYQ+xtG/KAi4ozTA5A+nJ7IU+kLQCbqaUjb5Rwy14M9upBWiQ4NutcmW04LJSRw==
+
 node-source-walk@^4.0.0, node-source-walk@^4.2.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/node-source-walk/-/node-source-walk-4.2.0.tgz#c2efe731ea8ba9c03c562aa0a9d984e54f27bc2c"
@@ -7753,7 +8113,7 @@
   resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
   integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
 
-picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
   integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
@@ -7935,17 +8295,17 @@
   resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
   integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
 
-prettier@^2.3.1:
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.1.tgz#76903c3f8c4449bc9ac597acefa24dc5ad4cbea6"
-  integrity sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA==
+prettier@^2.3.2:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d"
+  integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==
 
-pretty-format@^27.0.2:
-  version "27.0.2"
-  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.0.2.tgz#9283ff8c4f581b186b2d4da461617143dca478a4"
-  integrity sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==
+pretty-format@^27.0.6:
+  version "27.0.6"
+  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.0.6.tgz#ab770c47b2c6f893a21aefc57b75da63ef49a11f"
+  integrity sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==
   dependencies:
-    "@jest/types" "^27.0.2"
+    "@jest/types" "^27.0.6"
     ansi-regex "^5.0.0"
     ansi-styles "^5.0.0"
     react-is "^17.0.1"
@@ -8345,7 +8705,7 @@
   resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
   integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
 
-require-from-string@^2.0.2:
+require-from-string@^2.0.0, require-from-string@^2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
   integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
@@ -8395,7 +8755,7 @@
   resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
   integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
 
-resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.3.2:
+resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.3.2:
   version "1.20.0"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
   integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
@@ -8436,6 +8796,13 @@
   resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
   integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
 
+rimraf@^2.2.8:
+  version "2.7.1"
+  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
+  integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
+  dependencies:
+    glob "^7.1.3"
+
 rimraf@^3.0.0, rimraf@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
@@ -8458,6 +8825,13 @@
   dependencies:
     bn.js "^4.11.1"
 
+rollup@^2.56.2:
+  version "2.56.2"
+  resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.56.2.tgz#a045ff3f6af53ee009b5f5016ca3da0329e5470f"
+  integrity sha512-s8H00ZsRi29M2/lGdm1u8DJpJ9ML8SUOpVVBd33XNeEeL3NVaTiUcSBHzBdF3eAyR0l7VSpsuoVUGrRHq7aPwQ==
+  optionalDependencies:
+    fsevents "~2.3.2"
+
 run-async@^2.4.0:
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
@@ -8477,10 +8851,10 @@
   dependencies:
     tslib "^1.9.0"
 
-rxjs@^7.2.0:
-  version "7.2.0"
-  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.2.0.tgz#5cd12409639e9514a71c9f5f9192b2c4ae94de31"
-  integrity sha512-aX8w9OpKrQmiPKfT1bqETtUr9JygIz6GZ+gql8v7CijClsP0laoFUdKzxFAoWuRdSlOdU2+crss+cMf+cqMTnw==
+rxjs@^7.3.0:
+  version "7.3.0"
+  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.3.0.tgz#39fe4f3461dc1e50be1475b2b85a0a88c1e938c6"
+  integrity sha512-p2yuGIg9S1epc3vrjKf6iVb3RCaAYjYskkO+jHIaV0IjOPlJop4UnodOoFb2xeNwlguqLYvGw1b1McillYb5Gw==
   dependencies:
     tslib "~2.1.0"
 
@@ -8546,7 +8920,7 @@
   dependencies:
     semver "^6.3.0"
 
-"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.6.0:
+"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.6.0:
   version "5.7.1"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
   integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
@@ -8762,6 +9136,21 @@
     source-map-resolve "^0.5.0"
     use "^3.1.0"
 
+solc@^0.8.6:
+  version "0.8.6"
+  resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.6.tgz#e4341fa6780137df97b94a0cfbd59b3f2037d0e0"
+  integrity sha512-miiDaWdaUnD7A6Cktb/2ug9f+ajcOCDYRr7vgbPEsMoutSlBtp5rca57oMg8iHSuM7jilwdxePujWI/+rbNftQ==
+  dependencies:
+    command-exists "^1.2.8"
+    commander "3.0.2"
+    follow-redirects "^1.12.1"
+    fs-extra "^0.30.0"
+    js-sha3 "0.8.0"
+    memorystream "^0.3.1"
+    require-from-string "^2.0.0"
+    semver "^5.5.0"
+    tmp "0.0.33"
+
 sort-keys@^4.0.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-4.2.0.tgz#6b7638cee42c506fff8c1cecde7376d21315be18"
@@ -8813,6 +9202,11 @@
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
   integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
 
+sourcemap-codec@^1.4.4:
+  version "1.4.8"
+  resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
+  integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
+
 spdx-correct@^3.0.0:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
@@ -9210,7 +9604,7 @@
   resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
   integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=
 
-tmp@^0.0.33:
+tmp@0.0.33, tmp@^0.0.33:
   version "0.0.33"
   resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
   integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
@@ -9358,7 +9752,7 @@
   dependencies:
     tslib "^1.8.1"
 
-tsutils@^3.17.1, tsutils@^3.21.0:
+tsutils@^3.21.0:
   version "3.21.0"
   resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
   integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
@@ -9372,15 +9766,15 @@
   dependencies:
     safe-buffer "^5.0.1"
 
+tweetnacl@1.x.x, tweetnacl@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596"
+  integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==
+
 tweetnacl@^0.14.3, tweetnacl@~0.14.0:
   version "0.14.5"
   resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
   integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
-
-tweetnacl@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596"
-  integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==
 
 type-check@^0.4.0, type-check@~0.4.0:
   version "0.4.0"
@@ -9446,11 +9840,16 @@
   resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8"
   integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==
 
-typescript@^4.2.4, typescript@^4.3.4:
+typescript@^4.2.4:
   version "4.3.4"
   resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.4.tgz#3f85b986945bcf31071decdd96cf8bfa65f9dcbc"
   integrity sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==
 
+typescript@^4.3.5:
+  version "4.3.5"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4"
+  integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==
+
 uglify-js@^3.1.4:
   version "3.13.9"
   resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.9.tgz#4d8d21dcd497f29cfd8e9378b9df123ad025999b"
@@ -10258,7 +10657,7 @@
     y18n "^5.0.5"
     yargs-parser "^20.2.2"
 
-yargs@^17.0.0, yargs@^17.0.1:
+yargs@^17.0.0:
   version "17.0.1"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.0.1.tgz#6a1ced4ed5ee0b388010ba9fd67af83b9362e0bb"
   integrity sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ==
@@ -10271,6 +10670,19 @@
     y18n "^5.0.5"
     yargs-parser "^20.2.2"
 
+yargs@^17.1.0, yargs@^17.1.1:
+  version "17.1.1"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.1.1.tgz#c2a8091564bdb196f7c0a67c1d12e5b85b8067ba"
+  integrity sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ==
+  dependencies:
+    cliui "^7.0.2"
+    escalade "^3.1.1"
+    get-caller-file "^2.0.5"
+    require-directory "^2.1.1"
+    string-width "^4.2.0"
+    y18n "^5.0.5"
+    yargs-parser "^20.2.2"
+
 yn@3.1.1:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"