git.delta.rocks / unique-network / refs/commits / 6913914899af

difftreelog

build upgrade frontier

Yaroslav Bolyukin2022-11-16parent: #e8d45f9.patch.diff
in: master

51 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -75,9 +75,9 @@
 
 [[package]]
 name = "aho-corasick"
-version = "0.7.19"
+version = "0.7.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
+checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
 dependencies = [
  "memchr",
 ]
@@ -137,9 +137,9 @@
 
 [[package]]
 name = "array-bytes"
-version = "4.1.0"
+version = "4.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a913633b0c922e6b745072795f50d90ebea78ba31a57e2ac8c2fc7b50950949"
+checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6"
 
 [[package]]
 name = "arrayref"
@@ -196,30 +196,30 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28"
 dependencies = [
- "concurrent-queue",
+ "concurrent-queue 1.2.4",
  "event-listener",
  "futures-core",
 ]
 
 [[package]]
 name = "async-executor"
-version = "1.4.1"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965"
+checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b"
 dependencies = [
+ "async-lock",
  "async-task",
- "concurrent-queue",
+ "concurrent-queue 2.0.0",
  "fastrand",
  "futures-lite",
- "once_cell",
  "slab",
 ]
 
 [[package]]
 name = "async-global-executor"
-version = "2.3.0"
+version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0da5b41ee986eed3f524c380e6d64965aea573882a8907682ad100f7859305ca"
+checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776"
 dependencies = [
  "async-channel",
  "async-executor",
@@ -232,16 +232,16 @@
 
 [[package]]
 name = "async-io"
-version = "1.9.0"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83e21f3a490c72b3b0cf44962180e60045de2925d8dff97918f7ee43c8f637c7"
+checksum = "e8121296a9f05be7f34aa4196b1747243b3b62e048bb7906f644f3fbfc490cf7"
 dependencies = [
+ "async-lock",
  "autocfg",
- "concurrent-queue",
+ "concurrent-queue 1.2.4",
  "futures-lite",
  "libc",
  "log",
- "once_cell",
  "parking",
  "polling",
  "slab",
@@ -340,9 +340,9 @@
 
 [[package]]
 name = "asynchronous-codec"
-version = "0.6.0"
+version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0de5164e5edbf51c45fb8c2d9664ae1c095cce1b265ecf7569093c0d66ef690"
+checksum = "06a0daa378f5fd10634e44b0a29b2a87b890657658e072a30d6f26e57ddee182"
 dependencies = [
  "bytes",
  "futures-sink",
@@ -595,16 +595,16 @@
  "funty 2.0.0",
  "radium 0.7.0",
  "tap",
- "wyz 0.5.0",
+ "wyz 0.5.1",
 ]
 
 [[package]]
 name = "blake2"
-version = "0.10.4"
+version = "0.10.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388"
+checksum = "b12e5fd123190ce1c2e559308a94c9bacad77907d4c6005d9e58fe1a0689e55e"
 dependencies = [
- "digest 0.10.5",
+ "digest 0.10.6",
 ]
 
 [[package]]
@@ -614,7 +614,7 @@
 checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
 dependencies = [
  "arrayvec 0.4.12",
- "constant_time_eq",
+ "constant_time_eq 0.1.5",
 ]
 
 [[package]]
@@ -625,7 +625,7 @@
 dependencies = [
  "arrayref",
  "arrayvec 0.7.2",
- "constant_time_eq",
+ "constant_time_eq 0.1.5",
 ]
 
 [[package]]
@@ -636,21 +636,21 @@
 dependencies = [
  "arrayref",
  "arrayvec 0.7.2",
- "constant_time_eq",
+ "constant_time_eq 0.1.5",
 ]
 
 [[package]]
 name = "blake3"
-version = "1.3.1"
+version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f"
+checksum = "895adc16c8b3273fbbc32685a7d55227705eda08c01e77704020f3491924b44b"
 dependencies = [
  "arrayref",
  "arrayvec 0.7.2",
  "cc",
  "cfg-if 1.0.0",
- "constant_time_eq",
- "digest 0.10.5",
+ "constant_time_eq 0.2.4",
+ "digest 0.10.6",
 ]
 
 [[package]]
@@ -769,9 +769,9 @@
 
 [[package]]
 name = "byte-slice-cast"
-version = "1.2.1"
+version = "1.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e"
+checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c"
 
 [[package]]
 name = "byte-tools"
@@ -787,9 +787,9 @@
 
 [[package]]
 name = "bytes"
-version = "1.2.1"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
+checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
 
 [[package]]
 name = "bzip2-sys"
@@ -841,9 +841,9 @@
 
 [[package]]
 name = "cc"
-version = "1.0.73"
+version = "1.0.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
 dependencies = [
  "jobserver",
 ]
@@ -911,9 +911,9 @@
 
 [[package]]
 name = "chrono"
-version = "0.4.22"
+version = "0.4.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
+checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
 dependencies = [
  "iana-time-zone",
  "js-sys",
@@ -973,7 +973,7 @@
 dependencies = [
  "glob",
  "libc",
- "libloading 0.7.3",
+ "libloading 0.7.4",
 ]
 
 [[package]]
@@ -1017,9 +1017,9 @@
 
 [[package]]
 name = "cmake"
-version = "0.1.48"
+version = "0.1.49"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a"
+checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c"
 dependencies = [
  "cc",
 ]
@@ -1048,9 +1048,9 @@
 
 [[package]]
 name = "comfy-table"
-version = "6.1.1"
+version = "6.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b3d16bb3da60be2f7c7acfc438f2ae6f3496897ce68c291d0509bb67b4e248e"
+checksum = "e621e7e86c46fd8a14c32c6ae3cb95656621b4743a27d0cffedb831d46e7ad21"
 dependencies = [
  "strum",
  "strum_macros",
@@ -1059,9 +1059,9 @@
 
 [[package]]
 name = "concat-idents"
-version = "1.1.3"
+version = "1.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b6f90860248d75014b7b103db8fee4f291c07bfb41306cdf77a0a5ab7a10d2f"
+checksum = "0fe0e1d9f7de897d18e590a7496b5facbe87813f746cf4b8db596ba77e07e832"
 dependencies = [
  "quote",
  "syn",
@@ -1077,6 +1077,15 @@
 ]
 
 [[package]]
+name = "concurrent-queue"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
 name = "console"
 version = "0.15.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1102,6 +1111,12 @@
 checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
 
 [[package]]
+name = "constant_time_eq"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279"
+
+[[package]]
 name = "convert_case"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1152,18 +1167,18 @@
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.88.1"
+version = "0.88.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44409ccf2d0f663920cab563d2b79fcd6b2e9a2bcc6e929fef76c8f82ad6c17a"
+checksum = "52056f6d0584484b57fa6c1a65c1fcb15f3780d8b6a758426d9e3084169b2ddd"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.88.1"
+version = "0.88.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98de2018ad96eb97f621f7d6b900a0cc661aec8d02ea4a50e56ecb48e5a2fcaf"
+checksum = "18fed94c8770dc25d01154c3ffa64ed0b3ba9d583736f305fed7beebe5d9cf74"
 dependencies = [
  "arrayvec 0.7.2",
  "bumpalo",
@@ -1181,33 +1196,33 @@
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.88.1"
+version = "0.88.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5287ce36e6c4758fbaf298bd1a8697ad97a4f2375a3d1b61142ea538db4877e5"
+checksum = "1c451b81faf237d11c7e4f3165eeb6bac61112762c5cfe7b4c0fb7241474358f"
 dependencies = [
  "cranelift-codegen-shared",
 ]
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.88.1"
+version = "0.88.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2855c24219e2f08827f3f4ffb2da92e134ae8d8ecc185b11ec8f9878cf5f588e"
+checksum = "e7c940133198426d26128f08be2b40b0bd117b84771fd36798969c4d712d81fc"
 
 [[package]]
 name = "cranelift-entity"
-version = "0.88.1"
+version = "0.88.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b65673279d75d34bf11af9660ae2dbd1c22e6d28f163f5c72f4e1dc56d56103"
+checksum = "87a0f1b2fdc18776956370cf8d9b009ded3f855350c480c1c52142510961f352"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.88.1"
+version = "0.88.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed2b3d7a4751163f6c4a349205ab1b7d9c00eecf19dcea48592ef1f7688eefc"
+checksum = "34897538b36b216cc8dd324e73263596d51b8cf610da6498322838b2546baf8a"
 dependencies = [
  "cranelift-codegen",
  "log",
@@ -1217,15 +1232,15 @@
 
 [[package]]
 name = "cranelift-isle"
-version = "0.88.1"
+version = "0.88.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3be64cecea9d90105fc6a2ba2d003e98c867c1d6c4c86cc878f97ad9fb916293"
+checksum = "1b2629a569fae540f16a76b70afcc87ad7decb38dc28fa6c648ac73b51e78470"
 
 [[package]]
 name = "cranelift-native"
-version = "0.88.1"
+version = "0.88.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4a03a6ac1b063e416ca4b93f6247978c991475e8271465340caa6f92f3c16a4"
+checksum = "20937dab4e14d3e225c5adfc9c7106bafd4ac669bdb43027b911ff794c6fb318"
 dependencies = [
  "cranelift-codegen",
  "libc",
@@ -1234,9 +1249,9 @@
 
 [[package]]
 name = "cranelift-wasm"
-version = "0.88.1"
+version = "0.88.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c699873f7b30bc5f20dd03a796b4183e073a46616c91704792ec35e45d13f913"
+checksum = "80fc2288957a94fd342a015811479de1837850924166d1f1856d8406e6f3609b"
 dependencies = [
  "cranelift-codegen",
  "cranelift-entity",
@@ -1280,22 +1295,22 @@
 
 [[package]]
 name = "crossbeam-epoch"
-version = "0.9.11"
+version = "0.9.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348"
+checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
 dependencies = [
  "autocfg",
  "cfg-if 1.0.0",
  "crossbeam-utils",
- "memoffset",
+ "memoffset 0.7.1",
  "scopeguard",
 ]
 
 [[package]]
 name = "crossbeam-queue"
-version = "0.3.6"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7"
+checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
 dependencies = [
  "cfg-if 1.0.0",
  "crossbeam-utils",
@@ -1303,9 +1318,9 @@
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.12"
+version = "0.8.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac"
+checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
 dependencies = [
  "cfg-if 1.0.0",
 ]
@@ -1872,9 +1887,9 @@
 
 [[package]]
 name = "cxx"
-version = "1.0.80"
+version = "1.0.82"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a"
+checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453"
 dependencies = [
  "cc",
  "cxxbridge-flags",
@@ -1884,9 +1899,9 @@
 
 [[package]]
 name = "cxx-build"
-version = "1.0.80"
+version = "1.0.82"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827"
+checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -1899,15 +1914,15 @@
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.80"
+version = "1.0.82"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a"
+checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.80"
+version = "1.0.82"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7"
+checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1993,9 +2008,9 @@
 
 [[package]]
 name = "digest"
-version = "0.10.5"
+version = "0.10.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c"
+checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
 dependencies = [
  "block-buffer 0.10.3",
  "crypto-common",
@@ -2216,9 +2231,9 @@
 
 [[package]]
 name = "env_logger"
-version = "0.9.1"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272"
+checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
 dependencies = [
  "atty",
  "humantime",
@@ -2479,7 +2494,7 @@
 [[package]]
 name = "fc-consensus"
 version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
 dependencies = [
  "async-trait",
  "fc-db",
@@ -2498,14 +2513,16 @@
 [[package]]
 name = "fc-db"
 version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
 dependencies = [
  "fp-storage",
  "kvdb-rocksdb",
+ "log",
  "parity-db",
  "parity-scale-codec 3.2.1",
  "parking_lot 0.12.1",
  "sc-client-db",
+ "sp-blockchain",
  "sp-core",
  "sp-database",
  "sp-runtime",
@@ -2514,7 +2531,7 @@
 [[package]]
 name = "fc-mapping-sync"
 version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
 dependencies = [
  "fc-db",
  "fp-consensus",
@@ -2531,13 +2548,15 @@
 [[package]]
 name = "fc-rpc"
 version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
 dependencies = [
  "ethereum",
  "ethereum-types",
  "evm",
  "fc-db",
  "fc-rpc-core",
+ "fp-ethereum",
+ "fp-evm",
  "fp-rpc",
  "fp-storage",
  "futures 0.3.25",
@@ -2545,12 +2564,11 @@
  "jsonrpsee",
  "libsecp256k1",
  "log",
- "lru 0.7.8",
+ "lru 0.8.1",
  "parity-scale-codec 3.2.1",
  "prometheus",
  "rand 0.8.5",
  "rlp",
- "rustc-hex",
  "sc-client-api",
  "sc-network",
  "sc-network-common",
@@ -2573,7 +2591,7 @@
 [[package]]
 name = "fc-rpc-core"
 version = "1.1.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
 dependencies = [
  "ethereum",
  "ethereum-types",
@@ -2713,7 +2731,7 @@
 [[package]]
 name = "fp-consensus"
 version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
 dependencies = [
  "ethereum",
  "parity-scale-codec 3.2.1",
@@ -2723,9 +2741,24 @@
 ]
 
 [[package]]
+name = "fp-ethereum"
+version = "1.0.0-dev"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
+dependencies = [
+ "ethereum",
+ "ethereum-types",
+ "fp-evm",
+ "frame-support",
+ "num_enum",
+ "parity-scale-codec 3.2.1",
+ "sp-core",
+ "sp-std",
+]
+
+[[package]]
 name = "fp-evm"
 version = "3.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
 dependencies = [
  "evm",
  "frame-support",
@@ -2739,7 +2772,7 @@
 [[package]]
 name = "fp-evm-mapping"
 version = "0.1.0"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
 dependencies = [
  "frame-support",
  "sp-core",
@@ -2748,7 +2781,7 @@
 [[package]]
 name = "fp-rpc"
 version = "3.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
 dependencies = [
  "ethereum",
  "ethereum-types",
@@ -2765,7 +2798,7 @@
 [[package]]
 name = "fp-self-contained"
 version = "1.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
 dependencies = [
  "ethereum",
  "frame-support",
@@ -2773,17 +2806,16 @@
  "parity-util-mem",
  "scale-info",
  "serde",
- "sp-debug-derive",
- "sp-io",
  "sp-runtime",
 ]
 
 [[package]]
 name = "fp-storage"
 version = "2.0.0"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
 dependencies = [
  "parity-scale-codec 3.2.1",
+ "serde",
 ]
 
 [[package]]
@@ -3040,9 +3072,9 @@
 
 [[package]]
 name = "fs-err"
-version = "2.8.1"
+version = "2.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64db3e262960f0662f43a6366788d5f10f7f244b8f7d7d987f560baf5ded5c50"
+checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541"
 
 [[package]]
 name = "fs-swap"
@@ -3512,9 +3544,9 @@
 
 [[package]]
 name = "hyper"
-version = "0.14.20"
+version = "0.14.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac"
+checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c"
 dependencies = [
  "bytes",
  "futures-channel",
@@ -3536,9 +3568,9 @@
 
 [[package]]
 name = "hyper-rustls"
-version = "0.23.0"
+version = "0.23.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac"
+checksum = "59df7c4e19c950e6e0e868dcc0a300b09a9b88e9ec55bd879ca819087a77355d"
 dependencies = [
  "http",
  "hyper",
@@ -3551,9 +3583,9 @@
 
 [[package]]
 name = "iana-time-zone"
-version = "0.1.51"
+version = "0.1.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed"
+checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
 dependencies = [
  "android_system_properties",
  "core-foundation-sys",
@@ -3662,9 +3694,9 @@
 
 [[package]]
 name = "indexmap"
-version = "1.9.1"
+version = "1.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
 dependencies = [
  "autocfg",
  "hashbrown",
@@ -3706,11 +3738,21 @@
 
 [[package]]
 name = "io-lifetimes"
-version = "0.7.4"
+version = "0.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6e481ccbe3dea62107216d0d1138bb8ad8e5e5c43009a098bd1990272c497b0"
+checksum = "59ce5ef949d49ee85593fc4d3f3f95ad61657076395cbbce23e2121fc5542074"
 
 [[package]]
+name = "io-lifetimes"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7d367024b3f3414d8e01f437f704f41a9f64ab36f9067fa73e526ad4c763c87"
+dependencies = [
+ "libc",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
 name = "ip_network"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3718,9 +3760,9 @@
 
 [[package]]
 name = "ipconfig"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "723519edce41262b05d4143ceb95050e4c614f483e78e9fd9e39a8275a84ad98"
+checksum = "bd302af1b90f2463a98fa5ad469fc212c8e3175a41c3068601bfa2727591c5be"
 dependencies = [
  "socket2",
  "widestring",
@@ -3730,9 +3772,9 @@
 
 [[package]]
 name = "ipnet"
-version = "2.5.0"
+version = "2.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
+checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745"
 
 [[package]]
 name = "itertools"
@@ -3925,9 +3967,12 @@
 
 [[package]]
 name = "keccak"
-version = "0.1.2"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838"
+checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768"
+dependencies = [
+ "cpufeatures",
+]
 
 [[package]]
 name = "kusama-runtime"
@@ -4113,9 +4158,9 @@
 
 [[package]]
 name = "libloading"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
 dependencies = [
  "cfg-if 1.0.0",
  "winapi",
@@ -4123,9 +4168,9 @@
 
 [[package]]
 name = "libm"
-version = "0.2.5"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565"
+checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
 
 [[package]]
 name = "libp2p"
@@ -4757,6 +4802,12 @@
 checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d"
 
 [[package]]
+name = "linux-raw-sys"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb68f22743a3fb35785f1e7f844ca5a3de2dde5bd0c0ef5b372065814699b121"
+
+[[package]]
 name = "lock_api"
 version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4880,18 +4931,18 @@
 
 [[package]]
 name = "memfd"
-version = "0.6.1"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "480b5a5de855d11ff13195950bdc8b98b5e942ef47afc447f6615cdcc4e15d80"
+checksum = "b20a59d985586e4a5aef64564ac77299f8586d8be6cf9106a5a40207e8908efb"
 dependencies = [
- "rustix",
+ "rustix 0.36.2",
 ]
 
 [[package]]
 name = "memmap2"
-version = "0.5.7"
+version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498"
+checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc"
 dependencies = [
  "libc",
 ]
@@ -4906,6 +4957,15 @@
 ]
 
 [[package]]
+name = "memoffset"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
 name = "memory-db"
 version = "0.29.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5020,7 +5080,7 @@
  "blake2s_simd",
  "blake3",
  "core2",
- "digest 0.10.5",
+ "digest 0.10.6",
  "multihash-derive",
  "sha2 0.10.6",
  "sha3",
@@ -5291,15 +5351,36 @@
 
 [[package]]
 name = "num_cpus"
-version = "1.13.1"
+version = "1.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
 dependencies = [
  "hermit-abi",
  "libc",
 ]
 
 [[package]]
+name = "num_enum"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9"
+dependencies = [
+ "num_enum_derive",
+]
+
+[[package]]
+name = "num_enum_derive"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "num_threads"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5322,9 +5403,9 @@
 
 [[package]]
 name = "once_cell"
-version = "1.15.0"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
+checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
 
 [[package]]
 name = "opal-runtime"
@@ -5577,9 +5658,9 @@
 
 [[package]]
 name = "os_str_bytes"
-version = "6.3.0"
+version = "6.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff"
+checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
 
 [[package]]
 name = "owning_ref"
@@ -5724,7 +5805,7 @@
 [[package]]
 name = "pallet-base-fee"
 version = "1.0.0"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
 dependencies = [
  "fp-evm",
  "frame-support",
@@ -5940,12 +6021,13 @@
 [[package]]
 name = "pallet-ethereum"
 version = "4.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
 dependencies = [
  "ethereum",
  "ethereum-types",
  "evm",
  "fp-consensus",
+ "fp-ethereum",
  "fp-evm",
  "fp-evm-mapping",
  "fp-rpc",
@@ -5953,14 +6035,12 @@
  "fp-storage",
  "frame-support",
  "frame-system",
- "log",
  "pallet-evm",
  "pallet-timestamp",
  "parity-scale-codec 3.2.1",
  "rlp",
  "scale-info",
  "serde",
- "sha3",
  "sp-io",
  "sp-runtime",
  "sp-std",
@@ -5969,8 +6049,9 @@
 [[package]]
 name = "pallet-evm"
 version = "6.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30#65930cb2982258bee67b73a1f017711f6f4aa0a4"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.30-2#6fce4a7f9c3591f4090dd1db39fe71f6562804d0"
 dependencies = [
+ "environmental",
  "evm",
  "fp-evm",
  "fp-evm-mapping",
@@ -5986,7 +6067,6 @@
  "rlp",
  "scale-info",
  "serde",
- "sha3",
  "sp-core",
  "sp-io",
  "sp-runtime",
@@ -7163,9 +7243,9 @@
 
 [[package]]
 name = "pest"
-version = "2.4.0"
+version = "2.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbc7bc69c062e492337d74d59b120c274fd3d261b6bf6d3207d499b4b379c41a"
+checksum = "a528564cc62c19a7acac4d81e01f39e53e25e17b934878f4c6d25cc2836e62f8"
 dependencies = [
  "thiserror",
  "ucd-trie",
@@ -7173,9 +7253,9 @@
 
 [[package]]
 name = "pest_derive"
-version = "2.4.0"
+version = "2.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60b75706b9642ebcb34dab3bc7750f811609a0eb1dd8b88c2d15bf628c1c65b2"
+checksum = "d5fd9bc6500181952d34bd0b2b0163a54d794227b498be0b7afa7698d0a7b18f"
 dependencies = [
  "pest",
  "pest_generator",
@@ -7183,9 +7263,9 @@
 
 [[package]]
 name = "pest_generator"
-version = "2.4.0"
+version = "2.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4f9272122f5979a6511a749af9db9bfc810393f63119970d7085fed1c4ea0db"
+checksum = "d2610d5ac5156217b4ff8e46ddcef7cdf44b273da2ac5bca2ecbfa86a330e7c4"
 dependencies = [
  "pest",
  "pest_meta",
@@ -7196,9 +7276,9 @@
 
 [[package]]
 name = "pest_meta"
-version = "2.4.0"
+version = "2.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c8717927f9b79515e565a64fe46c38b8cd0427e64c40680b14a7365ab09ac8d"
+checksum = "824749bf7e21dd66b36fbe26b3f45c713879cccd4a009a917ab8e045ca8246fe"
 dependencies = [
  "once_cell",
  "pest",
@@ -8556,11 +8636,21 @@
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.16"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
 
 [[package]]
+name = "prettyplease"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51"
+dependencies = [
+ "proc-macro2",
+ "syn",
+]
+
+[[package]]
 name = "primitive-types"
 version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -8682,12 +8772,12 @@
 
 [[package]]
 name = "prost"
-version = "0.11.0"
+version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "399c3c31cdec40583bb68f0b18403400d01ec4289c383aa047560439952c4dd7"
+checksum = "a0841812012b2d4a6145fae9a6af1534873c32aa67fff26bd09f8fa42c83f95a"
 dependencies = [
  "bytes",
- "prost-derive 0.11.0",
+ "prost-derive 0.11.2",
 ]
 
 [[package]]
@@ -8714,9 +8804,9 @@
 
 [[package]]
 name = "prost-build"
-version = "0.11.1"
+version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f835c582e6bd972ba8347313300219fed5bfa52caf175298d860b61ff6069bb"
+checksum = "1d8b442418ea0822409d9e7d047cbf1e7e9e1760b172bf9982cf29d517c93511"
 dependencies = [
  "bytes",
  "heck",
@@ -8725,9 +8815,11 @@
  "log",
  "multimap",
  "petgraph",
- "prost 0.11.0",
- "prost-types 0.11.1",
+ "prettyplease",
+ "prost 0.11.2",
+ "prost-types 0.11.2",
  "regex",
+ "syn",
  "tempfile",
  "which",
 ]
@@ -8760,9 +8852,9 @@
 
 [[package]]
 name = "prost-derive"
-version = "0.11.0"
+version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7345d5f0e08c0536d7ac7229952590239e77abf0a0100a1b1d890add6ea96364"
+checksum = "164ae68b6587001ca506d3bf7f1000bfa248d0e1217b618108fba4ec1d0cc306"
 dependencies = [
  "anyhow",
  "itertools",
@@ -8783,12 +8875,12 @@
 
 [[package]]
 name = "prost-types"
-version = "0.11.1"
+version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dfaa718ad76a44b3415e6c4d53b17c8f99160dcb3a99b10470fce8ad43f6e3e"
+checksum = "747761bc3dc48f9a34553bf65605cf6cb6288ba219f3450b4275dbd81539551a"
 dependencies = [
  "bytes",
- "prost 0.11.0",
+ "prost 0.11.2",
 ]
 
 [[package]]
@@ -9039,11 +9131,10 @@
 
 [[package]]
 name = "rayon"
-version = "1.5.3"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
+checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b"
 dependencies = [
- "autocfg",
  "crossbeam-deque",
  "either",
  "rayon-core",
@@ -9051,9 +9142,9 @@
 
 [[package]]
 name = "rayon-core"
-version = "1.9.3"
+version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
+checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
 dependencies = [
  "crossbeam-channel",
  "crossbeam-deque",
@@ -9096,18 +9187,18 @@
 
 [[package]]
 name = "ref-cast"
-version = "1.0.12"
+version = "1.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12a733f1746c929b4913fe48f8697fcf9c55e3304ba251a79ffb41adfeaf49c2"
+checksum = "53b15debb4f9d60d767cd8ca9ef7abb2452922f3214671ff052defc7f3502c44"
 dependencies = [
  "ref-cast-impl",
 ]
 
 [[package]]
 name = "ref-cast-impl"
-version = "1.0.12"
+version = "1.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5887de4a01acafd221861463be6113e6e87275e79804e56779f4cdc131c60368"
+checksum = "abfa8511e9e94fd3de6585a3d3cd00e01ed556dc9814829280af0e8dc72a8f36"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -9128,9 +9219,9 @@
 
 [[package]]
 name = "regex"
-version = "1.6.0"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -9148,9 +9239,9 @@
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.27"
+version = "0.6.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
 
 [[package]]
 name = "remote-externalities"
@@ -9426,16 +9517,30 @@
 
 [[package]]
 name = "rustix"
-version = "0.35.12"
+version = "0.35.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "985947f9b6423159c4726323f373be0a21bdb514c5af06a849cb3d2dce2d01e8"
+checksum = "727a1a6d65f786ec22df8a81ca3121107f235970dc1705ed681d3e6e8b9cd5f9"
 dependencies = [
  "bitflags",
  "errno",
- "io-lifetimes",
+ "io-lifetimes 0.7.5",
  "libc",
- "linux-raw-sys",
- "windows-sys 0.36.1",
+ "linux-raw-sys 0.0.46",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "rustix"
+version = "0.36.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "203974af07ea769452490ee8de3e5947971efc3a090dca8a779dd432d3fa46a7"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes 1.0.1",
+ "libc",
+ "linux-raw-sys 0.1.2",
+ "windows-sys 0.42.0",
 ]
 
 [[package]]
@@ -9976,7 +10081,7 @@
  "once_cell",
  "parity-scale-codec 3.2.1",
  "parity-wasm 0.45.0",
- "rustix",
+ "rustix 0.35.13",
  "sc-allocator",
  "sc-executor-common",
  "sp-runtime-interface",
@@ -10135,8 +10240,8 @@
  "futures 0.3.25",
  "libp2p",
  "log",
- "prost 0.11.0",
- "prost-build 0.11.1",
+ "prost 0.11.2",
+ "prost-build 0.11.2",
  "sc-client-api",
  "sc-network-common",
  "sp-blockchain",
@@ -10612,9 +10717,9 @@
 
 [[package]]
 name = "scale-info"
-version = "2.2.0"
+version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "333af15b02563b8182cd863f925bd31ef8fa86a0e095d30c091956057d436153"
+checksum = "88d8a765117b237ef233705cc2cc4c6a27fccd46eea6ef0c8c6dae5f3ef407f8"
 dependencies = [
  "bitvec 1.0.1",
  "cfg-if 1.0.0",
@@ -10626,9 +10731,9 @@
 
 [[package]]
 name = "scale-info-derive"
-version = "2.2.0"
+version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53f56acbd0743d29ffa08f911ab5397def774ad01bab3786804cf6ee057fb5e1"
+checksum = "cdcd47b380d8c4541044e341dcd9475f55ba37ddc50c908d945fc036a8642496"
 dependencies = [
  "proc-macro-crate",
  "proc-macro2",
@@ -10804,9 +10909,9 @@
 
 [[package]]
 name = "serde_json"
-version = "1.0.87"
+version = "1.0.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45"
+checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
 dependencies = [
  "itoa",
  "ryu",
@@ -10843,7 +10948,7 @@
 dependencies = [
  "cfg-if 1.0.0",
  "cpufeatures",
- "digest 0.10.5",
+ "digest 0.10.6",
 ]
 
 [[package]]
@@ -10879,7 +10984,7 @@
 dependencies = [
  "cfg-if 1.0.0",
  "cpufeatures",
- "digest 0.10.5",
+ "digest 0.10.6",
 ]
 
 [[package]]
@@ -10888,7 +10993,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9"
 dependencies = [
- "digest 0.10.5",
+ "digest 0.10.6",
  "keccak",
 ]
 
@@ -10956,9 +11061,9 @@
 
 [[package]]
 name = "similar"
-version = "2.2.0"
+version = "2.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62ac7f900db32bf3fd12e0117dd3dc4da74bc52ebaac97f39668446d89694803"
+checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf"
 dependencies = [
  "bstr",
  "unicode-segmentation",
@@ -11018,9 +11123,9 @@
 
 [[package]]
 name = "snap"
-version = "1.0.5"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45456094d1983e2ee2a18fdfebce3189fa451699d0502cb8e3b49dba5ba41451"
+checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831"
 
 [[package]]
 name = "snow"
@@ -11318,7 +11423,7 @@
 dependencies = [
  "blake2",
  "byteorder",
- "digest 0.10.5",
+ "digest 0.10.6",
  "sha2 0.10.6",
  "sha3",
  "sp-std",
@@ -11816,9 +11921,9 @@
 
 [[package]]
 name = "ss58-registry"
-version = "1.33.0"
+version = "1.35.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ab7554f8a8b6f8d71cd5a8e6536ef116e2ce0504cf97ebf16311d58065dc8a6"
+checksum = "fa0813c10b9dbdc842c2305f949f724c64866e4ef4d09c9151e96f6a2106773c"
 dependencies = [
  "Inflector",
  "num-format",
@@ -12141,9 +12246,9 @@
 
 [[package]]
 name = "target-lexicon"
-version = "0.12.4"
+version = "0.12.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1"
+checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d"
 
 [[package]]
 name = "tempfile"
@@ -12368,9 +12473,9 @@
 
 [[package]]
 name = "tokio"
-version = "1.21.2"
+version = "1.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099"
+checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3"
 dependencies = [
  "autocfg",
  "bytes",
@@ -12694,7 +12799,7 @@
 checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
 dependencies = [
  "cfg-if 1.0.0",
- "digest 0.10.5",
+ "digest 0.10.6",
  "rand 0.8.5",
  "static_assertions",
 ]
@@ -13340,9 +13445,9 @@
 
 [[package]]
 name = "wasmtime"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1f511c4917c83d04da68333921107db75747c4e11a2f654a8e909cc5e0520dc"
+checksum = "4ad5af6ba38311282f2a21670d96e78266e8c8e2f38cbcd52c254df6ccbc7731"
 dependencies = [
  "anyhow",
  "bincode",
@@ -13368,18 +13473,18 @@
 
 [[package]]
 name = "wasmtime-asm-macros"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39bf3debfe744bf19dd3732990ce6f8c0ced7439e2370ba4e1d8f5a3660a3178"
+checksum = "45de63ddfc8b9223d1adc8f7b2ee5f35d1f6d112833934ad7ea66e4f4339e597"
 dependencies = [
  "cfg-if 1.0.0",
 ]
 
 [[package]]
 name = "wasmtime-cache"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ece42fa4676a263f7558cdaaf5a71c2592bebcbac22a0580e33cf3406c103da2"
+checksum = "bcd849399d17d2270141cfe47fa0d91ee52d5f8ea9b98cf7ddde0d53e5f79882"
 dependencies = [
  "anyhow",
  "base64",
@@ -13387,7 +13492,7 @@
  "directories-next",
  "file-per-thread-logger",
  "log",
- "rustix",
+ "rustix 0.35.13",
  "serde",
  "sha2 0.9.9",
  "toml",
@@ -13397,9 +13502,9 @@
 
 [[package]]
 name = "wasmtime-cranelift"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "058217e28644b012bdcdf0e445f58d496d78c2e0b6a6dd93558e701591dad705"
+checksum = "4bd91339b742ff20bfed4532a27b73c86b5bcbfedd6bea2dcdf2d64471e1b5c6"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -13418,9 +13523,9 @@
 
 [[package]]
 name = "wasmtime-environ"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7af06848df28b7661471d9a80d30a973e0f401f2e3ed5396ad7e225ed217047"
+checksum = "ebb881c61f4f627b5d45c54e629724974f8a8890d455bcbe634330cc27309644"
 dependencies = [
  "anyhow",
  "cranelift-entity",
@@ -13437,9 +13542,9 @@
 
 [[package]]
 name = "wasmtime-jit"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9028fb63a54185b3c192b7500ef8039c7bb8d7f62bfc9e7c258483a33a3d13bb"
+checksum = "1985c628011fe26adf5e23a5301bdc79b245e0e338f14bb58b39e4e25e4d8681"
 dependencies = [
  "addr2line",
  "anyhow",
@@ -13450,7 +13555,7 @@
  "log",
  "object",
  "rustc-demangle",
- "rustix",
+ "rustix 0.35.13",
  "serde",
  "target-lexicon",
  "thiserror",
@@ -13462,20 +13567,20 @@
 
 [[package]]
 name = "wasmtime-jit-debug"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25e82d4ef93296785de7efca92f7679dc67fe68a13b625a5ecc8d7503b377a37"
+checksum = "f671b588486f5ccec8c5a3dba6b4c07eac2e66ab8c60e6f4e53717c77f709731"
 dependencies = [
  "object",
  "once_cell",
- "rustix",
+ "rustix 0.35.13",
 ]
 
 [[package]]
 name = "wasmtime-runtime"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f0e9bea7d517d114fe66b930b2124ee086516ee93eeebfd97f75f366c5b0553"
+checksum = "ee8f92ad4b61736339c29361da85769ebc200f184361959d1792832e592a1afd"
 dependencies = [
  "anyhow",
  "cc",
@@ -13485,10 +13590,10 @@
  "log",
  "mach",
  "memfd",
- "memoffset",
+ "memoffset 0.6.5",
  "paste",
  "rand 0.8.5",
- "rustix",
+ "rustix 0.35.13",
  "thiserror",
  "wasmtime-asm-macros",
  "wasmtime-environ",
@@ -13498,9 +13603,9 @@
 
 [[package]]
 name = "wasmtime-types"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69b83e93ed41b8fdc936244cfd5e455480cf1eca1fd60c78a0040038b4ce5075"
+checksum = "d23d61cb4c46e837b431196dd06abb11731541021916d03476a178b54dc07aeb"
 dependencies = [
  "cranelift-entity",
  "serde",
@@ -13841,9 +13946,9 @@
 
 [[package]]
 name = "winreg"
-version = "0.7.0"
+version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
+checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
 dependencies = [
  "winapi",
 ]
@@ -13856,9 +13961,9 @@
 
 [[package]]
 name = "wyz"
-version = "0.5.0"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e"
+checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
 dependencies = [
  "tap",
 ]
modifiedclient/rpc/Cargo.tomldiffbeforeafterboth
--- a/client/rpc/Cargo.toml
+++ b/client/rpc/Cargo.toml
@@ -19,4 +19,4 @@
 sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-rpc = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
modifiedcrates/evm-coder/Cargo.tomldiffbeforeafterboth
--- a/crates/evm-coder/Cargo.toml
+++ b/crates/evm-coder/Cargo.toml
@@ -19,7 +19,7 @@
 # We have tuple-heavy code in solidity.rs
 impl-trait-for-tuples = "0.2.2"
 
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 
 [dev-dependencies]
 # We want to assert some large binary blobs equality in tests
modifiedcrates/evm-coder/src/lib.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/lib.rs
+++ b/crates/evm-coder/src/lib.rs
@@ -197,7 +197,7 @@
 	impl EthCrossAccount {
 		pub fn from_sub_cross_account<T>(cross_account_id: &T::CrossAccountId) -> Self
 		where
-			T: pallet_evm::account::Config,
+			T: pallet_evm::Config,
 			T::AccountId: AsRef<[u8; 32]>,
 		{
 			if cross_account_id.is_canonical_substrate() {
@@ -215,7 +215,7 @@
 
 		pub fn into_sub_cross_account<T>(&self) -> crate::execution::Result<T::CrossAccountId>
 		where
-			T: pallet_evm::account::Config,
+			T: pallet_evm::Config,
 			T::AccountId: From<[u8; 32]>,
 		{
 			if self.eth == Default::default() && self.sub == Default::default() {
@@ -231,7 +231,7 @@
 	}
 
 	/// Convert `CrossAccountId` to `uint256`.
-	pub fn convert_cross_account_to_uint256<T: pallet_evm::account::Config>(
+	pub fn convert_cross_account_to_uint256<T: pallet_evm::Config>(
 		from: &T::CrossAccountId,
 	) -> uint256
 	where
@@ -242,7 +242,7 @@
 	}
 
 	/// Convert `uint256` to `CrossAccountId`.
-	pub fn convert_uint256_to_cross_account<T: pallet_evm::account::Config>(
+	pub fn convert_uint256_to_cross_account<T: pallet_evm::Config>(
 		from: uint256,
 	) -> T::CrossAccountId
 	where
modifiednode/cli/Cargo.tomldiffbeforeafterboth
--- a/node/cli/Cargo.toml
+++ b/node/cli/Cargo.toml
@@ -309,13 +309,13 @@
 jsonrpsee = { version = "0.15.1", features = ["server", "macros"] }
 tokio = { version = "1.19.2", features = ["time"] }
 
-fc-rpc-core = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fc-consensus = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fc-mapping-sync = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fc-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fc-db = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fp-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+fc-rpc-core = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fc-consensus = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fc-mapping-sync = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fc-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fc-db = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fp-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 
 unique-rpc = { default-features = false, path = "../rpc" }
 app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false }
modifiednode/cli/src/service.rsdiffbeforeafterboth
--- a/node/cli/src/service.rs
+++ b/node/cli/src/service.rs
@@ -45,7 +45,8 @@
 use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface, RelayChainResult};
 use cumulus_relay_chain_rpc_interface::{RelayChainRpcInterface, create_client_and_start_worker};
 
-// Substrate Imports
+// Substrate ImportsA
+use sp_api::BlockT;
 use sc_executor::NativeElseWasmExecutor;
 use sc_executor::NativeExecutionDispatch;
 use sc_network::{NetworkService, NetworkBlock};
@@ -159,7 +160,10 @@
 	}
 }
 
-pub fn open_frontier_backend(config: &Configuration) -> Result<Arc<fc_db::Backend<Block>>, String> {
+pub fn open_frontier_backend<Block: BlockT, C: sp_blockchain::HeaderBackend<Block>>(
+	client: Arc<C>,
+	config: &Configuration,
+) -> Result<Arc<fc_db::Backend<Block>>, String> {
 	let config_dir = config
 		.base_path
 		.as_ref()
@@ -170,6 +174,7 @@
 	let database_dir = config_dir.join("frontier").join("db");
 
 	Ok(Arc::new(fc_db::Backend::<Block>::new(
+		client,
 		&fc_db::DatabaseSettings {
 			source: fc_db::DatabaseSource::RocksDb {
 				path: database_dir,
@@ -285,7 +290,7 @@
 
 	let filter_pool: Option<FilterPool> = Some(Arc::new(Mutex::new(BTreeMap::new())));
 
-	let frontier_backend = open_frontier_backend(config)?;
+	let frontier_backend = open_frontier_backend(client.clone(), config)?;
 
 	let import_queue = build_import_queue(
 		client.clone(),
modifiednode/rpc/Cargo.tomldiffbeforeafterboth
--- a/node/rpc/Cargo.toml
+++ b/node/rpc/Cargo.toml
@@ -40,20 +40,20 @@
 substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 tokio = { version = "1.19.2", features = ["macros", "sync"] }
 
-pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fc-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fp-storage = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fc-rpc-core = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fc-db = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fc-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fp-storage = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fc-rpc-core = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fc-db = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 
 pallet-common = { default-features = false, path = "../../pallets/common" }
 up-common = { path = "../../primitives/common" }
 pallet-unique = { path = "../../pallets/unique" }
 uc-rpc = { path = "../../client/rpc" }
 up-rpc = { path = "../../primitives/rpc" }
-app-promotion-rpc = { path = "../../primitives/app_promotion_rpc"}
+app-promotion-rpc = { path = "../../primitives/app_promotion_rpc" }
 rmrk-rpc = { path = "../../primitives/rmrk-rpc" }
 up-data-structs = { default-features = false, path = "../../primitives/data-structs" }
 
modifiednode/rpc/src/lib.rsdiffbeforeafterboth
--- a/node/rpc/src/lib.rs
+++ b/node/rpc/src/lib.rs
@@ -230,6 +230,7 @@
 			block_data_cache.clone(),
 			fee_history_cache,
 			fee_history_limit,
+			10,
 		)
 		.into_rpc(),
 	)?;
modifiedpallets/app-promotion/Cargo.tomldiffbeforeafterboth
--- a/pallets/app-promotion/Cargo.toml
+++ b/pallets/app-promotion/Cargo.toml
@@ -47,28 +47,30 @@
 ################################################################################
 # Substrate Dependencies
 
-codec = { default-features = false, features = ['derive'], package = 'parity-scale-codec', version = '3.1.2' }
-frame-benchmarking = {default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+codec = { default-features = false, features = [
+    'derive',
+], package = 'parity-scale-codec', version = '3.1.2' }
+frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-frame-system ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-pallet-balances ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-pallet-timestamp ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-pallet-randomness-collective-flip ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-pallet-evm ={ default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-sp-std ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+pallet-timestamp = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+pallet-randomness-collective-flip = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-sp-io ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 serde = { default-features = false, features = ['derive'], version = '1.0.130' }
 
 ################################################################################
 # local dependencies
 
-up-data-structs ={ default-features = false, path = "../../primitives/data-structs" }
-pallet-common ={ default-features = false, path = "../common" }
-pallet-unique ={ default-features = false, path = "../unique" }
-pallet-evm-contract-helpers ={ default-features = false, path = "../evm-contract-helpers" }
-pallet-evm-migration ={ default-features = false, path = "../evm-migration" }
+up-data-structs = { default-features = false, path = "../../primitives/data-structs" }
+pallet-common = { default-features = false, path = "../common" }
+pallet-unique = { default-features = false, path = "../unique" }
+pallet-evm-contract-helpers = { default-features = false, path = "../evm-contract-helpers" }
+pallet-evm-migration = { default-features = false, path = "../evm-migration" }
 
 # [dev-dependencies]
 
modifiedpallets/app-promotion/src/lib.rsdiffbeforeafterboth
--- a/pallets/app-promotion/src/lib.rs
+++ b/pallets/app-promotion/src/lib.rs
@@ -102,7 +102,7 @@
 	use frame_system::pallet_prelude::*;
 
 	#[pallet::config]
-	pub trait Config: frame_system::Config + pallet_evm::account::Config {
+	pub trait Config: frame_system::Config + pallet_evm::Config {
 		/// Type to interact with the native token
 		type Currency: ExtendedLockableCurrency<Self::AccountId>
 			+ ReservableCurrency<Self::AccountId>;
@@ -274,11 +274,13 @@
 
 			if !block_pending.is_empty() {
 				block_pending.into_iter().for_each(|(staker, amount)| {
-					<T::Currency as ReservableCurrency<T::AccountId>>::unreserve(&staker, amount);
+					<<T as Config>::Currency as ReservableCurrency<T::AccountId>>::unreserve(
+						&staker, amount,
+					);
 				});
 			}
 
-			T::WeightInfo::on_initialize(counter)
+			<T as Config>::WeightInfo::on_initialize(counter)
 		}
 	}
 
@@ -297,7 +299,7 @@
 		/// # Arguments
 		///
 		/// * `admin`: account of the new admin.
-		#[pallet::weight(T::WeightInfo::set_admin_address())]
+		#[pallet::weight(<T as Config>::WeightInfo::set_admin_address())]
 		pub fn set_admin_address(origin: OriginFor<T>, admin: T::CrossAccountId) -> DispatchResult {
 			ensure_root(origin)?;
 
@@ -315,7 +317,7 @@
 		/// # Arguments
 		///
 		/// * `amount`: in native tokens.
-		#[pallet::weight(T::WeightInfo::stake())]
+		#[pallet::weight(<T as Config>::WeightInfo::stake())]
 		pub fn stake(staker: OriginFor<T>, amount: BalanceOf<T>) -> DispatchResult {
 			let staker_id = ensure_signed(staker)?;
 
@@ -388,7 +390,7 @@
 		/// Moves the sum of all stakes to the `reserved` state.
 		/// After the end of `PendingInterval` this sum becomes completely
 		/// free for further use.
-		#[pallet::weight(T::WeightInfo::unstake())]
+		#[pallet::weight(<T as Config>::WeightInfo::unstake())]
 		pub fn unstake(staker: OriginFor<T>) -> DispatchResultWithPostInfo {
 			let staker_id = ensure_signed(staker)?;
 
@@ -421,7 +423,10 @@
 
 			Self::unlock_balance(&staker_id, total_staked)?;
 
-			<T::Currency as ReservableCurrency<T::AccountId>>::reserve(&staker_id, total_staked)?;
+			<<T as Config>::Currency as ReservableCurrency<T::AccountId>>::reserve(
+				&staker_id,
+				total_staked,
+			)?;
 
 			TotalStaked::<T>::set(
 				TotalStaked::<T>::get()
@@ -445,7 +450,7 @@
 		/// # Arguments
 		///
 		/// * `collection_id`: ID of the collection that will be sponsored by `pallet_id`
-		#[pallet::weight(T::WeightInfo::sponsor_collection())]
+		#[pallet::weight(<T as Config>::WeightInfo::sponsor_collection())]
 		pub fn sponsor_collection(
 			admin: OriginFor<T>,
 			collection_id: CollectionId,
@@ -470,7 +475,7 @@
 		/// # Arguments
 		///
 		/// * `collection_id`: ID of the collection that is sponsored by `pallet_id`
-		#[pallet::weight(T::WeightInfo::stop_sponsoring_collection())]
+		#[pallet::weight(<T as Config>::WeightInfo::stop_sponsoring_collection())]
 		pub fn stop_sponsoring_collection(
 			admin: OriginFor<T>,
 			collection_id: CollectionId,
@@ -499,7 +504,7 @@
 		/// # Arguments
 		///
 		/// * `contract_id`: the contract address that will be sponsored by `pallet_id`
-		#[pallet::weight(T::WeightInfo::sponsor_contract())]
+		#[pallet::weight(<T as Config>::WeightInfo::sponsor_contract())]
 		pub fn sponsor_contract(admin: OriginFor<T>, contract_id: H160) -> DispatchResult {
 			let admin_id = ensure_signed(admin)?;
 
@@ -525,7 +530,7 @@
 		/// # Arguments
 		///
 		/// * `contract_id`: the contract address that is sponsored by `pallet_id`
-		#[pallet::weight(T::WeightInfo::stop_sponsoring_contract())]
+		#[pallet::weight(<T as Config>::WeightInfo::stop_sponsoring_contract())]
 		pub fn stop_sponsoring_contract(admin: OriginFor<T>, contract_id: H160) -> DispatchResult {
 			let admin_id = ensure_signed(admin)?;
 
@@ -555,7 +560,7 @@
 		/// # Arguments
 		///
 		/// * `stakers_number`: the number of stakers for which recalculation will be performed
-		#[pallet::weight(T::WeightInfo::payout_stakers(stakers_number.unwrap_or(20) as u32))]
+		#[pallet::weight(<T as Config>::WeightInfo::payout_stakers(stakers_number.unwrap_or(20) as u32))]
 		pub fn payout_stakers(admin: OriginFor<T>, stakers_number: Option<u8>) -> DispatchResult {
 			let admin_id = ensure_signed(admin)?;
 
@@ -589,7 +594,7 @@
 				let flush_stake = || -> DispatchResult {
 					if let Some(last_id) = &*last_id.borrow() {
 						if !income_acc.borrow().is_zero() {
-							<T::Currency as Currency<T::AccountId>>::transfer(
+							<<T as Config>::Currency as Currency<T::AccountId>>::transfer(
 								&T::TreasuryAccountId::get(),
 								last_id,
 								*income_acc.borrow(),
@@ -700,9 +705,12 @@
 	/// - `amount`: amount of locked funds.
 	fn set_lock_unchecked(staker: &T::AccountId, amount: BalanceOf<T>) {
 		if amount.is_zero() {
-			<T::Currency as LockableCurrency<T::AccountId>>::remove_lock(LOCK_IDENTIFIER, &staker);
+			<<T as Config>::Currency as LockableCurrency<T::AccountId>>::remove_lock(
+				LOCK_IDENTIFIER,
+				&staker,
+			);
 		} else {
-			<T::Currency as LockableCurrency<T::AccountId>>::set_lock(
+			<<T as Config>::Currency as LockableCurrency<T::AccountId>>::set_lock(
 				LOCK_IDENTIFIER,
 				staker,
 				amount,
@@ -717,7 +725,7 @@
 	pub fn get_locked_balance(
 		staker: impl EncodeLike<T::AccountId>,
 	) -> Option<BalanceLock<BalanceOf<T>>> {
-		<T::Currency as ExtendedLockableCurrency<T::AccountId>>::locks(staker)
+		<<T as Config>::Currency as ExtendedLockableCurrency<T::AccountId>>::locks(staker)
 			.into_iter()
 			.find(|l| l.id == LOCK_IDENTIFIER)
 	}
modifiedpallets/common/Cargo.tomldiffbeforeafterboth
--- a/pallets/common/Cargo.toml
+++ b/pallets/common/Cargo.toml
@@ -17,12 +17,12 @@
 sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
 pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
 evm-coder = { default-features = false, path = '../../crates/evm-coder' }
 ethereum = { version = "0.12.0", default-features = false }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 
 serde = { version = "1.0.130", default-features = false }
 scale-info = { version = "2.0.1", default-features = false, features = [
modifiedpallets/common/src/eth.rsdiffbeforeafterboth
--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -17,7 +17,7 @@
 //! The module contains a number of functions for converting and checking ethereum identifiers.
 
 use evm_coder::types::{uint256, address};
-pub use pallet_evm::account::{Config, CrossAccountId};
+pub use pallet_evm::{Config, account::CrossAccountId};
 use sp_core::H160;
 use up_data_structs::CollectionId;
 
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -342,7 +342,6 @@
 #[frame_support::pallet]
 pub mod pallet {
 	use super::*;
-	use pallet_evm::account;
 	use dispatch::CollectionDispatch;
 	use frame_support::{Blake2_128Concat, pallet_prelude::*, storage::Key, traits::StorageVersion};
 	use frame_system::pallet_prelude::*;
@@ -353,11 +352,7 @@
 
 	#[pallet::config]
 	pub trait Config:
-		frame_system::Config
-		+ pallet_evm_coder_substrate::Config
-		+ pallet_evm::Config
-		+ TypeInfo
-		+ account::Config
+		frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::Config + TypeInfo
 	{
 		/// Weight information for functions of this pallet.
 		type WeightInfo: WeightInfo;
modifiedpallets/configuration/Cargo.tomldiffbeforeafterboth
--- a/pallets/configuration/Cargo.toml
+++ b/pallets/configuration/Cargo.toml
@@ -16,7 +16,7 @@
 sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 smallvec = "1.6.1"
 
 [features]
modifiedpallets/evm-coder-substrate/Cargo.tomldiffbeforeafterboth
--- a/pallets/evm-coder-substrate/Cargo.toml
+++ b/pallets/evm-coder-substrate/Cargo.toml
@@ -12,8 +12,8 @@
 sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 ethereum = { version = "0.12.0", default-features = false }
 evm-coder = { default-features = false, path = "../../crates/evm-coder" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
modifiedpallets/evm-contract-helpers/Cargo.tomldiffbeforeafterboth
--- a/pallets/evm-contract-helpers/Cargo.toml
+++ b/pallets/evm-contract-helpers/Cargo.toml
@@ -19,8 +19,8 @@
 sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 
 # Unique
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.30" }
 
 # Locals
modifiedpallets/evm-contract-helpers/src/lib.rsdiffbeforeafterboth
--- a/pallets/evm-contract-helpers/src/lib.rs
+++ b/pallets/evm-contract-helpers/src/lib.rs
@@ -41,7 +41,7 @@
 
 	#[pallet::config]
 	pub trait Config:
-		frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::account::Config
+		frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::Config
 	{
 		/// Overarching event type.
 		type RuntimeEvent: IsType<<Self as frame_system::Config>::RuntimeEvent> + From<Event<Self>>;
modifiedpallets/evm-migration/Cargo.tomldiffbeforeafterboth
--- a/pallets/evm-migration/Cargo.toml
+++ b/pallets/evm-migration/Cargo.toml
@@ -16,8 +16,8 @@
 sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 
 [dependencies.codec]
 default-features = false
modifiedpallets/evm-transaction-payment/Cargo.tomldiffbeforeafterboth
--- a/pallets/evm-transaction-payment/Cargo.toml
+++ b/pallets/evm-transaction-payment/Cargo.toml
@@ -14,11 +14,11 @@
 sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.30" }
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 
 [dependencies.codec]
 default-features = false
modifiedpallets/evm-transaction-payment/src/lib.rsdiffbeforeafterboth
--- a/pallets/evm-transaction-payment/src/lib.rs
+++ b/pallets/evm-transaction-payment/src/lib.rs
@@ -44,7 +44,7 @@
 	}
 
 	#[pallet::config]
-	pub trait Config: frame_system::Config + pallet_evm::account::Config {
+	pub trait Config: frame_system::Config + pallet_evm::Config {
 		/// Loosly-coupled handlers for evm call sponsoring
 		type EvmSponsorshipHandler: SponsorshipHandler<Self::CrossAccountId, CallContext>;
 	}
modifiedpallets/fungible/Cargo.tomldiffbeforeafterboth
--- a/pallets/fungible/Cargo.toml
+++ b/pallets/fungible/Cargo.toml
@@ -23,7 +23,7 @@
 pallet-evm-coder-substrate = { default-features = false, path = '../evm-coder-substrate' }
 ethereum = { version = "0.12.0", default-features = false }
 frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 scale-info = { version = "2.0.1", default-features = false, features = [
     "derive",
 ] }
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -106,7 +106,7 @@
 pub mod erc;
 pub mod weights;
 
-pub type CreateItemData<T> = (<T as pallet_evm::account::Config>::CrossAccountId, u128);
+pub type CreateItemData<T> = (<T as pallet_evm::Config>::CrossAccountId, u128);
 pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
 
 #[frame_support::pallet]
modifiedpallets/nonfungible/Cargo.tomldiffbeforeafterboth
--- a/pallets/nonfungible/Cargo.toml
+++ b/pallets/nonfungible/Cargo.toml
@@ -16,7 +16,7 @@
 sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 pallet-common = { default-features = false, path = '../common' }
 pallet-structure = { default-features = false, path = '../structure' }
 up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -127,7 +127,7 @@
 pub mod erc;
 pub mod weights;
 
-pub type CreateItemData<T> = CreateNftExData<<T as pallet_evm::account::Config>::CrossAccountId>;
+pub type CreateItemData<T> = CreateNftExData<<T as pallet_evm::Config>::CrossAccountId>;
 pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
 
 /// Token data, stored independently from other data used to describe it
modifiedpallets/proxy-rmrk-core/Cargo.tomldiffbeforeafterboth
--- a/pallets/proxy-rmrk-core/Cargo.toml
+++ b/pallets/proxy-rmrk-core/Cargo.toml
@@ -20,7 +20,7 @@
 pallet-nonfungible = { default-features = false, path = "../../pallets/nonfungible" }
 pallet-structure = { default-features = false, path = "../../pallets/structure" }
 up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 rmrk-traits = { default-features = false, path = "../../primitives/rmrk-traits" }
 scale-info = { version = "2.0.1", default-features = false, features = [
modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
before · pallets/proxy-rmrk-core/src/lib.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! # RMRK Core Proxy Pallet18//!19//! A pallet used as proxy for RMRK Core (<https://rmrk-team.github.io/rmrk-substrate/#/pallets/rmrk-core>).20//!21//! - [`Config`]22//! - [`Call`]23//! - [`Pallet`]24//!25//! ## Overview26//!27//! The RMRK Core Proxy pallet mirrors the functionality of RMRK Core,28//! binding its externalities to Unique's own underlying structure.29//! It is purposed to mimic RMRK Core exactly, allowing seamless integrations30//! of solutions based on RMRK.31//!32//! RMRK Core itself contains essential functionality for RMRK's nested and33//! multi-resourced NFTs.34//!35//! *Note*, that while RMRK itself is subject to active development and restructuring,36//! the proxy may be caught temporarily out of date.37//!38//! ### What is RMRK?39//!40//! RMRK is a set of NFT standards which compose several "NFT 2.0 lego" primitives.41//! Putting these legos together allows a user to create NFT systems of arbitrary complexity.42//!43//! Meaning, RMRK NFTs are dynamic, able to nest into each other and form a hierarchy,44//! make use of specific changeable and partially shared metadata in the form of resources,45//! and more.46//!47//! Visit RMRK documentation and repositories to learn more:48//! - Docs: <https://docs.rmrk.app/getting-started/>49//! - FAQ: <https://coda.io/@rmrk/faq>50//! - Substrate code repository: <https://github.com/rmrk-team/rmrk-substrate>51//! - RMRK specification repository: <https://github.com/rmrk-team/rmrk-spec>52//!53//! ## Terminology54//!55//! For more information on RMRK, see RMRK's own documentation.56//!57//! ### Intro to RMRK58//!59//! - **Resource:** Additional piece of metadata of an NFT usually serving to add60//! a piece of media on top of the root metadata (NFT's own), be it a different wing61//! on the root template bird or something entirely unrelated.62//!63//! - **Base:** A list of possible "components" - Parts, a combination of which can64//! be appended/equipped to/on an NFT.65//!66//! - **Part:** Something that, together with other Parts, can constitute an NFT.67//! Parts are defined in the Base to which they belong. Parts can be either68//! of the `slot` type or `fixed` type. Slots are intended for equippables.69//! Note that "part of something" and "Part of a Base" can be easily confused,70//! and so in this documentation these words are distinguished by the capital letter.71//!72//! - **Theme:** Named objects of variable => value pairs which get interpolated into73//! the Base's `themable` Parts. Themes can hold any value, but are often represented74//! in RMRK's examples as colors applied to visible Parts.75//!76//! ### Peculiarities in Unique77//!78//! - **Scoped properties:** Properties that are normally obscured from users.79//! Their purpose is to contain structured metadata that was not included in the Unique standard80//! for collections and tokens, meant to be operated on by proxies and other outliers.81//! Scoped property keys are prefixed with `some-scope:`, where `some-scope` is82//! an arbitrary keyword, like "rmrk". `:` is considered an unacceptable symbol in user-defined83//! properties, which, along with other safeguards, makes scoped ones impossible to tamper with.84//!85//! - **Auxiliary properties:** A slightly different structure of properties,86//! trading universality of use for more convenient storage, writes and access.87//! Meant to be inaccessible to end users.88//!89//! ## Proxy Implementation90//!91//! An external user is supposed to be able to utilize this proxy as they would92//! utilize RMRK, and get exactly the same results. Normally, Unique transactions93//! are off-limits to RMRK collections and tokens, and vice versa. However,94//! the information stored on chain can be freely interpreted by storage reads and Unique RPCs.95//!96//! ### ID Mapping97//!98//! RMRK's collections' IDs are counted independently of Unique's and start at 0.99//! Note that tokens' IDs still start at 1.100//! The collections themselves, as well as tokens, are stored as Unique collections,101//! and thus RMRK IDs are mapped to Unique IDs (but not vice versa).102//!103//! ### External/Internal Collection Insulation104//!105//! A Unique transaction cannot target collections purposed for RMRK,106//! and they are flagged as `external` to specify that. On the other hand,107//! due to the mapping, RMRK transactions and RPCs simply cannot reach Unique collections.108//!109//! ### Native Properties110//!111//! Many of RMRK's native parameters are stored as scoped properties of a collection112//! or an NFT on the chain. Scoped properties are prefixed with `rmrk:`, where `:`113//! is an unacceptable symbol in user-defined properties, which, along with other safeguards,114//! makes them impossible to tamper with.115//!116//! ### Collection and NFT Types, or Base, Parts and Themes Handling117//!118//! RMRK introduces the concept of a Base, which is a catalogue of Parts,119//! possible components of an NFT. Due to its similarity with the functionality120//! of a token collection, a Base is stored and handled as one, and the Base's Parts and Themes121//! are this collection's NFTs. See [`CollectionType`] and [`NftType`].122//!123//! ## Interface124//!125//! ### Dispatchables126//!127//! - `create_collection` - Create a new collection of NFTs.128//! - `destroy_collection` - Destroy a collection.129//! - `change_collection_issuer` - Change the issuer of a collection.130//! Analogous to Unique's collection's [`owner`](up_data_structs::Collection).131//! - `lock_collection` - "Lock" the collection and prevent new token creation. **Cannot be undone.**132//! - `mint_nft` - Mint an NFT in a specified collection.133//! - `burn_nft` - Burn an NFT, destroying it and its nested tokens.134//! - `send` - Transfer an NFT from an account/NFT A to another account/NFT B.135//! - `accept_nft` - Accept an NFT sent from another account to self or an owned NFT.136//! - `reject_nft` - Reject an NFT sent from another account to self or owned NFT and **burn it**.137//! - `accept_resource` - Accept the addition of a newly created pending resource to an existing NFT.138//! - `accept_resource_removal` - Accept the removal of a removal-pending resource from an NFT.139//! - `set_property` - Add or edit a custom user property of a token or a collection.140//! - `set_priority` - Set a different order of resource priorities for an NFT.141//! - `add_basic_resource` - Create and set/propose a basic resource for an NFT.142//! - `add_composable_resource` - Create and set/propose a composable resource for an NFT.143//! - `add_slot_resource` - Create and set/propose a slot resource for an NFT.144//! - `remove_resource` - Remove and erase a resource from an NFT.145146#![cfg_attr(not(feature = "std"), no_std)]147148use frame_support::{pallet_prelude::*, BoundedVec, dispatch::DispatchResult};149use frame_system::{pallet_prelude::*, ensure_signed};150use sp_runtime::{DispatchError, Permill, traits::StaticLookup};151use sp_std::{152	vec::Vec,153	collections::{btree_set::BTreeSet, btree_map::BTreeMap},154};155use up_data_structs::{*, mapping::TokenAddressMapping};156use pallet_common::{157	Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,158};159use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};160use pallet_structure::{Pallet as PalletStructure, Error as StructureError};161use pallet_evm::account::CrossAccountId;162use core::convert::AsRef;163164pub use pallet::*;165166#[cfg(feature = "runtime-benchmarks")]167pub mod benchmarking;168pub mod misc;169pub mod property;170pub mod rpc;171pub mod weights;172173pub type SelfWeightOf<T> = <T as Config>::WeightInfo;174175use weights::WeightInfo;176use misc::*;177pub use property::*;178179use RmrkProperty::*;180181/// Maximum number of levels of depth in the token nesting tree.182pub const NESTING_BUDGET: u32 = 5;183184type PendingTarget = (CollectionId, TokenId);185type PendingChild = (RmrkCollectionId, RmrkNftId);186type PendingChildrenSet = BTreeSet<PendingChild>;187188type BasesMap = BTreeMap<RmrkBaseId, u32>;189190#[frame_support::pallet]191pub mod pallet {192	use super::*;193	use pallet_evm::account;194195	#[pallet::config]196	pub trait Config:197		frame_system::Config + pallet_common::Config + pallet_nonfungible::Config + account::Config198	{199		/// Overarching event type.200		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;201202		/// The weight information of this pallet.203		type WeightInfo: WeightInfo;204	}205206	/// Latest yet-unused collection ID.207	#[pallet::storage]208	#[pallet::getter(fn collection_index)]209	pub type CollectionIndex<T: Config> = StorageValue<_, RmrkCollectionId, ValueQuery>;210211	/// Mapping from RMRK collection ID to Unique's.212	#[pallet::storage]213	pub type UniqueCollectionId<T: Config> =214		StorageMap<_, Twox64Concat, RmrkCollectionId, CollectionId, ValueQuery>;215216	#[pallet::pallet]217	#[pallet::generate_store(pub(super) trait Store)]218	pub struct Pallet<T>(_);219220	#[pallet::event]221	#[pallet::generate_deposit(pub(super) fn deposit_event)]222	pub enum Event<T: Config> {223		CollectionCreated {224			issuer: T::AccountId,225			collection_id: RmrkCollectionId,226		},227		CollectionDestroyed {228			issuer: T::AccountId,229			collection_id: RmrkCollectionId,230		},231		IssuerChanged {232			old_issuer: T::AccountId,233			new_issuer: T::AccountId,234			collection_id: RmrkCollectionId,235		},236		CollectionLocked {237			issuer: T::AccountId,238			collection_id: RmrkCollectionId,239		},240		NftMinted {241			owner: T::AccountId,242			collection_id: RmrkCollectionId,243			nft_id: RmrkNftId,244		},245		NFTBurned {246			owner: T::AccountId,247			nft_id: RmrkNftId,248		},249		NFTSent {250			sender: T::AccountId,251			recipient: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,252			collection_id: RmrkCollectionId,253			nft_id: RmrkNftId,254			approval_required: bool,255		},256		NFTAccepted {257			sender: T::AccountId,258			recipient: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,259			collection_id: RmrkCollectionId,260			nft_id: RmrkNftId,261		},262		NFTRejected {263			sender: T::AccountId,264			collection_id: RmrkCollectionId,265			nft_id: RmrkNftId,266		},267		PropertySet {268			collection_id: RmrkCollectionId,269			maybe_nft_id: Option<RmrkNftId>,270			key: RmrkKeyString,271			value: RmrkValueString,272		},273		ResourceAdded {274			nft_id: RmrkNftId,275			resource_id: RmrkResourceId,276		},277		ResourceRemoval {278			nft_id: RmrkNftId,279			resource_id: RmrkResourceId,280		},281		ResourceAccepted {282			nft_id: RmrkNftId,283			resource_id: RmrkResourceId,284		},285		ResourceRemovalAccepted {286			nft_id: RmrkNftId,287			resource_id: RmrkResourceId,288		},289		PrioritySet {290			collection_id: RmrkCollectionId,291			nft_id: RmrkNftId,292		},293	}294295	#[pallet::error]296	pub enum Error<T> {297		/* Unique proxy-specific events */298		/// Property of the type of RMRK collection could not be read successfully.299		CorruptedCollectionType,300		// NftTypeEncodeError,301		/// Too many symbols supplied as the property key. The maximum is [256](up_data_structs::MAX_PROPERTY_KEY_LENGTH).302		RmrkPropertyKeyIsTooLong,303		/// Too many bytes supplied as the property value. The maximum is [32768](up_data_structs::MAX_PROPERTY_VALUE_LENGTH).304		RmrkPropertyValueIsTooLong,305		/// Could not find a property by the supplied key.306		RmrkPropertyIsNotFound,307		/// Something went wrong when decoding encoded data from the storage.308		/// Perhaps, there was a wrong key supplied for the type, or the data was improperly stored.309		UnableToDecodeRmrkData,310311		/* RMRK compatible events */312		/// Only destroying collections without tokens is allowed.313		CollectionNotEmpty,314		/// Could not find an ID for a collection. It is likely there were too many collections created on the chain, causing an overflow.315		NoAvailableCollectionId,316		/// Token does not exist, or there is no suitable ID for it, likely too many tokens were created in a collection, causing an overflow.317		NoAvailableNftId,318		/// Collection does not exist, has a wrong type, or does not map to a Unique ID.319		CollectionUnknown,320		/// No permission to perform action.321		NoPermission,322		/// Token is marked as non-transferable, and thus cannot be transferred.323		NonTransferable,324		/// Too many tokens created in the collection, no new ones are allowed.325		CollectionFullOrLocked,326		/// No such resource found.327		ResourceDoesntExist,328		/// If an NFT is sent to a descendant, that would form a nesting loop, an ouroboros.329		/// Sending to self is redundant.330		CannotSendToDescendentOrSelf,331		/// Not the target owner of the sent NFT.332		CannotAcceptNonOwnedNft,333		/// Not the target owner of the sent NFT.334		CannotRejectNonOwnedNft,335		/// NFT was not sent and is not pending.336		CannotRejectNonPendingNft,337		/// Resource is not pending for the operation.338		ResourceNotPending,339		/// Could not find an ID for the resource. It is likely there were too many resources created on an NFT, causing an overflow.340		NoAvailableResourceId,341	}342343	#[pallet::call]344	impl<T: Config> Pallet<T> {345		// todo :refactor replace every collection_id with rmrk_collection_id (and nft_id) in arguments for uniformity?346347		/// Create a new collection of NFTs.348		///349		/// # Permissions:350		/// * Anyone - will be assigned as the issuer of the collection.351		///352		/// # Arguments:353		/// - `origin`: sender of the transaction354		/// - `metadata`: Metadata describing the collection, e.g. IPFS hash. Cannot be changed.355		/// - `max`: Optional maximum number of tokens.356		/// - `symbol`: UTF-8 string with token prefix, by which to represent the token in wallets and UIs.357		/// Analogous to Unique's [`token_prefix`](up_data_structs::Collection). Cannot be changed.358		#[pallet::weight(<SelfWeightOf<T>>::create_collection())]359		pub fn create_collection(360			origin: OriginFor<T>,361			metadata: RmrkString,362			max: Option<u32>,363			symbol: RmrkCollectionSymbol,364		) -> DispatchResult {365			let sender = ensure_signed(origin)?;366367			let limits = CollectionLimits {368				owner_can_transfer: Some(false),369				token_limit: max,370				..Default::default()371			};372373			let data = CreateCollectionData {374				limits: Some(limits),375				token_prefix: symbol376					.into_inner()377					.try_into()378					.map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,379				permissions: Some(CollectionPermissions {380					nesting: Some(NestingPermissions {381						token_owner: true,382						collection_admin: false,383						restricted: None,384						#[cfg(feature = "runtime-benchmarks")]385						permissive: false,386					}),387					..Default::default()388				}),389				..Default::default()390			};391392			let unique_collection_id = Self::init_collection(393				T::CrossAccountId::from_sub(sender.clone()),394				data,395				[396					Self::encode_rmrk_property(Metadata, &metadata)?,397					Self::encode_rmrk_property(CollectionType, &misc::CollectionType::Regular)?,398				]399				.into_iter(),400			)?;401			let rmrk_collection_id = <CollectionIndex<T>>::get();402403			<UniqueCollectionId<T>>::insert(rmrk_collection_id, unique_collection_id);404405			<PalletCommon<T>>::set_scoped_collection_property(406				unique_collection_id,407				RMRK_SCOPE,408				Self::encode_rmrk_property(RmrkInternalCollectionId, &rmrk_collection_id)?,409			)?;410411			<CollectionIndex<T>>::mutate(|n| *n += 1);412413			Self::deposit_event(Event::CollectionCreated {414				issuer: sender,415				collection_id: rmrk_collection_id,416			});417418			Ok(())419		}420421		/// Destroy a collection.422		///423		/// Only empty collections can be destroyed. If it has any tokens, they must be burned first.424		///425		/// # Permissions:426		/// * Collection issuer427		///428		/// # Arguments:429		/// - `origin`: sender of the transaction430		/// - `collection_id`: RMRK ID of the collection to destroy.431		#[pallet::weight(<SelfWeightOf<T>>::destroy_collection())]432		pub fn destroy_collection(433			origin: OriginFor<T>,434			collection_id: RmrkCollectionId,435		) -> DispatchResult {436			let sender = ensure_signed(origin)?;437			let cross_sender = T::CrossAccountId::from_sub(sender.clone());438439			let collection = Self::get_typed_nft_collection(440				Self::unique_collection_id(collection_id)?,441				misc::CollectionType::Regular,442			)?;443			collection.check_is_external()?;444445			<PalletNft<T>>::destroy_collection(collection, &cross_sender)446				.map_err(Self::map_unique_err_to_proxy)?;447448			Self::deposit_event(Event::CollectionDestroyed {449				issuer: sender,450				collection_id,451			});452453			Ok(())454		}455456		/// Change the issuer of a collection. Analogous to Unique's collection's [`owner`](up_data_structs::Collection).457		///458		/// # Permissions:459		/// * Collection issuer460		///461		/// # Arguments:462		/// - `origin`: sender of the transaction463		/// - `collection_id`: RMRK collection ID to change the issuer of.464		/// - `new_issuer`: Collection's new issuer.465		#[pallet::weight(<SelfWeightOf<T>>::change_collection_issuer())]466		pub fn change_collection_issuer(467			origin: OriginFor<T>,468			collection_id: RmrkCollectionId,469			new_issuer: <T::Lookup as StaticLookup>::Source,470		) -> DispatchResult {471			let sender = ensure_signed(origin)?;472473			let collection = Self::get_nft_collection(Self::unique_collection_id(collection_id)?)?;474			collection.check_is_external()?;475476			let new_issuer = T::Lookup::lookup(new_issuer)?;477478			Self::change_collection_owner(479				Self::unique_collection_id(collection_id)?,480				misc::CollectionType::Regular,481				sender.clone(),482				new_issuer.clone(),483			)?;484485			Self::deposit_event(Event::IssuerChanged {486				old_issuer: sender,487				new_issuer,488				collection_id,489			});490491			Ok(())492		}493494		/// "Lock" the collection and prevent new token creation. Cannot be undone.495		///496		/// # Permissions:497		/// * Collection issuer498		///499		/// # Arguments:500		/// - `origin`: sender of the transaction501		/// - `collection_id`: RMRK ID of the collection to lock.502		#[pallet::weight(<SelfWeightOf<T>>::lock_collection())]503		pub fn lock_collection(504			origin: OriginFor<T>,505			collection_id: RmrkCollectionId,506		) -> DispatchResult {507			let sender = ensure_signed(origin)?;508			let cross_sender = T::CrossAccountId::from_sub(sender.clone());509510			let collection = Self::get_typed_nft_collection(511				Self::unique_collection_id(collection_id)?,512				misc::CollectionType::Regular,513			)?;514			collection.check_is_external()?;515516			Self::check_collection_owner(&collection, &cross_sender)?;517518			let token_count = collection.total_supply();519520			let mut collection = collection.into_inner();521			collection.limits.token_limit = Some(token_count);522			collection.save()?;523524			Self::deposit_event(Event::CollectionLocked {525				issuer: sender,526				collection_id,527			});528529			Ok(())530		}531532		/// Mint an NFT in a specified collection.533		///534		/// # Permissions:535		/// * Collection issuer536		///537		/// # Arguments:538		/// - `origin`: sender of the transaction539		/// - `owner`: Owner account of the NFT. If set to None, defaults to the sender (collection issuer).540		/// - `collection_id`: RMRK collection ID for the NFT to be minted within. Cannot be changed.541		/// - `recipient`: Receiver account of the royalty. Has no effect if the `royalty_amount` is not set. Cannot be changed.542		/// - `royalty_amount`: Optional permillage reward from each trade for the `recipient`. Cannot be changed.543		/// - `metadata`: Arbitrary data about an NFT, e.g. IPFS hash. Cannot be changed.544		/// - `transferable`: Can this NFT be transferred? Cannot be changed.545		/// - `resources`: Resource data to be added to the NFT immediately after minting.546		#[pallet::weight(<SelfWeightOf<T>>::mint_nft(resources.as_ref().map(|r| r.len() as u32).unwrap_or(0)))]547		pub fn mint_nft(548			origin: OriginFor<T>,549			owner: Option<T::AccountId>,550			collection_id: RmrkCollectionId,551			recipient: Option<T::AccountId>,552			royalty_amount: Option<Permill>,553			metadata: RmrkString,554			transferable: bool,555			resources: Option<BoundedVec<RmrkResourceTypes, MaxResourcesOnMint>>,556		) -> DispatchResult {557			let sender = ensure_signed(origin)?;558			let cross_sender = T::CrossAccountId::from_sub(sender.clone());559560			let owner = owner.unwrap_or(sender.clone());561			let cross_owner = T::CrossAccountId::from_sub(owner.clone());562563			let collection = Self::get_typed_nft_collection(564				Self::unique_collection_id(collection_id)?,565				misc::CollectionType::Regular,566			)?;567			collection.check_is_external()?;568569			let royalty_info = royalty_amount.map(|amount| rmrk_traits::RoyaltyInfo {570				recipient: recipient.unwrap_or_else(|| owner.clone()),571				amount,572			});573574			let nft_id = Self::create_nft(575				&cross_sender,576				&cross_owner,577				&collection,578				[579					Self::encode_rmrk_property(TokenType, &NftType::Regular)?,580					Self::encode_rmrk_property(Transferable, &transferable)?,581					Self::encode_rmrk_property(PendingNftAccept, &None::<PendingTarget>)?,582					Self::encode_rmrk_property(RoyaltyInfo, &royalty_info)?,583					Self::encode_rmrk_property(Metadata, &metadata)?,584					Self::encode_rmrk_property(Equipped, &false)?,585					Self::encode_rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,586					Self::encode_rmrk_property(NextResourceId, &(0 as RmrkResourceId))?,587					Self::encode_rmrk_property(PendingChildren, &PendingChildrenSet::new())?,588					Self::encode_rmrk_property(AssociatedBases, &BasesMap::new())?,589				]590				.into_iter(),591			)592			.map_err(|err| match err {593				DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),594				err => Self::map_unique_err_to_proxy(err),595			})?;596597			if let Some(resources) = resources {598				for resource in resources {599					Self::resource_add(sender.clone(), collection.id, nft_id, resource)?;600				}601			}602603			Self::deposit_event(Event::NftMinted {604				owner,605				collection_id,606				nft_id: nft_id.0,607			});608609			Ok(())610		}611612		/// Burn an NFT, destroying it and its nested tokens up to the specified limit.613		/// If the burning budget is exceeded, the transaction is reverted.614		///615		/// This is the way to burn a nested token as well.616		///617		/// For more information, see [`burn_recursively`](pallet_nonfungible::pallet::Pallet::burn_recursively).618		///619		/// # Permissions:620		/// * Token owner621		///622		/// # Arguments:623		/// - `origin`: sender of the transaction624		/// - `collection_id`: RMRK ID of the collection in which the NFT to burn belongs to.625		/// - `nft_id`: ID of the NFT to be destroyed.626		/// - `max_burns`: Maximum number of tokens to burn, assuming nesting. The transaction627		/// is reverted if there are more tokens to burn in the nesting tree than this number.628		/// This is primarily a mechanism of transaction weight control.629		#[pallet::weight(<SelfWeightOf<T>>::burn_nft(*max_burns))]630		pub fn burn_nft(631			origin: OriginFor<T>,632			collection_id: RmrkCollectionId,633			nft_id: RmrkNftId,634			max_burns: u32,635		) -> DispatchResult {636			let sender = ensure_signed(origin)?;637			let cross_sender = T::CrossAccountId::from_sub(sender.clone());638639			let collection = Self::get_typed_nft_collection(640				Self::unique_collection_id(collection_id)?,641				misc::CollectionType::Regular,642			)?;643			collection.check_is_external()?;644645			Self::destroy_nft(646				cross_sender,647				Self::unique_collection_id(collection_id)?,648				nft_id.into(),649				max_burns,650				<Error<T>>::NoPermission,651			)652			.map_err(|err| Self::map_unique_err_to_proxy(err.error))?;653654			Self::deposit_event(Event::NFTBurned {655				owner: sender,656				nft_id,657			});658659			Ok(())660		}661662		/// Transfer an NFT from an account/NFT A to another account/NFT B.663		/// The token must be transferable. Nesting cannot occur deeper than the [`NESTING_BUDGET`].664		///665		/// If the target owner is an NFT owned by another account, then the NFT will enter666		/// the pending state and will have to be accepted by the other account.667		///668		/// # Permissions:669		/// - Token owner670		///671		/// # Arguments:672		/// - `origin`: sender of the transaction673		/// - `rmrk_collection_id`: RMRK ID of the collection of the NFT to be transferred.674		/// - `rmrk_nft_id`: ID of the NFT to be transferred.675		/// - `new_owner`: New owner of the nft which can be either an account or a NFT.676		#[pallet::weight(<SelfWeightOf<T>>::send())]677		pub fn send(678			origin: OriginFor<T>,679			rmrk_collection_id: RmrkCollectionId,680			rmrk_nft_id: RmrkNftId,681			new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,682		) -> DispatchResult {683			let sender = ensure_signed(origin.clone())?;684			let cross_sender = T::CrossAccountId::from_sub(sender.clone());685686			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;687			let nft_id = rmrk_nft_id.into();688689			let collection =690				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;691			collection.check_is_external()?;692693			let token_data =694				<TokenData<T>>::get((collection_id, nft_id)).ok_or(<Error<T>>::NoAvailableNftId)?;695696			let from = token_data.owner;697698			ensure!(699				Self::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Transferable)?,700				<Error<T>>::NonTransferable701			);702703			ensure!(704				Self::get_nft_property_decoded::<Option<PendingTarget>>(705					collection_id,706					nft_id,707					RmrkProperty::PendingNftAccept708				)?709				.is_none(),710				<Error<T>>::NoPermission711			);712713			let target_owner;714			let approval_required;715716			match new_owner {717				RmrkAccountIdOrCollectionNftTuple::AccountId(ref account_id) => {718					target_owner = T::CrossAccountId::from_sub(account_id.clone());719					approval_required = false;720				}721				RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(722					target_collection_id,723					target_nft_id,724				) => {725					let target_collection_id = Self::unique_collection_id(target_collection_id)?;726727					let target_nft_budget = budget::Value::new(NESTING_BUDGET);728729					let target_nft_owner = <PalletStructure<T>>::get_checked_topmost_owner(730						target_collection_id,731						target_nft_id.into(),732						Some((collection_id, nft_id)),733						&target_nft_budget,734					)735					.map_err(Self::map_unique_err_to_proxy)?;736737					approval_required = cross_sender != target_nft_owner;738739					if approval_required {740						target_owner = target_nft_owner;741742						<PalletNft<T>>::set_scoped_token_property(743							collection.id,744							nft_id,745							RMRK_SCOPE,746							Self::encode_rmrk_property::<Option<PendingTarget>>(747								PendingNftAccept,748								&Some((target_collection_id, target_nft_id.into())),749							)?,750						)?;751752						Self::insert_pending_child(753							(target_collection_id, target_nft_id.into()),754							(rmrk_collection_id, rmrk_nft_id),755						)?;756					} else {757						target_owner = T::CrossTokenAddressMapping::token_to_address(758							target_collection_id,759							target_nft_id.into(),760						);761					}762				}763			}764765			let src_nft_budget = budget::Value::new(NESTING_BUDGET);766767			<PalletNft<T>>::transfer_from(768				&collection,769				&cross_sender,770				&from,771				&target_owner,772				nft_id,773				&src_nft_budget,774			)775			.map_err(Self::map_unique_err_to_proxy)?;776777			Self::deposit_event(Event::NFTSent {778				sender,779				recipient: new_owner,780				collection_id: rmrk_collection_id,781				nft_id: rmrk_nft_id,782				approval_required,783			});784785			Ok(())786		}787788		/// Accept an NFT sent from another account to self or an owned NFT.789		///790		/// The NFT in question must be pending, and, thus, be [sent](`Pallet::send`) first.791		///792		/// # Permissions:793		/// - Token-owner-to-be794		///795		/// # Arguments:796		/// - `origin`: sender of the transaction797		/// - `rmrk_collection_id`: RMRK collection ID of the NFT to be accepted.798		/// - `rmrk_nft_id`: ID of the NFT to be accepted.799		/// - `new_owner`: Either the sender's account ID or a sender-owned NFT,800		/// whichever the accepted NFT was sent to.801		#[pallet::weight(<SelfWeightOf<T>>::accept_nft())]802		pub fn accept_nft(803			origin: OriginFor<T>,804			rmrk_collection_id: RmrkCollectionId,805			rmrk_nft_id: RmrkNftId,806			new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,807		) -> DispatchResult {808			let sender = ensure_signed(origin.clone())?;809			let cross_sender = T::CrossAccountId::from_sub(sender.clone());810811			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;812			let nft_id = rmrk_nft_id.into();813814			let collection =815				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;816			collection.check_is_external()?;817818			let new_cross_owner = match new_owner {819				RmrkAccountIdOrCollectionNftTuple::AccountId(ref account_id) => {820					T::CrossAccountId::from_sub(account_id.clone())821				}822				RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(823					target_collection_id,824					target_nft_id,825				) => {826					let target_collection_id = Self::unique_collection_id(target_collection_id)?;827828					T::CrossTokenAddressMapping::token_to_address(829						target_collection_id,830						TokenId(target_nft_id),831					)832				}833			};834835			let budget = budget::Value::new(NESTING_BUDGET);836837			<PalletNft<T>>::transfer(838				&collection,839				&cross_sender,840				&new_cross_owner,841				nft_id,842				&budget,843			)844			.map_err(|err| {845				if err == <CommonError<T>>::UserIsNotAllowedToNest.into() {846					<Error<T>>::CannotAcceptNonOwnedNft.into()847				} else {848					Self::map_unique_err_to_proxy(err)849				}850			})?;851852			let pending_target = Self::get_nft_property_decoded::<Option<PendingTarget>>(853				collection_id,854				nft_id,855				RmrkProperty::PendingNftAccept,856			)?;857858			if let Some(pending_target) = pending_target {859				Self::remove_pending_child(pending_target, (rmrk_collection_id, rmrk_nft_id))?;860861				<PalletNft<T>>::set_scoped_token_property(862					collection.id,863					nft_id,864					RMRK_SCOPE,865					Self::encode_rmrk_property(PendingNftAccept, &None::<PendingTarget>)?,866				)?;867			}868869			Self::deposit_event(Event::NFTAccepted {870				sender,871				recipient: new_owner,872				collection_id: rmrk_collection_id,873				nft_id: rmrk_nft_id,874			});875876			Ok(())877		}878879		/// Reject an NFT sent from another account to self or owned NFT.880		/// The NFT in question will not be sent back and burnt instead.881		///882		/// The NFT in question must be pending, and, thus, be [sent](`Pallet::send`) first.883		///884		/// # Permissions:885		/// - Token-owner-to-be-not886		///887		/// # Arguments:888		/// - `origin`: sender of the transaction889		/// - `rmrk_collection_id`: RMRK ID of the NFT to be rejected.890		/// - `rmrk_nft_id`: ID of the NFT to be rejected.891		#[pallet::weight(<SelfWeightOf<T>>::reject_nft())]892		pub fn reject_nft(893			origin: OriginFor<T>,894			rmrk_collection_id: RmrkCollectionId,895			rmrk_nft_id: RmrkNftId,896		) -> DispatchResult {897			let sender = ensure_signed(origin)?;898			let cross_sender = T::CrossAccountId::from_sub(sender.clone());899900			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;901			let nft_id = rmrk_nft_id.into();902903			let collection =904				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;905			collection.check_is_external()?;906907			ensure!(908				<TokenData<T>>::get((collection_id, nft_id)).is_some(),909				<Error<T>>::NoAvailableNftId910			);911912			let pending_target = Self::get_nft_property_decoded::<Option<PendingTarget>>(913				collection_id,914				nft_id,915				RmrkProperty::PendingNftAccept,916			)?;917918			match pending_target {919				Some(pending_target) => {920					Self::remove_pending_child(pending_target, (rmrk_collection_id, rmrk_nft_id))?921				}922				None => return Err(<Error<T>>::CannotRejectNonPendingNft.into()),923			}924925			Self::destroy_nft(926				cross_sender,927				collection_id,928				nft_id,929				NESTING_BUDGET,930				<Error<T>>::CannotRejectNonOwnedNft,931			)932			.map_err(|err| Self::map_unique_err_to_proxy(err.error))?;933934			Self::deposit_event(Event::NFTRejected {935				sender,936				collection_id: rmrk_collection_id,937				nft_id: rmrk_nft_id,938			});939940			Ok(())941		}942943		/// Accept the addition of a newly created pending resource to an existing NFT.944		///945		/// This transaction is needed when a resource is created and assigned to an NFT946		/// by a non-owner, i.e. the collection issuer, with one of the947		/// [`add_...` transactions](Pallet::add_basic_resource).948		///949		/// # Permissions:950		/// - Token owner951		///952		/// # Arguments:953		/// - `origin`: sender of the transaction954		/// - `rmrk_collection_id`: RMRK collection ID of the NFT.955		/// - `rmrk_nft_id`: ID of the NFT with a pending resource to be accepted.956		/// - `resource_id`: ID of the newly created pending resource.957		/// accept the addition of a new resource to an existing NFT958		#[pallet::weight(<SelfWeightOf<T>>::accept_resource())]959		pub fn accept_resource(960			origin: OriginFor<T>,961			rmrk_collection_id: RmrkCollectionId,962			rmrk_nft_id: RmrkNftId,963			resource_id: RmrkResourceId,964		) -> DispatchResult {965			let sender = ensure_signed(origin)?;966			let cross_sender = T::CrossAccountId::from_sub(sender);967968			let collection_id = Self::unique_collection_id(rmrk_collection_id)969				.map_err(|_| <Error<T>>::ResourceDoesntExist)?;970			let collection =971				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;972			collection.check_is_external()?;973974			let nft_id = rmrk_nft_id.into();975976			let budget = budget::Value::new(NESTING_BUDGET);977978			let nft_owner =979				<PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)980					.map_err(|_| <Error<T>>::ResourceDoesntExist)?;981982			Self::try_mutate_resource_info(collection_id, nft_id, resource_id, |res| {983				ensure!(res.pending, <Error<T>>::ResourceNotPending);984				ensure!(cross_sender == nft_owner, <Error<T>>::NoPermission);985986				res.pending = false;987988				Ok(())989			})?;990991			Self::deposit_event(Event::<T>::ResourceAccepted {992				nft_id: rmrk_nft_id,993				resource_id,994			});995996			Ok(())997		}998999		/// Accept the removal of a removal-pending resource from an NFT.1000		///1001		/// This transaction is needed when a non-owner, i.e. the collection issuer,1002		/// requests a [removal](`Pallet::remove_resource`) of a resource from an NFT.1003		///1004		/// # Permissions:1005		/// - Token owner1006		///1007		/// # Arguments:1008		/// - `origin`: sender of the transaction1009		/// - `rmrk_collection_id`: RMRK collection ID of the NFT.1010		/// - `rmrk_nft_id`: ID of the NFT with a resource to be removed.1011		/// - `resource_id`: ID of the removal-pending resource.1012		#[pallet::weight(<SelfWeightOf<T>>::accept_resource_removal())]1013		pub fn accept_resource_removal(1014			origin: OriginFor<T>,1015			rmrk_collection_id: RmrkCollectionId,1016			rmrk_nft_id: RmrkNftId,1017			resource_id: RmrkResourceId,1018		) -> DispatchResult {1019			let sender = ensure_signed(origin)?;1020			let cross_sender = T::CrossAccountId::from_sub(sender);10211022			let collection_id = Self::unique_collection_id(rmrk_collection_id)1023				.map_err(|_| <Error<T>>::ResourceDoesntExist)?;1024			let collection =1025				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1026			collection.check_is_external()?;10271028			let nft_id = rmrk_nft_id.into();10291030			let budget = budget::Value::new(NESTING_BUDGET);10311032			let nft_owner =1033				<PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)1034					.map_err(|_| <Error<T>>::ResourceDoesntExist)?;10351036			ensure!(cross_sender == nft_owner, <Error<T>>::NoPermission);10371038			let resource_id_key = Self::get_scoped_property_key(ResourceId(resource_id))?;10391040			let resource_info = <PalletNft<T>>::token_aux_property((1041				collection_id,1042				nft_id,1043				RMRK_SCOPE,1044				resource_id_key.clone(),1045			))1046			.ok_or(<Error<T>>::ResourceDoesntExist)?;10471048			let resource_info: RmrkResourceInfo = Self::decode_property_value(&resource_info)?;10491050			ensure!(1051				resource_info.pending_removal,1052				<Error<T>>::ResourceNotPending1053			);10541055			<PalletNft<T>>::remove_token_aux_property(1056				collection_id,1057				nft_id,1058				RMRK_SCOPE,1059				resource_id_key,1060			);10611062			if let RmrkResourceTypes::Composable(resource) = resource_info.resource {1063				let base_id = resource.base;10641065				Self::remove_associated_base_id(collection_id, nft_id, base_id)?;1066			}10671068			Self::deposit_event(Event::<T>::ResourceRemovalAccepted {1069				nft_id: rmrk_nft_id,1070				resource_id,1071			});10721073			Ok(())1074		}10751076		/// Add or edit a custom user property, a key-value pair, describing the metadata1077		/// of a token or a collection, on either one of these.1078		///1079		/// Note that in this proxy implementation many details regarding RMRK are stored1080		/// as scoped properties prefixed with "rmrk:", normally inaccessible1081		/// to external transactions and RPCs.1082		///1083		/// # Permissions:1084		/// - Collection issuer - in case of collection property1085		/// - Token owner - in case of NFT property1086		///1087		/// # Arguments:1088		/// - `origin`: sender of the transaction1089		/// - `rmrk_collection_id`: RMRK collection ID.1090		/// - `maybe_nft_id`: Optional ID of the NFT. If left empty, then the property is set for the collection.1091		/// - `key`: Key of the custom property to be referenced by.1092		/// - `value`: Value of the custom property to be stored.1093		#[pallet::weight(<SelfWeightOf<T>>::set_property())]1094		pub fn set_property(1095			origin: OriginFor<T>,1096			#[pallet::compact] rmrk_collection_id: RmrkCollectionId,1097			maybe_nft_id: Option<RmrkNftId>,1098			key: RmrkKeyString,1099			value: RmrkValueString,1100		) -> DispatchResult {1101			let sender = ensure_signed(origin)?;1102			let sender = T::CrossAccountId::from_sub(sender);11031104			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;1105			let collection =1106				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1107			collection.check_is_external()?;11081109			let budget = budget::Value::new(NESTING_BUDGET);11101111			match maybe_nft_id {1112				Some(nft_id) => {1113					let token_id: TokenId = nft_id.into();11141115					Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;1116					Self::ensure_nft_owner(collection_id, token_id, &sender, &budget)?;11171118					<PalletNft<T>>::set_scoped_token_property(1119						collection_id,1120						token_id,1121						RMRK_SCOPE,1122						Self::encode_rmrk_property(UserProperty(key.as_slice()), &value)?,1123					)?;1124				}1125				None => {1126					let collection = Self::get_typed_nft_collection(1127						collection_id,1128						misc::CollectionType::Regular,1129					)?;11301131					Self::check_collection_owner(&collection, &sender)?;11321133					<PalletCommon<T>>::set_scoped_collection_property(1134						collection_id,1135						RMRK_SCOPE,1136						Self::encode_rmrk_property(UserProperty(key.as_slice()), &value)?,1137					)?;1138				}1139			}11401141			Self::deposit_event(Event::PropertySet {1142				collection_id: rmrk_collection_id,1143				maybe_nft_id,1144				key,1145				value,1146			});11471148			Ok(())1149		}11501151		/// Set a different order of resource priorities for an NFT. Priorities can be used,1152		/// for example, for order of rendering.1153		///1154		/// Note that the priorities are not updated automatically, and are an empty vector1155		/// by default. There is no pre-set definition for the order to be particular,1156		/// it can be interpreted arbitrarily use-case by use-case.1157		///1158		/// # Permissions:1159		/// - Token owner1160		///1161		/// # Arguments:1162		/// - `origin`: sender of the transaction1163		/// - `rmrk_collection_id`: RMRK collection ID of the NFT.1164		/// - `rmrk_nft_id`: ID of the NFT to rearrange resource priorities for.1165		/// - `priorities`: Ordered vector of resource IDs.1166		#[pallet::weight(<SelfWeightOf<T>>::set_priority())]1167		pub fn set_priority(1168			origin: OriginFor<T>,1169			rmrk_collection_id: RmrkCollectionId,1170			rmrk_nft_id: RmrkNftId,1171			priorities: BoundedVec<RmrkResourceId, RmrkMaxPriorities>,1172		) -> DispatchResult {1173			let sender = ensure_signed(origin)?;1174			let sender = T::CrossAccountId::from_sub(sender);11751176			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;1177			let nft_id = rmrk_nft_id.into();11781179			let collection =1180				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1181			collection.check_is_external()?;11821183			let budget = budget::Value::new(NESTING_BUDGET);11841185			Self::ensure_nft_type(collection_id, nft_id, NftType::Regular)?;1186			Self::ensure_nft_owner(collection_id, nft_id, &sender, &budget)?;11871188			<PalletNft<T>>::set_scoped_token_property(1189				collection_id,1190				nft_id,1191				RMRK_SCOPE,1192				Self::encode_rmrk_property(ResourcePriorities, &priorities.into_inner())?,1193			)?;11941195			Self::deposit_event(Event::<T>::PrioritySet {1196				collection_id: rmrk_collection_id,1197				nft_id: rmrk_nft_id,1198			});11991200			Ok(())1201		}12021203		/// Create and set/propose a basic resource for an NFT.1204		///1205		/// A basic resource is the simplest, lacking a Base and anything that comes with it.1206		/// See RMRK docs for more information and examples.1207		///1208		/// # Permissions:1209		/// - Collection issuer - if not the token owner, adding the resource will warrant1210		/// the owner's [acceptance](Pallet::accept_resource).1211		///1212		/// # Arguments:1213		/// - `origin`: sender of the transaction1214		/// - `rmrk_collection_id`: RMRK collection ID of the NFT.1215		/// - `nft_id`: ID of the NFT to assign a resource to.1216		/// - `resource`: Data of the resource to be created.1217		#[pallet::weight(<SelfWeightOf<T>>::add_basic_resource())]1218		pub fn add_basic_resource(1219			origin: OriginFor<T>,1220			rmrk_collection_id: RmrkCollectionId,1221			nft_id: RmrkNftId,1222			resource: RmrkBasicResource,1223		) -> DispatchResult {1224			let sender = ensure_signed(origin.clone())?;12251226			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;1227			let collection =1228				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1229			collection.check_is_external()?;12301231			let resource_id = Self::resource_add(1232				sender,1233				collection_id,1234				nft_id.into(),1235				RmrkResourceTypes::Basic(resource),1236			)?;12371238			Self::deposit_event(Event::ResourceAdded {1239				nft_id,1240				resource_id,1241			});1242			Ok(())1243		}12441245		/// Create and set/propose a composable resource for an NFT.1246		///1247		/// A composable resource links to a Base and has a subset of its Parts it is composed of.1248		/// See RMRK docs for more information and examples.1249		///1250		/// # Permissions:1251		/// - Collection issuer - if not the token owner, adding the resource will warrant1252		/// the owner's [acceptance](Pallet::accept_resource).1253		///1254		/// # Arguments:1255		/// - `origin`: sender of the transaction1256		/// - `rmrk_collection_id`: RMRK collection ID of the NFT.1257		/// - `nft_id`: ID of the NFT to assign a resource to.1258		/// - `resource`: Data of the resource to be created.1259		#[pallet::weight(<SelfWeightOf<T>>::add_composable_resource())]1260		pub fn add_composable_resource(1261			origin: OriginFor<T>,1262			rmrk_collection_id: RmrkCollectionId,1263			nft_id: RmrkNftId,1264			resource: RmrkComposableResource,1265		) -> DispatchResult {1266			let sender = ensure_signed(origin.clone())?;12671268			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;1269			let collection =1270				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1271			collection.check_is_external()?;12721273			let base_id = resource.base;12741275			let resource_id = Self::resource_add(1276				sender,1277				collection_id,1278				nft_id.into(),1279				RmrkResourceTypes::Composable(resource),1280			)?;12811282			<PalletNft<T>>::try_mutate_token_aux_property(1283				collection_id,1284				nft_id.into(),1285				RMRK_SCOPE,1286				Self::get_scoped_property_key(AssociatedBases)?,1287				|value| -> DispatchResult {1288					let mut bases: BasesMap = match value {1289						Some(value) => Self::decode_property_value(value)?,1290						None => BasesMap::new(),1291					};12921293					*bases.entry(base_id).or_insert(0) += 1;12941295					*value = Some(Self::encode_property_value(&bases)?);1296					Ok(())1297				},1298			)?;12991300			Self::deposit_event(Event::ResourceAdded {1301				nft_id,1302				resource_id,1303			});1304			Ok(())1305		}13061307		/// Create and set/propose a slot resource for an NFT.1308		///1309		/// A slot resource links to a Base and a slot ID in it which it can fit into.1310		/// See RMRK docs for more information and examples.1311		///1312		/// # Permissions:1313		/// - Collection issuer - if not the token owner, adding the resource will warrant1314		/// the owner's [acceptance](Pallet::accept_resource).1315		///1316		/// # Arguments:1317		/// - `origin`: sender of the transaction1318		/// - `rmrk_collection_id`: RMRK collection ID of the NFT.1319		/// - `nft_id`: ID of the NFT to assign a resource to.1320		/// - `resource`: Data of the resource to be created.1321		#[pallet::weight(<SelfWeightOf<T>>::add_slot_resource())]1322		pub fn add_slot_resource(1323			origin: OriginFor<T>,1324			rmrk_collection_id: RmrkCollectionId,1325			nft_id: RmrkNftId,1326			resource: RmrkSlotResource,1327		) -> DispatchResult {1328			let sender = ensure_signed(origin.clone())?;13291330			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;1331			let collection =1332				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1333			collection.check_is_external()?;13341335			let resource_id = Self::resource_add(1336				sender,1337				collection_id,1338				nft_id.into(),1339				RmrkResourceTypes::Slot(resource),1340			)?;13411342			Self::deposit_event(Event::ResourceAdded {1343				nft_id,1344				resource_id,1345			});1346			Ok(())1347		}13481349		/// Remove and erase a resource from an NFT.1350		///1351		/// If the sender does not own the NFT, then it will be pending confirmation,1352		/// and will have to be [accepted](Pallet::accept_resource_removal) by the token owner.1353		///1354		/// # Permissions1355		/// - Collection issuer1356		///1357		/// # Arguments1358		/// - `origin`: sender of the transaction1359		/// - `rmrk_collection_id`: RMRK ID of a collection to which the NFT making use of the resource belongs to.1360		/// - `nft_id`: ID of the NFT with a resource to be removed.1361		/// - `resource_id`: ID of the resource to be removed.1362		#[pallet::weight(<SelfWeightOf<T>>::remove_resource())]1363		pub fn remove_resource(1364			origin: OriginFor<T>,1365			rmrk_collection_id: RmrkCollectionId,1366			nft_id: RmrkNftId,1367			resource_id: RmrkResourceId,1368		) -> DispatchResult {1369			let sender = ensure_signed(origin.clone())?;13701371			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;1372			let collection =1373				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1374			collection.check_is_external()?;13751376			Self::resource_remove(sender, collection_id, nft_id.into(), resource_id)?;13771378			Self::deposit_event(Event::ResourceRemoval {1379				nft_id,1380				resource_id,1381			});1382			Ok(())1383		}1384	}1385}13861387impl<T: Config> Pallet<T> {1388	/// Transform one of possible RMRK keys into a byte key with a RMRK scope.1389	pub fn get_scoped_property_key(rmrk_key: RmrkProperty) -> Result<PropertyKey, DispatchError> {1390		let key = rmrk_key.to_key::<T>()?;13911392		let scoped_key = RMRK_SCOPE1393			.apply(key)1394			.map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)?;13951396		Ok(scoped_key)1397	}13981399	/// Form a Unique property, transforming a RMRK key into bytes (without assigning the scope yet)1400	/// and encoding the value from an arbitrary type into bytes.1401	pub fn encode_rmrk_property<E: Encode>(1402		rmrk_key: RmrkProperty,1403		value: &E,1404	) -> Result<Property, DispatchError> {1405		let key = rmrk_key.to_key::<T>()?;14061407		let value = Self::encode_property_value(value)?;14081409		let property = Property { key, value };14101411		Ok(property)1412	}14131414	/// Encode property value from an arbitrary type into bytes for storage.1415	pub fn encode_property_value<E: Encode, S: Get<u32>>(1416		value: &E,1417	) -> Result<BoundedBytes<S>, DispatchError> {1418		let value = value1419			.encode()1420			.try_into()1421			.map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong)?;14221423		Ok(value)1424	}14251426	/// Decode property value from bytes into an arbitrary type.1427	pub fn decode_property_value<D: Decode, S: Get<u32>>(1428		vec: &BoundedBytes<S>,1429	) -> Result<D, DispatchError> {1430		vec.decode()1431			.map_err(|_| <Error<T>>::UnableToDecodeRmrkData.into())1432	}14331434	/// Change the limit of a property value byte vector.1435	pub fn rebind<L, S>(vec: &BoundedVec<u8, L>) -> Result<BoundedVec<u8, S>, DispatchError>1436	where1437		BoundedVec<u8, S>: TryFrom<Vec<u8>>,1438	{1439		vec.rebind()1440			.map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong.into())1441	}14421443	/// Initialize a new NFT collection with certain RMRK-scoped properties.1444	///1445	/// See [`init_collection`](pallet_nonfungible::pallet::Pallet::init_collection) for more details.1446	fn init_collection(1447		sender: T::CrossAccountId,1448		data: CreateCollectionData<T::AccountId>,1449		properties: impl Iterator<Item = Property>,1450	) -> Result<CollectionId, DispatchError> {1451		let collection_id = <PalletNft<T>>::init_collection(1452			sender.clone(),1453			sender,1454			data,1455			up_data_structs::CollectionFlags {1456				external: true,1457				..Default::default()1458			},1459		);14601461		if let Err(DispatchError::Arithmetic(_)) = &collection_id {1462			return Err(<Error<T>>::NoAvailableCollectionId.into());1463		}14641465		<PalletCommon<T>>::set_scoped_collection_properties(1466			collection_id?,1467			RMRK_SCOPE,1468			properties,1469		)?;14701471		collection_id1472	}14731474	/// Mint a new NFT with certain RMRK-scoped properties. Sender must be the collection owner.1475	///1476	/// See [`create_item`](pallet_nonfungible::pallet::Pallet::create_item) for more details.1477	pub fn create_nft(1478		sender: &T::CrossAccountId,1479		owner: &T::CrossAccountId,1480		collection: &NonfungibleHandle<T>,1481		properties: impl Iterator<Item = Property>,1482	) -> Result<TokenId, DispatchError> {1483		let data = CreateNftExData {1484			properties: BoundedVec::default(),1485			owner: owner.clone(),1486		};14871488		let budget = budget::Value::new(NESTING_BUDGET);14891490		<PalletNft<T>>::create_item(collection, sender, data, &budget)?;14911492		let nft_id = <PalletNft<T>>::current_token_id(collection.id);14931494		<PalletNft<T>>::set_scoped_token_properties(collection.id, nft_id, RMRK_SCOPE, properties)?;14951496		Ok(nft_id)1497	}14981499	/// Burn an NFT, along with its nested children, limited by `max_burns`. The sender must be the token owner.1500	///1501	/// See [`burn_recursively`](pallet_nonfungible::pallet::Pallet::burn_recursively) for more details.1502	fn destroy_nft(1503		sender: T::CrossAccountId,1504		collection_id: CollectionId,1505		token_id: TokenId,1506		max_burns: u32,1507		error_if_not_owned: Error<T>,1508	) -> DispatchResultWithPostInfo {1509		let collection =1510			Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;15111512		let token_data =1513			<TokenData<T>>::get((collection_id, token_id)).ok_or(<Error<T>>::NoAvailableNftId)?;15141515		let from = token_data.owner;15161517		let owner_check_budget = budget::Value::new(NESTING_BUDGET);15181519		ensure!(1520			<PalletStructure<T>>::check_indirectly_owned(1521				sender.clone(),1522				collection_id,1523				token_id,1524				None,1525				&owner_check_budget1526			)?,1527			error_if_not_owned,1528		);15291530		let burns_budget = budget::Value::new(max_burns);1531		let breadth_budget = budget::Value::new(max_burns);15321533		<PalletNft<T>>::burn_recursively(1534			&collection,1535			&from,1536			token_id,1537			&burns_budget,1538			&breadth_budget,1539		)1540	}15411542	/// Add a sent token pending acceptance to the target owning token as a property.1543	fn insert_pending_child(1544		target: (CollectionId, TokenId),1545		child: (RmrkCollectionId, RmrkNftId),1546	) -> DispatchResult {1547		Self::mutate_pending_children(target, |pending_children| {1548			pending_children.insert(child);1549		})1550	}15511552	/// Remove a sent token pending acceptance from the target token's properties.1553	fn remove_pending_child(1554		target: (CollectionId, TokenId),1555		child: (RmrkCollectionId, RmrkNftId),1556	) -> DispatchResult {1557		Self::mutate_pending_children(target, |pending_children| {1558			pending_children.remove(&child);1559		})1560	}15611562	/// Apply a mutation to the property of a token containing sent tokens1563	/// that are currently pending acceptance.1564	fn mutate_pending_children(1565		(target_collection_id, target_nft_id): (CollectionId, TokenId),1566		f: impl FnOnce(&mut PendingChildrenSet),1567	) -> DispatchResult {1568		<PalletNft<T>>::try_mutate_token_aux_property(1569			target_collection_id,1570			target_nft_id,1571			RMRK_SCOPE,1572			Self::get_scoped_property_key(PendingChildren)?,1573			|pending_children| -> DispatchResult {1574				let mut map = match pending_children {1575					Some(map) => Self::decode_property_value(map)?,1576					None => PendingChildrenSet::new(),1577				};15781579				f(&mut map);15801581				*pending_children = Some(Self::encode_property_value(&map)?);15821583				Ok(())1584			},1585		)1586	}15871588	/// Get an iterator from a token's property containing tokens sent to it1589	/// that are currently pending acceptance.1590	fn iterate_pending_children(1591		collection_id: CollectionId,1592		nft_id: TokenId,1593	) -> Result<impl Iterator<Item = PendingChild>, DispatchError> {1594		let property = <PalletNft<T>>::token_aux_property((1595			collection_id,1596			nft_id,1597			RMRK_SCOPE,1598			Self::get_scoped_property_key(PendingChildren)?,1599		));16001601		let pending_children = match property {1602			Some(map) => Self::decode_property_value(&map)?,1603			None => PendingChildrenSet::new(),1604		};16051606		Ok(pending_children.into_iter())1607	}16081609	/// Get incremented resource ID from within an NFT's properties and store the new latest ID.1610	/// Thus, the returned resource ID should be used.1611	///1612	/// Resource IDs are unique only across an NFT.1613	fn acquire_next_resource_id(1614		collection_id: CollectionId,1615		nft_id: TokenId,1616	) -> Result<RmrkResourceId, DispatchError> {1617		let resource_id: RmrkResourceId =1618			Self::get_nft_property_decoded(collection_id, nft_id, NextResourceId)?;16191620		let next_id = resource_id1621			.checked_add(1)1622			.ok_or(<Error<T>>::NoAvailableResourceId)?;16231624		<PalletNft<T>>::set_scoped_token_property(1625			collection_id,1626			nft_id,1627			RMRK_SCOPE,1628			Self::encode_rmrk_property(NextResourceId, &next_id)?,1629		)?;16301631		Ok(resource_id)1632	}16331634	/// Create and add a resource for a regular NFT, mark it as pending if the sender1635	/// is not the token owner. The sender must be the collection owner.1636	fn resource_add(1637		sender: T::AccountId,1638		collection_id: CollectionId,1639		nft_id: TokenId,1640		resource: RmrkResourceTypes,1641	) -> Result<RmrkResourceId, DispatchError> {1642		let collection =1643			Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1644		ensure!(collection.owner == sender, Error::<T>::NoPermission);16451646		let sender = T::CrossAccountId::from_sub(sender);1647		let budget = budget::Value::new(NESTING_BUDGET);16481649		let nft_owner = <PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)1650			.map_err(Self::map_unique_err_to_proxy)?;16511652		let pending = sender != nft_owner;16531654		let id = Self::acquire_next_resource_id(collection_id, nft_id)?;16551656		let resource_info = RmrkResourceInfo {1657			id,1658			resource,1659			pending,1660			pending_removal: false,1661		};16621663		<PalletNft<T>>::try_mutate_token_aux_property(1664			collection_id,1665			nft_id,1666			RMRK_SCOPE,1667			Self::get_scoped_property_key(ResourceId(id))?,1668			|value| -> DispatchResult {1669				*value = Some(Self::encode_property_value(&resource_info)?);16701671				Ok(())1672			},1673		)?;16741675		Ok(id)1676	}16771678	/// Designate a resource for erasure from an NFT, and remove it if the sender is the token owner.1679	/// The sender must be the collection owner.1680	fn resource_remove(1681		sender: T::AccountId,1682		collection_id: CollectionId,1683		nft_id: TokenId,1684		resource_id: RmrkResourceId,1685	) -> DispatchResult {1686		let collection =1687			Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1688		ensure!(collection.owner == sender, Error::<T>::NoPermission);16891690		let resource_id_key = Self::get_scoped_property_key(ResourceId(resource_id))?;16911692		let resource = <PalletNft<T>>::token_aux_property((1693			collection_id,1694			nft_id,1695			RMRK_SCOPE,1696			resource_id_key.clone(),1697		))1698		.ok_or(<Error<T>>::ResourceDoesntExist)?;16991700		let resource_info: RmrkResourceInfo = Self::decode_property_value(&resource)?;17011702		let budget = up_data_structs::budget::Value::new(NESTING_BUDGET);1703		let topmost_owner =1704			<PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)?;17051706		let sender = T::CrossAccountId::from_sub(sender);1707		if topmost_owner == sender {1708			<PalletNft<T>>::remove_token_aux_property(1709				collection_id,1710				nft_id,1711				RMRK_SCOPE,1712				Self::get_scoped_property_key(ResourceId(resource_id))?,1713			);17141715			if let RmrkResourceTypes::Composable(resource) = resource_info.resource {1716				let base_id = resource.base;17171718				Self::remove_associated_base_id(collection_id, nft_id, base_id)?;1719			}1720		} else {1721			Self::try_mutate_resource_info(collection_id, nft_id, resource_id, |res| {1722				res.pending_removal = true;17231724				Ok(())1725			})?;1726		}17271728		Ok(())1729	}17301731	/// Remove a Base ID from an NFT if they are associated.1732	/// The Base itself is deleted if the number of associated NFTs reaches 0.1733	fn remove_associated_base_id(1734		collection_id: CollectionId,1735		nft_id: TokenId,1736		base_id: RmrkBaseId,1737	) -> DispatchResult {1738		<PalletNft<T>>::try_mutate_token_aux_property(1739			collection_id,1740			nft_id,1741			RMRK_SCOPE,1742			Self::get_scoped_property_key(AssociatedBases)?,1743			|value| -> DispatchResult {1744				let mut bases: BasesMap = match value {1745					Some(value) => Self::decode_property_value(value)?,1746					None => BasesMap::new(),1747				};17481749				let remaining = bases.get(&base_id);17501751				if let Some(remaining) = remaining {1752					if let Some(0) | None = remaining.checked_sub(1) {1753						bases.remove(&base_id);1754					}1755				}17561757				*value = Some(Self::encode_property_value(&bases)?);1758				Ok(())1759			},1760		)1761	}17621763	/// Apply a mutation to a resource stored in the token properties of an NFT.1764	fn try_mutate_resource_info(1765		collection_id: CollectionId,1766		nft_id: TokenId,1767		resource_id: RmrkResourceId,1768		f: impl FnOnce(&mut RmrkResourceInfo) -> DispatchResult,1769	) -> DispatchResult {1770		<PalletNft<T>>::try_mutate_token_aux_property(1771			collection_id,1772			nft_id,1773			RMRK_SCOPE,1774			Self::get_scoped_property_key(ResourceId(resource_id))?,1775			|value| match value {1776				Some(value) => {1777					let mut resource_info: RmrkResourceInfo = Self::decode_property_value(value)?;17781779					f(&mut resource_info)?;17801781					*value = Self::encode_property_value(&resource_info)?;17821783					Ok(())1784				}1785				None => Err(<Error<T>>::ResourceDoesntExist.into()),1786			},1787		)1788	}17891790	/// Change the owner of an NFT collection, ensuring that the sender is the current owner.1791	fn change_collection_owner(1792		collection_id: CollectionId,1793		collection_type: misc::CollectionType,1794		sender: T::AccountId,1795		new_owner: T::AccountId,1796	) -> DispatchResult {1797		let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;1798		Self::check_collection_owner(&collection, &T::CrossAccountId::from_sub(sender))?;17991800		let mut collection = collection.into_inner();18011802		collection.owner = new_owner;1803		collection.save()1804	}18051806	/// Ensure that an account is the collection owner/issuer, return an error if not.1807	pub fn check_collection_owner(1808		collection: &NonfungibleHandle<T>,1809		account: &T::CrossAccountId,1810	) -> DispatchResult {1811		collection1812			.check_is_owner(account)1813			.map_err(Self::map_unique_err_to_proxy)1814	}18151816	/// Get the latest yet-unused RMRK collection index from the storage.1817	pub fn last_collection_idx() -> RmrkCollectionId {1818		<CollectionIndex<T>>::get()1819	}18201821	/// Get a mapping from a RMRK collection ID to its corresponding Unique collection ID.1822	pub fn unique_collection_id(1823		rmrk_collection_id: RmrkCollectionId,1824	) -> Result<CollectionId, DispatchError> {1825		<UniqueCollectionId<T>>::try_get(rmrk_collection_id)1826			.map_err(|_| <Error<T>>::CollectionUnknown.into())1827	}18281829	/// Get a mapping from a Unique collection ID to its RMRK collection ID counterpart, if it exists.1830	pub fn rmrk_collection_id(1831		unique_collection_id: CollectionId,1832	) -> Result<RmrkCollectionId, DispatchError> {1833		Self::get_collection_property_decoded(unique_collection_id, RmrkInternalCollectionId)1834	}18351836	/// Fetch a Unique NFT collection.1837	pub fn get_nft_collection(1838		collection_id: CollectionId,1839	) -> Result<NonfungibleHandle<T>, DispatchError> {1840		let collection = <CollectionHandle<T>>::try_get(collection_id)1841			.map_err(|_| <Error<T>>::CollectionUnknown)?;18421843		match collection.mode {1844			CollectionMode::NFT => Ok(NonfungibleHandle::cast(collection)),1845			_ => Err(<Error<T>>::CollectionUnknown.into()),1846		}1847	}18481849	/// Check if an NFT collection with such an ID exists.1850	pub fn collection_exists(collection_id: CollectionId) -> bool {1851		<CollectionHandle<T>>::try_get(collection_id).is_ok()1852	}18531854	/// Fetch and decode a RMRK-scoped collection property value in bytes.1855	pub fn get_collection_property(1856		collection_id: CollectionId,1857		key: RmrkProperty,1858	) -> Result<PropertyValue, DispatchError> {1859		let collection_property = <PalletCommon<T>>::collection_properties(collection_id)1860			.get(&Self::get_scoped_property_key(key)?)1861			.ok_or(<Error<T>>::CollectionUnknown)?1862			.clone();18631864		Ok(collection_property)1865	}18661867	/// Fetch a RMRK-scoped collection property and decode it from bytes into an appropriate type.1868	pub fn get_collection_property_decoded<V: Decode>(1869		collection_id: CollectionId,1870		key: RmrkProperty,1871	) -> Result<V, DispatchError> {1872		Self::decode_property_value(&Self::get_collection_property(collection_id, key)?)1873	}18741875	/// Get the type of a collection stored as a scoped property.1876	///1877	/// RMRK Core proxy differentiates between regular collections as well as RMRK Bases as collections.1878	pub fn get_collection_type(1879		collection_id: CollectionId,1880	) -> Result<misc::CollectionType, DispatchError> {1881		Self::get_collection_property_decoded(collection_id, CollectionType).map_err(|err| {1882			if err != <Error<T>>::CollectionUnknown.into() {1883				<Error<T>>::CorruptedCollectionType.into()1884			} else {1885				err1886			}1887		})1888	}18891890	/// Ensure that the type of the collection equals the provided type,1891	/// otherwise return an error.1892	pub fn ensure_collection_type(1893		collection_id: CollectionId,1894		collection_type: misc::CollectionType,1895	) -> DispatchResult {1896		let actual_type = Self::get_collection_type(collection_id)?;1897		ensure!(1898			actual_type == collection_type,1899			<CommonError<T>>::NoPermission1900		);19011902		Ok(())1903	}19041905	/// Fetch an NFT collection, but make sure it has the appropriate type.1906	pub fn get_typed_nft_collection(1907		collection_id: CollectionId,1908		collection_type: misc::CollectionType,1909	) -> Result<NonfungibleHandle<T>, DispatchError> {1910		Self::ensure_collection_type(collection_id, collection_type)?;19111912		Self::get_nft_collection(collection_id)1913	}19141915	/// Same as [`get_typed_nft_collection`](crate::pallet::Pallet::get_typed_nft_collection),1916	/// but also return the Unique collection ID.1917	pub fn get_typed_nft_collection_mapped(1918		rmrk_collection_id: RmrkCollectionId,1919		collection_type: misc::CollectionType,1920	) -> Result<(NonfungibleHandle<T>, CollectionId), DispatchError> {1921		let unique_collection_id = match collection_type {1922			misc::CollectionType::Regular => Self::unique_collection_id(rmrk_collection_id)?,1923			_ => rmrk_collection_id.into(),1924		};19251926		let collection = Self::get_typed_nft_collection(unique_collection_id, collection_type)?;19271928		Ok((collection, unique_collection_id))1929	}19301931	/// Fetch and decode a RMRK-scoped NFT property value in bytes.1932	pub fn get_nft_property(1933		collection_id: CollectionId,1934		nft_id: TokenId,1935		key: RmrkProperty,1936	) -> Result<PropertyValue, DispatchError> {1937		let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))1938			.get(&Self::get_scoped_property_key(key)?)1939			.ok_or(<Error<T>>::RmrkPropertyIsNotFound)?1940			.clone();19411942		Ok(nft_property)1943	}19441945	/// Fetch a RMRK-scoped NFT property and decode it from bytes into an appropriate type.1946	pub fn get_nft_property_decoded<V: Decode>(1947		collection_id: CollectionId,1948		nft_id: TokenId,1949		key: RmrkProperty,1950	) -> Result<V, DispatchError> {1951		Self::decode_property_value(&Self::get_nft_property(collection_id, nft_id, key)?)1952	}19531954	/// Check that an NFT exists.1955	pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {1956		<TokenData<T>>::contains_key((collection_id, nft_id))1957	}19581959	/// Get the type of an NFT stored as a scoped property.1960	///1961	/// RMRK Core proxy differentiates between regular NFTs, and RMRK Parts and Themes.1962	pub fn get_nft_type(1963		collection_id: CollectionId,1964		token_id: TokenId,1965	) -> Result<NftType, DispatchError> {1966		Self::get_nft_property_decoded(collection_id, token_id, TokenType)1967			.map_err(|_| <Error<T>>::NoAvailableNftId.into())1968	}19691970	/// Ensure that the type of the NFT equals the provided type, otherwise return an error.1971	pub fn ensure_nft_type(1972		collection_id: CollectionId,1973		token_id: TokenId,1974		nft_type: NftType,1975	) -> DispatchResult {1976		let actual_type = Self::get_nft_type(collection_id, token_id)?;1977		ensure!(actual_type == nft_type, <Error<T>>::NoPermission);19781979		Ok(())1980	}19811982	/// Ensure that an account is the owner of the token, either directly1983	/// or at the top of the nesting hierarchy; return an error if it is not.1984	pub fn ensure_nft_owner(1985		collection_id: CollectionId,1986		token_id: TokenId,1987		possible_owner: &T::CrossAccountId,1988		nesting_budget: &dyn budget::Budget,1989	) -> DispatchResult {1990		let is_owned = <PalletStructure<T>>::check_indirectly_owned(1991			possible_owner.clone(),1992			collection_id,1993			token_id,1994			None,1995			nesting_budget,1996		)1997		.map_err(Self::map_unique_err_to_proxy)?;19981999		ensure!(is_owned, <Error<T>>::NoPermission);20002001		Ok(())2002	}20032004	/// Fetch non-scoped properties of a collection or a token that match the filter keys supplied,2005	/// or, if None are provided, return all non-scoped properties.2006	pub fn filter_user_properties<Key, Value, R, Mapper>(2007		collection_id: CollectionId,2008		token_id: Option<TokenId>,2009		filter_keys: Option<Vec<RmrkPropertyKey>>,2010		mapper: Mapper,2011	) -> Result<Vec<R>, DispatchError>2012	where2013		Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,2014		Value: Decode + Default,2015		Mapper: Fn(Key, Value) -> R,2016	{2017		filter_keys2018			.map(|keys| {2019				let properties = keys2020					.into_iter()2021					.filter_map(|key| {2022						let key: Key = key.try_into().ok()?;20232024						let value = match token_id {2025							Some(token_id) => Self::get_nft_property_decoded(2026								collection_id,2027								token_id,2028								UserProperty(key.as_ref()),2029							),2030							None => Self::get_collection_property_decoded(2031								collection_id,2032								UserProperty(key.as_ref()),2033							),2034						}2035						.ok()?;20362037						Some(mapper(key, value))2038					})2039					.collect();20402041				Ok(properties)2042			})2043			.unwrap_or_else(|| {2044				let properties =2045					Self::iterate_user_properties(collection_id, token_id, mapper)?.collect();20462047				Ok(properties)2048			})2049	}20502051	/// Get all non-scoped properties from a collection or a token, and apply some transformation,2052	/// supplied by `mapper`, to each key-value pair.2053	pub fn iterate_user_properties<Key, Value, R, Mapper>(2054		collection_id: CollectionId,2055		token_id: Option<TokenId>,2056		mapper: Mapper,2057	) -> Result<impl Iterator<Item = R>, DispatchError>2058	where2059		Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,2060		Value: Decode + Default,2061		Mapper: Fn(Key, Value) -> R,2062	{2063		let properties = match token_id {2064			Some(token_id) => <PalletNft<T>>::token_properties((collection_id, token_id)),2065			None => <PalletCommon<T>>::collection_properties(collection_id),2066		};20672068		let properties = properties.into_iter().filter_map(move |(key, value)| {2069			let key = strip_key_prefix(&key, USER_PROPERTY_PREFIX)?;20702071			let key: Key = key.to_vec().try_into().ok()?;2072			let value: Value = value.decode().ok()?;20732074			Some(mapper(key, value))2075		});20762077		Ok(properties)2078	}20792080	/// Match Unique errors to RMRK's own and return the RMRK error if a match is successful.2081	fn map_unique_err_to_proxy(err: DispatchError) -> DispatchError {2082		map_unique_err_to_proxy! {2083			match err {2084				CommonError::NoPermission => NoPermission,2085				CommonError::CollectionTokenLimitExceeded => CollectionFullOrLocked,2086				CommonError::PublicMintingNotAllowed => NoPermission,2087				CommonError::TokenNotFound => NoAvailableNftId,2088				CommonError::ApprovedValueTooLow => NoPermission,2089				CommonError::CantDestroyNotEmptyCollection => CollectionNotEmpty,2090				StructureError::TokenNotFound => NoAvailableNftId,2091				StructureError::OuroborosDetected => CannotSendToDescendentOrSelf,2092			}2093		}2094	}2095}
after · pallets/proxy-rmrk-core/src/lib.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! # RMRK Core Proxy Pallet18//!19//! A pallet used as proxy for RMRK Core (<https://rmrk-team.github.io/rmrk-substrate/#/pallets/rmrk-core>).20//!21//! - [`Config`]22//! - [`Call`]23//! - [`Pallet`]24//!25//! ## Overview26//!27//! The RMRK Core Proxy pallet mirrors the functionality of RMRK Core,28//! binding its externalities to Unique's own underlying structure.29//! It is purposed to mimic RMRK Core exactly, allowing seamless integrations30//! of solutions based on RMRK.31//!32//! RMRK Core itself contains essential functionality for RMRK's nested and33//! multi-resourced NFTs.34//!35//! *Note*, that while RMRK itself is subject to active development and restructuring,36//! the proxy may be caught temporarily out of date.37//!38//! ### What is RMRK?39//!40//! RMRK is a set of NFT standards which compose several "NFT 2.0 lego" primitives.41//! Putting these legos together allows a user to create NFT systems of arbitrary complexity.42//!43//! Meaning, RMRK NFTs are dynamic, able to nest into each other and form a hierarchy,44//! make use of specific changeable and partially shared metadata in the form of resources,45//! and more.46//!47//! Visit RMRK documentation and repositories to learn more:48//! - Docs: <https://docs.rmrk.app/getting-started/>49//! - FAQ: <https://coda.io/@rmrk/faq>50//! - Substrate code repository: <https://github.com/rmrk-team/rmrk-substrate>51//! - RMRK specification repository: <https://github.com/rmrk-team/rmrk-spec>52//!53//! ## Terminology54//!55//! For more information on RMRK, see RMRK's own documentation.56//!57//! ### Intro to RMRK58//!59//! - **Resource:** Additional piece of metadata of an NFT usually serving to add60//! a piece of media on top of the root metadata (NFT's own), be it a different wing61//! on the root template bird or something entirely unrelated.62//!63//! - **Base:** A list of possible "components" - Parts, a combination of which can64//! be appended/equipped to/on an NFT.65//!66//! - **Part:** Something that, together with other Parts, can constitute an NFT.67//! Parts are defined in the Base to which they belong. Parts can be either68//! of the `slot` type or `fixed` type. Slots are intended for equippables.69//! Note that "part of something" and "Part of a Base" can be easily confused,70//! and so in this documentation these words are distinguished by the capital letter.71//!72//! - **Theme:** Named objects of variable => value pairs which get interpolated into73//! the Base's `themable` Parts. Themes can hold any value, but are often represented74//! in RMRK's examples as colors applied to visible Parts.75//!76//! ### Peculiarities in Unique77//!78//! - **Scoped properties:** Properties that are normally obscured from users.79//! Their purpose is to contain structured metadata that was not included in the Unique standard80//! for collections and tokens, meant to be operated on by proxies and other outliers.81//! Scoped property keys are prefixed with `some-scope:`, where `some-scope` is82//! an arbitrary keyword, like "rmrk". `:` is considered an unacceptable symbol in user-defined83//! properties, which, along with other safeguards, makes scoped ones impossible to tamper with.84//!85//! - **Auxiliary properties:** A slightly different structure of properties,86//! trading universality of use for more convenient storage, writes and access.87//! Meant to be inaccessible to end users.88//!89//! ## Proxy Implementation90//!91//! An external user is supposed to be able to utilize this proxy as they would92//! utilize RMRK, and get exactly the same results. Normally, Unique transactions93//! are off-limits to RMRK collections and tokens, and vice versa. However,94//! the information stored on chain can be freely interpreted by storage reads and Unique RPCs.95//!96//! ### ID Mapping97//!98//! RMRK's collections' IDs are counted independently of Unique's and start at 0.99//! Note that tokens' IDs still start at 1.100//! The collections themselves, as well as tokens, are stored as Unique collections,101//! and thus RMRK IDs are mapped to Unique IDs (but not vice versa).102//!103//! ### External/Internal Collection Insulation104//!105//! A Unique transaction cannot target collections purposed for RMRK,106//! and they are flagged as `external` to specify that. On the other hand,107//! due to the mapping, RMRK transactions and RPCs simply cannot reach Unique collections.108//!109//! ### Native Properties110//!111//! Many of RMRK's native parameters are stored as scoped properties of a collection112//! or an NFT on the chain. Scoped properties are prefixed with `rmrk:`, where `:`113//! is an unacceptable symbol in user-defined properties, which, along with other safeguards,114//! makes them impossible to tamper with.115//!116//! ### Collection and NFT Types, or Base, Parts and Themes Handling117//!118//! RMRK introduces the concept of a Base, which is a catalogue of Parts,119//! possible components of an NFT. Due to its similarity with the functionality120//! of a token collection, a Base is stored and handled as one, and the Base's Parts and Themes121//! are this collection's NFTs. See [`CollectionType`] and [`NftType`].122//!123//! ## Interface124//!125//! ### Dispatchables126//!127//! - `create_collection` - Create a new collection of NFTs.128//! - `destroy_collection` - Destroy a collection.129//! - `change_collection_issuer` - Change the issuer of a collection.130//! Analogous to Unique's collection's [`owner`](up_data_structs::Collection).131//! - `lock_collection` - "Lock" the collection and prevent new token creation. **Cannot be undone.**132//! - `mint_nft` - Mint an NFT in a specified collection.133//! - `burn_nft` - Burn an NFT, destroying it and its nested tokens.134//! - `send` - Transfer an NFT from an account/NFT A to another account/NFT B.135//! - `accept_nft` - Accept an NFT sent from another account to self or an owned NFT.136//! - `reject_nft` - Reject an NFT sent from another account to self or owned NFT and **burn it**.137//! - `accept_resource` - Accept the addition of a newly created pending resource to an existing NFT.138//! - `accept_resource_removal` - Accept the removal of a removal-pending resource from an NFT.139//! - `set_property` - Add or edit a custom user property of a token or a collection.140//! - `set_priority` - Set a different order of resource priorities for an NFT.141//! - `add_basic_resource` - Create and set/propose a basic resource for an NFT.142//! - `add_composable_resource` - Create and set/propose a composable resource for an NFT.143//! - `add_slot_resource` - Create and set/propose a slot resource for an NFT.144//! - `remove_resource` - Remove and erase a resource from an NFT.145146#![cfg_attr(not(feature = "std"), no_std)]147148use frame_support::{pallet_prelude::*, BoundedVec, dispatch::DispatchResult};149use frame_system::{pallet_prelude::*, ensure_signed};150use sp_runtime::{DispatchError, Permill, traits::StaticLookup};151use sp_std::{152	vec::Vec,153	collections::{btree_set::BTreeSet, btree_map::BTreeMap},154};155use up_data_structs::{*, mapping::TokenAddressMapping};156use pallet_common::{157	Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,158};159use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};160use pallet_structure::{Pallet as PalletStructure, Error as StructureError};161use pallet_evm::account::CrossAccountId;162use core::convert::AsRef;163164pub use pallet::*;165166#[cfg(feature = "runtime-benchmarks")]167pub mod benchmarking;168pub mod misc;169pub mod property;170pub mod rpc;171pub mod weights;172173pub type SelfWeightOf<T> = <T as Config>::WeightInfo;174175use weights::WeightInfo;176use misc::*;177pub use property::*;178179use RmrkProperty::*;180181/// Maximum number of levels of depth in the token nesting tree.182pub const NESTING_BUDGET: u32 = 5;183184type PendingTarget = (CollectionId, TokenId);185type PendingChild = (RmrkCollectionId, RmrkNftId);186type PendingChildrenSet = BTreeSet<PendingChild>;187188type BasesMap = BTreeMap<RmrkBaseId, u32>;189190#[frame_support::pallet]191pub mod pallet {192	use super::*;193194	#[pallet::config]195	pub trait Config:196		frame_system::Config197		+ pallet_common::Config198		+ pallet_nonfungible::Config199		+ pallet_evm::Config200	{201		/// Overarching event type.202		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;203204		/// The weight information of this pallet.205		type WeightInfo: WeightInfo;206	}207208	/// Latest yet-unused collection ID.209	#[pallet::storage]210	#[pallet::getter(fn collection_index)]211	pub type CollectionIndex<T: Config> = StorageValue<_, RmrkCollectionId, ValueQuery>;212213	/// Mapping from RMRK collection ID to Unique's.214	#[pallet::storage]215	pub type UniqueCollectionId<T: Config> =216		StorageMap<_, Twox64Concat, RmrkCollectionId, CollectionId, ValueQuery>;217218	#[pallet::pallet]219	#[pallet::generate_store(pub(super) trait Store)]220	pub struct Pallet<T>(_);221222	#[pallet::event]223	#[pallet::generate_deposit(pub(super) fn deposit_event)]224	pub enum Event<T: Config> {225		CollectionCreated {226			issuer: T::AccountId,227			collection_id: RmrkCollectionId,228		},229		CollectionDestroyed {230			issuer: T::AccountId,231			collection_id: RmrkCollectionId,232		},233		IssuerChanged {234			old_issuer: T::AccountId,235			new_issuer: T::AccountId,236			collection_id: RmrkCollectionId,237		},238		CollectionLocked {239			issuer: T::AccountId,240			collection_id: RmrkCollectionId,241		},242		NftMinted {243			owner: T::AccountId,244			collection_id: RmrkCollectionId,245			nft_id: RmrkNftId,246		},247		NFTBurned {248			owner: T::AccountId,249			nft_id: RmrkNftId,250		},251		NFTSent {252			sender: T::AccountId,253			recipient: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,254			collection_id: RmrkCollectionId,255			nft_id: RmrkNftId,256			approval_required: bool,257		},258		NFTAccepted {259			sender: T::AccountId,260			recipient: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,261			collection_id: RmrkCollectionId,262			nft_id: RmrkNftId,263		},264		NFTRejected {265			sender: T::AccountId,266			collection_id: RmrkCollectionId,267			nft_id: RmrkNftId,268		},269		PropertySet {270			collection_id: RmrkCollectionId,271			maybe_nft_id: Option<RmrkNftId>,272			key: RmrkKeyString,273			value: RmrkValueString,274		},275		ResourceAdded {276			nft_id: RmrkNftId,277			resource_id: RmrkResourceId,278		},279		ResourceRemoval {280			nft_id: RmrkNftId,281			resource_id: RmrkResourceId,282		},283		ResourceAccepted {284			nft_id: RmrkNftId,285			resource_id: RmrkResourceId,286		},287		ResourceRemovalAccepted {288			nft_id: RmrkNftId,289			resource_id: RmrkResourceId,290		},291		PrioritySet {292			collection_id: RmrkCollectionId,293			nft_id: RmrkNftId,294		},295	}296297	#[pallet::error]298	pub enum Error<T> {299		/* Unique proxy-specific events */300		/// Property of the type of RMRK collection could not be read successfully.301		CorruptedCollectionType,302		// NftTypeEncodeError,303		/// Too many symbols supplied as the property key. The maximum is [256](up_data_structs::MAX_PROPERTY_KEY_LENGTH).304		RmrkPropertyKeyIsTooLong,305		/// Too many bytes supplied as the property value. The maximum is [32768](up_data_structs::MAX_PROPERTY_VALUE_LENGTH).306		RmrkPropertyValueIsTooLong,307		/// Could not find a property by the supplied key.308		RmrkPropertyIsNotFound,309		/// Something went wrong when decoding encoded data from the storage.310		/// Perhaps, there was a wrong key supplied for the type, or the data was improperly stored.311		UnableToDecodeRmrkData,312313		/* RMRK compatible events */314		/// Only destroying collections without tokens is allowed.315		CollectionNotEmpty,316		/// Could not find an ID for a collection. It is likely there were too many collections created on the chain, causing an overflow.317		NoAvailableCollectionId,318		/// Token does not exist, or there is no suitable ID for it, likely too many tokens were created in a collection, causing an overflow.319		NoAvailableNftId,320		/// Collection does not exist, has a wrong type, or does not map to a Unique ID.321		CollectionUnknown,322		/// No permission to perform action.323		NoPermission,324		/// Token is marked as non-transferable, and thus cannot be transferred.325		NonTransferable,326		/// Too many tokens created in the collection, no new ones are allowed.327		CollectionFullOrLocked,328		/// No such resource found.329		ResourceDoesntExist,330		/// If an NFT is sent to a descendant, that would form a nesting loop, an ouroboros.331		/// Sending to self is redundant.332		CannotSendToDescendentOrSelf,333		/// Not the target owner of the sent NFT.334		CannotAcceptNonOwnedNft,335		/// Not the target owner of the sent NFT.336		CannotRejectNonOwnedNft,337		/// NFT was not sent and is not pending.338		CannotRejectNonPendingNft,339		/// Resource is not pending for the operation.340		ResourceNotPending,341		/// Could not find an ID for the resource. It is likely there were too many resources created on an NFT, causing an overflow.342		NoAvailableResourceId,343	}344345	#[pallet::call]346	impl<T: Config> Pallet<T> {347		// todo :refactor replace every collection_id with rmrk_collection_id (and nft_id) in arguments for uniformity?348349		/// Create a new collection of NFTs.350		///351		/// # Permissions:352		/// * Anyone - will be assigned as the issuer of the collection.353		///354		/// # Arguments:355		/// - `origin`: sender of the transaction356		/// - `metadata`: Metadata describing the collection, e.g. IPFS hash. Cannot be changed.357		/// - `max`: Optional maximum number of tokens.358		/// - `symbol`: UTF-8 string with token prefix, by which to represent the token in wallets and UIs.359		/// Analogous to Unique's [`token_prefix`](up_data_structs::Collection). Cannot be changed.360		#[pallet::weight(<SelfWeightOf<T>>::create_collection())]361		pub fn create_collection(362			origin: OriginFor<T>,363			metadata: RmrkString,364			max: Option<u32>,365			symbol: RmrkCollectionSymbol,366		) -> DispatchResult {367			let sender = ensure_signed(origin)?;368369			let limits = CollectionLimits {370				owner_can_transfer: Some(false),371				token_limit: max,372				..Default::default()373			};374375			let data = CreateCollectionData {376				limits: Some(limits),377				token_prefix: symbol378					.into_inner()379					.try_into()380					.map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,381				permissions: Some(CollectionPermissions {382					nesting: Some(NestingPermissions {383						token_owner: true,384						collection_admin: false,385						restricted: None,386						#[cfg(feature = "runtime-benchmarks")]387						permissive: false,388					}),389					..Default::default()390				}),391				..Default::default()392			};393394			let unique_collection_id = Self::init_collection(395				T::CrossAccountId::from_sub(sender.clone()),396				data,397				[398					Self::encode_rmrk_property(Metadata, &metadata)?,399					Self::encode_rmrk_property(CollectionType, &misc::CollectionType::Regular)?,400				]401				.into_iter(),402			)?;403			let rmrk_collection_id = <CollectionIndex<T>>::get();404405			<UniqueCollectionId<T>>::insert(rmrk_collection_id, unique_collection_id);406407			<PalletCommon<T>>::set_scoped_collection_property(408				unique_collection_id,409				RMRK_SCOPE,410				Self::encode_rmrk_property(RmrkInternalCollectionId, &rmrk_collection_id)?,411			)?;412413			<CollectionIndex<T>>::mutate(|n| *n += 1);414415			Self::deposit_event(Event::CollectionCreated {416				issuer: sender,417				collection_id: rmrk_collection_id,418			});419420			Ok(())421		}422423		/// Destroy a collection.424		///425		/// Only empty collections can be destroyed. If it has any tokens, they must be burned first.426		///427		/// # Permissions:428		/// * Collection issuer429		///430		/// # Arguments:431		/// - `origin`: sender of the transaction432		/// - `collection_id`: RMRK ID of the collection to destroy.433		#[pallet::weight(<SelfWeightOf<T>>::destroy_collection())]434		pub fn destroy_collection(435			origin: OriginFor<T>,436			collection_id: RmrkCollectionId,437		) -> DispatchResult {438			let sender = ensure_signed(origin)?;439			let cross_sender = T::CrossAccountId::from_sub(sender.clone());440441			let collection = Self::get_typed_nft_collection(442				Self::unique_collection_id(collection_id)?,443				misc::CollectionType::Regular,444			)?;445			collection.check_is_external()?;446447			<PalletNft<T>>::destroy_collection(collection, &cross_sender)448				.map_err(Self::map_unique_err_to_proxy)?;449450			Self::deposit_event(Event::CollectionDestroyed {451				issuer: sender,452				collection_id,453			});454455			Ok(())456		}457458		/// Change the issuer of a collection. Analogous to Unique's collection's [`owner`](up_data_structs::Collection).459		///460		/// # Permissions:461		/// * Collection issuer462		///463		/// # Arguments:464		/// - `origin`: sender of the transaction465		/// - `collection_id`: RMRK collection ID to change the issuer of.466		/// - `new_issuer`: Collection's new issuer.467		#[pallet::weight(<SelfWeightOf<T>>::change_collection_issuer())]468		pub fn change_collection_issuer(469			origin: OriginFor<T>,470			collection_id: RmrkCollectionId,471			new_issuer: <T::Lookup as StaticLookup>::Source,472		) -> DispatchResult {473			let sender = ensure_signed(origin)?;474475			let collection = Self::get_nft_collection(Self::unique_collection_id(collection_id)?)?;476			collection.check_is_external()?;477478			let new_issuer = T::Lookup::lookup(new_issuer)?;479480			Self::change_collection_owner(481				Self::unique_collection_id(collection_id)?,482				misc::CollectionType::Regular,483				sender.clone(),484				new_issuer.clone(),485			)?;486487			Self::deposit_event(Event::IssuerChanged {488				old_issuer: sender,489				new_issuer,490				collection_id,491			});492493			Ok(())494		}495496		/// "Lock" the collection and prevent new token creation. Cannot be undone.497		///498		/// # Permissions:499		/// * Collection issuer500		///501		/// # Arguments:502		/// - `origin`: sender of the transaction503		/// - `collection_id`: RMRK ID of the collection to lock.504		#[pallet::weight(<SelfWeightOf<T>>::lock_collection())]505		pub fn lock_collection(506			origin: OriginFor<T>,507			collection_id: RmrkCollectionId,508		) -> DispatchResult {509			let sender = ensure_signed(origin)?;510			let cross_sender = T::CrossAccountId::from_sub(sender.clone());511512			let collection = Self::get_typed_nft_collection(513				Self::unique_collection_id(collection_id)?,514				misc::CollectionType::Regular,515			)?;516			collection.check_is_external()?;517518			Self::check_collection_owner(&collection, &cross_sender)?;519520			let token_count = collection.total_supply();521522			let mut collection = collection.into_inner();523			collection.limits.token_limit = Some(token_count);524			collection.save()?;525526			Self::deposit_event(Event::CollectionLocked {527				issuer: sender,528				collection_id,529			});530531			Ok(())532		}533534		/// Mint an NFT in a specified collection.535		///536		/// # Permissions:537		/// * Collection issuer538		///539		/// # Arguments:540		/// - `origin`: sender of the transaction541		/// - `owner`: Owner account of the NFT. If set to None, defaults to the sender (collection issuer).542		/// - `collection_id`: RMRK collection ID for the NFT to be minted within. Cannot be changed.543		/// - `recipient`: Receiver account of the royalty. Has no effect if the `royalty_amount` is not set. Cannot be changed.544		/// - `royalty_amount`: Optional permillage reward from each trade for the `recipient`. Cannot be changed.545		/// - `metadata`: Arbitrary data about an NFT, e.g. IPFS hash. Cannot be changed.546		/// - `transferable`: Can this NFT be transferred? Cannot be changed.547		/// - `resources`: Resource data to be added to the NFT immediately after minting.548		#[pallet::weight(<SelfWeightOf<T>>::mint_nft(resources.as_ref().map(|r| r.len() as u32).unwrap_or(0)))]549		pub fn mint_nft(550			origin: OriginFor<T>,551			owner: Option<T::AccountId>,552			collection_id: RmrkCollectionId,553			recipient: Option<T::AccountId>,554			royalty_amount: Option<Permill>,555			metadata: RmrkString,556			transferable: bool,557			resources: Option<BoundedVec<RmrkResourceTypes, MaxResourcesOnMint>>,558		) -> DispatchResult {559			let sender = ensure_signed(origin)?;560			let cross_sender = T::CrossAccountId::from_sub(sender.clone());561562			let owner = owner.unwrap_or(sender.clone());563			let cross_owner = T::CrossAccountId::from_sub(owner.clone());564565			let collection = Self::get_typed_nft_collection(566				Self::unique_collection_id(collection_id)?,567				misc::CollectionType::Regular,568			)?;569			collection.check_is_external()?;570571			let royalty_info = royalty_amount.map(|amount| rmrk_traits::RoyaltyInfo {572				recipient: recipient.unwrap_or_else(|| owner.clone()),573				amount,574			});575576			let nft_id = Self::create_nft(577				&cross_sender,578				&cross_owner,579				&collection,580				[581					Self::encode_rmrk_property(TokenType, &NftType::Regular)?,582					Self::encode_rmrk_property(Transferable, &transferable)?,583					Self::encode_rmrk_property(PendingNftAccept, &None::<PendingTarget>)?,584					Self::encode_rmrk_property(RoyaltyInfo, &royalty_info)?,585					Self::encode_rmrk_property(Metadata, &metadata)?,586					Self::encode_rmrk_property(Equipped, &false)?,587					Self::encode_rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,588					Self::encode_rmrk_property(NextResourceId, &(0 as RmrkResourceId))?,589					Self::encode_rmrk_property(PendingChildren, &PendingChildrenSet::new())?,590					Self::encode_rmrk_property(AssociatedBases, &BasesMap::new())?,591				]592				.into_iter(),593			)594			.map_err(|err| match err {595				DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),596				err => Self::map_unique_err_to_proxy(err),597			})?;598599			if let Some(resources) = resources {600				for resource in resources {601					Self::resource_add(sender.clone(), collection.id, nft_id, resource)?;602				}603			}604605			Self::deposit_event(Event::NftMinted {606				owner,607				collection_id,608				nft_id: nft_id.0,609			});610611			Ok(())612		}613614		/// Burn an NFT, destroying it and its nested tokens up to the specified limit.615		/// If the burning budget is exceeded, the transaction is reverted.616		///617		/// This is the way to burn a nested token as well.618		///619		/// For more information, see [`burn_recursively`](pallet_nonfungible::pallet::Pallet::burn_recursively).620		///621		/// # Permissions:622		/// * Token owner623		///624		/// # Arguments:625		/// - `origin`: sender of the transaction626		/// - `collection_id`: RMRK ID of the collection in which the NFT to burn belongs to.627		/// - `nft_id`: ID of the NFT to be destroyed.628		/// - `max_burns`: Maximum number of tokens to burn, assuming nesting. The transaction629		/// is reverted if there are more tokens to burn in the nesting tree than this number.630		/// This is primarily a mechanism of transaction weight control.631		#[pallet::weight(<SelfWeightOf<T>>::burn_nft(*max_burns))]632		pub fn burn_nft(633			origin: OriginFor<T>,634			collection_id: RmrkCollectionId,635			nft_id: RmrkNftId,636			max_burns: u32,637		) -> DispatchResult {638			let sender = ensure_signed(origin)?;639			let cross_sender = T::CrossAccountId::from_sub(sender.clone());640641			let collection = Self::get_typed_nft_collection(642				Self::unique_collection_id(collection_id)?,643				misc::CollectionType::Regular,644			)?;645			collection.check_is_external()?;646647			Self::destroy_nft(648				cross_sender,649				Self::unique_collection_id(collection_id)?,650				nft_id.into(),651				max_burns,652				<Error<T>>::NoPermission,653			)654			.map_err(|err| Self::map_unique_err_to_proxy(err.error))?;655656			Self::deposit_event(Event::NFTBurned {657				owner: sender,658				nft_id,659			});660661			Ok(())662		}663664		/// Transfer an NFT from an account/NFT A to another account/NFT B.665		/// The token must be transferable. Nesting cannot occur deeper than the [`NESTING_BUDGET`].666		///667		/// If the target owner is an NFT owned by another account, then the NFT will enter668		/// the pending state and will have to be accepted by the other account.669		///670		/// # Permissions:671		/// - Token owner672		///673		/// # Arguments:674		/// - `origin`: sender of the transaction675		/// - `rmrk_collection_id`: RMRK ID of the collection of the NFT to be transferred.676		/// - `rmrk_nft_id`: ID of the NFT to be transferred.677		/// - `new_owner`: New owner of the nft which can be either an account or a NFT.678		#[pallet::weight(<SelfWeightOf<T>>::send())]679		pub fn send(680			origin: OriginFor<T>,681			rmrk_collection_id: RmrkCollectionId,682			rmrk_nft_id: RmrkNftId,683			new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,684		) -> DispatchResult {685			let sender = ensure_signed(origin.clone())?;686			let cross_sender = T::CrossAccountId::from_sub(sender.clone());687688			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;689			let nft_id = rmrk_nft_id.into();690691			let collection =692				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;693			collection.check_is_external()?;694695			let token_data =696				<TokenData<T>>::get((collection_id, nft_id)).ok_or(<Error<T>>::NoAvailableNftId)?;697698			let from = token_data.owner;699700			ensure!(701				Self::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Transferable)?,702				<Error<T>>::NonTransferable703			);704705			ensure!(706				Self::get_nft_property_decoded::<Option<PendingTarget>>(707					collection_id,708					nft_id,709					RmrkProperty::PendingNftAccept710				)?711				.is_none(),712				<Error<T>>::NoPermission713			);714715			let target_owner;716			let approval_required;717718			match new_owner {719				RmrkAccountIdOrCollectionNftTuple::AccountId(ref account_id) => {720					target_owner = T::CrossAccountId::from_sub(account_id.clone());721					approval_required = false;722				}723				RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(724					target_collection_id,725					target_nft_id,726				) => {727					let target_collection_id = Self::unique_collection_id(target_collection_id)?;728729					let target_nft_budget = budget::Value::new(NESTING_BUDGET);730731					let target_nft_owner = <PalletStructure<T>>::get_checked_topmost_owner(732						target_collection_id,733						target_nft_id.into(),734						Some((collection_id, nft_id)),735						&target_nft_budget,736					)737					.map_err(Self::map_unique_err_to_proxy)?;738739					approval_required = cross_sender != target_nft_owner;740741					if approval_required {742						target_owner = target_nft_owner;743744						<PalletNft<T>>::set_scoped_token_property(745							collection.id,746							nft_id,747							RMRK_SCOPE,748							Self::encode_rmrk_property::<Option<PendingTarget>>(749								PendingNftAccept,750								&Some((target_collection_id, target_nft_id.into())),751							)?,752						)?;753754						Self::insert_pending_child(755							(target_collection_id, target_nft_id.into()),756							(rmrk_collection_id, rmrk_nft_id),757						)?;758					} else {759						target_owner = T::CrossTokenAddressMapping::token_to_address(760							target_collection_id,761							target_nft_id.into(),762						);763					}764				}765			}766767			let src_nft_budget = budget::Value::new(NESTING_BUDGET);768769			<PalletNft<T>>::transfer_from(770				&collection,771				&cross_sender,772				&from,773				&target_owner,774				nft_id,775				&src_nft_budget,776			)777			.map_err(Self::map_unique_err_to_proxy)?;778779			Self::deposit_event(Event::NFTSent {780				sender,781				recipient: new_owner,782				collection_id: rmrk_collection_id,783				nft_id: rmrk_nft_id,784				approval_required,785			});786787			Ok(())788		}789790		/// Accept an NFT sent from another account to self or an owned NFT.791		///792		/// The NFT in question must be pending, and, thus, be [sent](`Pallet::send`) first.793		///794		/// # Permissions:795		/// - Token-owner-to-be796		///797		/// # Arguments:798		/// - `origin`: sender of the transaction799		/// - `rmrk_collection_id`: RMRK collection ID of the NFT to be accepted.800		/// - `rmrk_nft_id`: ID of the NFT to be accepted.801		/// - `new_owner`: Either the sender's account ID or a sender-owned NFT,802		/// whichever the accepted NFT was sent to.803		#[pallet::weight(<SelfWeightOf<T>>::accept_nft())]804		pub fn accept_nft(805			origin: OriginFor<T>,806			rmrk_collection_id: RmrkCollectionId,807			rmrk_nft_id: RmrkNftId,808			new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,809		) -> DispatchResult {810			let sender = ensure_signed(origin.clone())?;811			let cross_sender = T::CrossAccountId::from_sub(sender.clone());812813			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;814			let nft_id = rmrk_nft_id.into();815816			let collection =817				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;818			collection.check_is_external()?;819820			let new_cross_owner = match new_owner {821				RmrkAccountIdOrCollectionNftTuple::AccountId(ref account_id) => {822					T::CrossAccountId::from_sub(account_id.clone())823				}824				RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(825					target_collection_id,826					target_nft_id,827				) => {828					let target_collection_id = Self::unique_collection_id(target_collection_id)?;829830					T::CrossTokenAddressMapping::token_to_address(831						target_collection_id,832						TokenId(target_nft_id),833					)834				}835			};836837			let budget = budget::Value::new(NESTING_BUDGET);838839			<PalletNft<T>>::transfer(840				&collection,841				&cross_sender,842				&new_cross_owner,843				nft_id,844				&budget,845			)846			.map_err(|err| {847				if err == <CommonError<T>>::UserIsNotAllowedToNest.into() {848					<Error<T>>::CannotAcceptNonOwnedNft.into()849				} else {850					Self::map_unique_err_to_proxy(err)851				}852			})?;853854			let pending_target = Self::get_nft_property_decoded::<Option<PendingTarget>>(855				collection_id,856				nft_id,857				RmrkProperty::PendingNftAccept,858			)?;859860			if let Some(pending_target) = pending_target {861				Self::remove_pending_child(pending_target, (rmrk_collection_id, rmrk_nft_id))?;862863				<PalletNft<T>>::set_scoped_token_property(864					collection.id,865					nft_id,866					RMRK_SCOPE,867					Self::encode_rmrk_property(PendingNftAccept, &None::<PendingTarget>)?,868				)?;869			}870871			Self::deposit_event(Event::NFTAccepted {872				sender,873				recipient: new_owner,874				collection_id: rmrk_collection_id,875				nft_id: rmrk_nft_id,876			});877878			Ok(())879		}880881		/// Reject an NFT sent from another account to self or owned NFT.882		/// The NFT in question will not be sent back and burnt instead.883		///884		/// The NFT in question must be pending, and, thus, be [sent](`Pallet::send`) first.885		///886		/// # Permissions:887		/// - Token-owner-to-be-not888		///889		/// # Arguments:890		/// - `origin`: sender of the transaction891		/// - `rmrk_collection_id`: RMRK ID of the NFT to be rejected.892		/// - `rmrk_nft_id`: ID of the NFT to be rejected.893		#[pallet::weight(<SelfWeightOf<T>>::reject_nft())]894		pub fn reject_nft(895			origin: OriginFor<T>,896			rmrk_collection_id: RmrkCollectionId,897			rmrk_nft_id: RmrkNftId,898		) -> DispatchResult {899			let sender = ensure_signed(origin)?;900			let cross_sender = T::CrossAccountId::from_sub(sender.clone());901902			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;903			let nft_id = rmrk_nft_id.into();904905			let collection =906				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;907			collection.check_is_external()?;908909			ensure!(910				<TokenData<T>>::get((collection_id, nft_id)).is_some(),911				<Error<T>>::NoAvailableNftId912			);913914			let pending_target = Self::get_nft_property_decoded::<Option<PendingTarget>>(915				collection_id,916				nft_id,917				RmrkProperty::PendingNftAccept,918			)?;919920			match pending_target {921				Some(pending_target) => {922					Self::remove_pending_child(pending_target, (rmrk_collection_id, rmrk_nft_id))?923				}924				None => return Err(<Error<T>>::CannotRejectNonPendingNft.into()),925			}926927			Self::destroy_nft(928				cross_sender,929				collection_id,930				nft_id,931				NESTING_BUDGET,932				<Error<T>>::CannotRejectNonOwnedNft,933			)934			.map_err(|err| Self::map_unique_err_to_proxy(err.error))?;935936			Self::deposit_event(Event::NFTRejected {937				sender,938				collection_id: rmrk_collection_id,939				nft_id: rmrk_nft_id,940			});941942			Ok(())943		}944945		/// Accept the addition of a newly created pending resource to an existing NFT.946		///947		/// This transaction is needed when a resource is created and assigned to an NFT948		/// by a non-owner, i.e. the collection issuer, with one of the949		/// [`add_...` transactions](Pallet::add_basic_resource).950		///951		/// # Permissions:952		/// - Token owner953		///954		/// # Arguments:955		/// - `origin`: sender of the transaction956		/// - `rmrk_collection_id`: RMRK collection ID of the NFT.957		/// - `rmrk_nft_id`: ID of the NFT with a pending resource to be accepted.958		/// - `resource_id`: ID of the newly created pending resource.959		/// accept the addition of a new resource to an existing NFT960		#[pallet::weight(<SelfWeightOf<T>>::accept_resource())]961		pub fn accept_resource(962			origin: OriginFor<T>,963			rmrk_collection_id: RmrkCollectionId,964			rmrk_nft_id: RmrkNftId,965			resource_id: RmrkResourceId,966		) -> DispatchResult {967			let sender = ensure_signed(origin)?;968			let cross_sender = T::CrossAccountId::from_sub(sender);969970			let collection_id = Self::unique_collection_id(rmrk_collection_id)971				.map_err(|_| <Error<T>>::ResourceDoesntExist)?;972			let collection =973				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;974			collection.check_is_external()?;975976			let nft_id = rmrk_nft_id.into();977978			let budget = budget::Value::new(NESTING_BUDGET);979980			let nft_owner =981				<PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)982					.map_err(|_| <Error<T>>::ResourceDoesntExist)?;983984			Self::try_mutate_resource_info(collection_id, nft_id, resource_id, |res| {985				ensure!(res.pending, <Error<T>>::ResourceNotPending);986				ensure!(cross_sender == nft_owner, <Error<T>>::NoPermission);987988				res.pending = false;989990				Ok(())991			})?;992993			Self::deposit_event(Event::<T>::ResourceAccepted {994				nft_id: rmrk_nft_id,995				resource_id,996			});997998			Ok(())999		}10001001		/// Accept the removal of a removal-pending resource from an NFT.1002		///1003		/// This transaction is needed when a non-owner, i.e. the collection issuer,1004		/// requests a [removal](`Pallet::remove_resource`) of a resource from an NFT.1005		///1006		/// # Permissions:1007		/// - Token owner1008		///1009		/// # Arguments:1010		/// - `origin`: sender of the transaction1011		/// - `rmrk_collection_id`: RMRK collection ID of the NFT.1012		/// - `rmrk_nft_id`: ID of the NFT with a resource to be removed.1013		/// - `resource_id`: ID of the removal-pending resource.1014		#[pallet::weight(<SelfWeightOf<T>>::accept_resource_removal())]1015		pub fn accept_resource_removal(1016			origin: OriginFor<T>,1017			rmrk_collection_id: RmrkCollectionId,1018			rmrk_nft_id: RmrkNftId,1019			resource_id: RmrkResourceId,1020		) -> DispatchResult {1021			let sender = ensure_signed(origin)?;1022			let cross_sender = T::CrossAccountId::from_sub(sender);10231024			let collection_id = Self::unique_collection_id(rmrk_collection_id)1025				.map_err(|_| <Error<T>>::ResourceDoesntExist)?;1026			let collection =1027				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1028			collection.check_is_external()?;10291030			let nft_id = rmrk_nft_id.into();10311032			let budget = budget::Value::new(NESTING_BUDGET);10331034			let nft_owner =1035				<PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)1036					.map_err(|_| <Error<T>>::ResourceDoesntExist)?;10371038			ensure!(cross_sender == nft_owner, <Error<T>>::NoPermission);10391040			let resource_id_key = Self::get_scoped_property_key(ResourceId(resource_id))?;10411042			let resource_info = <PalletNft<T>>::token_aux_property((1043				collection_id,1044				nft_id,1045				RMRK_SCOPE,1046				resource_id_key.clone(),1047			))1048			.ok_or(<Error<T>>::ResourceDoesntExist)?;10491050			let resource_info: RmrkResourceInfo = Self::decode_property_value(&resource_info)?;10511052			ensure!(1053				resource_info.pending_removal,1054				<Error<T>>::ResourceNotPending1055			);10561057			<PalletNft<T>>::remove_token_aux_property(1058				collection_id,1059				nft_id,1060				RMRK_SCOPE,1061				resource_id_key,1062			);10631064			if let RmrkResourceTypes::Composable(resource) = resource_info.resource {1065				let base_id = resource.base;10661067				Self::remove_associated_base_id(collection_id, nft_id, base_id)?;1068			}10691070			Self::deposit_event(Event::<T>::ResourceRemovalAccepted {1071				nft_id: rmrk_nft_id,1072				resource_id,1073			});10741075			Ok(())1076		}10771078		/// Add or edit a custom user property, a key-value pair, describing the metadata1079		/// of a token or a collection, on either one of these.1080		///1081		/// Note that in this proxy implementation many details regarding RMRK are stored1082		/// as scoped properties prefixed with "rmrk:", normally inaccessible1083		/// to external transactions and RPCs.1084		///1085		/// # Permissions:1086		/// - Collection issuer - in case of collection property1087		/// - Token owner - in case of NFT property1088		///1089		/// # Arguments:1090		/// - `origin`: sender of the transaction1091		/// - `rmrk_collection_id`: RMRK collection ID.1092		/// - `maybe_nft_id`: Optional ID of the NFT. If left empty, then the property is set for the collection.1093		/// - `key`: Key of the custom property to be referenced by.1094		/// - `value`: Value of the custom property to be stored.1095		#[pallet::weight(<SelfWeightOf<T>>::set_property())]1096		pub fn set_property(1097			origin: OriginFor<T>,1098			#[pallet::compact] rmrk_collection_id: RmrkCollectionId,1099			maybe_nft_id: Option<RmrkNftId>,1100			key: RmrkKeyString,1101			value: RmrkValueString,1102		) -> DispatchResult {1103			let sender = ensure_signed(origin)?;1104			let sender = T::CrossAccountId::from_sub(sender);11051106			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;1107			let collection =1108				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1109			collection.check_is_external()?;11101111			let budget = budget::Value::new(NESTING_BUDGET);11121113			match maybe_nft_id {1114				Some(nft_id) => {1115					let token_id: TokenId = nft_id.into();11161117					Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;1118					Self::ensure_nft_owner(collection_id, token_id, &sender, &budget)?;11191120					<PalletNft<T>>::set_scoped_token_property(1121						collection_id,1122						token_id,1123						RMRK_SCOPE,1124						Self::encode_rmrk_property(UserProperty(key.as_slice()), &value)?,1125					)?;1126				}1127				None => {1128					let collection = Self::get_typed_nft_collection(1129						collection_id,1130						misc::CollectionType::Regular,1131					)?;11321133					Self::check_collection_owner(&collection, &sender)?;11341135					<PalletCommon<T>>::set_scoped_collection_property(1136						collection_id,1137						RMRK_SCOPE,1138						Self::encode_rmrk_property(UserProperty(key.as_slice()), &value)?,1139					)?;1140				}1141			}11421143			Self::deposit_event(Event::PropertySet {1144				collection_id: rmrk_collection_id,1145				maybe_nft_id,1146				key,1147				value,1148			});11491150			Ok(())1151		}11521153		/// Set a different order of resource priorities for an NFT. Priorities can be used,1154		/// for example, for order of rendering.1155		///1156		/// Note that the priorities are not updated automatically, and are an empty vector1157		/// by default. There is no pre-set definition for the order to be particular,1158		/// it can be interpreted arbitrarily use-case by use-case.1159		///1160		/// # Permissions:1161		/// - Token owner1162		///1163		/// # Arguments:1164		/// - `origin`: sender of the transaction1165		/// - `rmrk_collection_id`: RMRK collection ID of the NFT.1166		/// - `rmrk_nft_id`: ID of the NFT to rearrange resource priorities for.1167		/// - `priorities`: Ordered vector of resource IDs.1168		#[pallet::weight(<SelfWeightOf<T>>::set_priority())]1169		pub fn set_priority(1170			origin: OriginFor<T>,1171			rmrk_collection_id: RmrkCollectionId,1172			rmrk_nft_id: RmrkNftId,1173			priorities: BoundedVec<RmrkResourceId, RmrkMaxPriorities>,1174		) -> DispatchResult {1175			let sender = ensure_signed(origin)?;1176			let sender = T::CrossAccountId::from_sub(sender);11771178			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;1179			let nft_id = rmrk_nft_id.into();11801181			let collection =1182				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1183			collection.check_is_external()?;11841185			let budget = budget::Value::new(NESTING_BUDGET);11861187			Self::ensure_nft_type(collection_id, nft_id, NftType::Regular)?;1188			Self::ensure_nft_owner(collection_id, nft_id, &sender, &budget)?;11891190			<PalletNft<T>>::set_scoped_token_property(1191				collection_id,1192				nft_id,1193				RMRK_SCOPE,1194				Self::encode_rmrk_property(ResourcePriorities, &priorities.into_inner())?,1195			)?;11961197			Self::deposit_event(Event::<T>::PrioritySet {1198				collection_id: rmrk_collection_id,1199				nft_id: rmrk_nft_id,1200			});12011202			Ok(())1203		}12041205		/// Create and set/propose a basic resource for an NFT.1206		///1207		/// A basic resource is the simplest, lacking a Base and anything that comes with it.1208		/// See RMRK docs for more information and examples.1209		///1210		/// # Permissions:1211		/// - Collection issuer - if not the token owner, adding the resource will warrant1212		/// the owner's [acceptance](Pallet::accept_resource).1213		///1214		/// # Arguments:1215		/// - `origin`: sender of the transaction1216		/// - `rmrk_collection_id`: RMRK collection ID of the NFT.1217		/// - `nft_id`: ID of the NFT to assign a resource to.1218		/// - `resource`: Data of the resource to be created.1219		#[pallet::weight(<SelfWeightOf<T>>::add_basic_resource())]1220		pub fn add_basic_resource(1221			origin: OriginFor<T>,1222			rmrk_collection_id: RmrkCollectionId,1223			nft_id: RmrkNftId,1224			resource: RmrkBasicResource,1225		) -> DispatchResult {1226			let sender = ensure_signed(origin.clone())?;12271228			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;1229			let collection =1230				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1231			collection.check_is_external()?;12321233			let resource_id = Self::resource_add(1234				sender,1235				collection_id,1236				nft_id.into(),1237				RmrkResourceTypes::Basic(resource),1238			)?;12391240			Self::deposit_event(Event::ResourceAdded {1241				nft_id,1242				resource_id,1243			});1244			Ok(())1245		}12461247		/// Create and set/propose a composable resource for an NFT.1248		///1249		/// A composable resource links to a Base and has a subset of its Parts it is composed of.1250		/// See RMRK docs for more information and examples.1251		///1252		/// # Permissions:1253		/// - Collection issuer - if not the token owner, adding the resource will warrant1254		/// the owner's [acceptance](Pallet::accept_resource).1255		///1256		/// # Arguments:1257		/// - `origin`: sender of the transaction1258		/// - `rmrk_collection_id`: RMRK collection ID of the NFT.1259		/// - `nft_id`: ID of the NFT to assign a resource to.1260		/// - `resource`: Data of the resource to be created.1261		#[pallet::weight(<SelfWeightOf<T>>::add_composable_resource())]1262		pub fn add_composable_resource(1263			origin: OriginFor<T>,1264			rmrk_collection_id: RmrkCollectionId,1265			nft_id: RmrkNftId,1266			resource: RmrkComposableResource,1267		) -> DispatchResult {1268			let sender = ensure_signed(origin.clone())?;12691270			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;1271			let collection =1272				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1273			collection.check_is_external()?;12741275			let base_id = resource.base;12761277			let resource_id = Self::resource_add(1278				sender,1279				collection_id,1280				nft_id.into(),1281				RmrkResourceTypes::Composable(resource),1282			)?;12831284			<PalletNft<T>>::try_mutate_token_aux_property(1285				collection_id,1286				nft_id.into(),1287				RMRK_SCOPE,1288				Self::get_scoped_property_key(AssociatedBases)?,1289				|value| -> DispatchResult {1290					let mut bases: BasesMap = match value {1291						Some(value) => Self::decode_property_value(value)?,1292						None => BasesMap::new(),1293					};12941295					*bases.entry(base_id).or_insert(0) += 1;12961297					*value = Some(Self::encode_property_value(&bases)?);1298					Ok(())1299				},1300			)?;13011302			Self::deposit_event(Event::ResourceAdded {1303				nft_id,1304				resource_id,1305			});1306			Ok(())1307		}13081309		/// Create and set/propose a slot resource for an NFT.1310		///1311		/// A slot resource links to a Base and a slot ID in it which it can fit into.1312		/// See RMRK docs for more information and examples.1313		///1314		/// # Permissions:1315		/// - Collection issuer - if not the token owner, adding the resource will warrant1316		/// the owner's [acceptance](Pallet::accept_resource).1317		///1318		/// # Arguments:1319		/// - `origin`: sender of the transaction1320		/// - `rmrk_collection_id`: RMRK collection ID of the NFT.1321		/// - `nft_id`: ID of the NFT to assign a resource to.1322		/// - `resource`: Data of the resource to be created.1323		#[pallet::weight(<SelfWeightOf<T>>::add_slot_resource())]1324		pub fn add_slot_resource(1325			origin: OriginFor<T>,1326			rmrk_collection_id: RmrkCollectionId,1327			nft_id: RmrkNftId,1328			resource: RmrkSlotResource,1329		) -> DispatchResult {1330			let sender = ensure_signed(origin.clone())?;13311332			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;1333			let collection =1334				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1335			collection.check_is_external()?;13361337			let resource_id = Self::resource_add(1338				sender,1339				collection_id,1340				nft_id.into(),1341				RmrkResourceTypes::Slot(resource),1342			)?;13431344			Self::deposit_event(Event::ResourceAdded {1345				nft_id,1346				resource_id,1347			});1348			Ok(())1349		}13501351		/// Remove and erase a resource from an NFT.1352		///1353		/// If the sender does not own the NFT, then it will be pending confirmation,1354		/// and will have to be [accepted](Pallet::accept_resource_removal) by the token owner.1355		///1356		/// # Permissions1357		/// - Collection issuer1358		///1359		/// # Arguments1360		/// - `origin`: sender of the transaction1361		/// - `rmrk_collection_id`: RMRK ID of a collection to which the NFT making use of the resource belongs to.1362		/// - `nft_id`: ID of the NFT with a resource to be removed.1363		/// - `resource_id`: ID of the resource to be removed.1364		#[pallet::weight(<SelfWeightOf<T>>::remove_resource())]1365		pub fn remove_resource(1366			origin: OriginFor<T>,1367			rmrk_collection_id: RmrkCollectionId,1368			nft_id: RmrkNftId,1369			resource_id: RmrkResourceId,1370		) -> DispatchResult {1371			let sender = ensure_signed(origin.clone())?;13721373			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;1374			let collection =1375				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1376			collection.check_is_external()?;13771378			Self::resource_remove(sender, collection_id, nft_id.into(), resource_id)?;13791380			Self::deposit_event(Event::ResourceRemoval {1381				nft_id,1382				resource_id,1383			});1384			Ok(())1385		}1386	}1387}13881389impl<T: Config> Pallet<T> {1390	/// Transform one of possible RMRK keys into a byte key with a RMRK scope.1391	pub fn get_scoped_property_key(rmrk_key: RmrkProperty) -> Result<PropertyKey, DispatchError> {1392		let key = rmrk_key.to_key::<T>()?;13931394		let scoped_key = RMRK_SCOPE1395			.apply(key)1396			.map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)?;13971398		Ok(scoped_key)1399	}14001401	/// Form a Unique property, transforming a RMRK key into bytes (without assigning the scope yet)1402	/// and encoding the value from an arbitrary type into bytes.1403	pub fn encode_rmrk_property<E: Encode>(1404		rmrk_key: RmrkProperty,1405		value: &E,1406	) -> Result<Property, DispatchError> {1407		let key = rmrk_key.to_key::<T>()?;14081409		let value = Self::encode_property_value(value)?;14101411		let property = Property { key, value };14121413		Ok(property)1414	}14151416	/// Encode property value from an arbitrary type into bytes for storage.1417	pub fn encode_property_value<E: Encode, S: Get<u32>>(1418		value: &E,1419	) -> Result<BoundedBytes<S>, DispatchError> {1420		let value = value1421			.encode()1422			.try_into()1423			.map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong)?;14241425		Ok(value)1426	}14271428	/// Decode property value from bytes into an arbitrary type.1429	pub fn decode_property_value<D: Decode, S: Get<u32>>(1430		vec: &BoundedBytes<S>,1431	) -> Result<D, DispatchError> {1432		vec.decode()1433			.map_err(|_| <Error<T>>::UnableToDecodeRmrkData.into())1434	}14351436	/// Change the limit of a property value byte vector.1437	pub fn rebind<L, S>(vec: &BoundedVec<u8, L>) -> Result<BoundedVec<u8, S>, DispatchError>1438	where1439		BoundedVec<u8, S>: TryFrom<Vec<u8>>,1440	{1441		vec.rebind()1442			.map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong.into())1443	}14441445	/// Initialize a new NFT collection with certain RMRK-scoped properties.1446	///1447	/// See [`init_collection`](pallet_nonfungible::pallet::Pallet::init_collection) for more details.1448	fn init_collection(1449		sender: T::CrossAccountId,1450		data: CreateCollectionData<T::AccountId>,1451		properties: impl Iterator<Item = Property>,1452	) -> Result<CollectionId, DispatchError> {1453		let collection_id = <PalletNft<T>>::init_collection(1454			sender.clone(),1455			sender,1456			data,1457			up_data_structs::CollectionFlags {1458				external: true,1459				..Default::default()1460			},1461		);14621463		if let Err(DispatchError::Arithmetic(_)) = &collection_id {1464			return Err(<Error<T>>::NoAvailableCollectionId.into());1465		}14661467		<PalletCommon<T>>::set_scoped_collection_properties(1468			collection_id?,1469			RMRK_SCOPE,1470			properties,1471		)?;14721473		collection_id1474	}14751476	/// Mint a new NFT with certain RMRK-scoped properties. Sender must be the collection owner.1477	///1478	/// See [`create_item`](pallet_nonfungible::pallet::Pallet::create_item) for more details.1479	pub fn create_nft(1480		sender: &T::CrossAccountId,1481		owner: &T::CrossAccountId,1482		collection: &NonfungibleHandle<T>,1483		properties: impl Iterator<Item = Property>,1484	) -> Result<TokenId, DispatchError> {1485		let data = CreateNftExData {1486			properties: BoundedVec::default(),1487			owner: owner.clone(),1488		};14891490		let budget = budget::Value::new(NESTING_BUDGET);14911492		<PalletNft<T>>::create_item(collection, sender, data, &budget)?;14931494		let nft_id = <PalletNft<T>>::current_token_id(collection.id);14951496		<PalletNft<T>>::set_scoped_token_properties(collection.id, nft_id, RMRK_SCOPE, properties)?;14971498		Ok(nft_id)1499	}15001501	/// Burn an NFT, along with its nested children, limited by `max_burns`. The sender must be the token owner.1502	///1503	/// See [`burn_recursively`](pallet_nonfungible::pallet::Pallet::burn_recursively) for more details.1504	fn destroy_nft(1505		sender: T::CrossAccountId,1506		collection_id: CollectionId,1507		token_id: TokenId,1508		max_burns: u32,1509		error_if_not_owned: Error<T>,1510	) -> DispatchResultWithPostInfo {1511		let collection =1512			Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;15131514		let token_data =1515			<TokenData<T>>::get((collection_id, token_id)).ok_or(<Error<T>>::NoAvailableNftId)?;15161517		let from = token_data.owner;15181519		let owner_check_budget = budget::Value::new(NESTING_BUDGET);15201521		ensure!(1522			<PalletStructure<T>>::check_indirectly_owned(1523				sender.clone(),1524				collection_id,1525				token_id,1526				None,1527				&owner_check_budget1528			)?,1529			error_if_not_owned,1530		);15311532		let burns_budget = budget::Value::new(max_burns);1533		let breadth_budget = budget::Value::new(max_burns);15341535		<PalletNft<T>>::burn_recursively(1536			&collection,1537			&from,1538			token_id,1539			&burns_budget,1540			&breadth_budget,1541		)1542	}15431544	/// Add a sent token pending acceptance to the target owning token as a property.1545	fn insert_pending_child(1546		target: (CollectionId, TokenId),1547		child: (RmrkCollectionId, RmrkNftId),1548	) -> DispatchResult {1549		Self::mutate_pending_children(target, |pending_children| {1550			pending_children.insert(child);1551		})1552	}15531554	/// Remove a sent token pending acceptance from the target token's properties.1555	fn remove_pending_child(1556		target: (CollectionId, TokenId),1557		child: (RmrkCollectionId, RmrkNftId),1558	) -> DispatchResult {1559		Self::mutate_pending_children(target, |pending_children| {1560			pending_children.remove(&child);1561		})1562	}15631564	/// Apply a mutation to the property of a token containing sent tokens1565	/// that are currently pending acceptance.1566	fn mutate_pending_children(1567		(target_collection_id, target_nft_id): (CollectionId, TokenId),1568		f: impl FnOnce(&mut PendingChildrenSet),1569	) -> DispatchResult {1570		<PalletNft<T>>::try_mutate_token_aux_property(1571			target_collection_id,1572			target_nft_id,1573			RMRK_SCOPE,1574			Self::get_scoped_property_key(PendingChildren)?,1575			|pending_children| -> DispatchResult {1576				let mut map = match pending_children {1577					Some(map) => Self::decode_property_value(map)?,1578					None => PendingChildrenSet::new(),1579				};15801581				f(&mut map);15821583				*pending_children = Some(Self::encode_property_value(&map)?);15841585				Ok(())1586			},1587		)1588	}15891590	/// Get an iterator from a token's property containing tokens sent to it1591	/// that are currently pending acceptance.1592	fn iterate_pending_children(1593		collection_id: CollectionId,1594		nft_id: TokenId,1595	) -> Result<impl Iterator<Item = PendingChild>, DispatchError> {1596		let property = <PalletNft<T>>::token_aux_property((1597			collection_id,1598			nft_id,1599			RMRK_SCOPE,1600			Self::get_scoped_property_key(PendingChildren)?,1601		));16021603		let pending_children = match property {1604			Some(map) => Self::decode_property_value(&map)?,1605			None => PendingChildrenSet::new(),1606		};16071608		Ok(pending_children.into_iter())1609	}16101611	/// Get incremented resource ID from within an NFT's properties and store the new latest ID.1612	/// Thus, the returned resource ID should be used.1613	///1614	/// Resource IDs are unique only across an NFT.1615	fn acquire_next_resource_id(1616		collection_id: CollectionId,1617		nft_id: TokenId,1618	) -> Result<RmrkResourceId, DispatchError> {1619		let resource_id: RmrkResourceId =1620			Self::get_nft_property_decoded(collection_id, nft_id, NextResourceId)?;16211622		let next_id = resource_id1623			.checked_add(1)1624			.ok_or(<Error<T>>::NoAvailableResourceId)?;16251626		<PalletNft<T>>::set_scoped_token_property(1627			collection_id,1628			nft_id,1629			RMRK_SCOPE,1630			Self::encode_rmrk_property(NextResourceId, &next_id)?,1631		)?;16321633		Ok(resource_id)1634	}16351636	/// Create and add a resource for a regular NFT, mark it as pending if the sender1637	/// is not the token owner. The sender must be the collection owner.1638	fn resource_add(1639		sender: T::AccountId,1640		collection_id: CollectionId,1641		nft_id: TokenId,1642		resource: RmrkResourceTypes,1643	) -> Result<RmrkResourceId, DispatchError> {1644		let collection =1645			Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1646		ensure!(collection.owner == sender, Error::<T>::NoPermission);16471648		let sender = T::CrossAccountId::from_sub(sender);1649		let budget = budget::Value::new(NESTING_BUDGET);16501651		let nft_owner = <PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)1652			.map_err(Self::map_unique_err_to_proxy)?;16531654		let pending = sender != nft_owner;16551656		let id = Self::acquire_next_resource_id(collection_id, nft_id)?;16571658		let resource_info = RmrkResourceInfo {1659			id,1660			resource,1661			pending,1662			pending_removal: false,1663		};16641665		<PalletNft<T>>::try_mutate_token_aux_property(1666			collection_id,1667			nft_id,1668			RMRK_SCOPE,1669			Self::get_scoped_property_key(ResourceId(id))?,1670			|value| -> DispatchResult {1671				*value = Some(Self::encode_property_value(&resource_info)?);16721673				Ok(())1674			},1675		)?;16761677		Ok(id)1678	}16791680	/// Designate a resource for erasure from an NFT, and remove it if the sender is the token owner.1681	/// The sender must be the collection owner.1682	fn resource_remove(1683		sender: T::AccountId,1684		collection_id: CollectionId,1685		nft_id: TokenId,1686		resource_id: RmrkResourceId,1687	) -> DispatchResult {1688		let collection =1689			Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1690		ensure!(collection.owner == sender, Error::<T>::NoPermission);16911692		let resource_id_key = Self::get_scoped_property_key(ResourceId(resource_id))?;16931694		let resource = <PalletNft<T>>::token_aux_property((1695			collection_id,1696			nft_id,1697			RMRK_SCOPE,1698			resource_id_key.clone(),1699		))1700		.ok_or(<Error<T>>::ResourceDoesntExist)?;17011702		let resource_info: RmrkResourceInfo = Self::decode_property_value(&resource)?;17031704		let budget = up_data_structs::budget::Value::new(NESTING_BUDGET);1705		let topmost_owner =1706			<PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)?;17071708		let sender = T::CrossAccountId::from_sub(sender);1709		if topmost_owner == sender {1710			<PalletNft<T>>::remove_token_aux_property(1711				collection_id,1712				nft_id,1713				RMRK_SCOPE,1714				Self::get_scoped_property_key(ResourceId(resource_id))?,1715			);17161717			if let RmrkResourceTypes::Composable(resource) = resource_info.resource {1718				let base_id = resource.base;17191720				Self::remove_associated_base_id(collection_id, nft_id, base_id)?;1721			}1722		} else {1723			Self::try_mutate_resource_info(collection_id, nft_id, resource_id, |res| {1724				res.pending_removal = true;17251726				Ok(())1727			})?;1728		}17291730		Ok(())1731	}17321733	/// Remove a Base ID from an NFT if they are associated.1734	/// The Base itself is deleted if the number of associated NFTs reaches 0.1735	fn remove_associated_base_id(1736		collection_id: CollectionId,1737		nft_id: TokenId,1738		base_id: RmrkBaseId,1739	) -> DispatchResult {1740		<PalletNft<T>>::try_mutate_token_aux_property(1741			collection_id,1742			nft_id,1743			RMRK_SCOPE,1744			Self::get_scoped_property_key(AssociatedBases)?,1745			|value| -> DispatchResult {1746				let mut bases: BasesMap = match value {1747					Some(value) => Self::decode_property_value(value)?,1748					None => BasesMap::new(),1749				};17501751				let remaining = bases.get(&base_id);17521753				if let Some(remaining) = remaining {1754					if let Some(0) | None = remaining.checked_sub(1) {1755						bases.remove(&base_id);1756					}1757				}17581759				*value = Some(Self::encode_property_value(&bases)?);1760				Ok(())1761			},1762		)1763	}17641765	/// Apply a mutation to a resource stored in the token properties of an NFT.1766	fn try_mutate_resource_info(1767		collection_id: CollectionId,1768		nft_id: TokenId,1769		resource_id: RmrkResourceId,1770		f: impl FnOnce(&mut RmrkResourceInfo) -> DispatchResult,1771	) -> DispatchResult {1772		<PalletNft<T>>::try_mutate_token_aux_property(1773			collection_id,1774			nft_id,1775			RMRK_SCOPE,1776			Self::get_scoped_property_key(ResourceId(resource_id))?,1777			|value| match value {1778				Some(value) => {1779					let mut resource_info: RmrkResourceInfo = Self::decode_property_value(value)?;17801781					f(&mut resource_info)?;17821783					*value = Self::encode_property_value(&resource_info)?;17841785					Ok(())1786				}1787				None => Err(<Error<T>>::ResourceDoesntExist.into()),1788			},1789		)1790	}17911792	/// Change the owner of an NFT collection, ensuring that the sender is the current owner.1793	fn change_collection_owner(1794		collection_id: CollectionId,1795		collection_type: misc::CollectionType,1796		sender: T::AccountId,1797		new_owner: T::AccountId,1798	) -> DispatchResult {1799		let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;1800		Self::check_collection_owner(&collection, &T::CrossAccountId::from_sub(sender))?;18011802		let mut collection = collection.into_inner();18031804		collection.owner = new_owner;1805		collection.save()1806	}18071808	/// Ensure that an account is the collection owner/issuer, return an error if not.1809	pub fn check_collection_owner(1810		collection: &NonfungibleHandle<T>,1811		account: &T::CrossAccountId,1812	) -> DispatchResult {1813		collection1814			.check_is_owner(account)1815			.map_err(Self::map_unique_err_to_proxy)1816	}18171818	/// Get the latest yet-unused RMRK collection index from the storage.1819	pub fn last_collection_idx() -> RmrkCollectionId {1820		<CollectionIndex<T>>::get()1821	}18221823	/// Get a mapping from a RMRK collection ID to its corresponding Unique collection ID.1824	pub fn unique_collection_id(1825		rmrk_collection_id: RmrkCollectionId,1826	) -> Result<CollectionId, DispatchError> {1827		<UniqueCollectionId<T>>::try_get(rmrk_collection_id)1828			.map_err(|_| <Error<T>>::CollectionUnknown.into())1829	}18301831	/// Get a mapping from a Unique collection ID to its RMRK collection ID counterpart, if it exists.1832	pub fn rmrk_collection_id(1833		unique_collection_id: CollectionId,1834	) -> Result<RmrkCollectionId, DispatchError> {1835		Self::get_collection_property_decoded(unique_collection_id, RmrkInternalCollectionId)1836	}18371838	/// Fetch a Unique NFT collection.1839	pub fn get_nft_collection(1840		collection_id: CollectionId,1841	) -> Result<NonfungibleHandle<T>, DispatchError> {1842		let collection = <CollectionHandle<T>>::try_get(collection_id)1843			.map_err(|_| <Error<T>>::CollectionUnknown)?;18441845		match collection.mode {1846			CollectionMode::NFT => Ok(NonfungibleHandle::cast(collection)),1847			_ => Err(<Error<T>>::CollectionUnknown.into()),1848		}1849	}18501851	/// Check if an NFT collection with such an ID exists.1852	pub fn collection_exists(collection_id: CollectionId) -> bool {1853		<CollectionHandle<T>>::try_get(collection_id).is_ok()1854	}18551856	/// Fetch and decode a RMRK-scoped collection property value in bytes.1857	pub fn get_collection_property(1858		collection_id: CollectionId,1859		key: RmrkProperty,1860	) -> Result<PropertyValue, DispatchError> {1861		let collection_property = <PalletCommon<T>>::collection_properties(collection_id)1862			.get(&Self::get_scoped_property_key(key)?)1863			.ok_or(<Error<T>>::CollectionUnknown)?1864			.clone();18651866		Ok(collection_property)1867	}18681869	/// Fetch a RMRK-scoped collection property and decode it from bytes into an appropriate type.1870	pub fn get_collection_property_decoded<V: Decode>(1871		collection_id: CollectionId,1872		key: RmrkProperty,1873	) -> Result<V, DispatchError> {1874		Self::decode_property_value(&Self::get_collection_property(collection_id, key)?)1875	}18761877	/// Get the type of a collection stored as a scoped property.1878	///1879	/// RMRK Core proxy differentiates between regular collections as well as RMRK Bases as collections.1880	pub fn get_collection_type(1881		collection_id: CollectionId,1882	) -> Result<misc::CollectionType, DispatchError> {1883		Self::get_collection_property_decoded(collection_id, CollectionType).map_err(|err| {1884			if err != <Error<T>>::CollectionUnknown.into() {1885				<Error<T>>::CorruptedCollectionType.into()1886			} else {1887				err1888			}1889		})1890	}18911892	/// Ensure that the type of the collection equals the provided type,1893	/// otherwise return an error.1894	pub fn ensure_collection_type(1895		collection_id: CollectionId,1896		collection_type: misc::CollectionType,1897	) -> DispatchResult {1898		let actual_type = Self::get_collection_type(collection_id)?;1899		ensure!(1900			actual_type == collection_type,1901			<CommonError<T>>::NoPermission1902		);19031904		Ok(())1905	}19061907	/// Fetch an NFT collection, but make sure it has the appropriate type.1908	pub fn get_typed_nft_collection(1909		collection_id: CollectionId,1910		collection_type: misc::CollectionType,1911	) -> Result<NonfungibleHandle<T>, DispatchError> {1912		Self::ensure_collection_type(collection_id, collection_type)?;19131914		Self::get_nft_collection(collection_id)1915	}19161917	/// Same as [`get_typed_nft_collection`](crate::pallet::Pallet::get_typed_nft_collection),1918	/// but also return the Unique collection ID.1919	pub fn get_typed_nft_collection_mapped(1920		rmrk_collection_id: RmrkCollectionId,1921		collection_type: misc::CollectionType,1922	) -> Result<(NonfungibleHandle<T>, CollectionId), DispatchError> {1923		let unique_collection_id = match collection_type {1924			misc::CollectionType::Regular => Self::unique_collection_id(rmrk_collection_id)?,1925			_ => rmrk_collection_id.into(),1926		};19271928		let collection = Self::get_typed_nft_collection(unique_collection_id, collection_type)?;19291930		Ok((collection, unique_collection_id))1931	}19321933	/// Fetch and decode a RMRK-scoped NFT property value in bytes.1934	pub fn get_nft_property(1935		collection_id: CollectionId,1936		nft_id: TokenId,1937		key: RmrkProperty,1938	) -> Result<PropertyValue, DispatchError> {1939		let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))1940			.get(&Self::get_scoped_property_key(key)?)1941			.ok_or(<Error<T>>::RmrkPropertyIsNotFound)?1942			.clone();19431944		Ok(nft_property)1945	}19461947	/// Fetch a RMRK-scoped NFT property and decode it from bytes into an appropriate type.1948	pub fn get_nft_property_decoded<V: Decode>(1949		collection_id: CollectionId,1950		nft_id: TokenId,1951		key: RmrkProperty,1952	) -> Result<V, DispatchError> {1953		Self::decode_property_value(&Self::get_nft_property(collection_id, nft_id, key)?)1954	}19551956	/// Check that an NFT exists.1957	pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {1958		<TokenData<T>>::contains_key((collection_id, nft_id))1959	}19601961	/// Get the type of an NFT stored as a scoped property.1962	///1963	/// RMRK Core proxy differentiates between regular NFTs, and RMRK Parts and Themes.1964	pub fn get_nft_type(1965		collection_id: CollectionId,1966		token_id: TokenId,1967	) -> Result<NftType, DispatchError> {1968		Self::get_nft_property_decoded(collection_id, token_id, TokenType)1969			.map_err(|_| <Error<T>>::NoAvailableNftId.into())1970	}19711972	/// Ensure that the type of the NFT equals the provided type, otherwise return an error.1973	pub fn ensure_nft_type(1974		collection_id: CollectionId,1975		token_id: TokenId,1976		nft_type: NftType,1977	) -> DispatchResult {1978		let actual_type = Self::get_nft_type(collection_id, token_id)?;1979		ensure!(actual_type == nft_type, <Error<T>>::NoPermission);19801981		Ok(())1982	}19831984	/// Ensure that an account is the owner of the token, either directly1985	/// or at the top of the nesting hierarchy; return an error if it is not.1986	pub fn ensure_nft_owner(1987		collection_id: CollectionId,1988		token_id: TokenId,1989		possible_owner: &T::CrossAccountId,1990		nesting_budget: &dyn budget::Budget,1991	) -> DispatchResult {1992		let is_owned = <PalletStructure<T>>::check_indirectly_owned(1993			possible_owner.clone(),1994			collection_id,1995			token_id,1996			None,1997			nesting_budget,1998		)1999		.map_err(Self::map_unique_err_to_proxy)?;20002001		ensure!(is_owned, <Error<T>>::NoPermission);20022003		Ok(())2004	}20052006	/// Fetch non-scoped properties of a collection or a token that match the filter keys supplied,2007	/// or, if None are provided, return all non-scoped properties.2008	pub fn filter_user_properties<Key, Value, R, Mapper>(2009		collection_id: CollectionId,2010		token_id: Option<TokenId>,2011		filter_keys: Option<Vec<RmrkPropertyKey>>,2012		mapper: Mapper,2013	) -> Result<Vec<R>, DispatchError>2014	where2015		Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,2016		Value: Decode + Default,2017		Mapper: Fn(Key, Value) -> R,2018	{2019		filter_keys2020			.map(|keys| {2021				let properties = keys2022					.into_iter()2023					.filter_map(|key| {2024						let key: Key = key.try_into().ok()?;20252026						let value = match token_id {2027							Some(token_id) => Self::get_nft_property_decoded(2028								collection_id,2029								token_id,2030								UserProperty(key.as_ref()),2031							),2032							None => Self::get_collection_property_decoded(2033								collection_id,2034								UserProperty(key.as_ref()),2035							),2036						}2037						.ok()?;20382039						Some(mapper(key, value))2040					})2041					.collect();20422043				Ok(properties)2044			})2045			.unwrap_or_else(|| {2046				let properties =2047					Self::iterate_user_properties(collection_id, token_id, mapper)?.collect();20482049				Ok(properties)2050			})2051	}20522053	/// Get all non-scoped properties from a collection or a token, and apply some transformation,2054	/// supplied by `mapper`, to each key-value pair.2055	pub fn iterate_user_properties<Key, Value, R, Mapper>(2056		collection_id: CollectionId,2057		token_id: Option<TokenId>,2058		mapper: Mapper,2059	) -> Result<impl Iterator<Item = R>, DispatchError>2060	where2061		Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,2062		Value: Decode + Default,2063		Mapper: Fn(Key, Value) -> R,2064	{2065		let properties = match token_id {2066			Some(token_id) => <PalletNft<T>>::token_properties((collection_id, token_id)),2067			None => <PalletCommon<T>>::collection_properties(collection_id),2068		};20692070		let properties = properties.into_iter().filter_map(move |(key, value)| {2071			let key = strip_key_prefix(&key, USER_PROPERTY_PREFIX)?;20722073			let key: Key = key.to_vec().try_into().ok()?;2074			let value: Value = value.decode().ok()?;20752076			Some(mapper(key, value))2077		});20782079		Ok(properties)2080	}20812082	/// Match Unique errors to RMRK's own and return the RMRK error if a match is successful.2083	fn map_unique_err_to_proxy(err: DispatchError) -> DispatchError {2084		map_unique_err_to_proxy! {2085			match err {2086				CommonError::NoPermission => NoPermission,2087				CommonError::CollectionTokenLimitExceeded => CollectionFullOrLocked,2088				CommonError::PublicMintingNotAllowed => NoPermission,2089				CommonError::TokenNotFound => NoAvailableNftId,2090				CommonError::ApprovedValueTooLow => NoPermission,2091				CommonError::CantDestroyNotEmptyCollection => CollectionNotEmpty,2092				StructureError::TokenNotFound => NoAvailableNftId,2093				StructureError::OuroborosDetected => CannotSendToDescendentOrSelf,2094			}2095		}2096	}2097}
modifiedpallets/proxy-rmrk-equip/Cargo.tomldiffbeforeafterboth
--- a/pallets/proxy-rmrk-equip/Cargo.toml
+++ b/pallets/proxy-rmrk-equip/Cargo.toml
@@ -19,7 +19,7 @@
 pallet-common = { default-features = false, path = '../common' }
 pallet-nonfungible = { default-features = false, path = "../../pallets/nonfungible" }
 up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 rmrk-traits = { default-features = false, path = "../../primitives/rmrk-traits" }
 scale-info = { version = "2.0.1", default-features = false, features = [
modifiedpallets/refungible/Cargo.tomldiffbeforeafterboth
--- a/pallets/refungible/Cargo.toml
+++ b/pallets/refungible/Cargo.toml
@@ -16,7 +16,7 @@
 sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 evm-coder = { default-features = false, path = '../../crates/evm-coder' }
 pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
 pallet-common = { default-features = false, path = '../common' }
modifiedpallets/structure/Cargo.tomldiffbeforeafterboth
--- a/pallets/structure/Cargo.toml
+++ b/pallets/structure/Cargo.toml
@@ -16,7 +16,7 @@
 	"derive",
 ] }
 up-data-structs = { path = "../../primitives/data-structs", default-features = false }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 
 [features]
 default = ["std"]
modifiedpallets/unique/Cargo.tomldiffbeforeafterboth
--- a/pallets/unique/Cargo.toml
+++ b/pallets/unique/Cargo.toml
@@ -100,7 +100,7 @@
 scale-info = { version = "2.0.1", default-features = false, features = [
     "derive",
 ] }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 pallet-common = { default-features = false, path = "../common" }
 evm-coder = { default-features = false, path = '../../crates/evm-coder' }
 pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -138,7 +138,7 @@
 	pub enum Event<T>
 	where
 		<T as frame_system::Config>::AccountId,
-		<T as pallet_evm::account::Config>::CrossAccountId,
+		<T as pallet_evm::Config>::CrossAccountId,
 	{
 		/// Collection sponsor was removed
 		///
modifiedprimitives/app_promotion_rpc/Cargo.tomldiffbeforeafterboth
--- a/primitives/app_promotion_rpc/Cargo.toml
+++ b/primitives/app_promotion_rpc/Cargo.toml
@@ -14,7 +14,7 @@
 sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 
 [features]
 default = ["std"]
modifiedprimitives/common/Cargo.tomldiffbeforeafterboth
--- a/primitives/common/Cargo.toml
+++ b/primitives/common/Cargo.toml
@@ -48,9 +48,9 @@
 [dependencies.fp-rpc]
 default-features = false
 git = "https://github.com/uniquenetwork/frontier"
-branch = "unique-polkadot-v0.9.30"
+branch = "unique-polkadot-v0.9.30-2"
 
 [dependencies.pallet-evm]
 default-features = false
 git = "https://github.com/uniquenetwork/frontier"
-branch = "unique-polkadot-v0.9.30"
+branch = "unique-polkadot-v0.9.30-2"
modifiedprimitives/data-structs/Cargo.tomldiffbeforeafterboth
--- a/primitives/data-structs/Cargo.toml
+++ b/primitives/data-structs/Cargo.toml
@@ -25,9 +25,11 @@
 sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 derivative = { version = "2.2.0", features = ["use_core"] }
 struct-versioning = { path = "../../crates/struct-versioning" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 rmrk-traits = { default-features = false, path = "../rmrk-traits" }
-bondrewd = { version = "0.1.14", features = ["derive"], default-features = false }
+bondrewd = { version = "0.1.14", features = [
+  "derive",
+], default-features = false }
 
 [features]
 default = ["std"]
modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -962,12 +962,15 @@
 		use scale_info::{
 			Type, Path,
 			build::{FieldsBuilder, UnnamedFields},
+			form::MetaForm,
 			type_params,
 		};
 		Type::builder()
 			.path(Path::new("up_data_structs", "PhantomType"))
 			.type_params(type_params!(T))
-			.composite(<FieldsBuilder<UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()))
+			.composite(
+				<FieldsBuilder<MetaForm, UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()),
+			)
 	}
 }
 impl<T> MaxEncodedLen for PhantomType<T> {
modifiedprimitives/rpc/Cargo.tomldiffbeforeafterboth
--- a/primitives/rpc/Cargo.toml
+++ b/primitives/rpc/Cargo.toml
@@ -14,7 +14,7 @@
 sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 
 [features]
 default = ["std"]
modifiedruntime/common/config/ethereum.rsdiffbeforeafterboth
--- a/runtime/common/config/ethereum.rs
+++ b/runtime/common/config/ethereum.rs
@@ -17,19 +17,15 @@
 
 pub type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;
 
-impl pallet_evm::account::Config for Runtime {
-	type CrossAccountId = CrossAccountId;
-	type EvmAddressMapping = pallet_evm::HashedAddressMapping<Self::Hashing>;
-	type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;
-}
-
 // Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case
 // (contract, which only writes a lot of data),
 // approximating on top of our real store write weight
 parameter_types! {
 	pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND.ref_time() / <Runtime as frame_system::Config>::DbWeight::get().write;
 	pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;
-	pub const WeightPerGas: u64 = WEIGHT_PER_SECOND.ref_time() / GasPerSecond::get();
+	pub const WeightTimePerGas: u64 = WEIGHT_PER_SECOND.ref_time() / GasPerSecond::get();
+
+	pub const WeightPerGas: Weight = Weight::from_ref_time(WeightTimePerGas::get());
 }
 
 /// Limiting EVM execution to 50% of block for substrate users and management tasks
@@ -37,17 +33,7 @@
 /// scheduled fairly
 const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);
 parameter_types! {
-	pub BlockGasLimit: U256 = U256::from((NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get()).ref_time());
-}
-
-pub enum FixedGasWeightMapping {}
-impl pallet_evm::GasWeightMapping for FixedGasWeightMapping {
-	fn gas_to_weight(gas: u64) -> Weight {
-		Weight::from_ref_time(gas).saturating_mul(WeightPerGas::get())
-	}
-	fn weight_to_gas(weight: Weight) -> u64 {
-		(weight / WeightPerGas::get()).ref_time()
-	}
+	pub BlockGasLimit: U256 = U256::from((NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightTimePerGas::get()).ref_time());
 }
 
 pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);
@@ -65,9 +51,13 @@
 }
 
 impl pallet_evm::Config for Runtime {
+	type CrossAccountId = CrossAccountId;
+	type EvmAddressMapping = pallet_evm::HashedAddressMapping<Self::Hashing>;
+	type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;
 	type BlockGasLimit = BlockGasLimit;
 	type FeeCalculator = pallet_configuration::FeeCalculator<Self>;
-	type GasWeightMapping = FixedGasWeightMapping;
+	type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
+	type WeightPerGas = WeightPerGas;
 	type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
 	type CallOrigin = EnsureAddressTruncated<Self>;
 	type WithdrawOrigin = EnsureAddressTruncated<Self>;
modifiedruntime/common/ethereum/self_contained_call.rsdiffbeforeafterboth
--- a/runtime/common/ethereum/self_contained_call.rs
+++ b/runtime/common/ethereum/self_contained_call.rs
@@ -69,9 +69,13 @@
 	fn pre_dispatch_self_contained(
 		&self,
 		info: &Self::SignedInfo,
+		dispatch_info: &DispatchInfoOf<RuntimeCall>,
+		len: usize,
 	) -> Option<Result<(), TransactionValidityError>> {
 		match self {
-			RuntimeCall::Ethereum(call) => call.pre_dispatch_self_contained(info),
+			RuntimeCall::Ethereum(call) => {
+				call.pre_dispatch_self_contained(info, dispatch_info, len)
+			}
 			_ => None,
 		}
 	}
modifiedruntime/common/runtime_apis.rsdiffbeforeafterboth
--- a/runtime/common/runtime_apis.rs
+++ b/runtime/common/runtime_apis.rs
@@ -493,6 +493,7 @@
                         nonce,
                         access_list.unwrap_or_default(),
                         is_transactional,
+                        false,
                         config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),
                     ).map_err(|err| err.error.into())
                 }
@@ -528,6 +529,7 @@
                         nonce,
                         access_list.unwrap_or_default(),
                         is_transactional,
+                        false,
                         config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),
                     ).map_err(|err| err.error.into())
                 }
modifiedruntime/opal/Cargo.tomldiffbeforeafterboth
--- a/runtime/opal/Cargo.toml
+++ b/runtime/opal/Cargo.toml
@@ -82,7 +82,6 @@
     'pallet-proxy-rmrk-equip/try-runtime',
     'pallet-app-promotion/try-runtime',
     'pallet-foreign-assets/try-runtime',
-    'pallet-evm/try-runtime',
     'pallet-ethereum/try-runtime',
     'pallet-evm-coder-substrate/try-runtime',
     'pallet-evm-contract-helpers/try-runtime',
@@ -174,7 +173,14 @@
     'pallet-test-utils?/std',
 ]
 limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
-opal-runtime = ['refungible', 'scheduler', 'rmrk', 'app-promotion', 'foreign-assets', 'pallet-test-utils']
+opal-runtime = [
+    'refungible',
+    'scheduler',
+    'rmrk',
+    'app-promotion',
+    'foreign-assets',
+    'pallet-test-utils',
+]
 
 refungible = []
 scheduler = []
@@ -461,7 +467,7 @@
 up-rpc = { path = "../../primitives/rpc", default-features = false }
 app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false }
 rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false }
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 pallet-inflation = { path = '../../pallets/inflation', default-features = false }
 pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }
 up-data-structs = { path = '../../primitives/data-structs', default-features = false }
@@ -479,11 +485,11 @@
 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, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 evm-coder = { default-features = false, path = '../../crates/evm-coder' }
 up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.30' }
 pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }
modifiedruntime/quartz/Cargo.tomldiffbeforeafterboth
--- a/runtime/quartz/Cargo.toml
+++ b/runtime/quartz/Cargo.toml
@@ -80,7 +80,6 @@
     'pallet-proxy-rmrk-equip/try-runtime',
     'pallet-app-promotion/try-runtime',
     'pallet-foreign-assets/try-runtime',
-    'pallet-evm/try-runtime',
     'pallet-ethereum/try-runtime',
     'pallet-evm-coder-substrate/try-runtime',
     'pallet-evm-contract-helpers/try-runtime',
@@ -460,7 +459,7 @@
 pallet-unique = { path = '../../pallets/unique', default-features = false }
 up-rpc = { path = "../../primitives/rpc", default-features = false }
 app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false }
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 pallet-inflation = { path = '../../pallets/inflation', default-features = false }
 pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }
 up-data-structs = { path = '../../primitives/data-structs', default-features = false }
@@ -478,11 +477,11 @@
 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, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 evm-coder = { default-features = false, path = '../../crates/evm-coder' }
 up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.30' }
 pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }
modifiedruntime/tests/Cargo.tomldiffbeforeafterboth
--- a/runtime/tests/Cargo.toml
+++ b/runtime/tests/Cargo.toml
@@ -16,7 +16,7 @@
 sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 
 frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
@@ -25,8 +25,8 @@
 pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
 
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 
 pallet-common = { path = '../../pallets/common' }
 pallet-structure = { path = '../../pallets/structure' }
modifiedruntime/tests/src/lib.rsdiffbeforeafterboth
--- a/runtime/tests/src/lib.rs
+++ b/runtime/tests/src/lib.rs
@@ -21,6 +21,7 @@
 	parameter_types,
 	traits::{Everything, ConstU32, ConstU64},
 	weights::IdentityFee,
+	pallet_prelude::Weight,
 };
 use sp_runtime::{
 	traits::{BlakeTwo256, IdentityLookup},
@@ -202,6 +203,7 @@
 
 parameter_types! {
 	pub BlockGasLimit: U256 = 0u32.into();
+	pub WeightPerGas: Weight = Weight::from_ref_time(20);
 }
 
 impl pallet_ethereum::Config for Test {
@@ -210,11 +212,15 @@
 }
 
 impl pallet_evm::Config for Test {
+	type CrossAccountId = TestCrossAccountId;
+	type EvmAddressMapping = TestEvmAddressMapping;
+	type EvmBackwardsAddressMapping = TestEvmBackwardsAddressMapping;
 	type RuntimeEvent = RuntimeEvent;
 	type FeeCalculator = ();
-	type GasWeightMapping = ();
-	type CallOrigin = EnsureAddressNever<Self::CrossAccountId>;
-	type WithdrawOrigin = EnsureAddressNever<Self::CrossAccountId>;
+	type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
+	type WeightPerGas = WeightPerGas;
+	type CallOrigin = EnsureAddressNever<Self>;
+	type WithdrawOrigin = EnsureAddressNever<Self>;
 	type AddressMapping = TestEvmAddressMapping;
 	type Currency = Balances;
 	type PrecompilesType = ();
@@ -242,12 +248,6 @@
 	type EvmTokenAddressMapping = EvmTokenAddressMapping;
 	type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;
 	type ContractAddress = EvmCollectionHelpersAddress;
-}
-
-impl pallet_evm::account::Config for Test {
-	type CrossAccountId = TestCrossAccountId;
-	type EvmAddressMapping = TestEvmAddressMapping;
-	type EvmBackwardsAddressMapping = TestEvmBackwardsAddressMapping;
 }
 
 impl pallet_structure::Config for Test {
modifiedruntime/unique/Cargo.tomldiffbeforeafterboth
--- a/runtime/unique/Cargo.toml
+++ b/runtime/unique/Cargo.toml
@@ -81,7 +81,6 @@
     'pallet-proxy-rmrk-equip/try-runtime',
     'pallet-app-promotion/try-runtime',
     'pallet-foreign-assets/try-runtime',
-    'pallet-evm/try-runtime',
     'pallet-ethereum/try-runtime',
     'pallet-evm-coder-substrate/try-runtime',
     'pallet-evm-contract-helpers/try-runtime',
@@ -472,12 +471,12 @@
 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, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30-2" }
 evm-coder = { default-features = false, path = '../../crates/evm-coder' }
 up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.30' }
 pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }
modifiedtests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth
--- a/tests/src/eth/contractSponsoring.test.ts
+++ b/tests/src/eth/contractSponsoring.test.ts
@@ -372,7 +372,7 @@
     const originalFlipperBalance = await helper.balance.getEthereum(flipper.options.address);
     expect(originalFlipperBalance).to.be.not.equal('0');
 
-    await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/InvalidTransaction::Payment/);
+    await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/Returned error: insufficient funds for gas \* price \+ value/);
     expect(await flipper.methods.getValue().call()).to.be.false;
 
     // Balance should be taken from flipper instead of caller
modifiedtests/src/interfaces/augment-api-errors.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-errors.ts
+++ b/tests/src/interfaces/augment-api-errors.ts
@@ -265,6 +265,14 @@
        **/
       FeeOverflow: AugmentedError<ApiType>;
       /**
+       * Gas limit is too high.
+       **/
+      GasLimitTooHigh: AugmentedError<ApiType>;
+      /**
+       * Gas limit is too low.
+       **/
+      GasLimitTooLow: AugmentedError<ApiType>;
+      /**
        * Gas price is too low.
        **/
       GasPriceTooLow: AugmentedError<ApiType>;
@@ -277,6 +285,14 @@
        **/
       PaymentOverflow: AugmentedError<ApiType>;
       /**
+       * EVM reentrancy
+       **/
+      Reentrancy: AugmentedError<ApiType>;
+      /**
+       * Undefined error.
+       **/
+      Undefined: AugmentedError<ApiType>;
+      /**
        * Withdraw fee failed
        **/
       WithdrawFailed: AugmentedError<ApiType>;
modifiedtests/src/interfaces/augment-api-events.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-events.ts
+++ b/tests/src/interfaces/augment-api-events.ts
@@ -6,7 +6,7 @@
 import '@polkadot/api-base/types/events';
 
 import type { ApiTypes, AugmentedEvent } from '@polkadot/api-base/types';
-import type { Bytes, Null, Option, Result, U256, U8aFixed, bool, u128, u32, u64, u8 } from '@polkadot/types-codec';
+import type { Bytes, Null, Option, Result, U8aFixed, bool, u128, u32, u64, u8 } from '@polkadot/types-codec';
 import type { ITuple } from '@polkadot/types-codec/types';
 import type { AccountId32, H160, H256, Weight } from '@polkadot/types/interfaces/runtime';
 import type { EthereumLog, EvmCoreErrorExitReason, FrameSupportDispatchDispatchInfo, FrameSupportScheduleLookupError, FrameSupportTokensMiscBalanceStatus, OrmlVestingVestingSchedule, PalletEvmAccountBasicCrossAccountIdRepr, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, RmrkTraitsNftAccountIdOrCollectionNftTuple, SpRuntimeDispatchError, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetMultiAssets, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation } from '@polkadot/types/lookup';
@@ -204,9 +204,9 @@
     };
     ethereum: {
       /**
-       * An ethereum transaction was successfully executed. [from, to/contract_address, transaction_hash, exit_reason]
+       * An ethereum transaction was successfully executed.
        **/
-      Executed: AugmentedEvent<ApiType, [H160, H160, H256, EvmCoreErrorExitReason]>;
+      Executed: AugmentedEvent<ApiType, [from: H160, to: H160, transactionHash: H256, exitReason: EvmCoreErrorExitReason], { from: H160, to: H160, transactionHash: H256, exitReason: EvmCoreErrorExitReason }>;
       /**
        * Generic event
        **/
@@ -214,33 +214,25 @@
     };
     evm: {
       /**
-       * A deposit has been made at a given address. \[sender, address, value\]
+       * A contract has been created at given address.
        **/
-      BalanceDeposit: AugmentedEvent<ApiType, [AccountId32, H160, U256]>;
+      Created: AugmentedEvent<ApiType, [address: H160], { address: H160 }>;
       /**
-       * A withdrawal has been made from a given address. \[sender, address, value\]
+       * A contract was attempted to be created, but the execution failed.
        **/
-      BalanceWithdraw: AugmentedEvent<ApiType, [AccountId32, H160, U256]>;
+      CreatedFailed: AugmentedEvent<ApiType, [address: H160], { address: H160 }>;
       /**
-       * A contract has been created at given \[address\].
+       * A contract has been executed successfully with states applied.
        **/
-      Created: AugmentedEvent<ApiType, [H160]>;
+      Executed: AugmentedEvent<ApiType, [address: H160], { address: H160 }>;
       /**
-       * A \[contract\] was attempted to be created, but the execution failed.
+       * A contract has been executed with errors. States are reverted with only gas fees applied.
        **/
-      CreatedFailed: AugmentedEvent<ApiType, [H160]>;
-      /**
-       * A \[contract\] has been executed successfully with states applied.
-       **/
-      Executed: AugmentedEvent<ApiType, [H160]>;
-      /**
-       * A \[contract\] has been executed with errors. States are reverted with only gas fees applied.
-       **/
-      ExecutedFailed: AugmentedEvent<ApiType, [H160]>;
+      ExecutedFailed: AugmentedEvent<ApiType, [address: H160], { address: H160 }>;
       /**
        * Ethereum events from contracts.
        **/
-      Log: AugmentedEvent<ApiType, [EthereumLog]>;
+      Log: AugmentedEvent<ApiType, [log: EthereumLog], { log: EthereumLog }>;
       /**
        * Generic event
        **/
modifiedtests/src/interfaces/default/types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/default/types.ts
+++ b/tests/src/interfaces/default/types.ts
@@ -1347,7 +1347,12 @@
 /** @name PalletEthereumEvent */
 export interface PalletEthereumEvent extends Enum {
   readonly isExecuted: boolean;
-  readonly asExecuted: ITuple<[H160, H160, H256, EvmCoreErrorExitReason]>;
+  readonly asExecuted: {
+    readonly from: H160;
+    readonly to: H160;
+    readonly transactionHash: H256;
+    readonly exitReason: EvmCoreErrorExitReason;
+  } & Struct;
   readonly type: 'Executed';
 }
 
@@ -1457,26 +1462,36 @@
   readonly isWithdrawFailed: boolean;
   readonly isGasPriceTooLow: boolean;
   readonly isInvalidNonce: boolean;
-  readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce';
+  readonly isGasLimitTooLow: boolean;
+  readonly isGasLimitTooHigh: boolean;
+  readonly isUndefined: boolean;
+  readonly isReentrancy: boolean;
+  readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce' | 'GasLimitTooLow' | 'GasLimitTooHigh' | 'Undefined' | 'Reentrancy';
 }
 
 /** @name PalletEvmEvent */
 export interface PalletEvmEvent extends Enum {
   readonly isLog: boolean;
-  readonly asLog: EthereumLog;
+  readonly asLog: {
+    readonly log: EthereumLog;
+  } & Struct;
   readonly isCreated: boolean;
-  readonly asCreated: H160;
+  readonly asCreated: {
+    readonly address: H160;
+  } & Struct;
   readonly isCreatedFailed: boolean;
-  readonly asCreatedFailed: H160;
+  readonly asCreatedFailed: {
+    readonly address: H160;
+  } & Struct;
   readonly isExecuted: boolean;
-  readonly asExecuted: H160;
+  readonly asExecuted: {
+    readonly address: H160;
+  } & Struct;
   readonly isExecutedFailed: boolean;
-  readonly asExecutedFailed: H160;
-  readonly isBalanceDeposit: boolean;
-  readonly asBalanceDeposit: ITuple<[AccountId32, H160, U256]>;
-  readonly isBalanceWithdraw: boolean;
-  readonly asBalanceWithdraw: ITuple<[AccountId32, H160, U256]>;
-  readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed' | 'BalanceDeposit' | 'BalanceWithdraw';
+  readonly asExecutedFailed: {
+    readonly address: H160;
+  } & Struct;
+  readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed';
 }
 
 /** @name PalletEvmMigrationCall */
modifiedtests/src/interfaces/lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/lookup.ts
+++ b/tests/src/interfaces/lookup.ts
@@ -1216,13 +1216,21 @@
    **/
   PalletEvmEvent: {
     _enum: {
-      Log: 'EthereumLog',
-      Created: 'H160',
-      CreatedFailed: 'H160',
-      Executed: 'H160',
-      ExecutedFailed: 'H160',
-      BalanceDeposit: '(AccountId32,H160,U256)',
-      BalanceWithdraw: '(AccountId32,H160,U256)'
+      Log: {
+        log: 'EthereumLog',
+      },
+      Created: {
+        address: 'H160',
+      },
+      CreatedFailed: {
+        address: 'H160',
+      },
+      Executed: {
+        address: 'H160',
+      },
+      ExecutedFailed: {
+        address: 'H160'
+      }
     }
   },
   /**
@@ -1234,15 +1242,20 @@
     data: 'Bytes'
   },
   /**
-   * Lookup116: pallet_ethereum::pallet::Event
+   * Lookup114: pallet_ethereum::pallet::Event
    **/
   PalletEthereumEvent: {
     _enum: {
-      Executed: '(H160,H160,H256,EvmCoreErrorExitReason)'
+      Executed: {
+        from: 'H160',
+        to: 'H160',
+        transactionHash: 'H256',
+        exitReason: 'EvmCoreErrorExitReason'
+      }
     }
   },
   /**
-   * Lookup117: evm_core::error::ExitReason
+   * Lookup115: evm_core::error::ExitReason
    **/
   EvmCoreErrorExitReason: {
     _enum: {
@@ -1253,13 +1266,13 @@
     }
   },
   /**
-   * Lookup118: evm_core::error::ExitSucceed
+   * Lookup116: evm_core::error::ExitSucceed
    **/
   EvmCoreErrorExitSucceed: {
     _enum: ['Stopped', 'Returned', 'Suicided']
   },
   /**
-   * Lookup119: evm_core::error::ExitError
+   * Lookup117: evm_core::error::ExitError
    **/
   EvmCoreErrorExitError: {
     _enum: {
@@ -1281,13 +1294,13 @@
     }
   },
   /**
-   * Lookup122: evm_core::error::ExitRevert
+   * Lookup120: evm_core::error::ExitRevert
    **/
   EvmCoreErrorExitRevert: {
     _enum: ['Reverted']
   },
   /**
-   * Lookup123: evm_core::error::ExitFatal
+   * Lookup121: evm_core::error::ExitFatal
    **/
   EvmCoreErrorExitFatal: {
     _enum: {
@@ -1298,7 +1311,7 @@
     }
   },
   /**
-   * Lookup124: pallet_evm_contract_helpers::pallet::Event<T>
+   * Lookup122: pallet_evm_contract_helpers::pallet::Event<T>
    **/
   PalletEvmContractHelpersEvent: {
     _enum: {
@@ -1308,19 +1321,19 @@
     }
   },
   /**
-   * Lookup125: pallet_maintenance::pallet::Event<T>
+   * Lookup123: pallet_maintenance::pallet::Event<T>
    **/
   PalletMaintenanceEvent: {
     _enum: ['MaintenanceEnabled', 'MaintenanceDisabled']
   },
   /**
-   * Lookup126: pallet_test_utils::pallet::Event<T>
+   * Lookup124: pallet_test_utils::pallet::Event<T>
    **/
   PalletTestUtilsEvent: {
     _enum: ['ValueIsSet', 'ShouldRollback']
   },
   /**
-   * Lookup127: frame_system::Phase
+   * Lookup125: frame_system::Phase
    **/
   FrameSystemPhase: {
     _enum: {
@@ -1330,14 +1343,14 @@
     }
   },
   /**
-   * Lookup129: frame_system::LastRuntimeUpgradeInfo
+   * Lookup127: frame_system::LastRuntimeUpgradeInfo
    **/
   FrameSystemLastRuntimeUpgradeInfo: {
     specVersion: 'Compact<u32>',
     specName: 'Text'
   },
   /**
-   * Lookup130: frame_system::pallet::Call<T>
+   * Lookup128: frame_system::pallet::Call<T>
    **/
   FrameSystemCall: {
     _enum: {
@@ -1375,7 +1388,7 @@
     }
   },
   /**
-   * Lookup135: frame_system::limits::BlockWeights
+   * Lookup133: frame_system::limits::BlockWeights
    **/
   FrameSystemLimitsBlockWeights: {
     baseBlock: 'Weight',
@@ -1383,7 +1396,7 @@
     perClass: 'FrameSupportDispatchPerDispatchClassWeightsPerClass'
   },
   /**
-   * Lookup136: frame_support::dispatch::PerDispatchClass<frame_system::limits::WeightsPerClass>
+   * Lookup134: frame_support::dispatch::PerDispatchClass<frame_system::limits::WeightsPerClass>
    **/
   FrameSupportDispatchPerDispatchClassWeightsPerClass: {
     normal: 'FrameSystemLimitsWeightsPerClass',
@@ -1391,7 +1404,7 @@
     mandatory: 'FrameSystemLimitsWeightsPerClass'
   },
   /**
-   * Lookup137: frame_system::limits::WeightsPerClass
+   * Lookup135: frame_system::limits::WeightsPerClass
    **/
   FrameSystemLimitsWeightsPerClass: {
     baseExtrinsic: 'Weight',
@@ -1400,13 +1413,13 @@
     reserved: 'Option<Weight>'
   },
   /**
-   * Lookup139: frame_system::limits::BlockLength
+   * Lookup137: frame_system::limits::BlockLength
    **/
   FrameSystemLimitsBlockLength: {
     max: 'FrameSupportDispatchPerDispatchClassU32'
   },
   /**
-   * Lookup140: frame_support::dispatch::PerDispatchClass<T>
+   * Lookup138: frame_support::dispatch::PerDispatchClass<T>
    **/
   FrameSupportDispatchPerDispatchClassU32: {
     normal: 'u32',
@@ -1414,14 +1427,14 @@
     mandatory: 'u32'
   },
   /**
-   * Lookup141: sp_weights::RuntimeDbWeight
+   * Lookup139: sp_weights::RuntimeDbWeight
    **/
   SpWeightsRuntimeDbWeight: {
     read: 'u64',
     write: 'u64'
   },
   /**
-   * Lookup142: sp_version::RuntimeVersion
+   * Lookup140: sp_version::RuntimeVersion
    **/
   SpVersionRuntimeVersion: {
     specName: 'Text',
@@ -1434,13 +1447,13 @@
     stateVersion: 'u8'
   },
   /**
-   * Lookup147: frame_system::pallet::Error<T>
+   * Lookup145: frame_system::pallet::Error<T>
    **/
   FrameSystemError: {
     _enum: ['InvalidSpecName', 'SpecVersionNeedsToIncrease', 'FailedToExtractRuntimeVersion', 'NonDefaultComposite', 'NonZeroRefCount', 'CallFiltered']
   },
   /**
-   * Lookup148: polkadot_primitives::v2::PersistedValidationData<primitive_types::H256, N>
+   * Lookup146: polkadot_primitives::v2::PersistedValidationData<primitive_types::H256, N>
    **/
   PolkadotPrimitivesV2PersistedValidationData: {
     parentHead: 'Bytes',
@@ -1449,19 +1462,19 @@
     maxPovSize: 'u32'
   },
   /**
-   * Lookup151: polkadot_primitives::v2::UpgradeRestriction
+   * Lookup149: polkadot_primitives::v2::UpgradeRestriction
    **/
   PolkadotPrimitivesV2UpgradeRestriction: {
     _enum: ['Present']
   },
   /**
-   * Lookup152: sp_trie::storage_proof::StorageProof
+   * Lookup150: sp_trie::storage_proof::StorageProof
    **/
   SpTrieStorageProof: {
     trieNodes: 'BTreeSet<Bytes>'
   },
   /**
-   * Lookup154: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot
+   * Lookup152: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot
    **/
   CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: {
     dmqMqcHead: 'H256',
@@ -1470,7 +1483,7 @@
     egressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>'
   },
   /**
-   * Lookup157: polkadot_primitives::v2::AbridgedHrmpChannel
+   * Lookup155: polkadot_primitives::v2::AbridgedHrmpChannel
    **/
   PolkadotPrimitivesV2AbridgedHrmpChannel: {
     maxCapacity: 'u32',
@@ -1481,7 +1494,7 @@
     mqcHead: 'Option<H256>'
   },
   /**
-   * Lookup158: polkadot_primitives::v2::AbridgedHostConfiguration
+   * Lookup156: polkadot_primitives::v2::AbridgedHostConfiguration
    **/
   PolkadotPrimitivesV2AbridgedHostConfiguration: {
     maxCodeSize: 'u32',
@@ -1495,14 +1508,14 @@
     validationUpgradeDelay: 'u32'
   },
   /**
-   * Lookup164: polkadot_core_primitives::OutboundHrmpMessage<polkadot_parachain::primitives::Id>
+   * Lookup162: polkadot_core_primitives::OutboundHrmpMessage<polkadot_parachain::primitives::Id>
    **/
   PolkadotCorePrimitivesOutboundHrmpMessage: {
     recipient: 'u32',
     data: 'Bytes'
   },
   /**
-   * Lookup165: cumulus_pallet_parachain_system::pallet::Call<T>
+   * Lookup163: cumulus_pallet_parachain_system::pallet::Call<T>
    **/
   CumulusPalletParachainSystemCall: {
     _enum: {
@@ -1521,7 +1534,7 @@
     }
   },
   /**
-   * Lookup166: cumulus_primitives_parachain_inherent::ParachainInherentData
+   * Lookup164: cumulus_primitives_parachain_inherent::ParachainInherentData
    **/
   CumulusPrimitivesParachainInherentParachainInherentData: {
     validationData: 'PolkadotPrimitivesV2PersistedValidationData',
@@ -1530,27 +1543,27 @@
     horizontalMessages: 'BTreeMap<u32, Vec<PolkadotCorePrimitivesInboundHrmpMessage>>'
   },
   /**
-   * Lookup168: polkadot_core_primitives::InboundDownwardMessage<BlockNumber>
+   * Lookup166: polkadot_core_primitives::InboundDownwardMessage<BlockNumber>
    **/
   PolkadotCorePrimitivesInboundDownwardMessage: {
     sentAt: 'u32',
     msg: 'Bytes'
   },
   /**
-   * Lookup171: polkadot_core_primitives::InboundHrmpMessage<BlockNumber>
+   * Lookup169: polkadot_core_primitives::InboundHrmpMessage<BlockNumber>
    **/
   PolkadotCorePrimitivesInboundHrmpMessage: {
     sentAt: 'u32',
     data: 'Bytes'
   },
   /**
-   * Lookup174: cumulus_pallet_parachain_system::pallet::Error<T>
+   * Lookup172: cumulus_pallet_parachain_system::pallet::Error<T>
    **/
   CumulusPalletParachainSystemError: {
     _enum: ['OverlappingUpgrades', 'ProhibitedByPolkadot', 'TooBig', 'ValidationDataNotAvailable', 'HostConfigurationNotAvailable', 'NotScheduled', 'NothingAuthorized', 'Unauthorized']
   },
   /**
-   * Lookup176: pallet_balances::BalanceLock<Balance>
+   * Lookup174: pallet_balances::BalanceLock<Balance>
    **/
   PalletBalancesBalanceLock: {
     id: '[u8;8]',
@@ -1558,26 +1571,26 @@
     reasons: 'PalletBalancesReasons'
   },
   /**
-   * Lookup177: pallet_balances::Reasons
+   * Lookup175: pallet_balances::Reasons
    **/
   PalletBalancesReasons: {
     _enum: ['Fee', 'Misc', 'All']
   },
   /**
-   * Lookup180: pallet_balances::ReserveData<ReserveIdentifier, Balance>
+   * Lookup178: pallet_balances::ReserveData<ReserveIdentifier, Balance>
    **/
   PalletBalancesReserveData: {
     id: '[u8;16]',
     amount: 'u128'
   },
   /**
-   * Lookup182: pallet_balances::Releases
+   * Lookup180: pallet_balances::Releases
    **/
   PalletBalancesReleases: {
     _enum: ['V1_0_0', 'V2_0_0']
   },
   /**
-   * Lookup183: pallet_balances::pallet::Call<T, I>
+   * Lookup181: pallet_balances::pallet::Call<T, I>
    **/
   PalletBalancesCall: {
     _enum: {
@@ -1610,13 +1623,13 @@
     }
   },
   /**
-   * Lookup186: pallet_balances::pallet::Error<T, I>
+   * Lookup184: pallet_balances::pallet::Error<T, I>
    **/
   PalletBalancesError: {
     _enum: ['VestingBalance', 'LiquidityRestrictions', 'InsufficientBalance', 'ExistentialDeposit', 'KeepAlive', 'ExistingVestingSchedule', 'DeadAccount', 'TooManyReserves']
   },
   /**
-   * Lookup188: pallet_timestamp::pallet::Call<T>
+   * Lookup186: pallet_timestamp::pallet::Call<T>
    **/
   PalletTimestampCall: {
     _enum: {
@@ -1626,13 +1639,13 @@
     }
   },
   /**
-   * Lookup190: pallet_transaction_payment::Releases
+   * Lookup188: pallet_transaction_payment::Releases
    **/
   PalletTransactionPaymentReleases: {
     _enum: ['V1Ancient', 'V2']
   },
   /**
-   * Lookup191: pallet_treasury::Proposal<sp_core::crypto::AccountId32, Balance>
+   * Lookup189: pallet_treasury::Proposal<sp_core::crypto::AccountId32, Balance>
    **/
   PalletTreasuryProposal: {
     proposer: 'AccountId32',
@@ -1641,7 +1654,7 @@
     bond: 'u128'
   },
   /**
-   * Lookup194: pallet_treasury::pallet::Call<T, I>
+   * Lookup192: pallet_treasury::pallet::Call<T, I>
    **/
   PalletTreasuryCall: {
     _enum: {
@@ -1665,17 +1678,17 @@
     }
   },
   /**
-   * Lookup197: frame_support::PalletId
+   * Lookup195: frame_support::PalletId
    **/
   FrameSupportPalletId: '[u8;8]',
   /**
-   * Lookup198: pallet_treasury::pallet::Error<T, I>
+   * Lookup196: pallet_treasury::pallet::Error<T, I>
    **/
   PalletTreasuryError: {
     _enum: ['InsufficientProposersBalance', 'InvalidIndex', 'TooManyApprovals', 'InsufficientPermission', 'ProposalNotApproved']
   },
   /**
-   * Lookup199: pallet_sudo::pallet::Call<T>
+   * Lookup197: pallet_sudo::pallet::Call<T>
    **/
   PalletSudoCall: {
     _enum: {
@@ -1699,7 +1712,7 @@
     }
   },
   /**
-   * Lookup201: orml_vesting::module::Call<T>
+   * Lookup199: orml_vesting::module::Call<T>
    **/
   OrmlVestingModuleCall: {
     _enum: {
@@ -1718,7 +1731,7 @@
     }
   },
   /**
-   * Lookup203: orml_xtokens::module::Call<T>
+   * Lookup201: orml_xtokens::module::Call<T>
    **/
   OrmlXtokensModuleCall: {
     _enum: {
@@ -1761,7 +1774,7 @@
     }
   },
   /**
-   * Lookup204: xcm::VersionedMultiAsset
+   * Lookup202: xcm::VersionedMultiAsset
    **/
   XcmVersionedMultiAsset: {
     _enum: {
@@ -1770,7 +1783,7 @@
     }
   },
   /**
-   * Lookup207: orml_tokens::module::Call<T>
+   * Lookup205: orml_tokens::module::Call<T>
    **/
   OrmlTokensModuleCall: {
     _enum: {
@@ -1804,7 +1817,7 @@
     }
   },
   /**
-   * Lookup208: cumulus_pallet_xcmp_queue::pallet::Call<T>
+   * Lookup206: cumulus_pallet_xcmp_queue::pallet::Call<T>
    **/
   CumulusPalletXcmpQueueCall: {
     _enum: {
@@ -1853,7 +1866,7 @@
     }
   },
   /**
-   * Lookup209: pallet_xcm::pallet::Call<T>
+   * Lookup207: pallet_xcm::pallet::Call<T>
    **/
   PalletXcmCall: {
     _enum: {
@@ -1907,7 +1920,7 @@
     }
   },
   /**
-   * Lookup210: xcm::VersionedXcm<RuntimeCall>
+   * Lookup208: xcm::VersionedXcm<RuntimeCall>
    **/
   XcmVersionedXcm: {
     _enum: {
@@ -1917,7 +1930,7 @@
     }
   },
   /**
-   * Lookup211: xcm::v0::Xcm<RuntimeCall>
+   * Lookup209: xcm::v0::Xcm<RuntimeCall>
    **/
   XcmV0Xcm: {
     _enum: {
@@ -1971,7 +1984,7 @@
     }
   },
   /**
-   * Lookup213: xcm::v0::order::Order<RuntimeCall>
+   * Lookup211: xcm::v0::order::Order<RuntimeCall>
    **/
   XcmV0Order: {
     _enum: {
@@ -2014,7 +2027,7 @@
     }
   },
   /**
-   * Lookup215: xcm::v0::Response
+   * Lookup213: xcm::v0::Response
    **/
   XcmV0Response: {
     _enum: {
@@ -2022,7 +2035,7 @@
     }
   },
   /**
-   * Lookup216: xcm::v1::Xcm<RuntimeCall>
+   * Lookup214: xcm::v1::Xcm<RuntimeCall>
    **/
   XcmV1Xcm: {
     _enum: {
@@ -2081,7 +2094,7 @@
     }
   },
   /**
-   * Lookup218: xcm::v1::order::Order<RuntimeCall>
+   * Lookup216: xcm::v1::order::Order<RuntimeCall>
    **/
   XcmV1Order: {
     _enum: {
@@ -2126,7 +2139,7 @@
     }
   },
   /**
-   * Lookup220: xcm::v1::Response
+   * Lookup218: xcm::v1::Response
    **/
   XcmV1Response: {
     _enum: {
@@ -2135,11 +2148,11 @@
     }
   },
   /**
-   * Lookup234: cumulus_pallet_xcm::pallet::Call<T>
+   * Lookup232: cumulus_pallet_xcm::pallet::Call<T>
    **/
   CumulusPalletXcmCall: 'Null',
   /**
-   * Lookup235: cumulus_pallet_dmp_queue::pallet::Call<T>
+   * Lookup233: cumulus_pallet_dmp_queue::pallet::Call<T>
    **/
   CumulusPalletDmpQueueCall: {
     _enum: {
@@ -2150,7 +2163,7 @@
     }
   },
   /**
-   * Lookup236: pallet_inflation::pallet::Call<T>
+   * Lookup234: pallet_inflation::pallet::Call<T>
    **/
   PalletInflationCall: {
     _enum: {
@@ -2160,7 +2173,7 @@
     }
   },
   /**
-   * Lookup237: pallet_unique::Call<T>
+   * Lookup235: pallet_unique::Call<T>
    **/
   PalletUniqueCall: {
     _enum: {
@@ -2292,7 +2305,7 @@
     }
   },
   /**
-   * Lookup242: up_data_structs::CollectionMode
+   * Lookup240: up_data_structs::CollectionMode
    **/
   UpDataStructsCollectionMode: {
     _enum: {
@@ -2302,7 +2315,7 @@
     }
   },
   /**
-   * Lookup243: up_data_structs::CreateCollectionData<sp_core::crypto::AccountId32>
+   * Lookup241: up_data_structs::CreateCollectionData<sp_core::crypto::AccountId32>
    **/
   UpDataStructsCreateCollectionData: {
     mode: 'UpDataStructsCollectionMode',
@@ -2317,13 +2330,13 @@
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup245: up_data_structs::AccessMode
+   * Lookup243: up_data_structs::AccessMode
    **/
   UpDataStructsAccessMode: {
     _enum: ['Normal', 'AllowList']
   },
   /**
-   * Lookup247: up_data_structs::CollectionLimits
+   * Lookup245: up_data_structs::CollectionLimits
    **/
   UpDataStructsCollectionLimits: {
     accountTokenOwnershipLimit: 'Option<u32>',
@@ -2337,7 +2350,7 @@
     transfersEnabled: 'Option<bool>'
   },
   /**
-   * Lookup249: up_data_structs::SponsoringRateLimit
+   * Lookup247: up_data_structs::SponsoringRateLimit
    **/
   UpDataStructsSponsoringRateLimit: {
     _enum: {
@@ -2346,7 +2359,7 @@
     }
   },
   /**
-   * Lookup252: up_data_structs::CollectionPermissions
+   * Lookup250: up_data_structs::CollectionPermissions
    **/
   UpDataStructsCollectionPermissions: {
     access: 'Option<UpDataStructsAccessMode>',
@@ -2354,7 +2367,7 @@
     nesting: 'Option<UpDataStructsNestingPermissions>'
   },
   /**
-   * Lookup254: up_data_structs::NestingPermissions
+   * Lookup252: up_data_structs::NestingPermissions
    **/
   UpDataStructsNestingPermissions: {
     tokenOwner: 'bool',
@@ -2362,18 +2375,18 @@
     restricted: 'Option<UpDataStructsOwnerRestrictedSet>'
   },
   /**
-   * Lookup256: up_data_structs::OwnerRestrictedSet
+   * Lookup254: up_data_structs::OwnerRestrictedSet
    **/
   UpDataStructsOwnerRestrictedSet: 'BTreeSet<u32>',
   /**
-   * Lookup261: up_data_structs::PropertyKeyPermission
+   * Lookup259: up_data_structs::PropertyKeyPermission
    **/
   UpDataStructsPropertyKeyPermission: {
     key: 'Bytes',
     permission: 'UpDataStructsPropertyPermission'
   },
   /**
-   * Lookup262: up_data_structs::PropertyPermission
+   * Lookup260: up_data_structs::PropertyPermission
    **/
   UpDataStructsPropertyPermission: {
     mutable: 'bool',
@@ -2381,14 +2394,14 @@
     tokenOwner: 'bool'
   },
   /**
-   * Lookup265: up_data_structs::Property
+   * Lookup263: up_data_structs::Property
    **/
   UpDataStructsProperty: {
     key: 'Bytes',
     value: 'Bytes'
   },
   /**
-   * Lookup268: up_data_structs::CreateItemData
+   * Lookup266: up_data_structs::CreateItemData
    **/
   UpDataStructsCreateItemData: {
     _enum: {
@@ -2398,26 +2411,26 @@
     }
   },
   /**
-   * Lookup269: up_data_structs::CreateNftData
+   * Lookup267: up_data_structs::CreateNftData
    **/
   UpDataStructsCreateNftData: {
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup270: up_data_structs::CreateFungibleData
+   * Lookup268: up_data_structs::CreateFungibleData
    **/
   UpDataStructsCreateFungibleData: {
     value: 'u128'
   },
   /**
-   * Lookup271: up_data_structs::CreateReFungibleData
+   * Lookup269: up_data_structs::CreateReFungibleData
    **/
   UpDataStructsCreateReFungibleData: {
     pieces: 'u128',
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup274: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup272: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateItemExData: {
     _enum: {
@@ -2428,14 +2441,14 @@
     }
   },
   /**
-   * Lookup276: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup274: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateNftExData: {
     properties: 'Vec<UpDataStructsProperty>',
     owner: 'PalletEvmAccountBasicCrossAccountIdRepr'
   },
   /**
-   * Lookup283: up_data_structs::CreateRefungibleExSingleOwner<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup281: up_data_structs::CreateRefungibleExSingleOwner<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateRefungibleExSingleOwner: {
     user: 'PalletEvmAccountBasicCrossAccountIdRepr',
@@ -2443,14 +2456,14 @@
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup285: up_data_structs::CreateRefungibleExMultipleOwners<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup283: up_data_structs::CreateRefungibleExMultipleOwners<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateRefungibleExMultipleOwners: {
     users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup286: pallet_unique_scheduler::pallet::Call<T>
+   * Lookup284: pallet_unique_scheduler::pallet::Call<T>
    **/
   PalletUniqueSchedulerCall: {
     _enum: {
@@ -2478,7 +2491,7 @@
     }
   },
   /**
-   * Lookup289: frame_support::traits::schedule::MaybeHashed<opal_runtime::RuntimeCall, primitive_types::H256>
+   * Lookup287: frame_support::traits::schedule::MaybeHashed<opal_runtime::RuntimeCall, primitive_types::H256>
    **/
   FrameSupportScheduleMaybeHashed: {
     _enum: {
@@ -2487,7 +2500,7 @@
     }
   },
   /**
-   * Lookup290: pallet_configuration::pallet::Call<T>
+   * Lookup288: pallet_configuration::pallet::Call<T>
    **/
   PalletConfigurationCall: {
     _enum: {
@@ -2500,15 +2513,15 @@
     }
   },
   /**
-   * Lookup292: pallet_template_transaction_payment::Call<T>
+   * Lookup290: pallet_template_transaction_payment::Call<T>
    **/
   PalletTemplateTransactionPaymentCall: 'Null',
   /**
-   * Lookup293: pallet_structure::pallet::Call<T>
+   * Lookup291: pallet_structure::pallet::Call<T>
    **/
   PalletStructureCall: 'Null',
   /**
-   * Lookup294: pallet_rmrk_core::pallet::Call<T>
+   * Lookup292: pallet_rmrk_core::pallet::Call<T>
    **/
   PalletRmrkCoreCall: {
     _enum: {
@@ -2599,7 +2612,7 @@
     }
   },
   /**
-   * Lookup300: rmrk_traits::resource::ResourceTypes<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup298: rmrk_traits::resource::ResourceTypes<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsResourceResourceTypes: {
     _enum: {
@@ -2609,7 +2622,7 @@
     }
   },
   /**
-   * Lookup302: rmrk_traits::resource::BasicResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup300: rmrk_traits::resource::BasicResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsResourceBasicResource: {
     src: 'Option<Bytes>',
@@ -2618,7 +2631,7 @@
     thumb: 'Option<Bytes>'
   },
   /**
-   * Lookup304: rmrk_traits::resource::ComposableResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup302: rmrk_traits::resource::ComposableResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsResourceComposableResource: {
     parts: 'Vec<u32>',
@@ -2629,7 +2642,7 @@
     thumb: 'Option<Bytes>'
   },
   /**
-   * Lookup305: rmrk_traits::resource::SlotResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup303: rmrk_traits::resource::SlotResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsResourceSlotResource: {
     base: 'u32',
@@ -2640,7 +2653,7 @@
     thumb: 'Option<Bytes>'
   },
   /**
-   * Lookup308: pallet_rmrk_equip::pallet::Call<T>
+   * Lookup306: pallet_rmrk_equip::pallet::Call<T>
    **/
   PalletRmrkEquipCall: {
     _enum: {
@@ -2661,7 +2674,7 @@
     }
   },
   /**
-   * Lookup311: rmrk_traits::part::PartType<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup309: rmrk_traits::part::PartType<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsPartPartType: {
     _enum: {
@@ -2670,7 +2683,7 @@
     }
   },
   /**
-   * Lookup313: rmrk_traits::part::FixedPart<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup311: rmrk_traits::part::FixedPart<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsPartFixedPart: {
     id: 'u32',
@@ -2678,7 +2691,7 @@
     src: 'Bytes'
   },
   /**
-   * Lookup314: rmrk_traits::part::SlotPart<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup312: rmrk_traits::part::SlotPart<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsPartSlotPart: {
     id: 'u32',
@@ -2687,7 +2700,7 @@
     z: 'u32'
   },
   /**
-   * Lookup315: rmrk_traits::part::EquippableList<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup313: rmrk_traits::part::EquippableList<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsPartEquippableList: {
     _enum: {
@@ -2697,7 +2710,7 @@
     }
   },
   /**
-   * Lookup317: rmrk_traits::theme::Theme<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<rmrk_traits::theme::ThemeProperty<sp_core::bounded::bounded_vec::BoundedVec<T, S>>, S>>
+   * Lookup315: rmrk_traits::theme::Theme<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<rmrk_traits::theme::ThemeProperty<sp_core::bounded::bounded_vec::BoundedVec<T, S>>, S>>
    **/
   RmrkTraitsTheme: {
     name: 'Bytes',
@@ -2705,14 +2718,14 @@
     inherit: 'bool'
   },
   /**
-   * Lookup319: rmrk_traits::theme::ThemeProperty<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup317: rmrk_traits::theme::ThemeProperty<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsThemeThemeProperty: {
     key: 'Bytes',
     value: 'Bytes'
   },
   /**
-   * Lookup321: pallet_app_promotion::pallet::Call<T>
+   * Lookup319: pallet_app_promotion::pallet::Call<T>
    **/
   PalletAppPromotionCall: {
     _enum: {
@@ -2741,7 +2754,7 @@
     }
   },
   /**
-   * Lookup322: pallet_foreign_assets::module::Call<T>
+   * Lookup320: pallet_foreign_assets::module::Call<T>
    **/
   PalletForeignAssetsModuleCall: {
     _enum: {
@@ -2758,7 +2771,7 @@
     }
   },
   /**
-   * Lookup323: pallet_evm::pallet::Call<T>
+   * Lookup321: pallet_evm::pallet::Call<T>
    **/
   PalletEvmCall: {
     _enum: {
@@ -3458,7 +3471,7 @@
    * Lookup450: pallet_evm::pallet::Error<T>
    **/
   PalletEvmError: {
-    _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce']
+    _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce', 'GasLimitTooLow', 'GasLimitTooHigh', 'Undefined', 'Reentrancy']
   },
   /**
    * Lookup453: fp_rpc::TransactionStatus
modifiedtests/src/interfaces/types-lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/types-lookup.ts
+++ b/tests/src/interfaces/types-lookup.ts
@@ -1371,20 +1371,26 @@
   /** @name PalletEvmEvent (111) */
   interface PalletEvmEvent extends Enum {
     readonly isLog: boolean;
-    readonly asLog: EthereumLog;
+    readonly asLog: {
+      readonly log: EthereumLog;
+    } & Struct;
     readonly isCreated: boolean;
-    readonly asCreated: H160;
+    readonly asCreated: {
+      readonly address: H160;
+    } & Struct;
     readonly isCreatedFailed: boolean;
-    readonly asCreatedFailed: H160;
+    readonly asCreatedFailed: {
+      readonly address: H160;
+    } & Struct;
     readonly isExecuted: boolean;
-    readonly asExecuted: H160;
+    readonly asExecuted: {
+      readonly address: H160;
+    } & Struct;
     readonly isExecutedFailed: boolean;
-    readonly asExecutedFailed: H160;
-    readonly isBalanceDeposit: boolean;
-    readonly asBalanceDeposit: ITuple<[AccountId32, H160, U256]>;
-    readonly isBalanceWithdraw: boolean;
-    readonly asBalanceWithdraw: ITuple<[AccountId32, H160, U256]>;
-    readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed' | 'BalanceDeposit' | 'BalanceWithdraw';
+    readonly asExecutedFailed: {
+      readonly address: H160;
+    } & Struct;
+    readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed';
   }
 
   /** @name EthereumLog (112) */
@@ -1394,14 +1400,19 @@
     readonly data: Bytes;
   }
 
-  /** @name PalletEthereumEvent (116) */
+  /** @name PalletEthereumEvent (114) */
   interface PalletEthereumEvent extends Enum {
     readonly isExecuted: boolean;
-    readonly asExecuted: ITuple<[H160, H160, H256, EvmCoreErrorExitReason]>;
+    readonly asExecuted: {
+      readonly from: H160;
+      readonly to: H160;
+      readonly transactionHash: H256;
+      readonly exitReason: EvmCoreErrorExitReason;
+    } & Struct;
     readonly type: 'Executed';
   }
 
-  /** @name EvmCoreErrorExitReason (117) */
+  /** @name EvmCoreErrorExitReason (115) */
   interface EvmCoreErrorExitReason extends Enum {
     readonly isSucceed: boolean;
     readonly asSucceed: EvmCoreErrorExitSucceed;
@@ -1414,7 +1425,7 @@
     readonly type: 'Succeed' | 'Error' | 'Revert' | 'Fatal';
   }
 
-  /** @name EvmCoreErrorExitSucceed (118) */
+  /** @name EvmCoreErrorExitSucceed (116) */
   interface EvmCoreErrorExitSucceed extends Enum {
     readonly isStopped: boolean;
     readonly isReturned: boolean;
@@ -1422,7 +1433,7 @@
     readonly type: 'Stopped' | 'Returned' | 'Suicided';
   }
 
-  /** @name EvmCoreErrorExitError (119) */
+  /** @name EvmCoreErrorExitError (117) */
   interface EvmCoreErrorExitError extends Enum {
     readonly isStackUnderflow: boolean;
     readonly isStackOverflow: boolean;
@@ -1443,13 +1454,13 @@
     readonly type: 'StackUnderflow' | 'StackOverflow' | 'InvalidJump' | 'InvalidRange' | 'DesignatedInvalid' | 'CallTooDeep' | 'CreateCollision' | 'CreateContractLimit' | 'OutOfOffset' | 'OutOfGas' | 'OutOfFund' | 'PcUnderflow' | 'CreateEmpty' | 'Other' | 'InvalidCode';
   }
 
-  /** @name EvmCoreErrorExitRevert (122) */
+  /** @name EvmCoreErrorExitRevert (120) */
   interface EvmCoreErrorExitRevert extends Enum {
     readonly isReverted: boolean;
     readonly type: 'Reverted';
   }
 
-  /** @name EvmCoreErrorExitFatal (123) */
+  /** @name EvmCoreErrorExitFatal (121) */
   interface EvmCoreErrorExitFatal extends Enum {
     readonly isNotSupported: boolean;
     readonly isUnhandledInterrupt: boolean;
@@ -1460,7 +1471,7 @@
     readonly type: 'NotSupported' | 'UnhandledInterrupt' | 'CallErrorAsFatal' | 'Other';
   }
 
-  /** @name PalletEvmContractHelpersEvent (124) */
+  /** @name PalletEvmContractHelpersEvent (122) */
   interface PalletEvmContractHelpersEvent extends Enum {
     readonly isContractSponsorSet: boolean;
     readonly asContractSponsorSet: ITuple<[H160, AccountId32]>;
@@ -1471,21 +1482,21 @@
     readonly type: 'ContractSponsorSet' | 'ContractSponsorshipConfirmed' | 'ContractSponsorRemoved';
   }
 
-  /** @name PalletMaintenanceEvent (125) */
+  /** @name PalletMaintenanceEvent (123) */
   interface PalletMaintenanceEvent extends Enum {
     readonly isMaintenanceEnabled: boolean;
     readonly isMaintenanceDisabled: boolean;
     readonly type: 'MaintenanceEnabled' | 'MaintenanceDisabled';
   }
 
-  /** @name PalletTestUtilsEvent (126) */
+  /** @name PalletTestUtilsEvent (124) */
   interface PalletTestUtilsEvent extends Enum {
     readonly isValueIsSet: boolean;
     readonly isShouldRollback: boolean;
     readonly type: 'ValueIsSet' | 'ShouldRollback';
   }
 
-  /** @name FrameSystemPhase (127) */
+  /** @name FrameSystemPhase (125) */
   interface FrameSystemPhase extends Enum {
     readonly isApplyExtrinsic: boolean;
     readonly asApplyExtrinsic: u32;
@@ -1494,13 +1505,13 @@
     readonly type: 'ApplyExtrinsic' | 'Finalization' | 'Initialization';
   }
 
-  /** @name FrameSystemLastRuntimeUpgradeInfo (129) */
+  /** @name FrameSystemLastRuntimeUpgradeInfo (127) */
   interface FrameSystemLastRuntimeUpgradeInfo extends Struct {
     readonly specVersion: Compact<u32>;
     readonly specName: Text;
   }
 
-  /** @name FrameSystemCall (130) */
+  /** @name FrameSystemCall (128) */
   interface FrameSystemCall extends Enum {
     readonly isFillBlock: boolean;
     readonly asFillBlock: {
@@ -1542,21 +1553,21 @@
     readonly type: 'FillBlock' | 'Remark' | 'SetHeapPages' | 'SetCode' | 'SetCodeWithoutChecks' | 'SetStorage' | 'KillStorage' | 'KillPrefix' | 'RemarkWithEvent';
   }
 
-  /** @name FrameSystemLimitsBlockWeights (135) */
+  /** @name FrameSystemLimitsBlockWeights (133) */
   interface FrameSystemLimitsBlockWeights extends Struct {
     readonly baseBlock: Weight;
     readonly maxBlock: Weight;
     readonly perClass: FrameSupportDispatchPerDispatchClassWeightsPerClass;
   }
 
-  /** @name FrameSupportDispatchPerDispatchClassWeightsPerClass (136) */
+  /** @name FrameSupportDispatchPerDispatchClassWeightsPerClass (134) */
   interface FrameSupportDispatchPerDispatchClassWeightsPerClass extends Struct {
     readonly normal: FrameSystemLimitsWeightsPerClass;
     readonly operational: FrameSystemLimitsWeightsPerClass;
     readonly mandatory: FrameSystemLimitsWeightsPerClass;
   }
 
-  /** @name FrameSystemLimitsWeightsPerClass (137) */
+  /** @name FrameSystemLimitsWeightsPerClass (135) */
   interface FrameSystemLimitsWeightsPerClass extends Struct {
     readonly baseExtrinsic: Weight;
     readonly maxExtrinsic: Option<Weight>;
@@ -1564,25 +1575,25 @@
     readonly reserved: Option<Weight>;
   }
 
-  /** @name FrameSystemLimitsBlockLength (139) */
+  /** @name FrameSystemLimitsBlockLength (137) */
   interface FrameSystemLimitsBlockLength extends Struct {
     readonly max: FrameSupportDispatchPerDispatchClassU32;
   }
 
-  /** @name FrameSupportDispatchPerDispatchClassU32 (140) */
+  /** @name FrameSupportDispatchPerDispatchClassU32 (138) */
   interface FrameSupportDispatchPerDispatchClassU32 extends Struct {
     readonly normal: u32;
     readonly operational: u32;
     readonly mandatory: u32;
   }
 
-  /** @name SpWeightsRuntimeDbWeight (141) */
+  /** @name SpWeightsRuntimeDbWeight (139) */
   interface SpWeightsRuntimeDbWeight extends Struct {
     readonly read: u64;
     readonly write: u64;
   }
 
-  /** @name SpVersionRuntimeVersion (142) */
+  /** @name SpVersionRuntimeVersion (140) */
   interface SpVersionRuntimeVersion extends Struct {
     readonly specName: Text;
     readonly implName: Text;
@@ -1594,7 +1605,7 @@
     readonly stateVersion: u8;
   }
 
-  /** @name FrameSystemError (147) */
+  /** @name FrameSystemError (145) */
   interface FrameSystemError extends Enum {
     readonly isInvalidSpecName: boolean;
     readonly isSpecVersionNeedsToIncrease: boolean;
@@ -1605,7 +1616,7 @@
     readonly type: 'InvalidSpecName' | 'SpecVersionNeedsToIncrease' | 'FailedToExtractRuntimeVersion' | 'NonDefaultComposite' | 'NonZeroRefCount' | 'CallFiltered';
   }
 
-  /** @name PolkadotPrimitivesV2PersistedValidationData (148) */
+  /** @name PolkadotPrimitivesV2PersistedValidationData (146) */
   interface PolkadotPrimitivesV2PersistedValidationData extends Struct {
     readonly parentHead: Bytes;
     readonly relayParentNumber: u32;
@@ -1613,18 +1624,18 @@
     readonly maxPovSize: u32;
   }
 
-  /** @name PolkadotPrimitivesV2UpgradeRestriction (151) */
+  /** @name PolkadotPrimitivesV2UpgradeRestriction (149) */
   interface PolkadotPrimitivesV2UpgradeRestriction extends Enum {
     readonly isPresent: boolean;
     readonly type: 'Present';
   }
 
-  /** @name SpTrieStorageProof (152) */
+  /** @name SpTrieStorageProof (150) */
   interface SpTrieStorageProof extends Struct {
     readonly trieNodes: BTreeSet<Bytes>;
   }
 
-  /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (154) */
+  /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (152) */
   interface CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot extends Struct {
     readonly dmqMqcHead: H256;
     readonly relayDispatchQueueSize: ITuple<[u32, u32]>;
@@ -1632,7 +1643,7 @@
     readonly egressChannels: Vec<ITuple<[u32, PolkadotPrimitivesV2AbridgedHrmpChannel]>>;
   }
 
-  /** @name PolkadotPrimitivesV2AbridgedHrmpChannel (157) */
+  /** @name PolkadotPrimitivesV2AbridgedHrmpChannel (155) */
   interface PolkadotPrimitivesV2AbridgedHrmpChannel extends Struct {
     readonly maxCapacity: u32;
     readonly maxTotalSize: u32;
@@ -1642,7 +1653,7 @@
     readonly mqcHead: Option<H256>;
   }
 
-  /** @name PolkadotPrimitivesV2AbridgedHostConfiguration (158) */
+  /** @name PolkadotPrimitivesV2AbridgedHostConfiguration (156) */
   interface PolkadotPrimitivesV2AbridgedHostConfiguration extends Struct {
     readonly maxCodeSize: u32;
     readonly maxHeadDataSize: u32;
@@ -1655,13 +1666,13 @@
     readonly validationUpgradeDelay: u32;
   }
 
-  /** @name PolkadotCorePrimitivesOutboundHrmpMessage (164) */
+  /** @name PolkadotCorePrimitivesOutboundHrmpMessage (162) */
   interface PolkadotCorePrimitivesOutboundHrmpMessage extends Struct {
     readonly recipient: u32;
     readonly data: Bytes;
   }
 
-  /** @name CumulusPalletParachainSystemCall (165) */
+  /** @name CumulusPalletParachainSystemCall (163) */
   interface CumulusPalletParachainSystemCall extends Enum {
     readonly isSetValidationData: boolean;
     readonly asSetValidationData: {
@@ -1682,7 +1693,7 @@
     readonly type: 'SetValidationData' | 'SudoSendUpwardMessage' | 'AuthorizeUpgrade' | 'EnactAuthorizedUpgrade';
   }
 
-  /** @name CumulusPrimitivesParachainInherentParachainInherentData (166) */
+  /** @name CumulusPrimitivesParachainInherentParachainInherentData (164) */
   interface CumulusPrimitivesParachainInherentParachainInherentData extends Struct {
     readonly validationData: PolkadotPrimitivesV2PersistedValidationData;
     readonly relayChainState: SpTrieStorageProof;
@@ -1690,19 +1701,19 @@
     readonly horizontalMessages: BTreeMap<u32, Vec<PolkadotCorePrimitivesInboundHrmpMessage>>;
   }
 
-  /** @name PolkadotCorePrimitivesInboundDownwardMessage (168) */
+  /** @name PolkadotCorePrimitivesInboundDownwardMessage (166) */
   interface PolkadotCorePrimitivesInboundDownwardMessage extends Struct {
     readonly sentAt: u32;
     readonly msg: Bytes;
   }
 
-  /** @name PolkadotCorePrimitivesInboundHrmpMessage (171) */
+  /** @name PolkadotCorePrimitivesInboundHrmpMessage (169) */
   interface PolkadotCorePrimitivesInboundHrmpMessage extends Struct {
     readonly sentAt: u32;
     readonly data: Bytes;
   }
 
-  /** @name CumulusPalletParachainSystemError (174) */
+  /** @name CumulusPalletParachainSystemError (172) */
   interface CumulusPalletParachainSystemError extends Enum {
     readonly isOverlappingUpgrades: boolean;
     readonly isProhibitedByPolkadot: boolean;
@@ -1715,14 +1726,14 @@
     readonly type: 'OverlappingUpgrades' | 'ProhibitedByPolkadot' | 'TooBig' | 'ValidationDataNotAvailable' | 'HostConfigurationNotAvailable' | 'NotScheduled' | 'NothingAuthorized' | 'Unauthorized';
   }
 
-  /** @name PalletBalancesBalanceLock (176) */
+  /** @name PalletBalancesBalanceLock (174) */
   interface PalletBalancesBalanceLock extends Struct {
     readonly id: U8aFixed;
     readonly amount: u128;
     readonly reasons: PalletBalancesReasons;
   }
 
-  /** @name PalletBalancesReasons (177) */
+  /** @name PalletBalancesReasons (175) */
   interface PalletBalancesReasons extends Enum {
     readonly isFee: boolean;
     readonly isMisc: boolean;
@@ -1730,20 +1741,20 @@
     readonly type: 'Fee' | 'Misc' | 'All';
   }
 
-  /** @name PalletBalancesReserveData (180) */
+  /** @name PalletBalancesReserveData (178) */
   interface PalletBalancesReserveData extends Struct {
     readonly id: U8aFixed;
     readonly amount: u128;
   }
 
-  /** @name PalletBalancesReleases (182) */
+  /** @name PalletBalancesReleases (180) */
   interface PalletBalancesReleases extends Enum {
     readonly isV100: boolean;
     readonly isV200: boolean;
     readonly type: 'V100' | 'V200';
   }
 
-  /** @name PalletBalancesCall (183) */
+  /** @name PalletBalancesCall (181) */
   interface PalletBalancesCall extends Enum {
     readonly isTransfer: boolean;
     readonly asTransfer: {
@@ -1780,7 +1791,7 @@
     readonly type: 'Transfer' | 'SetBalance' | 'ForceTransfer' | 'TransferKeepAlive' | 'TransferAll' | 'ForceUnreserve';
   }
 
-  /** @name PalletBalancesError (186) */
+  /** @name PalletBalancesError (184) */
   interface PalletBalancesError extends Enum {
     readonly isVestingBalance: boolean;
     readonly isLiquidityRestrictions: boolean;
@@ -1793,7 +1804,7 @@
     readonly type: 'VestingBalance' | 'LiquidityRestrictions' | 'InsufficientBalance' | 'ExistentialDeposit' | 'KeepAlive' | 'ExistingVestingSchedule' | 'DeadAccount' | 'TooManyReserves';
   }
 
-  /** @name PalletTimestampCall (188) */
+  /** @name PalletTimestampCall (186) */
   interface PalletTimestampCall extends Enum {
     readonly isSet: boolean;
     readonly asSet: {
@@ -1802,14 +1813,14 @@
     readonly type: 'Set';
   }
 
-  /** @name PalletTransactionPaymentReleases (190) */
+  /** @name PalletTransactionPaymentReleases (188) */
   interface PalletTransactionPaymentReleases extends Enum {
     readonly isV1Ancient: boolean;
     readonly isV2: boolean;
     readonly type: 'V1Ancient' | 'V2';
   }
 
-  /** @name PalletTreasuryProposal (191) */
+  /** @name PalletTreasuryProposal (189) */
   interface PalletTreasuryProposal extends Struct {
     readonly proposer: AccountId32;
     readonly value: u128;
@@ -1817,7 +1828,7 @@
     readonly bond: u128;
   }
 
-  /** @name PalletTreasuryCall (194) */
+  /** @name PalletTreasuryCall (192) */
   interface PalletTreasuryCall extends Enum {
     readonly isProposeSpend: boolean;
     readonly asProposeSpend: {
@@ -1844,10 +1855,10 @@
     readonly type: 'ProposeSpend' | 'RejectProposal' | 'ApproveProposal' | 'Spend' | 'RemoveApproval';
   }
 
-  /** @name FrameSupportPalletId (197) */
+  /** @name FrameSupportPalletId (195) */
   interface FrameSupportPalletId extends U8aFixed {}
 
-  /** @name PalletTreasuryError (198) */
+  /** @name PalletTreasuryError (196) */
   interface PalletTreasuryError extends Enum {
     readonly isInsufficientProposersBalance: boolean;
     readonly isInvalidIndex: boolean;
@@ -1857,7 +1868,7 @@
     readonly type: 'InsufficientProposersBalance' | 'InvalidIndex' | 'TooManyApprovals' | 'InsufficientPermission' | 'ProposalNotApproved';
   }
 
-  /** @name PalletSudoCall (199) */
+  /** @name PalletSudoCall (197) */
   interface PalletSudoCall extends Enum {
     readonly isSudo: boolean;
     readonly asSudo: {
@@ -1880,7 +1891,7 @@
     readonly type: 'Sudo' | 'SudoUncheckedWeight' | 'SetKey' | 'SudoAs';
   }
 
-  /** @name OrmlVestingModuleCall (201) */
+  /** @name OrmlVestingModuleCall (199) */
   interface OrmlVestingModuleCall extends Enum {
     readonly isClaim: boolean;
     readonly isVestedTransfer: boolean;
@@ -1900,7 +1911,7 @@
     readonly type: 'Claim' | 'VestedTransfer' | 'UpdateVestingSchedules' | 'ClaimFor';
   }
 
-  /** @name OrmlXtokensModuleCall (203) */
+  /** @name OrmlXtokensModuleCall (201) */
   interface OrmlXtokensModuleCall extends Enum {
     readonly isTransfer: boolean;
     readonly asTransfer: {
@@ -1947,7 +1958,7 @@
     readonly type: 'Transfer' | 'TransferMultiasset' | 'TransferWithFee' | 'TransferMultiassetWithFee' | 'TransferMulticurrencies' | 'TransferMultiassets';
   }
 
-  /** @name XcmVersionedMultiAsset (204) */
+  /** @name XcmVersionedMultiAsset (202) */
   interface XcmVersionedMultiAsset extends Enum {
     readonly isV0: boolean;
     readonly asV0: XcmV0MultiAsset;
@@ -1956,7 +1967,7 @@
     readonly type: 'V0' | 'V1';
   }
 
-  /** @name OrmlTokensModuleCall (207) */
+  /** @name OrmlTokensModuleCall (205) */
   interface OrmlTokensModuleCall extends Enum {
     readonly isTransfer: boolean;
     readonly asTransfer: {
@@ -1993,7 +2004,7 @@
     readonly type: 'Transfer' | 'TransferAll' | 'TransferKeepAlive' | 'ForceTransfer' | 'SetBalance';
   }
 
-  /** @name CumulusPalletXcmpQueueCall (208) */
+  /** @name CumulusPalletXcmpQueueCall (206) */
   interface CumulusPalletXcmpQueueCall extends Enum {
     readonly isServiceOverweight: boolean;
     readonly asServiceOverweight: {
@@ -2029,7 +2040,7 @@
     readonly type: 'ServiceOverweight' | 'SuspendXcmExecution' | 'ResumeXcmExecution' | 'UpdateSuspendThreshold' | 'UpdateDropThreshold' | 'UpdateResumeThreshold' | 'UpdateThresholdWeight' | 'UpdateWeightRestrictDecay' | 'UpdateXcmpMaxIndividualWeight';
   }
 
-  /** @name PalletXcmCall (209) */
+  /** @name PalletXcmCall (207) */
   interface PalletXcmCall extends Enum {
     readonly isSend: boolean;
     readonly asSend: {
@@ -2091,7 +2102,7 @@
     readonly type: 'Send' | 'TeleportAssets' | 'ReserveTransferAssets' | 'Execute' | 'ForceXcmVersion' | 'ForceDefaultXcmVersion' | 'ForceSubscribeVersionNotify' | 'ForceUnsubscribeVersionNotify' | 'LimitedReserveTransferAssets' | 'LimitedTeleportAssets';
   }
 
-  /** @name XcmVersionedXcm (210) */
+  /** @name XcmVersionedXcm (208) */
   interface XcmVersionedXcm extends Enum {
     readonly isV0: boolean;
     readonly asV0: XcmV0Xcm;
@@ -2102,7 +2113,7 @@
     readonly type: 'V0' | 'V1' | 'V2';
   }
 
-  /** @name XcmV0Xcm (211) */
+  /** @name XcmV0Xcm (209) */
   interface XcmV0Xcm extends Enum {
     readonly isWithdrawAsset: boolean;
     readonly asWithdrawAsset: {
@@ -2165,7 +2176,7 @@
     readonly type: 'WithdrawAsset' | 'ReserveAssetDeposit' | 'TeleportAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'RelayedFrom';
   }
 
-  /** @name XcmV0Order (213) */
+  /** @name XcmV0Order (211) */
   interface XcmV0Order extends Enum {
     readonly isNull: boolean;
     readonly isDepositAsset: boolean;
@@ -2213,14 +2224,14 @@
     readonly type: 'Null' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution';
   }
 
-  /** @name XcmV0Response (215) */
+  /** @name XcmV0Response (213) */
   interface XcmV0Response extends Enum {
     readonly isAssets: boolean;
     readonly asAssets: Vec<XcmV0MultiAsset>;
     readonly type: 'Assets';
   }
 
-  /** @name XcmV1Xcm (216) */
+  /** @name XcmV1Xcm (214) */
   interface XcmV1Xcm extends Enum {
     readonly isWithdrawAsset: boolean;
     readonly asWithdrawAsset: {
@@ -2289,7 +2300,7 @@
     readonly type: 'WithdrawAsset' | 'ReserveAssetDeposited' | 'ReceiveTeleportedAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'RelayedFrom' | 'SubscribeVersion' | 'UnsubscribeVersion';
   }
 
-  /** @name XcmV1Order (218) */
+  /** @name XcmV1Order (216) */
   interface XcmV1Order extends Enum {
     readonly isNoop: boolean;
     readonly isDepositAsset: boolean;
@@ -2339,7 +2350,7 @@
     readonly type: 'Noop' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution';
   }
 
-  /** @name XcmV1Response (220) */
+  /** @name XcmV1Response (218) */
   interface XcmV1Response extends Enum {
     readonly isAssets: boolean;
     readonly asAssets: XcmV1MultiassetMultiAssets;
@@ -2348,10 +2359,10 @@
     readonly type: 'Assets' | 'Version';
   }
 
-  /** @name CumulusPalletXcmCall (234) */
+  /** @name CumulusPalletXcmCall (232) */
   type CumulusPalletXcmCall = Null;
 
-  /** @name CumulusPalletDmpQueueCall (235) */
+  /** @name CumulusPalletDmpQueueCall (233) */
   interface CumulusPalletDmpQueueCall extends Enum {
     readonly isServiceOverweight: boolean;
     readonly asServiceOverweight: {
@@ -2361,7 +2372,7 @@
     readonly type: 'ServiceOverweight';
   }
 
-  /** @name PalletInflationCall (236) */
+  /** @name PalletInflationCall (234) */
   interface PalletInflationCall extends Enum {
     readonly isStartInflation: boolean;
     readonly asStartInflation: {
@@ -2370,7 +2381,7 @@
     readonly type: 'StartInflation';
   }
 
-  /** @name PalletUniqueCall (237) */
+  /** @name PalletUniqueCall (235) */
   interface PalletUniqueCall extends Enum {
     readonly isCreateCollection: boolean;
     readonly asCreateCollection: {
@@ -2528,7 +2539,7 @@
     readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition';
   }
 
-  /** @name UpDataStructsCollectionMode (242) */
+  /** @name UpDataStructsCollectionMode (240) */
   interface UpDataStructsCollectionMode extends Enum {
     readonly isNft: boolean;
     readonly isFungible: boolean;
@@ -2537,7 +2548,7 @@
     readonly type: 'Nft' | 'Fungible' | 'ReFungible';
   }
 
-  /** @name UpDataStructsCreateCollectionData (243) */
+  /** @name UpDataStructsCreateCollectionData (241) */
   interface UpDataStructsCreateCollectionData extends Struct {
     readonly mode: UpDataStructsCollectionMode;
     readonly access: Option<UpDataStructsAccessMode>;
@@ -2551,14 +2562,14 @@
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsAccessMode (245) */
+  /** @name UpDataStructsAccessMode (243) */
   interface UpDataStructsAccessMode extends Enum {
     readonly isNormal: boolean;
     readonly isAllowList: boolean;
     readonly type: 'Normal' | 'AllowList';
   }
 
-  /** @name UpDataStructsCollectionLimits (247) */
+  /** @name UpDataStructsCollectionLimits (245) */
   interface UpDataStructsCollectionLimits extends Struct {
     readonly accountTokenOwnershipLimit: Option<u32>;
     readonly sponsoredDataSize: Option<u32>;
@@ -2571,7 +2582,7 @@
     readonly transfersEnabled: Option<bool>;
   }
 
-  /** @name UpDataStructsSponsoringRateLimit (249) */
+  /** @name UpDataStructsSponsoringRateLimit (247) */
   interface UpDataStructsSponsoringRateLimit extends Enum {
     readonly isSponsoringDisabled: boolean;
     readonly isBlocks: boolean;
@@ -2579,43 +2590,43 @@
     readonly type: 'SponsoringDisabled' | 'Blocks';
   }
 
-  /** @name UpDataStructsCollectionPermissions (252) */
+  /** @name UpDataStructsCollectionPermissions (250) */
   interface UpDataStructsCollectionPermissions extends Struct {
     readonly access: Option<UpDataStructsAccessMode>;
     readonly mintMode: Option<bool>;
     readonly nesting: Option<UpDataStructsNestingPermissions>;
   }
 
-  /** @name UpDataStructsNestingPermissions (254) */
+  /** @name UpDataStructsNestingPermissions (252) */
   interface UpDataStructsNestingPermissions extends Struct {
     readonly tokenOwner: bool;
     readonly collectionAdmin: bool;
     readonly restricted: Option<UpDataStructsOwnerRestrictedSet>;
   }
 
-  /** @name UpDataStructsOwnerRestrictedSet (256) */
+  /** @name UpDataStructsOwnerRestrictedSet (254) */
   interface UpDataStructsOwnerRestrictedSet extends BTreeSet<u32> {}
 
-  /** @name UpDataStructsPropertyKeyPermission (261) */
+  /** @name UpDataStructsPropertyKeyPermission (259) */
   interface UpDataStructsPropertyKeyPermission extends Struct {
     readonly key: Bytes;
     readonly permission: UpDataStructsPropertyPermission;
   }
 
-  /** @name UpDataStructsPropertyPermission (262) */
+  /** @name UpDataStructsPropertyPermission (260) */
   interface UpDataStructsPropertyPermission extends Struct {
     readonly mutable: bool;
     readonly collectionAdmin: bool;
     readonly tokenOwner: bool;
   }
 
-  /** @name UpDataStructsProperty (265) */
+  /** @name UpDataStructsProperty (263) */
   interface UpDataStructsProperty extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name UpDataStructsCreateItemData (268) */
+  /** @name UpDataStructsCreateItemData (266) */
   interface UpDataStructsCreateItemData extends Enum {
     readonly isNft: boolean;
     readonly asNft: UpDataStructsCreateNftData;
@@ -2626,23 +2637,23 @@
     readonly type: 'Nft' | 'Fungible' | 'ReFungible';
   }
 
-  /** @name UpDataStructsCreateNftData (269) */
+  /** @name UpDataStructsCreateNftData (267) */
   interface UpDataStructsCreateNftData extends Struct {
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsCreateFungibleData (270) */
+  /** @name UpDataStructsCreateFungibleData (268) */
   interface UpDataStructsCreateFungibleData extends Struct {
     readonly value: u128;
   }
 
-  /** @name UpDataStructsCreateReFungibleData (271) */
+  /** @name UpDataStructsCreateReFungibleData (269) */
   interface UpDataStructsCreateReFungibleData extends Struct {
     readonly pieces: u128;
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsCreateItemExData (274) */
+  /** @name UpDataStructsCreateItemExData (272) */
   interface UpDataStructsCreateItemExData extends Enum {
     readonly isNft: boolean;
     readonly asNft: Vec<UpDataStructsCreateNftExData>;
@@ -2655,26 +2666,26 @@
     readonly type: 'Nft' | 'Fungible' | 'RefungibleMultipleItems' | 'RefungibleMultipleOwners';
   }
 
-  /** @name UpDataStructsCreateNftExData (276) */
+  /** @name UpDataStructsCreateNftExData (274) */
   interface UpDataStructsCreateNftExData extends Struct {
     readonly properties: Vec<UpDataStructsProperty>;
     readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
   }
 
-  /** @name UpDataStructsCreateRefungibleExSingleOwner (283) */
+  /** @name UpDataStructsCreateRefungibleExSingleOwner (281) */
   interface UpDataStructsCreateRefungibleExSingleOwner extends Struct {
     readonly user: PalletEvmAccountBasicCrossAccountIdRepr;
     readonly pieces: u128;
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsCreateRefungibleExMultipleOwners (285) */
+  /** @name UpDataStructsCreateRefungibleExMultipleOwners (283) */
   interface UpDataStructsCreateRefungibleExMultipleOwners extends Struct {
     readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name PalletUniqueSchedulerCall (286) */
+  /** @name PalletUniqueSchedulerCall (284) */
   interface PalletUniqueSchedulerCall extends Enum {
     readonly isScheduleNamed: boolean;
     readonly asScheduleNamed: {
@@ -2704,7 +2715,7 @@
     readonly type: 'ScheduleNamed' | 'CancelNamed' | 'ScheduleNamedAfter' | 'ChangeNamedPriority';
   }
 
-  /** @name FrameSupportScheduleMaybeHashed (289) */
+  /** @name FrameSupportScheduleMaybeHashed (287) */
   interface FrameSupportScheduleMaybeHashed extends Enum {
     readonly isValue: boolean;
     readonly asValue: Call;
@@ -2713,7 +2724,7 @@
     readonly type: 'Value' | 'Hash';
   }
 
-  /** @name PalletConfigurationCall (290) */
+  /** @name PalletConfigurationCall (288) */
   interface PalletConfigurationCall extends Enum {
     readonly isSetWeightToFeeCoefficientOverride: boolean;
     readonly asSetWeightToFeeCoefficientOverride: {
@@ -2726,13 +2737,13 @@
     readonly type: 'SetWeightToFeeCoefficientOverride' | 'SetMinGasPriceOverride';
   }
 
-  /** @name PalletTemplateTransactionPaymentCall (292) */
+  /** @name PalletTemplateTransactionPaymentCall (290) */
   type PalletTemplateTransactionPaymentCall = Null;
 
-  /** @name PalletStructureCall (293) */
+  /** @name PalletStructureCall (291) */
   type PalletStructureCall = Null;
 
-  /** @name PalletRmrkCoreCall (294) */
+  /** @name PalletRmrkCoreCall (292) */
   interface PalletRmrkCoreCall extends Enum {
     readonly isCreateCollection: boolean;
     readonly asCreateCollection: {
@@ -2838,7 +2849,7 @@
     readonly type: 'CreateCollection' | 'DestroyCollection' | 'ChangeCollectionIssuer' | 'LockCollection' | 'MintNft' | 'BurnNft' | 'Send' | 'AcceptNft' | 'RejectNft' | 'AcceptResource' | 'AcceptResourceRemoval' | 'SetProperty' | 'SetPriority' | 'AddBasicResource' | 'AddComposableResource' | 'AddSlotResource' | 'RemoveResource';
   }
 
-  /** @name RmrkTraitsResourceResourceTypes (300) */
+  /** @name RmrkTraitsResourceResourceTypes (298) */
   interface RmrkTraitsResourceResourceTypes extends Enum {
     readonly isBasic: boolean;
     readonly asBasic: RmrkTraitsResourceBasicResource;
@@ -2849,7 +2860,7 @@
     readonly type: 'Basic' | 'Composable' | 'Slot';
   }
 
-  /** @name RmrkTraitsResourceBasicResource (302) */
+  /** @name RmrkTraitsResourceBasicResource (300) */
   interface RmrkTraitsResourceBasicResource extends Struct {
     readonly src: Option<Bytes>;
     readonly metadata: Option<Bytes>;
@@ -2857,7 +2868,7 @@
     readonly thumb: Option<Bytes>;
   }
 
-  /** @name RmrkTraitsResourceComposableResource (304) */
+  /** @name RmrkTraitsResourceComposableResource (302) */
   interface RmrkTraitsResourceComposableResource extends Struct {
     readonly parts: Vec<u32>;
     readonly base: u32;
@@ -2867,7 +2878,7 @@
     readonly thumb: Option<Bytes>;
   }
 
-  /** @name RmrkTraitsResourceSlotResource (305) */
+  /** @name RmrkTraitsResourceSlotResource (303) */
   interface RmrkTraitsResourceSlotResource extends Struct {
     readonly base: u32;
     readonly src: Option<Bytes>;
@@ -2877,7 +2888,7 @@
     readonly thumb: Option<Bytes>;
   }
 
-  /** @name PalletRmrkEquipCall (308) */
+  /** @name PalletRmrkEquipCall (306) */
   interface PalletRmrkEquipCall extends Enum {
     readonly isCreateBase: boolean;
     readonly asCreateBase: {
@@ -2899,7 +2910,7 @@
     readonly type: 'CreateBase' | 'ThemeAdd' | 'Equippable';
   }
 
-  /** @name RmrkTraitsPartPartType (311) */
+  /** @name RmrkTraitsPartPartType (309) */
   interface RmrkTraitsPartPartType extends Enum {
     readonly isFixedPart: boolean;
     readonly asFixedPart: RmrkTraitsPartFixedPart;
@@ -2908,14 +2919,14 @@
     readonly type: 'FixedPart' | 'SlotPart';
   }
 
-  /** @name RmrkTraitsPartFixedPart (313) */
+  /** @name RmrkTraitsPartFixedPart (311) */
   interface RmrkTraitsPartFixedPart extends Struct {
     readonly id: u32;
     readonly z: u32;
     readonly src: Bytes;
   }
 
-  /** @name RmrkTraitsPartSlotPart (314) */
+  /** @name RmrkTraitsPartSlotPart (312) */
   interface RmrkTraitsPartSlotPart extends Struct {
     readonly id: u32;
     readonly equippable: RmrkTraitsPartEquippableList;
@@ -2923,7 +2934,7 @@
     readonly z: u32;
   }
 
-  /** @name RmrkTraitsPartEquippableList (315) */
+  /** @name RmrkTraitsPartEquippableList (313) */
   interface RmrkTraitsPartEquippableList extends Enum {
     readonly isAll: boolean;
     readonly isEmpty: boolean;
@@ -2932,20 +2943,20 @@
     readonly type: 'All' | 'Empty' | 'Custom';
   }
 
-  /** @name RmrkTraitsTheme (317) */
+  /** @name RmrkTraitsTheme (315) */
   interface RmrkTraitsTheme extends Struct {
     readonly name: Bytes;
     readonly properties: Vec<RmrkTraitsThemeThemeProperty>;
     readonly inherit: bool;
   }
 
-  /** @name RmrkTraitsThemeThemeProperty (319) */
+  /** @name RmrkTraitsThemeThemeProperty (317) */
   interface RmrkTraitsThemeThemeProperty extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name PalletAppPromotionCall (321) */
+  /** @name PalletAppPromotionCall (319) */
   interface PalletAppPromotionCall extends Enum {
     readonly isSetAdminAddress: boolean;
     readonly asSetAdminAddress: {
@@ -2979,7 +2990,7 @@
     readonly type: 'SetAdminAddress' | 'Stake' | 'Unstake' | 'SponsorCollection' | 'StopSponsoringCollection' | 'SponsorContract' | 'StopSponsoringContract' | 'PayoutStakers';
   }
 
-  /** @name PalletForeignAssetsModuleCall (322) */
+  /** @name PalletForeignAssetsModuleCall (320) */
   interface PalletForeignAssetsModuleCall extends Enum {
     readonly isRegisterForeignAsset: boolean;
     readonly asRegisterForeignAsset: {
@@ -2996,7 +3007,7 @@
     readonly type: 'RegisterForeignAsset' | 'UpdateForeignAsset';
   }
 
-  /** @name PalletEvmCall (323) */
+  /** @name PalletEvmCall (321) */
   interface PalletEvmCall extends Enum {
     readonly isWithdraw: boolean;
     readonly asWithdraw: {
@@ -3708,7 +3719,11 @@
     readonly isWithdrawFailed: boolean;
     readonly isGasPriceTooLow: boolean;
     readonly isInvalidNonce: boolean;
-    readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce';
+    readonly isGasLimitTooLow: boolean;
+    readonly isGasLimitTooHigh: boolean;
+    readonly isUndefined: boolean;
+    readonly isReentrancy: boolean;
+    readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce' | 'GasLimitTooLow' | 'GasLimitTooHigh' | 'Undefined' | 'Reentrancy';
   }
 
   /** @name FpRpcTransactionStatus (453) */
modifiedtests/src/maintenanceMode.seqtest.tsdiffbeforeafterboth
--- a/tests/src/maintenanceMode.seqtest.ts
+++ b/tests/src/maintenanceMode.seqtest.ts
@@ -237,7 +237,7 @@
     expect(tokenId).to.be.equal('1');
 
     await expect(contract.methods.mintWithTokenURI(receiver, 'Test URI').send())
-      .to.be.rejectedWith(/submit transaction to pool failed: Pool\(InvalidTransaction\(InvalidTransaction::Call\)\)/);
+      .to.be.rejectedWith(/Returned error: unknown error/);
 
     await expect(contract.methods.ownerOf(tokenId).call()).rejectedWith(/token not found/);