diff --git a/Cargo.lock b/Cargo.lock index cb3d02d24..e17b09b97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "always-assert" @@ -142,47 +142,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.11" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -493,24 +494,23 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" +checksum = "136d4d23bcc79e27423727b36823d86233aad06dfea531837b038394d11e9928" dependencies = [ "concurrent-queue", - "event-listener 5.0.0", - "event-listener-strategy 0.5.0", + "event-listener 5.3.0", + "event-listener-strategy 0.5.2", "futures-core", "pin-project-lite 0.2.13", ] [[package]] name = "async-executor" -version = "1.8.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" +checksum = "b10202063978b3351199d68f8b22c4e47e4b1b822f8d43fd862d5ea8c006b29a" dependencies = [ - "async-lock 3.3.0", "async-task", "concurrent-queue", "fastrand 2.0.1", @@ -619,9 +619,9 @@ dependencies = [ [[package]] name = "async-recursion" -version = "1.0.5" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", @@ -630,12 +630,12 @@ dependencies = [ [[package]] name = "async-signal" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +checksum = "afe66191c335039c7bb78f99dc7520b0cbb166b3a1cb33a03f53d8a1c6f2afda" dependencies = [ "async-io 2.3.1", - "async-lock 2.8.0", + "async-lock 3.3.0", "atomic-waker", "cfg-if", "futures-core", @@ -643,14 +643,14 @@ dependencies = [ "rustix 0.38.31", "signal-hook-registry", "slab", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "async-task" -version = "4.7.0" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" @@ -811,7 +811,7 @@ dependencies = [ "lazy_static", "lazycell", "peeking_take_while", - "prettyplease 0.2.16", + "prettyplease 0.2.17", "proc-macro2", "quote", "regex", @@ -902,9 +902,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" dependencies = [ "arrayref", "arrayvec 0.7.4", @@ -954,18 +954,16 @@ dependencies = [ [[package]] name = "blocking" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +checksum = "495f7104e962b7356f0aeb34247aca1fe7d2e783b346582db7f2904cb5717e88" dependencies = [ - "async-channel 2.2.0", + "async-channel 2.2.1", "async-lock 3.3.0", "async-task", - "fastrand 2.0.1", "futures-io", "futures-lite 2.2.0", "piper", - "tracing", ] [[package]] @@ -1164,9 +1162,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ "serde", ] @@ -1325,9 +1323,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.0" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80c21025abd42669a92efc996ef13cfb2c5c627858421ea58d5c3b331a6c134f" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -1335,23 +1333,23 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.0" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458bf1f341769dfcf849846f65dffdf9146daa56bcd2a47cb4e1de9915567c99" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.0", + "strsim 0.11.1", ] [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "syn 2.0.48", @@ -1386,39 +1384,39 @@ dependencies = [ [[package]] name = "color-print" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a858372ff14bab9b1b30ea504f2a4bc534582aee3e42ba2d41d2a7baba63d5d" +checksum = "1ee543c60ff3888934877a5671f45494dd27ed4ba25c6670b9a7576b7ed7a8c0" dependencies = [ "color-print-proc-macro", ] [[package]] name = "color-print-proc-macro" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57e37866456a721d0a404439a1adae37a31be4e0055590d053dfe6981e05003f" +checksum = "77ff1a80c5f3cb1ca7c06ffdd71b6a6dd6d8f896c42141fbd43f50ed28dcdb93" dependencies = [ "nom", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "comfy-table" -version = "7.1.0" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c64043d6c7b7a4c58e39e7efccfdea7b93d885a795d0c054a69dbbf4dd52686" +checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7" dependencies = [ - "strum 0.25.0", - "strum_macros 0.25.3", + "strum 0.26.2", + "strum_macros 0.26.2", "unicode-width", ] @@ -1706,7 +1704,7 @@ checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" name = "crowdloan-verifier" version = "0.1.0" dependencies = [ - "clap 4.5.0", + "clap 4.5.4", "csv", "pallet-rewards", "polkadex-primitives", @@ -1798,7 +1796,7 @@ name = "cumulus-client-cli" version = "0.1.0" source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.1.0#c8d2251cafadc108ba2f1f8a3208dc547ff38901" dependencies = [ - "clap 4.5.0", + "clap 4.5.4", "parity-scale-codec", "sc-chain-spec", "sc-cli", @@ -2410,9 +2408,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.116" +version = "1.0.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8aff472b83efd22bfc0176aa8ba34617dd5c17364670eb201a5f06d339b8abf7" +checksum = "bb497fad022245b29c2a0351df572e2d67c1046bcef2260ebc022aec81efea82" dependencies = [ "cc", "cxxbridge-flags", @@ -2422,9 +2420,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.116" +version = "1.0.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf6e7a52c19013a9a0ec421c7d9c2d1125faf333551227e0a017288d71b47c3" +checksum = "9327c7f9fbd6329a200a5d4aa6f674c60ab256525ff0084b52a889d4e4c60cee" dependencies = [ "cc", "codespan-reporting", @@ -2437,15 +2435,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.116" +version = "1.0.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589e83d02fc1d4fb78f5ad56ca08835341e23499d086d2821315869426d618dc" +checksum = "688c799a4a846f1c0acb9f36bb9c6272d9b3d9457f3633c7753c6057270df13c" [[package]] name = "cxxbridge-macro" -version = "1.0.116" +version = "1.0.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2cb1fd8ffae4230c7cfbbaf3698dbeaf750fa8c5dadf7ed897df581b9b572a5" +checksum = "928bc249a7e3cd554fd2e8e08a426e9670c50bbfc9a621653cfa9accc9641783" dependencies = [ "proc-macro2", "quote", @@ -2728,9 +2726,9 @@ checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" [[package]] name = "downcast-rs" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "dtoa" @@ -2985,9 +2983,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.0.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b72557800024fabbaa2449dd4bf24e37b93702d457a4d4f2b0dd1f0f039f20c1" +checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" dependencies = [ "concurrent-queue", "parking", @@ -3006,11 +3004,11 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener 5.0.0", + "event-listener 5.3.0", "pin-project-lite 0.2.13", ] @@ -3288,7 +3286,7 @@ dependencies = [ "Inflector", "array-bytes", "chrono", - "clap 4.5.0", + "clap 4.5.4", "comfy-table", "frame-benchmarking", "frame-support", @@ -3930,6 +3928,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -4112,7 +4116,7 @@ dependencies = [ "http", "hyper", "log", - "rustls 0.21.10", + "rustls 0.21.12", "rustls-native-certs", "tokio", "tokio-rustls", @@ -4375,6 +4379,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.10.5" @@ -4664,12 +4674,12 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-targets 0.52.0", ] [[package]] @@ -6791,6 +6801,7 @@ dependencies = [ "frame-support", "frame-system", "hash-db", + "hex", "lazy_static", "log", "num-traits", @@ -7306,6 +7317,21 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-uniques" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.1.0#c8d2251cafadc108ba2f1f8a3208dc547ff38901" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-utility" version = "4.0.0-dev" @@ -7410,7 +7436,7 @@ dependencies = [ name = "parachain-polkadex-node" version = "1.1.0" dependencies = [ - "clap 4.5.0", + "clap 4.5.4", "color-print", "cumulus-client-cli", "cumulus-client-collator", @@ -7734,9 +7760,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.7" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219c0dcc30b6a27553f9cc242972b67f75b60eb0db71f0b5462f38b058c41546" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" dependencies = [ "memchr", "thiserror", @@ -7745,9 +7771,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.7" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e1288dbd7786462961e69bfd4df7848c1e37e8b74303dbdab82c3a9cdd2809" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" dependencies = [ "pest", "pest_generator", @@ -7755,9 +7781,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.7" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1381c29a877c6d34b8c176e734f35d7f7f5b3adaefe940cb4d1bb7af94678e2e" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" dependencies = [ "pest", "pest_meta", @@ -7768,9 +7794,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.7" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0934d6907f148c22a3acbda520c7eed243ad7487a30f51f6ce52b58b7077a8a" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" dependencies = [ "once_cell", "pest", @@ -7879,7 +7905,7 @@ dependencies = [ name = "polkadex-node" version = "6.0.0" dependencies = [ - "clap 4.5.0", + "clap 4.5.4", "frame-benchmarking-cli", "frame-support", "frame-system", @@ -7978,6 +8004,33 @@ dependencies = [ "staging-xcm", ] +[[package]] +name = "polkadex-xcm-simulator" +version = "1.0.0" +dependencies = [ + "frame-support", + "frame-system", + "log", + "pallet-balances", + "pallet-message-queue", + "pallet-uniques", + "pallet-xcm", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "polkadot-runtime-parachains", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-tracing", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "xcm-simulator", +] + [[package]] name = "polkadot-approval-distribution" version = "1.0.0" @@ -8061,7 +8114,7 @@ name = "polkadot-cli" version = "1.1.0" source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.1.0#c8d2251cafadc108ba2f1f8a3208dc547ff38901" dependencies = [ - "clap 4.5.0", + "clap 4.5.4", "frame-benchmarking-cli", "futures 0.3.30", "log", @@ -9289,9 +9342,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" +checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" dependencies = [ "proc-macro2", "syn 2.0.48", @@ -10204,9 +10257,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring 0.17.7", @@ -10411,7 +10464,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot dependencies = [ "array-bytes", "chrono", - "clap 4.5.0", + "clap 4.5.4", "fdlimit", "futures 0.3.30", "libp2p-identity", @@ -11297,7 +11350,7 @@ name = "sc-storage-monitor" version = "0.1.0" source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.1.0#c8d2251cafadc108ba2f1f8a3208dc547ff38901" dependencies = [ - "clap 4.5.0", + "clap 4.5.4", "fs4", "log", "sc-client-db", @@ -11611,9 +11664,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -11624,9 +11677,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -11817,9 +11870,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -13065,9 +13118,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "structopt" @@ -13104,9 +13157,9 @@ dependencies = [ [[package]] name = "strum" -version = "0.25.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" [[package]] name = "strum_macros" @@ -13123,9 +13176,9 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.25.3" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -13524,6 +13577,7 @@ dependencies = [ "pallet-xcm", "parachain-info", "parity-scale-codec", + "polkadex-primitives", "scale-info", "sp-core", "sp-io", @@ -13545,7 +13599,9 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "hex", "log", + "orderbook-primitives", "pallet-asset-conversion", "pallet-assets", "pallet-balances", @@ -13833,7 +13889,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.10", + "rustls 0.21.12", "tokio", ] @@ -14164,7 +14220,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.1.0#c8d2251cafadc108ba2f1f8a3208dc547ff38901" dependencies = [ "async-trait", - "clap 4.5.0", + "clap 4.5.4", "frame-remote-externalities", "frame-try-runtime", "hex", @@ -14265,9 +14321,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" [[package]] name = "unicode-xid" @@ -14581,9 +14637,9 @@ dependencies = [ [[package]] name = "wasmparser-nostd" -version = "0.100.1" +version = "0.100.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9157cab83003221bfd385833ab587a039f5d6fa7304854042ba358a3b09e0724" +checksum = "d5a015fe95f3504a94bb1462c717aae75253e39b9dd6c3fb1062c934535c64aa" dependencies = [ "indexmap-nostd", ] @@ -15326,6 +15382,24 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "xcm-simulator" +version = "1.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.1.0#c8d2251cafadc108ba2f1f8a3208dc547ff38901" +dependencies = [ + "frame-support", + "parity-scale-codec", + "paste", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "polkadot-runtime-parachains", + "sp-io", + "sp-std", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", +] + [[package]] name = "yamux" version = "0.10.2" diff --git a/Cargo.toml b/Cargo.toml index 9fbe69239..667dd71d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,31 +49,10 @@ members = [ "pallets/xcm-helper", "misc/load-testing", "misc/crowdloan-verifier", + "polkadex-xcm-simulator", ] exclude = ["scripts/check-off-on-deviation"] -default-members = [ - "client", - "nodes/mainnet", - "nodes/parachain", - "runtimes/mainnet", - "runtimes/parachain", - "pallets/pdex-migration", - "pallets/pdex-migration", - "pallets/ocex", - "pallets/ocex/rpc", - "pallets/liquidity-mining", - "pallets/ocex/rpc/runtime-api", - "pallets/rewards", - "primitives/orderbook", - "primitives/polkadex", - "primitives/thea", - "primitives/bls", - "pallets/thea", - "pallets/thea-executor", - "pallets/rewards/rpc", - "pallets/rewards/rpc/runtime-api", - "rpc/swap", -] + [workspace.dependencies] log = { version = "0.4.8", default-features = false } @@ -133,7 +112,6 @@ pallet-authority-discovery = { git = "https://github.com/paritytech/polkadot-sdk pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false } pallet-staking-reward-curve = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false } pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false } -#pallet-randomness-collective-flip = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false } pallet-election-provider-multi-phase = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false } pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false } pallet-statement = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false } diff --git a/check-all-ci-tests.sh b/check-all-ci-tests.sh index 99877716b..9b7827e3c 100755 --- a/check-all-ci-tests.sh +++ b/check-all-ci-tests.sh @@ -22,4 +22,4 @@ cargo build --features try-runtime || exit cargo build --features runtime-benchmarks || exit ./target/debug/polkadex-node benchmark pallet --pallet "*" --extrinsic "*" --steps 2 --repeat 1 || exit cargo clippy -- -D warnings || exit -RUSTFLAGS="-D warnings" cargo test || exit +RUSTFLAGS="-D warnings" cargo test --workspace || exit diff --git a/pallets/liquidity-mining/src/mock.rs b/pallets/liquidity-mining/src/mock.rs index 698d7c4a1..bb8ecfd55 100644 --- a/pallets/liquidity-mining/src/mock.rs +++ b/pallets/liquidity-mining/src/mock.rs @@ -145,6 +145,7 @@ impl ocex::Config for Test { type CrowdSourceLiqudityMining = LiqudityMining; type OBWithdrawalLimit = OBWithdrawalLimit; type WeightInfo = ocex::weights::WeightInfo; + type CrossChainGadget = (); } parameter_types! { diff --git a/pallets/ocex/Cargo.toml b/pallets/ocex/Cargo.toml index ffcaac73c..a4255ff85 100644 --- a/pallets/ocex/Cargo.toml +++ b/pallets/ocex/Cargo.toml @@ -44,6 +44,7 @@ sp-io = { workspace = true } pallet-lmp = { path = "../liquidity-mining", default-features = false } lazy_static = "1.4.0" sequential-test = "0.2.4" +hex = "0.4.3" [features] default = ["std"] diff --git a/pallets/ocex/src/benchmarking.rs b/pallets/ocex/src/benchmarking.rs index 8d040ea4f..f556245a9 100644 --- a/pallets/ocex/src/benchmarking.rs +++ b/pallets/ocex/src/benchmarking.rs @@ -222,14 +222,9 @@ benchmarks! { let proxy = account::("proxy", x, 0); Ocex::::register_main_account(RawOrigin::Signed(user.clone()).into(), proxy)?; let call = Call::::deposit { asset, amount }; + let id = H160::zero(); }: { call.dispatch_bypass_filter(RawOrigin::Signed(user.clone()).into())? } - verify { - assert_last_event::(Event::DepositSuccessful { - user, - asset, - amount - }.into()); - } + remove_proxy_account { let x in 1 .. 255; // should not overflow u8 @@ -285,12 +280,13 @@ benchmarks! { let mut vec_withdrawals = Vec::with_capacity(1); let fees = Decimal::new(100, 5); vec_withdrawals.push(Withdrawal { + id: Default::default(), amount: Decimal::new(x.into(), 0), stid:0, asset, main_account: main.clone(), fees, - }); + destination: None,}); let mut wm = sp_std::collections::btree_map::BTreeMap::new(); wm.insert(main.clone(), vec_withdrawals.clone()); >::insert(x as u64, wm); @@ -580,11 +576,13 @@ fn get_dummy_snapshot() -> SnapshotSummary { ); for _ in 0..50 { withdrawals.push(Withdrawal { + id: Default::default(), main_account: T::AccountId::decode(&mut &[0u8; 32][..]).unwrap(), amount: Decimal::one(), asset: AssetId::Polkadex, fees: Decimal::one(), stid: 1, + destination: None, }); } SnapshotSummary { diff --git a/pallets/ocex/src/integration_tests.rs b/pallets/ocex/src/integration_tests.rs index ae4eb5ef4..bb0993990 100644 --- a/pallets/ocex/src/integration_tests.rs +++ b/pallets/ocex/src/integration_tests.rs @@ -43,7 +43,7 @@ use rust_decimal::Decimal; use sequential_test::sequential; use sp_core::crypto::AccountId32; use sp_core::sr25519::Signature; -use sp_core::{Pair, H256}; +use sp_core::{Pair, H160, H256}; use sp_runtime::offchain::storage::StorageValueRef; use std::collections::BTreeMap; @@ -84,66 +84,6 @@ fn test_run_on_chain_validation_trades_happy_path() { }); } -#[test] -#[sequential] -fn test_lmp_complete_flow() { - new_test_ext().execute_with(|| { - set_lmp_config(); - push_trade_user_actions(1, 1, 4768084); - assert_ok!(OCEX::run_on_chain_validation(1)); - let snapshot_id: u64 = 1; - let mut key = LAST_PROCESSED_SNAPSHOT.to_vec(); - key.append(&mut snapshot_id.encode()); - let summay_ref = StorageValueRef::persistent(&key); - match summay_ref - .get::<(SnapshotSummary, crate::sr25519::AuthoritySignature, u16)>() - { - Ok(Some((summary, signature, index))) => { - println!("Summary {:?}", summary); - assert_eq!(summary.snapshot_id, 1); - assert_eq!(summary.state_change_id, 1); - assert_eq!(summary.last_processed_blk, 4768084); - assert_ok!(OCEX::submit_snapshot(RuntimeOrigin::none(), summary, Vec::new())); - }, - _ => panic!("Snapshot not found"), - }; - OCEX::start_new_epoch(2); - push_trade_user_actions(2, 1, 4768085); - let s_info = StorageValueRef::persistent(&WORKER_STATUS); - s_info.set(&false); - assert_ok!(OCEX::run_on_chain_validation(2)); - let snapshot_id: u64 = 2; - let mut key = LAST_PROCESSED_SNAPSHOT.to_vec(); - key.append(&mut snapshot_id.encode()); - let summay_ref = StorageValueRef::persistent(&key); - match summay_ref - .get::<(SnapshotSummary, crate::sr25519::AuthoritySignature, u16)>() - { - Ok(Some((summary, signature, index))) => { - println!("Summary {:?}", summary); - assert_eq!(summary.snapshot_id, 2); - assert_eq!(summary.state_change_id, 2); - assert_eq!(summary.last_processed_blk, 4768085); - assert_ok!(OCEX::submit_snapshot(RuntimeOrigin::none(), summary, Vec::new())); - }, - _ => panic!("Snapshot not found"), - }; - OCEX::start_new_epoch(3); - let (maker_account, taker_account) = get_maker_and_taker_account(); - let trading_pair = TradingPair { base: AssetId::Polkadex, quote: AssetId::Asset(1) }; - assert_ok!(OCEX::claim_lmp_rewards( - RuntimeOrigin::signed(maker_account.clone()), - 1, - trading_pair - )); - assert_ok!(OCEX::claim_lmp_rewards( - RuntimeOrigin::signed(taker_account.clone()), - 1, - trading_pair - )); - }) -} - #[test] #[sequential] fn test_on_chain_validation_with_auction() { @@ -321,10 +261,18 @@ fn push_trade_user_actions(stid: u64, snapshot_id: u64, block_no: u64) { fn get_block_import(block_no: u64) -> u64 { let block_no = block_no; let (maker_account, taker_account) = get_maker_and_taker_account(); - let maker_ingress_message = - IngressMessages::Deposit(maker_account, AssetId::Asset(1), Decimal::from(100)); - let taker_ingress_message = - IngressMessages::Deposit(taker_account, AssetId::Polkadex, Decimal::from(100)); + let maker_ingress_message = IngressMessages::Deposit( + H160::zero(), + maker_account, + AssetId::Asset(1), + Decimal::from(100), + ); + let taker_ingress_message = IngressMessages::Deposit( + H160::zero(), + taker_account, + AssetId::Polkadex, + Decimal::from(100), + ); >::insert( block_no, vec![maker_ingress_message, taker_ingress_message], diff --git a/pallets/ocex/src/lib.rs b/pallets/ocex/src/lib.rs index 9a5068e98..b6206d4e2 100644 --- a/pallets/ocex/src/lib.rs +++ b/pallets/ocex/src/lib.rs @@ -55,10 +55,12 @@ use frame_support::traits::fungible::Inspect as InspectNative; use frame_system::pallet_prelude::BlockNumberFor; use orderbook_primitives::lmp::LMPMarketConfig; use orderbook_primitives::ocex::TradingPairConfig; +use orderbook_primitives::traits::OrderbookOperations; use orderbook_primitives::{ types::{AccountAsset, TradingPair}, SnapshotSummary, ValidatorSet, GENESIS_AUTHORITY_SET_ID, }; +use sp_core::H160; use sp_std::vec::Vec; #[cfg(test)] @@ -144,6 +146,7 @@ pub trait OcexWeightInfo { #[frame_support::pallet] pub mod pallet { use orderbook_primitives::traits::LiquidityMiningCrowdSourcePallet; + use polkadex_primitives::withdrawal::WithdrawalDestination; use sp_std::collections::btree_map::BTreeMap; // Import various types used to declare pallet in scope. use super::*; @@ -168,6 +171,7 @@ pub mod pallet { }; use parity_scale_codec::Compact; use polkadex_primitives::auction::AuctionInfo; + use polkadex_primitives::traits::CrossChainWithdraw; use polkadex_primitives::{assets::AssetId, withdrawal::Withdrawal, ProxyLimit, UNIT_BALANCE}; use rust_decimal::{prelude::ToPrimitive, Decimal}; use sp_application_crypto::RuntimeAppPublic; @@ -278,6 +282,9 @@ pub mod pallet { ::AccountId, >; + /// CrossChain Withdrawal + type CrossChainGadget: CrossChainWithdraw; + /// Type representing the weight of this pallet type WeightInfo: OcexWeightInfo; } @@ -729,7 +736,7 @@ pub mod pallet { #[pallet::compact] amount: BalanceOf, ) -> DispatchResult { let user = ensure_signed(origin)?; - Self::do_deposit(user, asset, amount)?; + Self::do_deposit(Self::new_random_id(None), user, asset, amount)?; Ok(()) } @@ -1055,6 +1062,21 @@ pub mod pallet { Self::start_new_epoch(current_blk); Ok(()) } + + /// Governance endpoint for submit Snapshot Summary + #[pallet::call_index(24)] + #[pallet::weight(< T as Config >::WeightInfo::submit_snapshot())] + pub fn force_submit_snapshot( + origin: OriginFor, + summary: SnapshotSummary, + ) -> DispatchResult { + ensure_root(origin)?; + let id = summary.snapshot_id; + >::put(id); + >::insert(id, summary); + Self::deposit_event(crate::pallet::Event::::SnapshotProcessed(id)); + Ok(()) + } } /// Events are a simple means of reporting specific conditions and @@ -1082,6 +1104,7 @@ pub mod pallet { quote: AssetId, }, DepositSuccessful { + id: H160, user: T::AccountId, asset: AssetId, amount: BalanceOf, @@ -1114,7 +1137,7 @@ pub mod pallet { /// AllowlistedTokenRemoved AllowlistedTokenRemoved(AssetId), /// Withdrawal ready to claim - WithdrawalReady(u64, Withdrawal), + WithdrawalReady(u64, Box>), /// Exchange state has been updated ExchangeStateUpdated(bool), /// DisputePeriod has been updated @@ -1313,6 +1336,16 @@ pub mod pallet { StorageValue<_, AuctionInfo>, OptionQuery>; impl crate::pallet::Pallet { + pub fn new_random_id(prefix: Option<[u8; 4]>) -> H160 { + let mut entropy: [u8; 20] = [0u8; 20]; + if let Some(prefix) = prefix { + entropy[0..4].copy_from_slice(&prefix); + } + let current_blk = frame_system::Pallet::::current_block_number(); + entropy[4..].copy_from_slice(&sp_io::hashing::blake2_128(&((current_blk).encode()))); + H160::from(entropy) + } + pub fn do_withdraw( snapshot_id: u64, mut withdrawal_vector: Vec>, @@ -1323,14 +1356,14 @@ pub mod pallet { // Perform pop operation to ensure we do not leave any withdrawal left // for a double spend if let Some(withdrawal) = withdrawal_vector.pop() { - if Self::on_idle_withdrawal_processor(withdrawal.clone()) { + if Self::on_idle_withdrawal_processor(withdrawal.clone()).is_ok() { processed_withdrawals.push(withdrawal.to_owned()); } else { // Storing the failed withdrawals back into the storage item failed_withdrawals.push(withdrawal.to_owned()); Self::deposit_event(Event::WithdrawalReady( snapshot_id, - withdrawal.to_owned(), + Box::from(withdrawal.to_owned()), )); } } @@ -1700,6 +1733,7 @@ pub mod pallet { } pub fn do_deposit( + id: H160, user: T::AccountId, asset: AssetId, amount: BalanceOf, @@ -1728,12 +1762,13 @@ pub mod pallet { let current_blk = frame_system::Pallet::::current_block_number(); >::mutate(current_blk, |ingress_messages| { ingress_messages.push(orderbook_primitives::ingress::IngressMessages::Deposit( + id, user.clone(), asset, converted_amount, )); }); - Self::deposit_event(Event::DepositSuccessful { user, asset, amount }); + Self::deposit_event(Event::DepositSuccessful { id, user, asset, amount }); Ok(()) } @@ -1812,22 +1847,52 @@ pub mod pallet { /// Performs actual transfer of assets from pallet account to target destination /// Used to finalize withdrawals in extrinsic or on_idle + #[transactional] fn on_idle_withdrawal_processor( withdrawal: Withdrawal<::AccountId>, - ) -> bool { - if let Some(converted_withdrawal) = - withdrawal.amount.saturating_mul(Decimal::from(UNIT_BALANCE)).to_u128() - { - Self::transfer_asset( - &Self::get_pallet_account(), - &withdrawal.main_account, - converted_withdrawal.saturated_into(), - withdrawal.asset, - ) - .is_ok() - } else { - false + ) -> DispatchResult { + let converted_withdrawal = withdrawal + .amount + .saturating_mul(Decimal::from(UNIT_BALANCE)) + .to_u128() + .ok_or(Error::::FailedToConvertDecimaltoBalance)?; + + Self::transfer_asset( + &Self::get_pallet_account(), + &withdrawal.main_account, + converted_withdrawal.saturated_into(), + withdrawal.asset, + )?; + + // on_idle_withdrawal_processor is called in a transacitonal manner so it is okay. + if let Some(destination) = withdrawal.destination { + match destination { + WithdrawalDestination::Polkadot(multi_location, None) => { + T::CrossChainGadget::parachain_withdraw( + withdrawal.main_account, + withdrawal.asset, + converted_withdrawal, + multi_location, + None, + None, + withdrawal.id, + )? + }, + WithdrawalDestination::Polkadot( + multi_location, + Some((fee_asset_id, fee_amount)), + ) => T::CrossChainGadget::parachain_withdraw( + withdrawal.main_account, + withdrawal.asset, + converted_withdrawal, + multi_location, + Some(fee_asset_id), + Some(fee_amount), + withdrawal.id, + )?, + } } + Ok(()) } /// Collects onchain registered main and proxy accounts @@ -1903,11 +1968,7 @@ pub mod pallet { account_ids.push((Self::get_pot_account(), Default::default())); let mut balances: BTreeMap = BTreeMap::new(); - let mut q_scores_uptime_map = BTreeMap::new(); - let mut maker_volume_map = BTreeMap::new(); - let mut taker_volume_map = BTreeMap::new(); - let mut fees_paid_map = BTreeMap::new(); - let mut total_maker_volume_map = BTreeMap::new(); + // all offchain balances for main accounts for (account, _) in &account_ids { let main = Self::transform_account(account.clone())?; @@ -1922,76 +1983,12 @@ pub mod pallet { let snapshot_id = state_info.snapshot_id; let state_change_id = state_info.stid; - let mut root = crate::storage::load_trie_root(); - let mut storage = crate::storage::State; - let mut state = OffchainState::load(&mut storage, &mut root); - - let registered_tradingpairs = >::iter() - .map(|(base, quote, _)| (base, quote)) - .collect::>(); - - let current_epoch = >::get(); - - for epoch in 0..=current_epoch { - for (base, quote) in ®istered_tradingpairs { - let pair = TradingPair::from(*quote, *base); - for (account, _) in &account_ids { - let main = Self::transform_account(account.clone())?; - // Get Q scores - let q_scores_map = crate::lmp::get_q_score_and_uptime_for_checkpoint( - &mut state, epoch, &pair, &main, - )?; - - if !q_scores_map.is_empty() { - q_scores_uptime_map.insert((epoch, pair, main.clone()), q_scores_map); - } - - let fees_paid = crate::lmp::get_fees_paid_by_main_account_in_quote( - &mut state, epoch, &pair, &main, - )?; - - if !fees_paid.is_zero() { - fees_paid_map.insert((epoch, pair, main.clone()), fees_paid); - } - - let maker_volume = crate::lmp::get_maker_volume_by_main_account( - &mut state, epoch, &pair, &main, - )?; - - if !maker_volume.is_zero() { - maker_volume_map.insert((epoch, pair, main.clone()), maker_volume); - } - - let trade_volume = crate::lmp::get_trade_volume_by_main_account( - &mut state, epoch, &pair, &main, - )?; - - if !trade_volume.is_zero() { - taker_volume_map.insert((epoch, pair, main.clone()), trade_volume); - } - } - let total_maker_volume = - crate::lmp::get_total_maker_volume(&mut state, epoch, &pair)?; - if !total_maker_volume.is_zero() { - total_maker_volume_map.insert((epoch, pair), total_maker_volume); - } - } - } - - let config = crate::lmp::get_lmp_config(&mut state, current_epoch)?; - log::debug!(target:"ocex", "fetch_checkpoint returning"); Ok(ObCheckpointRaw { snapshot_id, balances, last_processed_block_number, state_change_id, - config, - q_scores_uptime_map, - maker_volume_map, - taker_volume_map, - fees_paid_map, - total_maker_volume_map, }) } @@ -2395,3 +2392,9 @@ impl OneSessionHandler for Pallet { fn on_disabled(_i: u32) {} } + +impl OrderbookOperations for Pallet { + fn deposit(id: H160, main: T::AccountId, asset: AssetId, amount: u128) -> DispatchResult { + Self::do_deposit(id, main, asset, amount.saturated_into()) + } +} diff --git a/pallets/ocex/src/lmp.rs b/pallets/ocex/src/lmp.rs index e9196f84e..a886a184d 100644 --- a/pallets/ocex/src/lmp.rs +++ b/pallets/ocex/src/lmp.rs @@ -17,10 +17,11 @@ // along with this program. If not, see . use crate::lmp::keys::{ - get_fees_paid_by_main_account, get_maker_volume_by_main_account_key, + get_fees_paid_by_main_account, get_lmp_config_key, get_maker_volume_by_main_account_key, get_q_score_uptime_by_main_account, get_total_maker_volume_key, get_trade_volume_by_main_account_key, }; +use crate::pallet::Accounts; use crate::{ pallet::{IngressMessages, PriceOracle, TraderMetrics, TradingPairs}, storage::OffchainState, @@ -334,7 +335,8 @@ pub fn get_q_score_and_uptime( } } -/// Returns the individial Q score and uptime indexe +/// Returns the individial Q score and uptime index +#[allow(dead_code)] pub fn get_q_score_and_uptime_for_checkpoint( state: &mut OffchainState, epoch: u16, @@ -357,6 +359,36 @@ pub fn get_q_score_and_uptime_for_checkpoint( } impl Pallet { + /// Clears the lmp's offchain storage + pub fn clear_lmp_storages(state: &mut OffchainState) -> Result<(), &'static str> { + let current_epoch: u16 = >::get(); + let trading_pairs = >::iter_keys() + .map(|(base, quote)| TradingPair::from(quote, base)) + .collect::>(); + let main_accounts = >::iter_keys().collect::>(); + for main in &main_accounts { + let main_type: AccountId = + Decode::decode(&mut &main.encode()[..]).map_err(|_| "Unable to decode decimal")?; + for epoch in 0..=current_epoch { + for pair in &trading_pairs { + let key1 = get_trade_volume_by_main_account_key(epoch, *pair, &main_type); + let key2 = get_maker_volume_by_main_account_key(epoch, *pair, &main_type); + let key3 = get_total_maker_volume_key(epoch, *pair); + let key4 = get_fees_paid_by_main_account(epoch, *pair, &main_type); + let key5 = get_q_score_uptime_by_main_account(epoch, *pair, &main_type); + state.remove(key1); + state.remove(key2); + state.remove(key3); + state.remove(key4); + state.remove(key5); + } + } + } + let lmp_config_key = get_lmp_config_key(); + state.remove(lmp_config_key); + + Ok(()) + } /// Updates the respective offchain DB trie keys for LMP metrics from given trade pub fn update_lmp_storage_from_trade( state: &mut OffchainState, @@ -482,12 +514,22 @@ impl LiquidityMining> for Pallet { .saturating_mul(unit) .to_u128() .ok_or(Error::::FailedToConvertDecimaltoBalance)?; - Self::do_deposit(pool.clone(), market.base, base_amount_in_u128.saturated_into())?; + Self::do_deposit( + Self::new_random_id(None), + pool.clone(), + market.base, + base_amount_in_u128.saturated_into(), + )?; let quote_amount_in_u128 = quote_amount .saturating_mul(unit) .to_u128() .ok_or(Error::::FailedToConvertDecimaltoBalance)?; - Self::do_deposit(pool.clone(), market.quote, quote_amount_in_u128.saturated_into())?; + Self::do_deposit( + Self::new_random_id(None), + pool.clone(), + market.quote, + quote_amount_in_u128.saturated_into(), + )?; let current_blk = frame_system::Pallet::::current_block_number(); >::mutate(current_blk, |messages| { messages.push(orderbook_primitives::ingress::IngressMessages::AddLiquidity( diff --git a/pallets/ocex/src/mock.rs b/pallets/ocex/src/mock.rs index 9c1380fba..e20f4ece9 100644 --- a/pallets/ocex/src/mock.rs +++ b/pallets/ocex/src/mock.rs @@ -149,6 +149,7 @@ impl Config for Test { type CrowdSourceLiqudityMining = LiqudityMining; type WeightInfo = crate::weights::WeightInfo; type OBWithdrawalLimit = OBWithdrawalLimit; + type CrossChainGadget = (); } parameter_types! { diff --git a/pallets/ocex/src/rpc.rs b/pallets/ocex/src/rpc.rs index 025ded704..dcf242311 100644 --- a/pallets/ocex/src/rpc.rs +++ b/pallets/ocex/src/rpc.rs @@ -127,8 +127,12 @@ impl Pallet { let ingress_msgs = >::get(blk.saturated_into::>()); for msg in ingress_msgs { - if let orderbook_primitives::ingress::IngressMessages::Deposit(_, asset, amt) = - msg + if let orderbook_primitives::ingress::IngressMessages::Deposit( + _, + _, + asset, + amt, + ) = msg { onchain_inventory .entry(asset) diff --git a/pallets/ocex/src/settlement.rs b/pallets/ocex/src/settlement.rs index d3e30d142..3469b849f 100644 --- a/pallets/ocex/src/settlement.rs +++ b/pallets/ocex/src/settlement.rs @@ -161,7 +161,7 @@ impl Pallet { let pot_account: AccountId = FEE_POT_PALLET_ID.into_account_truncating(); // Handle Fees here, and update the total fees paid, maker volume for LMP calculations // Update balances - let maker_fees = { + let _maker_fees = { let (maker_asset, mut maker_credit) = trade.credit(true); let maker_fees = maker_credit.saturating_mul(maker_fees.maker_fraction); maker_credit = maker_credit.saturating_sub(maker_fees); @@ -173,7 +173,7 @@ impl Pallet { sub_balance(state, &maker_asset.main, maker_asset.asset, maker_debit, false)?; maker_fees }; - let taker_fees = { + let _taker_fees = { let (taker_asset, mut taker_credit) = trade.credit(false); let taker_fees = taker_credit.saturating_mul(taker_fees.taker_fraction); taker_credit = taker_credit.saturating_sub(taker_fees); @@ -187,7 +187,7 @@ impl Pallet { }; // Updates the LMP Storage - Self::update_lmp_storage_from_trade(state, trade, config, maker_fees, taker_fees)?; + // Self::update_lmp_storage_from_trade(state, trade, config, maker_fees, taker_fees)?; Ok(()) } diff --git a/pallets/ocex/src/storage.rs b/pallets/ocex/src/storage.rs index 3cb11b622..4a1517151 100644 --- a/pallets/ocex/src/storage.rs +++ b/pallets/ocex/src/storage.rs @@ -34,12 +34,13 @@ const TRIE_ROOT: [u8; 24] = *b"offchain-ocex::trie_root"; pub struct OffchainState<'a> { cache: sp_std::collections::btree_map::BTreeMap, Vec>, trie: TrieDBMut<'a, LayoutV1>, + keys_to_remove: sp_std::collections::btree_set::BTreeSet>, } impl<'a> OffchainState<'a> { pub fn load(storage: &'a mut State, root: &'a mut H256) -> Self { let trie = crate::storage::get_state_trie(storage, root); - Self { cache: Default::default(), trie } + Self { cache: Default::default(), trie, keys_to_remove: Default::default() } } pub fn is_empty(&self) -> bool { @@ -66,14 +67,25 @@ impl<'a> OffchainState<'a> { } pub fn insert(&mut self, key: Vec, value: Vec) { + self.keys_to_remove.remove(&key); self.cache.insert(key, value); } + pub fn remove(&mut self, key: Vec) { + self.cache.remove(&key); + self.keys_to_remove.insert(key); + } + pub fn commit(&mut self) -> Result { for (key, value) in self.cache.iter() { self.trie.insert(key, value).map_err(map_trie_error)?; } + + for key in &self.keys_to_remove { + self.trie.remove(key).map_err(map_trie_error)?; + } self.cache.clear(); + self.keys_to_remove.clear(); self.trie.commit(); Ok(*self.trie.root()) } @@ -267,6 +279,32 @@ mod tests { tests::register_offchain_ext, }; + #[test] + pub fn test_removal_same_as_not_existing() { + let mut ext = new_test_ext(); + register_offchain_ext(&mut ext); + log::trace!(target:"ocex","test_trie_storage test starting.."); + ext.execute_with(|| { + let mut root = load_trie_root(); + { + let mut storage = State; + + let mut state = OffchainState::load(&mut storage, &mut root); + + let empty_root = state.commit().unwrap(); + + state.insert(b"1".to_vec(), b"a".to_vec()); + let intermediate_root1 = state.commit().unwrap(); + assert_ne!(empty_root, intermediate_root1); + state.insert(b"2".to_vec(), b"b".to_vec()); + let _intermediate_root2 = state.commit().unwrap(); + state.remove(b"2".to_vec()); + let final_root = state.commit().unwrap(); + assert_eq!(intermediate_root1, final_root) + } + }); + } + #[test] pub fn test_commit_change_revert_pattern() { let mut ext = new_test_ext(); diff --git a/pallets/ocex/src/tests.rs b/pallets/ocex/src/tests.rs index 1ccaf0e7b..7b0eb5579 100644 --- a/pallets/ocex/src/tests.rs +++ b/pallets/ocex/src/tests.rs @@ -1548,16 +1548,12 @@ fn test_deposit() { 9999999999999999999900 ); assert_eq!(::NativeCurrency::free_balance(custodian_account.clone()), 100); - assert_last_event::( - crate::Event::DepositSuccessful { - user: account_id.clone(), - asset: AssetId::Polkadex, - amount: 100_u128, - } - .into(), + let event: IngressMessages = IngressMessages::Deposit( + H160::from_slice(&hex::decode("000000009ea2d098b5f70192f96c06f38d3fbc97").unwrap()), + account_id, + AssetId::Polkadex, + Decimal::new(10, 11), ); - let event: IngressMessages = - IngressMessages::Deposit(account_id, AssetId::Polkadex, Decimal::new(10, 11)); let blk = frame_system::Pallet::::current_block_number(); assert_eq!(OCEX::ingress_messages(blk)[2], event); }); @@ -1998,11 +1994,13 @@ fn get_dummy_snapshot( let mut withdrawals = vec![]; for _ in 0..withdrawals_len { withdrawals.push(Withdrawal { + id: Default::default(), main_account: main.clone(), amount: Decimal::one(), asset: AssetId::Polkadex, fees: Default::default(), stid: 0, + destination: None, }) } diff --git a/pallets/ocex/src/validator.rs b/pallets/ocex/src/validator.rs index 96eb86352..1c516d9c7 100644 --- a/pallets/ocex/src/validator.rs +++ b/pallets/ocex/src/validator.rs @@ -17,7 +17,6 @@ // along with this program. If not, see . use crate::lmp::{get_lmp_config, get_total_maker_volume, store_lmp_config}; -use crate::pallet::LMPEpoch; use crate::{ aggregator::AggregatorClient, lmp::{ @@ -106,11 +105,29 @@ impl Pallet { let next_nonce = >::get().saturating_add(1); let mut root = crate::storage::load_trie_root(); log::info!(target:"ocex","block: {:?}, state_root {:?}", block_num, root); + let mut storage = crate::storage::State; + let root_clone = root; let mut state = OffchainState::load(&mut storage, &mut root); // Load the state to memory let mut state_info = match Self::load_state_info(&mut state) { - Ok(info) => info, + Ok(info) => { + // Check if last processed snapshot id root from on-chain is same as our offchain root + if let Some(summary) = >::get(info.snapshot_id) { + if summary.state_hash != root_clone { + log::error!(target:"ocex","Last processed snapshot root is not same as on-chain root"); + store_trie_root(H256::zero()); + return Err("Last processed snapshot root is not same as on-chain root"); + } + info + } else if info.snapshot_id != 0 { + log::error!(target:"ocex","Unable to load last processed snapshot summary from on-chain: {:?}",info.snapshot_id); + store_trie_root(H256::zero()); + return Err("Unable to load last processed snapshot summary from on-chain"); + } else { + info + } + }, Err(err) => { log::error!(target:"ocex","Err loading state info from storage: {:?}",err); store_trie_root(H256::zero()); @@ -309,7 +326,7 @@ impl Pallet { for message in messages { match message { - IngressMessages::Deposit(main, asset, amt) => add_balance( + IngressMessages::Deposit(_, main, asset, amt) => add_balance( state, &Decode::decode(&mut &main.encode()[..]) .map_err(|_| "account id decode error")?, @@ -737,14 +754,14 @@ impl Pallet { let withdrawal = Self::withdraw(request, state, *stid)?; withdrawals.push(withdrawal); }, - UserActions::OneMinLMPReport(market, _total, scores) => { - let current_on_chain_epoch = >::get(); - Self::store_q_scores(state, *market, scores, current_on_chain_epoch)?; + UserActions::OneMinLMPReport(_market, _total, _scores) => { + // let current_on_chain_epoch = >::get(); + // Self::store_q_scores(state, *market, scores, current_on_chain_epoch)?; }, } } - let trader_metrics = Self::compute_trader_metrics(state)?; - Ok((withdrawals, egress_messages, trader_metrics)) + // let trader_metrics = Self::compute_trader_metrics(state)?; + Ok((withdrawals, egress_messages, None)) } /// Stores the Q scores generated by the offchain engine in the Offchain state trie @@ -756,7 +773,13 @@ impl Pallet { ) -> Result<(), &'static str> { let mut config = get_lmp_config(state, current_on_chain_epoch)?; // We wrap around the index if we overflow - let next_index = config.index.checked_add(1).unwrap_or(0); + let next_index = match config.index.checked_add(1) { + None => { + log::error!(target:"ocex","Index overflow for LMPConfig {:?}", config.index); + 0 + }, + Some(index) => index, + }; for (main, score) in scores { store_q_score_and_uptime( state, @@ -866,47 +889,6 @@ impl Pallet { value.insert(account_asset.asset, *balance); state.insert(key, value.encode()); } - // Store LMP Config - crate::lmp::store_lmp_config(state, checkpoint.config); - // Restore Q scores and Uptime map - for ((epoch, pair, main), map) in &checkpoint.q_scores_uptime_map { - for (index, q_score) in map { - crate::lmp::store_q_score_and_uptime(state, *epoch, *index, *q_score, pair, main)?; - } - } - // Restore maker volume - for ((epoch, pair, main), maker_volume) in &checkpoint.maker_volume_map { - crate::lmp::update_maker_volume_by_main_account( - state, - *epoch, - *pair, - *maker_volume, - main, - )?; - } - - // Restore taker volume - for ((epoch, pair, main), maker_volume) in &checkpoint.taker_volume_map { - crate::lmp::update_trade_volume_by_main_account( - state, - *epoch, - *pair, - *maker_volume, - main, - )?; - } - - // Restore trading fees - for ((epoch, pair, main), fees_paid) in &checkpoint.fees_paid_map { - crate::lmp::store_fees_paid_by_main_account_in_quote( - state, *epoch, *pair, *fees_paid, main, - )?; - } - - // Restore total maker volume - for ((epoch, pair), total_maker_volume) in &checkpoint.total_maker_volume_map { - crate::lmp::update_total_maker_volume(state, *epoch, *pair, *total_maker_volume)?; - } Ok(()) } diff --git a/pallets/thea-council/Cargo.toml b/pallets/thea-council/Cargo.toml index 81435922f..65c0450f2 100644 --- a/pallets/thea-council/Cargo.toml +++ b/pallets/thea-council/Cargo.toml @@ -18,9 +18,10 @@ sp-std = { workspace = true, default-features = false } xcm-helper = { path = "../xcm-helper", default-features = false } sp-runtime = { workspace = true, default-features = false } thea-primitives = { workspace = true, default-features = false } +polkadex-primitives = { workspace = true, default-features = false } +sp-core = { workspace = true, default-features = false } [dev-dependencies] -sp-core = { workspace = true, default-features = false } sp-io = { workspace = true, default-features = false } orml-xtokens = { workspace = true, default-features = false } orml-traits = { workspace = true, default-features = false } @@ -39,7 +40,9 @@ default = ["std"] std = [ "thea-message-handler/std", "thea-primitives/std", + 'polkadex-primitives/std', "codec/std", + "sp-core/std", "frame-benchmarking?/std", "frame-support/std", "frame-system/std", diff --git a/pallets/thea-council/src/benchmarking.rs b/pallets/thea-council/src/benchmarking.rs index 252b627d4..86f299eb0 100644 --- a/pallets/thea-council/src/benchmarking.rs +++ b/pallets/thea-council/src/benchmarking.rs @@ -20,7 +20,9 @@ use crate::Pallet as TheaCouncil; use frame_benchmarking::v1::{account, benchmarks}; use frame_support::{sp_runtime::SaturatedConversion, BoundedVec}; use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin}; -use sp_std::{vec, vec::Vec}; +use sp_core::H160; +use sp_std::vec; +use thea_primitives::extras::ExtraData; use thea_primitives::types::Withdraw; const SEED: u32 = 0; @@ -79,12 +81,13 @@ benchmarks! { // Add Pending Withdrawal let block_no: BlockNumberFor = 100u64.saturated_into(); let pending_withdrawal = Withdraw { - id: Vec::new(), - asset_id: 0, + id: H160::zero(), + asset_id: polkadex_primitives::AssetId::Asset(0), amount: 0, destination: vec![], + fee_asset_id: None,fee_amount: None, is_blocked: false, - extra: vec![] + extra: ExtraData::None }; xcm_helper::Pallet::::insert_pending_withdrawal(block_no, pending_withdrawal); }: _(RawOrigin::Signed(council_member), block_no, 0u32) diff --git a/pallets/thea-executor/Cargo.toml b/pallets/thea-executor/Cargo.toml index 54635b4a0..f3bef6117 100644 --- a/pallets/thea-executor/Cargo.toml +++ b/pallets/thea-executor/Cargo.toml @@ -19,6 +19,7 @@ frame-benchmarking = { workspace = true, default-features = false, optional = tr sp-core = { workspace = true, default-features = false } sp-io = { workspace = true, default-features = false } thea-primitives = { path = "../../primitives/thea", default-features = false } +orderbook-primitives = { path = "../../primitives/orderbook", default-features = false } xcm = { workspace = true, default-features = false } [dev-dependencies] @@ -27,6 +28,7 @@ pallet-balances = { workspace = true, features = ["std"] } sp-application-crypto = { workspace = true } sp-keystore = { workspace = true } thea = { path = "../thea" } +hex = "0.4.3" [features] default = ["std"] @@ -35,6 +37,7 @@ std = [ "sp-application-crypto/std", "pallet-asset-conversion/std", "thea-primitives/std", + "orderbook-primitives/std", "parity-scale-codec/std", "scale-info/std", "frame-support/std", diff --git a/pallets/thea-executor/src/benchmarking.rs b/pallets/thea-executor/src/benchmarking.rs index 096a09b91..9bd4d6060 100644 --- a/pallets/thea-executor/src/benchmarking.rs +++ b/pallets/thea-executor/src/benchmarking.rs @@ -27,23 +27,24 @@ use frame_support::traits::{ }; use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin}; use parity_scale_codec::Decode; -use polkadex_primitives::UNIT_BALANCE; +use polkadex_primitives::{AssetId, UNIT_BALANCE}; +use sp_core::H160; use sp_runtime::{traits::AccountIdConversion, SaturatedConversion}; use sp_std::{boxed::Box, collections::btree_set::BTreeSet, vec, vec::Vec}; -use thea_primitives::types::NewWithdraw; +use thea_primitives::types::Withdraw; use thea_primitives::types::{AssetMetadata, Deposit}; use xcm::VersionedMultiLocation; fn create_deposit(recipient: T::AccountId) -> Vec> { let mut pending_deposits = vec![]; - let asset_id = 100; + let asset_id = AssetId::Asset(100); for _i in 1..20 { let deposit: Deposit = Deposit { - id: vec![], + id: H160::zero(), recipient: recipient.clone(), asset_id, amount: 1_000_000_000_000, - extra: vec![], + extra: ExtraData::None, }; pending_deposits.push(deposit); } @@ -62,7 +63,7 @@ benchmarks! { update_asset_metadata { let r in 1 .. 1000; - let asset_id = r as u128; + let asset_id = AssetId::Asset(r as u128); let decimal: u8 = 8; }: _(RawOrigin::Root, asset_id, decimal) verify { @@ -83,10 +84,10 @@ benchmarks! { let pallet_acc = T::TheaPalletId::get().into_account_truncating(); ::Currency::mint_into(&pallet_acc, 100_000_000_000_000_000_000u128.saturated_into()).unwrap(); let metadata = AssetMetadata::new(3).unwrap(); - >::insert(100, metadata); + >::insert( AssetId::Asset(100), metadata); >::insert(network_id, 10); let benificary = vec![1;32]; - }: _(RawOrigin::Signed(account.clone()), 100, 1_000, benificary, true, network_id, false) + }: _(RawOrigin::Signed(account.clone()), AssetId::Asset(100), 1_000, benificary, true, network_id, false) verify { let ready_withdrawal = >::get(>::block_number(), network_id); assert_eq!(ready_withdrawal.len(), 1); @@ -104,11 +105,11 @@ benchmarks! { ::Assets::mint_into(asset_id.into(), &account, 100_000_000_000_000_000_000u128.saturated_into()).unwrap(); ::Currency::mint_into(&account, 100_000_000_000_000u128.saturated_into()).unwrap(); let metadata = AssetMetadata::new(10).unwrap(); - >::insert(100, metadata); + >::insert( AssetId::Asset(100), metadata); >::insert(network_id, 1_000); let multilocation = MultiLocation { parents: 1, interior: Junctions::Here }; let benificary = VersionedMultiLocation::V3(multilocation); - }: _(RawOrigin::Signed(account.clone()), 100, 1_000_000_000_000, Box::new(benificary), None, None, true, false) + }: _(RawOrigin::Signed(account.clone()), AssetId::Asset(100), 1_000_000_000_000, Box::new(benificary), None, None, true, false) verify { let ready_withdrawal = >::get(>::block_number(), network_id); assert_eq!(ready_withdrawal.len(), 1); @@ -116,7 +117,7 @@ benchmarks! { evm_withdraw { let r in 1 .. 1000; - let asset_id: ::AssetId = 100u128.into(); + let asset_id : ::AssetId = 100.into(); let admin = account::("admin", 1, r); let network_id = 2; ::Assets::create(asset_id.into(), admin, true, 1u128.saturated_into()).unwrap(); @@ -126,10 +127,10 @@ benchmarks! { ::Assets::mint_into(asset_id.into(), &account, 100_000_000_000_000_000_000u128.saturated_into()).unwrap(); ::Currency::mint_into(&account, 100_000_000_000_000u128.saturated_into()).unwrap(); let metadata = AssetMetadata::new(10).unwrap(); - >::insert(100, metadata); + >::insert( AssetId::Asset(100), metadata); >::insert(network_id, 1_000); let beneficiary: sp_core::H160 = sp_core::H160::default(); - }: _(RawOrigin::Signed(account.clone()), 100, 1_000_000_000_000, beneficiary, network_id, true, false) + }: _(RawOrigin::Signed(account.clone()), AssetId::Asset(100), 1_000_000_000_000, beneficiary, network_id, true, false) verify { let ready_withdrawal = >::get(>::block_number(), network_id); assert_eq!(ready_withdrawal.len(), 1); @@ -140,15 +141,15 @@ benchmarks! { let y in 1 .. 1_000; let network_len: usize = x as usize; let network_len: u8 = network_len as u8; - let withdrawal = NewWithdraw { - id: vec![], - asset_id: 100, + let withdrawal = Withdraw { + id: H160::zero(), + asset_id: polkadex_primitives::AssetId::Asset(100), amount: 1_000_000_000_000, destination: vec![], fee_asset_id: None, fee_amount: None, is_blocked: false, - extra: vec![], + extra: ExtraData::None, }; let mut withdrawal_vec = Vec::new(); for _ in 0..y { @@ -178,10 +179,10 @@ benchmarks! { claim_deposit { let r in 1 .. 1000; let account = account::("alice", 1, r); - let asset_id: ::AssetId = 100u128.into(); + let asset_id : ::AssetId = 100.into(); let deposits = create_deposit::(account.clone()); let metadata = AssetMetadata::new(10).unwrap(); - >::insert(100, metadata); + >::insert(polkadex_primitives::AssetId::Asset(100), metadata); ::Currency::mint_into(&account, 100_000_000_000_000u128.saturated_into()).unwrap(); >::insert(account.clone(), deposits); }: _(RawOrigin::Signed(account.clone()), 10,account.clone()) @@ -193,6 +194,7 @@ benchmarks! { #[cfg(test)] use frame_benchmarking::impl_benchmark_test_suite; +use thea_primitives::extras::ExtraData; use xcm::latest::{Junctions, MultiLocation}; #[cfg(test)] diff --git a/pallets/thea-executor/src/lib.rs b/pallets/thea-executor/src/lib.rs index e1e879090..4b8d49e9e 100644 --- a/pallets/thea-executor/src/lib.rs +++ b/pallets/thea-executor/src/lib.rs @@ -62,12 +62,14 @@ pub mod pallet { transactional, }; use frame_system::pallet_prelude::*; + use orderbook_primitives::traits::OrderbookOperations; use pallet_asset_conversion::Swap; use polkadex_primitives::{AssetId, Resolver}; - use sp_core::{H160, H256}; + use sp_core::H160; use sp_runtime::{traits::AccountIdConversion, Saturating}; use sp_std::vec::Vec; - use thea_primitives::types::NewWithdraw; + use thea_primitives::extras::ExtraData; + use thea_primitives::types::Withdraw; use thea_primitives::{ types::{AssetMetadata, Deposit}, Network, TheaBenchmarkHelper, TheaIncomingExecutor, TheaOutgoingExecutor, NATIVE_NETWORK, @@ -99,6 +101,7 @@ pub mod pallet { + MaybeSerializeDeserialize + MaxEncodedLen + Into<<::Assets as Inspect>::AssetId> + + From + From; type MultiAssetIdAdapter: From + Into<::MultiAssetId>; @@ -123,6 +126,7 @@ pub mod pallet { u128, polkadex_primitives::AssetId, >; + type Orderbook: OrderbookOperations; /// Total Withdrawals #[pallet::constant] type WithdrawalSize: Get; @@ -145,7 +149,7 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn pending_withdrawals)] pub(super) type PendingWithdrawals = - StorageMap<_, Blake2_128Concat, Network, Vec, ValueQuery>; + StorageMap<_, Blake2_128Concat, Network, Vec, ValueQuery>; /// Withdrawal Fees for each network #[pallet::storage] @@ -162,7 +166,7 @@ pub mod pallet { BlockNumberFor, Blake2_128Concat, Network, - Vec, + Vec, ValueQuery, >; @@ -172,9 +176,11 @@ pub mod pallet { StorageMap<_, Blake2_128Concat, T::AccountId, Vec>, ValueQuery>; /// Stores the metadata ( asset_id => Metadata ) + /// TODO: @zktony, migrate from u128 key to polkadex_primitives::AssetId #[pallet::storage] #[pallet::getter(fn asset_metadata)] - pub type Metadata = StorageMap<_, Identity, u128, AssetMetadata, OptionQuery>; + pub type Metadata = + StorageMap<_, Identity, polkadex_primitives::AssetId, AssetMetadata, OptionQuery>; // Pallets use events to inform users when important changes are made. // https://docs.substrate.io/main-docs/build/events-errors/ @@ -184,17 +190,17 @@ pub mod pallet { /// Asset Metadata set ( config ) AssetMetadataSet(AssetMetadata), /// Deposit Approved event ( Network, recipient, asset_id, amount, id)) - DepositApproved(Network, T::AccountId, u128, u128, Vec), + DepositApproved(Network, T::AccountId, AssetId, u128, H160), /// Deposit claimed event ( recipient, asset id, amount, id ) - DepositClaimed(T::AccountId, u128, u128, Vec), + DepositClaimed(T::AccountId, AssetId, u128, H160), /// Deposit failed event ( network, encoded deposit) DepositFailed(Network, Vec), /// Withdrawal Queued ( network, from, beneficiary, assetId, amount, id ) - WithdrawalQueued(Network, T::AccountId, Vec, u128, u128, Vec), + WithdrawalQueued(Network, T::AccountId, Vec, AssetId, u128, H160), /// Withdrawal Ready (Network id ) WithdrawalReady(Network), /// Withdrawal Failed ( Network ,Vec) - WithdrawalFailed(Network, Vec), + WithdrawalFailed(Network, Vec), /// Thea Public Key Updated ( network, new session id ) TheaKeyUpdated(Network, u32), /// Withdrawal Fee Set (NetworkId, Amount) @@ -202,7 +208,7 @@ pub mod pallet { /// Native Token Burn event NativeTokenBurned(T::AccountId, u128), /// Withdrawal Sent (Network, Withdrawal Id,Batch Outgoing Nonce, Withdrawal Index) - WithdrawalSent(Network, Vec, u64, u8), + WithdrawalSent(Network, H160, u64, u8), } // Errors inform users that something went wrong. @@ -257,7 +263,7 @@ pub mod pallet { for (index, withdrawal) in withdrawals.iter().enumerate() { Self::deposit_event(Event::::WithdrawalSent( network_id, - withdrawal.id.clone(), + withdrawal.id, batch_nonce, index as u8, )); @@ -281,7 +287,7 @@ pub mod pallet { #[transactional] pub fn withdraw( origin: OriginFor, - asset_id: u128, + asset_id: AssetId, amount: u128, beneficiary: Vec, pay_for_remaining: bool, @@ -300,6 +306,7 @@ pub mod pallet { pay_for_remaining, network, pay_with_tokens, + None, )?; Ok(()) } @@ -328,10 +335,10 @@ pub mod pallet { #[pallet::weight(< T as Config >::TheaExecWeightInfo::parachain_withdraw(1))] pub fn parachain_withdraw( origin: OriginFor, - asset_id: u128, + asset_id: AssetId, amount: u128, beneficiary: sp_std::boxed::Box, - fee_asset_id: Option, + fee_asset_id: Option, fee_amount: Option, pay_for_remaining: bool, pay_with_tokens: bool, @@ -348,6 +355,7 @@ pub mod pallet { pay_for_remaining, network, pay_with_tokens, + None, )?; Ok(()) } @@ -362,7 +370,7 @@ pub mod pallet { #[pallet::weight(< T as Config >::TheaExecWeightInfo::update_asset_metadata(1))] pub fn update_asset_metadata( origin: OriginFor, - asset_id: u128, + asset_id: polkadex_primitives::AssetId, decimal: u8, ) -> DispatchResult { T::GovernanceOrigin::ensure_origin(origin)?; @@ -409,7 +417,7 @@ pub mod pallet { #[pallet::weight(< T as Config >::TheaExecWeightInfo::evm_withdraw(1))] pub fn evm_withdraw( origin: OriginFor, - asset_id: u128, + asset_id: AssetId, amount: u128, beneficiary: H160, network: Network, @@ -427,6 +435,7 @@ pub mod pallet { pay_for_remaining, network, pay_with_tokens, + None, )?; Ok(()) } @@ -501,15 +510,20 @@ pub mod pallet { } impl Pallet { - /// Generates a new random id for withdrawals - fn new_random_id() -> Vec { + /// Generates a new random id for withdrawals with an optional prefix + fn new_random_id(prefix: Option<[u8; 4]>) -> H160 { let mut nonce = >::get(); nonce = nonce.wrapping_add(1); >::put(nonce); - let entropy = sp_io::hashing::blake2_256(&(NATIVE_NETWORK, nonce).encode()); - let entropy = H256::from_slice(&entropy).0[..10].to_vec(); - entropy.to_vec() + let mut entropy: [u8; 20] = [0u8; 20]; + if let Some(prefix) = prefix { + entropy[0..4].copy_from_slice(&prefix); + } + entropy[4..] + .copy_from_slice(&sp_io::hashing::blake2_128(&((NATIVE_NETWORK, nonce).encode()))); + H160::from(entropy) } + pub fn thea_account() -> T::AccountId { T::TheaPalletId::get().into_account_truncating() } @@ -517,18 +531,20 @@ pub mod pallet { #[transactional] pub fn do_withdraw( user: T::AccountId, - asset_id: u128, + asset_id: AssetId, mut amount: u128, beneficiary: Vec, - fee_asset_id: Option, + fee_asset_id: Option, fee_amount: Option, pay_for_remaining: bool, network: Network, pay_with_tokens: bool, + txid: Option, ) -> Result<(), DispatchError> { ensure!(beneficiary.len() <= 1000, Error::::BeneficiaryTooLong); ensure!(network != 0, Error::::WrongNetwork); let mut pending_withdrawals = >::get(network); + // Get Metadata let metadata = >::get(asset_id).ok_or(Error::::AssetNotRegistered)?; if let Some(fee_asset_id) = fee_asset_id { let _metadata = >::get(fee_asset_id) @@ -552,12 +568,9 @@ pub mod pallet { )) } - if pay_with_tokens { + if pay_with_tokens && asset_id != AssetId::Polkadex { // User wants to pay with withdrawing tokens. - let path = sp_std::vec![ - polkadex_primitives::AssetId::Asset(asset_id), - polkadex_primitives::AssetId::Polkadex - ]; + let path = sp_std::vec![asset_id, polkadex_primitives::AssetId::Polkadex]; let token_taken = T::Swap::swap_tokens_for_exact_tokens( user.clone(), path, @@ -590,15 +603,15 @@ pub mod pallet { )?; } - let mut withdraw = NewWithdraw { - id: Self::new_random_id(), + let mut withdraw = Withdraw { + id: txid.unwrap_or(Self::new_random_id(None)), asset_id, amount, destination: beneficiary.clone(), fee_asset_id, fee_amount, is_blocked: false, - extra: Vec::new(), + extra: thea_primitives::extras::ExtraData::None, }; Self::deposit_event(Event::::WithdrawalQueued( @@ -607,7 +620,7 @@ pub mod pallet { beneficiary, asset_id, amount, - withdraw.id.clone(), + withdraw.id, )); // Convert back to origin decimals @@ -659,50 +672,69 @@ pub mod pallet { // Get the metadata let metadata = >::get(deposit.asset_id).ok_or(Error::::AssetNotRegistered)?; - let deposit_amount = deposit.amount_in_native_decimals(metadata); // Convert the decimals configured in metadata - if !frame_system::Pallet::::account_exists(&deposit.recipient) { - let path = sp_std::vec![ - polkadex_primitives::AssetId::Asset(deposit.asset_id), - polkadex_primitives::AssetId::Polkadex - ]; - let amount_out: T::AssetBalanceAdapter = T::ExistentialDeposit::get().into(); - Self::resolve_mint(&Self::thea_account(), deposit.asset_id.into(), deposit_amount)?; + let deposit_amount = deposit.amount_in_native_decimals(metadata); // Convert the decimals configured in metadata - // If swap doesn't work then it will in the system account - thea_account() - if let Ok(fee_amount) = T::Swap::swap_tokens_for_exact_tokens( - Self::thea_account(), - path, - amount_out.into(), - Some(deposit_amount), - deposit.recipient.clone(), - true, - ) { + let final_deposit_amount = + if !frame_system::Pallet::::account_exists(&deposit.recipient) + && deposit.asset_id != AssetId::Polkadex + { + let path = + sp_std::vec![deposit.asset_id, polkadex_primitives::AssetId::Polkadex]; + let amount_out: T::AssetBalanceAdapter = T::ExistentialDeposit::get().into(); + Self::resolve_mint( + &Self::thea_account(), + deposit.asset_id.into(), + deposit_amount, + )?; + // If swap doesn't work then it will in the system account - thea_account() + let fee_amount = T::Swap::swap_tokens_for_exact_tokens( + Self::thea_account(), + path, + amount_out.into(), + Some(deposit_amount), + deposit.recipient.clone(), + true, + )?; + let final_amount = deposit_amount.saturating_sub(fee_amount); Self::resolve_transfer( deposit.asset_id.into(), &Self::thea_account(), &deposit.recipient, - deposit_amount.saturating_sub(fee_amount), + final_amount, )?; - } - } else { - Self::resolver_deposit( - deposit.asset_id.into(), - deposit_amount, - &deposit.recipient, - Self::thea_account(), - 1u128, - Self::thea_account(), - )?; - } + final_amount + } else { + Self::resolver_deposit( + deposit.asset_id.into(), + deposit_amount, + &deposit.recipient, + Self::thea_account(), + 1u128, + Self::thea_account(), + )?; + deposit_amount + }; // Emit event Self::deposit_event(Event::::DepositClaimed( deposit.recipient.clone(), deposit.asset_id, - deposit.amount_in_native_decimals(metadata), + final_deposit_amount, deposit.id, )); + + match deposit.extra { + ExtraData::None => {}, + ExtraData::DirectDeposit => { + T::Orderbook::deposit( + deposit.id, + deposit.recipient, + deposit.asset_id, + final_deposit_amount, + )?; + }, + } Ok(()) } } @@ -731,9 +763,34 @@ pub mod pallet { impl TheaBenchmarkHelper for Pallet { fn set_metadata(asset_id: AssetId) { let metadata = AssetMetadata::new(12).unwrap(); - if let AssetId::Asset(asset) = asset_id { - >::insert(asset, metadata); - } + >::insert(asset_id, metadata); + } + } + + impl polkadex_primitives::traits::CrossChainWithdraw for Pallet { + fn parachain_withdraw( + user: T::AccountId, + asset_id: AssetId, + amount: u128, + beneficiary: xcm::latest::MultiLocation, + fee_asset_id: Option, + fee_amount: Option, + id: H160, + ) -> DispatchResult { + let network = 1; + let versioned_multilocation: xcm::VersionedMultiLocation = beneficiary.into(); + Self::do_withdraw( + user, + asset_id, + amount, + versioned_multilocation.encode(), + fee_asset_id, + fee_amount, + true, + network, + true, + Some(id), + ) } } } diff --git a/pallets/thea-executor/src/mock.rs b/pallets/thea-executor/src/mock.rs index 3f67acc52..4ae3096a4 100644 --- a/pallets/thea-executor/src/mock.rs +++ b/pallets/thea-executor/src/mock.rs @@ -205,6 +205,7 @@ impl thea_executor::Config for Test { type NativeAssetId = PolkadexAssetId; type TheaPalletId = TheaPalletId; type Swap = AssetConversion; + type Orderbook = (); type WithdrawalSize = WithdrawalSize; type ExistentialDeposit = ExistentialDeposit; type ParaId = ParaId; diff --git a/pallets/thea-executor/src/tests.rs b/pallets/thea-executor/src/tests.rs index 2cbde072e..802e391d8 100644 --- a/pallets/thea-executor/src/tests.rs +++ b/pallets/thea-executor/src/tests.rs @@ -27,12 +27,15 @@ use frame_support::{ }; use frame_system::EventRecord; use parity_scale_codec::Encode; +use polkadex_primitives::AssetId; +use polkadex_primitives::AssetId::Asset; use sp_core::H160; use sp_runtime::{ traits::{AccountIdConversion, BadOrigin}, SaturatedConversion, }; -use thea_primitives::types::NewWithdraw; +use thea_primitives::extras::ExtraData; +use thea_primitives::types::Withdraw; use thea_primitives::types::{AssetMetadata, Deposit}; use xcm::v3::Junction; use xcm::{opaque::lts::Junctions, v3::MultiLocation, VersionedMultiLocation}; @@ -53,7 +56,7 @@ fn test_withdraw_returns_ok() { assert_noop!( TheaExecutor::withdraw( RuntimeOrigin::signed(1), - 1u128, + Asset(1u128), 1000u128, beneficiary.to_vec(), false, @@ -79,7 +82,7 @@ fn test_transfer_native_asset() { admin, 1u128 )); - assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), asset_id, 12)); + assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), asset_id.into(), 12)); // Set balance for User Balances::set_balance(&user, 1_000_000_000_000_000_000); assert_ok!(Assets::mint_into(asset_id, &user, 1_000_000_000_000_000_000)); @@ -87,7 +90,7 @@ fn test_transfer_native_asset() { assert_ok!(TheaExecutor::set_withdrawal_fee(RuntimeOrigin::root(), 1, 0)); assert_ok!(TheaExecutor::withdraw( RuntimeOrigin::signed(user), - asset_id, + asset_id.into(), 10_000_000_000_000u128, vec![1; 32], false, @@ -96,15 +99,15 @@ fn test_transfer_native_asset() { )); // Verify let pending_withdrawal = >::get(1); - let approved_withdraw = NewWithdraw { - id: Vec::from([179, 96, 16, 235, 40, 92, 21, 74, 140, 214]), - asset_id, + let approved_withdraw = Withdraw { + id: H160::from_slice(&hex::decode("00000000ec73991183eca9d2e5da0e7cd3ffaf93").unwrap()), + asset_id: asset_id.into(), amount: 10_000_000_000_000u128, destination: vec![1; 32], fee_asset_id: None, fee_amount: None, is_blocked: false, - extra: vec![], + extra: ExtraData::None, }; assert_eq!(pending_withdrawal.to_vec().pop().unwrap(), approved_withdraw); }) @@ -124,14 +127,14 @@ fn test_deposit_with_valid_args_returns_ok() { admin, 1u128 )); - assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), asset_id, 12)); + assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), asset_id.into(), 12)); assert_ok!(TheaExecutor::set_withdrawal_fee(RuntimeOrigin::root(), 1, 0)); let deposit = Deposit { - id: Vec::new(), + id: H160::zero(), recipient, - asset_id, + asset_id: asset_id.into(), amount: 1_000_000_000_000_000_000u128, - extra: vec![], + extra: ExtraData::None, }; assert_ok!(TheaExecutor::do_deposit(1, &vec![deposit].encode())); }) @@ -166,7 +169,7 @@ fn test_set_withdrawal_fee_full() { fn test_parachain_withdraw_full() { new_test_ext().execute_with(|| { // setup code - let asset_id: ::AssetId = 100u128; + let asset_id: AssetId = 100u128.into(); let admin = 1u64; let network_id = 1; Balances::set_balance(&admin, 100_000_000_000_000_000_000u128.saturated_into()); @@ -177,7 +180,7 @@ fn test_parachain_withdraw_full() { .unwrap(); ::Assets::create( RuntimeOrigin::signed(admin), - asset_id.into(), + 100u128.into(), admin, 1u128.saturated_into(), ) @@ -196,13 +199,13 @@ fn test_parachain_withdraw_full() { 100_000_000_000_000_000_000u128.saturated_into(), ) .unwrap(); - Assets::mint_into(asset_id, &account, 100_000_000_000_000_000_000u128.saturated_into()) + Assets::mint_into(100u128, &account, 100_000_000_000_000_000_000u128.saturated_into()) .unwrap(); ::Currency::mint_into(&account, 100_000_000_000_000u128.saturated_into()) .unwrap(); Balances::set_balance(&account, 100_000_000_000_000u128.saturated_into()); let metadata = AssetMetadata::new(10).unwrap(); - >::insert(100, metadata); + >::insert(asset_id, metadata); >::insert(network_id, 1_000); let multilocation = MultiLocation { parents: 1, interior: Junctions::Here }; let beneficiary = Box::new(VersionedMultiLocation::V3(multilocation)); @@ -210,7 +213,7 @@ fn test_parachain_withdraw_full() { assert_noop!( TheaExecutor::parachain_withdraw( RuntimeOrigin::root(), - u128::MAX, + u128::MAX.into(), 1_000_000_000, beneficiary.clone(), None, @@ -223,7 +226,7 @@ fn test_parachain_withdraw_full() { assert_noop!( TheaExecutor::parachain_withdraw( RuntimeOrigin::none(), - u128::MAX, + u128::MAX.into(), 1_000_000_000, beneficiary.clone(), None, @@ -237,7 +240,7 @@ fn test_parachain_withdraw_full() { assert_noop!( TheaExecutor::parachain_withdraw( RuntimeOrigin::signed(account), - u128::MAX, + u128::MAX.into(), 1_000_000_000, beneficiary.clone(), None, @@ -280,23 +283,30 @@ fn test_update_asset_metadata_full() { new_test_ext().execute_with(|| { // bad origins assert_noop!( - TheaExecutor::update_asset_metadata(RuntimeOrigin::signed(1), 1, 1), + TheaExecutor::update_asset_metadata(RuntimeOrigin::signed(1), 1.into(), 1), BadOrigin ); assert_noop!( - TheaExecutor::update_asset_metadata(RuntimeOrigin::signed(u64::MAX), 1, 1), + TheaExecutor::update_asset_metadata(RuntimeOrigin::signed(u64::MAX), 1.into(), 1), + BadOrigin + ); + assert_noop!( + TheaExecutor::update_asset_metadata(RuntimeOrigin::none(), 1.into(), 1), BadOrigin ); - assert_noop!(TheaExecutor::update_asset_metadata(RuntimeOrigin::none(), 1, 1), BadOrigin); // invalid decimal assert_noop!( - TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), u128::MAX, u8::MIN), + TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), u128::MAX.into(), u8::MIN), Error::::InvalidDecimal ); // proper cases System::set_block_number(1); - assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), 0, u8::MAX)); - assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), u128::MAX, u8::MAX)); + assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), 0.into(), u8::MAX)); + assert_ok!(TheaExecutor::update_asset_metadata( + RuntimeOrigin::root(), + u128::MAX.into(), + u8::MAX + )); let md = AssetMetadata::new(u8::MAX).unwrap(); assert_last_event::(Event::::AssetMetadataSet(md).into()); }) @@ -315,14 +325,14 @@ fn test_resolve_deposit() { admin, 1u128 )); - assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), asset_id, 12)); + assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), asset_id.into(), 12)); Balances::set_balance(&recipient, 1_000_000_000_000_000_000); let deposit = Deposit { - id: Vec::new(), + id: H160::zero(), recipient, - asset_id, + asset_id: asset_id.into(), amount: 1_000_000_000_000_000_000u128, - extra: vec![], + extra: ExtraData::None, }; assert_ok!(TheaExecutor::execute_deposit(deposit)); }) @@ -336,14 +346,14 @@ fn test_deposit_without_account() { let admin = 1u64; let recipient = 2u64; Balances::set_balance(&admin, 1_000_000_000_000_000_000); - assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), asset_id, 12)); + assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), asset_id.into(), 12)); Balances::set_balance(&TheaExecutor::thea_account(), 1_000_000_000_000_000_000); let deposit = Deposit { - id: Vec::new(), + id: H160::zero(), recipient, - asset_id, + asset_id: asset_id.into(), amount: 1_000_000_000_000_000u128, - extra: vec![], + extra: ExtraData::None, }; assert_ok!(TheaExecutor::execute_deposit(deposit)); assert_eq!(Balances::free_balance(&recipient), 50); @@ -367,10 +377,10 @@ fn test_do_withdrawal() { let _ = Assets::mint_into(asset_id, &sender, 1_000_000_000_000_000_000); // Set withdrawal Fee assert_ok!(TheaExecutor::set_withdrawal_fee(RuntimeOrigin::root(), 1, 100)); - assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), asset_id, 12)); + assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), asset_id.into(), 12)); assert_ok!(TheaExecutor::withdraw( RuntimeOrigin::signed(sender), - asset_id, + asset_id.into(), 1_000_000_000_000_000u128, vec![1; 32], true, @@ -394,11 +404,11 @@ fn test_do_withdrawal_with_total_amount_consumed_returns_error() { assert_ok!(Assets::mint_into(asset_id, &sender, 100_300_903u128)); // Set withdrawal Fee assert_ok!(TheaExecutor::set_withdrawal_fee(RuntimeOrigin::root(), 1, 100)); - assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), asset_id, 12)); + assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), asset_id.into(), 12)); assert_noop!( TheaExecutor::withdraw( RuntimeOrigin::signed(sender), - asset_id, + asset_id.into(), 1_000_000_000_000_000u128, vec![1; 32], true, @@ -449,12 +459,12 @@ fn test_evm_withdraw() { .unwrap(); Balances::set_balance(&account, 100_000_000_000_000u128.saturated_into()); let metadata = AssetMetadata::new(10).unwrap(); - >::insert(100, metadata); + >::insert(Asset(100), metadata); >::insert(network_id, 1_000); let beneficiary = H160::from_slice(&[1; 20]); assert_ok!(TheaExecutor::evm_withdraw( RuntimeOrigin::signed(account), - asset_id, + asset_id.into(), 1_000_000_000, beneficiary.clone(), network_id, @@ -477,14 +487,14 @@ fn test_claim_deposit_returns_ok() { admin, 1u128 )); - assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), asset_id, 12)); + assert_ok!(TheaExecutor::update_asset_metadata(RuntimeOrigin::root(), asset_id.into(), 12)); Balances::set_balance(&recipient, 1_000_000_000_000_000_000); let deposit = Deposit { - id: Vec::new(), + id: H160::zero(), recipient, - asset_id, + asset_id: asset_id.into(), amount: 1_000_000_000_000_000_000u128, - extra: vec![], + extra: ExtraData::None, }; assert_ok!(TheaExecutor::do_deposit(1, &vec![deposit].encode())); assert_ok!(TheaExecutor::claim_deposit(RuntimeOrigin::signed(recipient), 1, recipient)); @@ -506,11 +516,11 @@ fn test_claim_deposit_returns_asset_not_registered() { )); Balances::set_balance(&recipient, 1_000_000_000_000_000_000); let deposit = Deposit { - id: Vec::new(), + id: H160::zero(), recipient, - asset_id, + asset_id: asset_id.into(), amount: 1_000_000_000_000_000_000u128, - extra: vec![], + extra: ExtraData::None, }; assert_noop!( TheaExecutor::do_deposit(1, &vec![deposit].encode()), @@ -535,7 +545,7 @@ fn test_create_parachain_asset() { )); let asset_id = polkadex_primitives::assets::generate_asset_id_for_parachain(Box::new(asset)); - assert!(Assets::asset_exists(asset_id)); + assert!(Assets::asset_exists(asset_id.into())); let expected_metadata = AssetMetadata::new(10); let actual_metadata = >::get(asset_id); assert_eq!(expected_metadata, actual_metadata); diff --git a/pallets/thea-message-handler/src/benchmarking.rs b/pallets/thea-message-handler/src/benchmarking.rs index e010dcb9d..782a3674b 100644 --- a/pallets/thea-message-handler/src/benchmarking.rs +++ b/pallets/thea-message-handler/src/benchmarking.rs @@ -30,14 +30,15 @@ const KEY: [u8; 33] = [ 2, 10, 16, 145, 52, 31, 229, 102, 75, 250, 23, 130, 213, 224, 71, 121, 104, 144, 104, 201, 22, 176, 76, 179, 101, 236, 49, 83, 117, 86, 132, 217, 161, ]; +use sp_core::H160; fn generate_deposit_payload() -> Vec> { sp_std::vec![Deposit { - id: H256::zero().0.to_vec(), + id: H160::zero(), recipient: T::AccountId::decode(&mut &[0u8; 32][..]).unwrap(), - asset_id: 0, + asset_id: AssetId::Asset(0), amount: 0, - extra: Vec::new(), + extra: ExtraData::None, }] } @@ -91,7 +92,8 @@ benchmarks! { #[cfg(test)] use frame_benchmarking::impl_benchmark_test_suite; -use sp_core::H256; +use polkadex_primitives::AssetId; +use thea_primitives::extras::ExtraData; use thea_primitives::types::Deposit; #[cfg(test)] diff --git a/pallets/thea-message-handler/src/mock.rs b/pallets/thea-message-handler/src/mock.rs index 635b8af69..471a461ec 100644 --- a/pallets/thea-message-handler/src/mock.rs +++ b/pallets/thea-message-handler/src/mock.rs @@ -194,18 +194,19 @@ impl thea_executor::Config for Test { type Currency = Balances; type Assets = Assets; type AssetId = u128; + type MultiAssetIdAdapter = AssetId; + type AssetBalanceAdapter = u128; type AssetCreateUpdateOrigin = EnsureRoot; type Executor = Thea; type NativeAssetId = PolkadexAssetId; type TheaPalletId = TheaPalletId; + type Swap = AssetConversion; + type Orderbook = (); type WithdrawalSize = WithdrawalSize; + type ExistentialDeposit = ExistentialDeposit; type ParaId = ParaId; - type Swap = AssetConversion; - type TheaExecWeightInfo = thea_executor::weights::WeightInfo; - type MultiAssetIdAdapter = AssetId; - type AssetBalanceAdapter = u128; type GovernanceOrigin = EnsureRoot; - type ExistentialDeposit = ExistentialDeposit; + type TheaExecWeightInfo = thea_executor::weights::WeightInfo; } impl crate::Config for Test { diff --git a/pallets/thea/src/benchmarking.rs b/pallets/thea/src/benchmarking.rs index 0ac0af2ea..0a89834e7 100644 --- a/pallets/thea/src/benchmarking.rs +++ b/pallets/thea/src/benchmarking.rs @@ -27,6 +27,7 @@ use frame_system::RawOrigin; use parity_scale_codec::Decode; use polkadex_primitives::AssetId; use polkadex_primitives::UNIT_BALANCE; +use sp_core::H160; use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet}; use thea_primitives::types::{ IncomingMessage, MisbehaviourReport, SignedMessage, THEA_HOLD_REASON, @@ -35,11 +36,11 @@ use thea_primitives::TheaBenchmarkHelper; fn generate_deposit_payload() -> Vec> { sp_std::vec![Deposit { - id: H256::zero().0.to_vec(), + id: H160::zero(), recipient: T::AccountId::decode(&mut &[0u8; 32][..]).unwrap(), - asset_id: 1, + asset_id: AssetId::Asset(1), amount: 0, - extra: Vec::new(), + extra: ExtraData::None, }] } @@ -245,7 +246,7 @@ benchmarks! { #[cfg(test)] use frame_benchmarking::impl_benchmark_test_suite; -use sp_core::H256; +use thea_primitives::extras::ExtraData; use thea_primitives::types::Deposit; #[cfg(test)] diff --git a/pallets/thea/src/lib.rs b/pallets/thea/src/lib.rs index cf07dfb4e..974a59710 100644 --- a/pallets/thea/src/lib.rs +++ b/pallets/thea/src/lib.rs @@ -37,6 +37,7 @@ use sp_runtime::{ transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, RuntimeAppPublic, SaturatedConversion, }; +use sp_std::collections::btree_set::BTreeSet; use sp_std::prelude::*; use thea_primitives::{ types::{Message, NetworkType, PayloadType}, @@ -102,7 +103,6 @@ pub mod pallet { }; use frame_system::offchain::SendTransactionTypes; use polkadex_primitives::Balance; - use sp_std::collections::btree_set::BTreeSet; use thea_primitives::{ types::{IncomingMessage, Message, MisbehaviourReport, SignedMessage, THEA_HOLD_REASON}, TheaIncomingExecutor, TheaOutgoingExecutor, @@ -770,7 +770,8 @@ impl Pallet { // that is, the incoming set is has different session keys from outgoing set. // This last message should be signed by the outgoing set // Similar to how Grandpa's session change works. - if incoming != queued { + let incoming_set = BTreeSet::from_iter(incoming.to_vec()); + if incoming_set != BTreeSet::from_iter(queued.to_vec()) { let uncompressed_keys: Vec<[u8; 20]> = vec![]; // TODO: Uncomment the following when parsing is fixed for ethereum keys. // for public_key in queued.clone().into_iter() { @@ -844,7 +845,7 @@ impl Pallet { } >::put(queued); } - if incoming != outgoing { + if incoming_set != BTreeSet::from_iter(outgoing.to_vec()) { // This will happen when new era starts, or end of the last epoch >::insert(new_id, incoming); >::put(new_id); diff --git a/pallets/thea/src/mock.rs b/pallets/thea/src/mock.rs index 0557c7d08..9ea796fe2 100644 --- a/pallets/thea/src/mock.rs +++ b/pallets/thea/src/mock.rs @@ -209,6 +209,7 @@ impl thea_executor::Config for Test { type AssetBalanceAdapter = u128; type GovernanceOrigin = EnsureRoot; type ExistentialDeposit = ExistentialDeposit; + type Orderbook = (); } impl frame_system::offchain::SendTransactionTypes for Test diff --git a/pallets/thea/src/validation.rs b/pallets/thea/src/validation.rs index 3b0a2f5ba..40a204c7d 100644 --- a/pallets/thea/src/validation.rs +++ b/pallets/thea/src/validation.rs @@ -81,6 +81,7 @@ impl Pallet { None => continue, Some(msg) => msg, }; + let msg_hash = sp_io::hashing::sha2_256(message.encode().as_slice()); // Note: this is a double hash signing let signature = diff --git a/pallets/xcm-helper/src/lib.rs b/pallets/xcm-helper/src/lib.rs index cb6833941..f999f690f 100644 --- a/pallets/xcm-helper/src/lib.rs +++ b/pallets/xcm-helper/src/lib.rs @@ -130,15 +130,16 @@ pub mod pallet { __private::log, }; use frame_system::pallet_prelude::*; + use thea_primitives::extras::{extract_data_from_multilocation, ExtraData}; use polkadex_primitives::Resolver; - use sp_core::sp_std; + use sp_core::{sp_std, H160}; use sp_runtime::{traits::Convert, SaturatedConversion}; use crate::MAXIMUM_BLOCK_WEIGHT; use sp_std::{boxed::Box, vec, vec::Vec}; use thea_primitives::{ - types::{Deposit, NewWithdraw, Withdraw}, + types::{Deposit, Withdraw}, Network, TheaIncomingExecutor, TheaOutgoingExecutor, }; use xcm::{ @@ -163,14 +164,18 @@ pub mod pallet { pub trait AssetIdConverter { /// Converts AssetId to MultiLocation - fn convert_asset_id_to_location(asset_id: u128) -> Option; + fn convert_asset_id_to_location( + asset_id: polkadex_primitives::AssetId, + ) -> Option; /// Converts Location to AssetId - fn convert_location_to_asset_id(location: MultiLocation) -> Option; + fn convert_location_to_asset_id( + location: MultiLocation, + ) -> Option; } pub trait WhitelistedTokenHandler { /// Check if token is whitelisted - fn check_whitelisted_token(asset_id: u128) -> bool; + fn check_whitelisted_token(asset_id: polkadex_primitives::AssetId) -> bool; } /// Configure the pallet by specifying the parameters and types on which it depends. @@ -193,8 +198,7 @@ pub mod pallet { + MaybeSerializeDeserialize + MaxEncodedLen + Into<<::Assets as Inspect>::AssetId> - + From - + Into; + + From; /// Balances Pallet type Currency: frame_support::traits::tokens::fungible::Mutate + frame_support::traits::tokens::fungible::Inspect; @@ -226,33 +230,25 @@ pub mod pallet { pub(super) type PendingWithdrawals = StorageMap<_, Blake2_128Concat, BlockNumberFor, Vec, ValueQuery>; - /// Pending Withdrawals - #[pallet::storage] - #[pallet::getter(fn get_new_pending_withdrawals)] - pub(super) type NewPendingWithdrawals = - StorageMap<_, Blake2_128Concat, BlockNumberFor, Vec, ValueQuery>; - /// Failed Withdrawals #[pallet::storage] #[pallet::getter(fn get_failed_withdrawals)] pub(super) type FailedWithdrawals = StorageMap<_, Blake2_128Concat, BlockNumberFor, Vec, ValueQuery>; - /// Failed Withdrawals - #[pallet::storage] - #[pallet::getter(fn get_new_failed_withdrawals)] - pub(super) type NewFailedWithdrawals = - StorageMap<_, Blake2_128Concat, BlockNumberFor, Vec, ValueQuery>; - /// Asset mapping from u128 asset to multi asset. + /// // TODO: @zktony migrate from u128 to AssetId #[pallet::storage] #[pallet::getter(fn assets_mapping)] - pub type ParachainAssets = StorageMap<_, Identity, u128, AssetId, OptionQuery>; + pub type ParachainAssets = + StorageMap<_, Identity, polkadex_primitives::AssetId, AssetId, OptionQuery>; /// Whitelist Tokens + /// // TODO: @zktony migrate from u128 to AssetId #[pallet::storage] #[pallet::getter(fn get_whitelisted_tokens)] - pub type WhitelistedTokens = StorageValue<_, Vec, ValueQuery>; + pub type WhitelistedTokens = + StorageValue<_, Vec, ValueQuery>; /// Nonce used to generate randomness for txn id #[pallet::storage] @@ -269,19 +265,27 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { /// Asset Deposited from XCM - /// parameters. [recipient, multiasset, asset_id] - AssetDeposited(Box, Box, u128), - AssetWithdrawn(T::AccountId, Box), + /// parameters. [id, recipient, multi-asset, asset_id, extradata] + AssetDeposited( + H160, + Box, + Box, + polkadex_primitives::AssetId, + ExtraData, + ), + /// Asset Withdraw using XCM + /// parameters. [id, asset_id] + AssetWithdrawn(H160, polkadex_primitives::AssetId), /// New Asset Created [asset_id] - TheaAssetCreated(u128), + TheaAssetCreated(polkadex_primitives::AssetId), /// Token Whitelisted For Xcm [token] - TokenWhitelistedForXcm(u128), + TokenWhitelistedForXcm(polkadex_primitives::AssetId), /// Xcm Fee Transferred [recipient, amount] XcmFeeTransferred(T::AccountId, u128), /// Native asset id mapping is registered - NativeAssetIdMappingRegistered(u128, Box), + NativeAssetIdMappingRegistered(polkadex_primitives::AssetId, Box), /// Whitelisted Token removed - WhitelistedTokenRemoved(u128), + WhitelistedTokenRemoved(polkadex_primitives::AssetId), } // Errors inform users that something went wrong. @@ -322,7 +326,6 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet { fn on_initialize(n: BlockNumberFor) -> Weight { - Self::handle_old_pending_withdrawals(n); Self::handle_new_pending_withdrawals(n); // Only update the storage if vector is not empty // TODO: We are currently over estimating the weight here to 1/4th of total block time @@ -386,13 +389,16 @@ pub mod pallet { } } - impl Convert> for Pallet { - fn convert(asset_id: u128) -> Option { + impl Convert> for Pallet { + fn convert(asset_id: polkadex_primitives::AssetId) -> Option { Self::convert_asset_id_to_location(asset_id) } } - impl TransactAsset for Pallet { + impl TransactAsset for Pallet + where + ::AccountId: From<[u8; 32]>, + { /// Generate Ingress Message for new Deposit fn deposit_asset( what: &MultiAsset, @@ -401,25 +407,30 @@ pub mod pallet { ) -> xcm::latest::Result { // Create approved deposit let MultiAsset { id, fun } = what; - let recipient = - T::AccountIdConvert::convert_location(who).ok_or(XcmError::FailedToDecode)?; + + let (recipient, extra) = + extract_data_from_multilocation(*who).ok_or(XcmError::FailedToDecode)?; + let amount: u128 = Self::get_amount(fun).ok_or(XcmError::Trap(101))?; let asset_id = Self::generate_asset_id_for_parachain(*id); let deposit: Deposit = Deposit { - id: Self::new_random_id(), - recipient, + id: Self::new_random_id(None), + recipient: recipient.into(), asset_id, amount, - extra: Vec::new(), + extra: extra.clone(), }; let parachain_network_id = T::SubstrateNetworkId::get(); + let unique_id = deposit.id; T::Executor::execute_withdrawals(parachain_network_id, sp_std::vec![deposit].encode()) .map_err(|_| XcmError::Trap(102))?; Self::deposit_event(Event::::AssetDeposited( + unique_id, Box::new(*who), Box::new(what.clone()), asset_id, + extra, )); Ok(()) } @@ -462,14 +473,19 @@ pub mod pallet { } impl Pallet { - /// Generates a new random id for withdrawals - fn new_random_id() -> Vec { + /// Generates a new random id for withdrawals with an optional prefix + fn new_random_id(prefix: Option<[u8; 4]>) -> H160 { let mut nonce = >::get(); nonce = nonce.wrapping_add(1); >::put(nonce); let network_id = T::SubstrateNetworkId::get(); - let entropy = sp_io::hashing::blake2_256(&((network_id, nonce).encode())); - entropy.to_vec() + let mut entropy: [u8; 20] = [0u8; 20]; + if let Some(prefix) = prefix { + entropy[0..4].copy_from_slice(&prefix); + } + entropy[4..] + .copy_from_slice(&sp_io::hashing::blake2_128(&((network_id, nonce).encode()))); + H160::from(entropy) } /// Get Pallet Id @@ -543,14 +559,14 @@ pub mod pallet { } /// Retrieves the existing assetid for given assetid or generates and stores a new assetid - pub fn generate_asset_id_for_parachain(asset: AssetId) -> u128 { + pub fn generate_asset_id_for_parachain(asset: AssetId) -> polkadex_primitives::AssetId { // Check if its native or not. if asset == AssetId::Concrete(MultiLocation { parents: 1, interior: Junctions::X1(Parachain(T::ParachainId::get())), }) { - return T::NativeAssetId::get().into(); + return polkadex_primitives::AssetId::Polkadex; } // If it's not native, then hash and generate the asset id let asset_id = @@ -582,7 +598,9 @@ pub mod pallet { } /// Converts asset_id to XCM::MultiLocation - pub fn convert_asset_id_to_location(asset_id: u128) -> Option { + pub fn convert_asset_id_to_location( + asset_id: polkadex_primitives::AssetId, + ) -> Option { Self::assets_mapping(asset_id).and_then(|asset| match asset { AssetId::Concrete(location) => Some(location), AssetId::Abstract(_) => None, @@ -590,7 +608,9 @@ pub mod pallet { } /// Converts Multilocation to u128 - pub fn convert_location_to_asset_id(location: MultiLocation) -> u128 { + pub fn convert_location_to_asset_id( + location: MultiLocation, + ) -> polkadex_primitives::AssetId { Self::generate_asset_id_for_parachain(AssetId::Concrete(location)) } @@ -598,79 +618,9 @@ pub mod pallet { >::insert(block_no, vec![withdrawal]); } - pub fn handle_old_pending_withdrawals(n: BlockNumberFor) { + pub fn handle_new_pending_withdrawals(n: BlockNumberFor) { let mut failed_withdrawal: Vec = Vec::default(); >::mutate(n, |withdrawals| { - while let Some(withdrawal) = withdrawals.pop() { - if !withdrawal.is_blocked { - let destination = match VersionedMultiLocation::decode( - &mut &withdrawal.destination[..], - ) { - Ok(dest) => dest, - Err(_) => { - failed_withdrawal.push(withdrawal); - log::error!(target:"xcm-helper","Withdrawal failed: Not able to decode destination"); - continue; - }, - }; - if !Self::is_polkadex_parachain_destination(&destination) { - if let Some(asset) = Self::assets_mapping(withdrawal.asset_id) { - let multi_asset = MultiAsset { - id: asset, - fun: Fungibility::Fungible(withdrawal.amount), - }; - let pallet_account: T::AccountId = - T::AssetHandlerPalletId::get().into_account_truncating(); - // Mint - if Self::resolver_deposit( - withdrawal.asset_id.into(), - withdrawal.amount, - &pallet_account, - pallet_account.clone(), - 1u128, - pallet_account.clone(), - ) - .is_err() - { - failed_withdrawal.push(withdrawal.clone()); - log::error!(target:"xcm-helper","Withdrawal failed: Not able to mint token"); - }; - if orml_xtokens::module::Pallet::::transfer_multiassets( - RawOrigin::Signed( - T::AssetHandlerPalletId::get().into_account_truncating(), - ) - .into(), - Box::new(multi_asset.into()), - 0, - Box::new(destination.clone()), - cumulus_primitives_core::WeightLimit::Unlimited, - ) - .is_err() - { - failed_withdrawal.push(withdrawal.clone()); - log::error!(target:"xcm-helper","Withdrawal failed: Not able to make xcm calls"); - } - } else { - failed_withdrawal.push(withdrawal) - } - } else if Self::handle_deposit(withdrawal.clone(), destination).is_err() { - failed_withdrawal.push(withdrawal); - log::error!(target:"xcm-helper","Withdrawal failed: Not able to handle dest"); - } - } else { - failed_withdrawal.push(withdrawal); - log::error!(target:"xcm-helper","Withdrawal failed: Withdrawal is blocked"); - } - } - }); - if !failed_withdrawal.is_empty() { - >::insert(n, failed_withdrawal); - } - } - - pub fn handle_new_pending_withdrawals(n: BlockNumberFor) { - let mut failed_withdrawal: Vec = Vec::default(); - >::mutate(n, |withdrawals| { while let Some(withdrawal) = withdrawals.pop() { if !withdrawal.is_blocked { let destination = match VersionedMultiLocation::decode( @@ -743,6 +693,12 @@ pub mod pallet { { failed_withdrawal.push(withdrawal.clone()); log::error!(target:"xcm-helper","Withdrawal failed: Not able to make xcm calls"); + } else { + // Deposit event + Self::deposit_event(Event::::AssetWithdrawn( + withdrawal.id, + withdrawal.asset_id, + )); } } } else if let Some(asset) = Self::assets_mapping(withdrawal.asset_id) { @@ -780,13 +736,17 @@ pub mod pallet { { failed_withdrawal.push(withdrawal.clone()); log::error!(target:"xcm-helper","Withdrawal failed: Not able to make xcm calls"); + } else { + // Deposit event + Self::deposit_event(Event::::AssetWithdrawn( + withdrawal.id, + withdrawal.asset_id, + )) } } else { failed_withdrawal.push(withdrawal) } - } else if Self::handle_deposit(withdrawal.clone().into(), destination) - .is_err() - { + } else if Self::handle_deposit(withdrawal.clone(), destination).is_err() { failed_withdrawal.push(withdrawal); log::error!(target:"xcm-helper","Withdrawal failed: Not able to handle dest"); } @@ -798,23 +758,27 @@ pub mod pallet { }); // Only update the storage if vector is not empty if !failed_withdrawal.is_empty() { - >::insert(n, failed_withdrawal); + >::insert(n, failed_withdrawal); } } } impl AssetIdConverter for Pallet { - fn convert_asset_id_to_location(asset_id: u128) -> Option { + fn convert_asset_id_to_location( + asset_id: polkadex_primitives::AssetId, + ) -> Option { Self::convert_asset_id_to_location(asset_id) } - fn convert_location_to_asset_id(location: MultiLocation) -> Option { + fn convert_location_to_asset_id( + location: MultiLocation, + ) -> Option { Some(Self::convert_location_to_asset_id(location)) } } impl WhitelistedTokenHandler for Pallet { - fn check_whitelisted_token(asset_id: u128) -> bool { + fn check_whitelisted_token(asset_id: polkadex_primitives::AssetId) -> bool { let whitelisted_tokens = >::get(); whitelisted_tokens.contains(&asset_id) } @@ -822,7 +786,7 @@ pub mod pallet { impl TheaIncomingExecutor for Pallet { fn execute_deposits(_: Network, deposits: Vec) { - let deposits = Vec::::decode(&mut &deposits[..]).unwrap_or_default(); + let deposits = Vec::::decode(&mut &deposits[..]).unwrap_or_default(); for deposit in deposits { // Calculate the withdrawal execution delay let withdrawal_execution_block: BlockNumberFor = @@ -833,7 +797,7 @@ pub mod pallet { ) .into(); // Queue the withdrawal for execution - >::mutate( + >::mutate( withdrawal_execution_block, |pending_withdrawals| { pending_withdrawals.push(deposit); diff --git a/pallets/xcm-helper/src/tests.rs b/pallets/xcm-helper/src/tests.rs index 20cf72f40..c674c1603 100644 --- a/pallets/xcm-helper/src/tests.rs +++ b/pallets/xcm-helper/src/tests.rs @@ -15,7 +15,9 @@ use crate::{mock::*, Error, PendingWithdrawals}; use frame_support::{assert_noop, assert_ok, traits::Currency}; +use sp_core::H160; use sp_runtime::{traits::AccountIdConversion, DispatchError, SaturatedConversion}; +use thea_primitives::extras::ExtraData; use thea_primitives::types::Withdraw; use xcm::latest::{AssetId, MultiLocation}; @@ -124,31 +126,37 @@ fn test_transfer_fee_with_bad_origin_will_return_bad_origin_error() { fn test_block_by_ele() { new_test_ext().execute_with(|| { let first_withdrawal = Withdraw { - id: Vec::new(), - asset_id: 1, + id: H160::zero(), + asset_id: polkadex_primitives::AssetId::Asset(1), amount: 1, destination: vec![], + fee_asset_id: None, + fee_amount: None, is_blocked: false, - extra: vec![], + extra: ExtraData::None, }; let sec_withdrawal = Withdraw { - id: Vec::new(), - asset_id: 2, + id: H160::zero(), + asset_id: polkadex_primitives::AssetId::Asset(1), amount: 2, destination: vec![], + fee_asset_id: None, + fee_amount: None, is_blocked: false, - extra: vec![], + extra: ExtraData::None, }; >::insert(1, vec![first_withdrawal, sec_withdrawal]); assert_ok!(XcmHelper::block_by_ele(1, 1)); let actual_withdrawals = >::get(1); let expected_withdraw = Withdraw { - id: Vec::new(), - asset_id: 2, + id: H160::zero(), + asset_id: polkadex_primitives::AssetId::Asset(1), amount: 2, destination: vec![], + fee_asset_id: None, + fee_amount: None, is_blocked: true, - extra: vec![], + extra: ExtraData::None, }; assert_eq!(actual_withdrawals[1], expected_withdraw); assert_noop!(XcmHelper::block_by_ele(1, 4), Error::::IndexNotFound); diff --git a/polkadex-xcm-simulator/Cargo.toml b/polkadex-xcm-simulator/Cargo.toml new file mode 100644 index 000000000..37ae52ba2 --- /dev/null +++ b/polkadex-xcm-simulator/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "polkadex-xcm-simulator" +version = "1.0.0" +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.6.1" } +scale-info = { version = "2.5.0", features = ["derive"] } +log = { version = "0.4.14", default-features = false } + +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +pallet-message-queue = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +pallet-uniques = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +sp-tracing = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } + +xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +xcm-simulator = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +pallet-xcm = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } +polkadot-parachain-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0" } + +[features] +default = [] +runtime-benchmarks = [ + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-message-queue/runtime-benchmarks", + "pallet-uniques/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "polkadot-parachain-primitives/runtime-benchmarks", + "polkadot-runtime-parachains/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "xcm-executor/runtime-benchmarks", +] diff --git a/polkadex-xcm-simulator/src/lib.rs b/polkadex-xcm-simulator/src/lib.rs new file mode 100644 index 000000000..4b7958bf0 --- /dev/null +++ b/polkadex-xcm-simulator/src/lib.rs @@ -0,0 +1,651 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +mod parachain; +mod relay_chain; + +use sp_runtime::BuildStorage; +use xcm::prelude::*; +use xcm_executor::traits::ConvertLocation; +use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt}; + +pub const ALICE: sp_runtime::AccountId32 = sp_runtime::AccountId32::new([0u8; 32]); +pub const INITIAL_BALANCE: u128 = 1_000_000_000; + +decl_test_parachain! { + pub struct ParaA { + Runtime = parachain::Runtime, + XcmpMessageHandler = parachain::MsgQueue, + DmpMessageHandler = parachain::MsgQueue, + new_ext = para_ext(1), + } +} + +decl_test_parachain! { + pub struct ParaB { + Runtime = parachain::Runtime, + XcmpMessageHandler = parachain::MsgQueue, + DmpMessageHandler = parachain::MsgQueue, + new_ext = para_ext(2), + } +} + +decl_test_relay_chain! { + pub struct Relay { + Runtime = relay_chain::Runtime, + RuntimeCall = relay_chain::RuntimeCall, + RuntimeEvent = relay_chain::RuntimeEvent, + XcmConfig = relay_chain::XcmConfig, + MessageQueue = relay_chain::MessageQueue, + System = relay_chain::System, + new_ext = relay_ext(), + } +} + +decl_test_network! { + pub struct MockNet { + relay_chain = Relay, + parachains = vec![ + (1, ParaA), + (2, ParaB), + ], + } +} + +pub fn parent_account_id() -> parachain::AccountId { + let location = (Parent,); + parachain::LocationToAccountId::convert_location(&location.into()).unwrap() +} + +pub fn child_account_id(para: u32) -> relay_chain::AccountId { + let location = (Parachain(para),); + relay_chain::LocationToAccountId::convert_location(&location.into()).unwrap() +} + +pub fn child_account_account_id(para: u32, who: sp_runtime::AccountId32) -> relay_chain::AccountId { + let location = (Parachain(para), AccountId32 { network: None, id: who.into() }); + relay_chain::LocationToAccountId::convert_location(&location.into()).unwrap() +} + +pub fn sibling_account_account_id(para: u32, who: sp_runtime::AccountId32) -> parachain::AccountId { + let location = (Parent, Parachain(para), AccountId32 { network: None, id: who.into() }); + parachain::LocationToAccountId::convert_location(&location.into()).unwrap() +} + +pub fn parent_account_account_id(who: sp_runtime::AccountId32) -> parachain::AccountId { + let location = (Parent, AccountId32 { network: None, id: who.into() }); + parachain::LocationToAccountId::convert_location(&location.into()).unwrap() +} + +pub fn para_ext(para_id: u32) -> sp_io::TestExternalities { + use parachain::{MsgQueue, Runtime, System}; + + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + + pallet_balances::GenesisConfig:: { + balances: vec![(ALICE, INITIAL_BALANCE), (parent_account_id(), INITIAL_BALANCE)], + } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + sp_tracing::try_init_simple(); + System::set_block_number(1); + MsgQueue::set_para_id(para_id.into()); + }); + ext +} + +pub fn relay_ext() -> sp_io::TestExternalities { + use relay_chain::{Runtime, RuntimeOrigin, System, Uniques}; + + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + + pallet_balances::GenesisConfig:: { + balances: vec![ + (ALICE, INITIAL_BALANCE), + (child_account_id(1), INITIAL_BALANCE), + (child_account_id(2), INITIAL_BALANCE), + ], + } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + assert_eq!(Uniques::force_create(RuntimeOrigin::root(), 1, ALICE, true), Ok(())); + assert_eq!(Uniques::mint(RuntimeOrigin::signed(ALICE), 1, 42, child_account_id(1)), Ok(())); + }); + ext +} + +pub type RelayChainPalletXcm = pallet_xcm::Pallet; +pub type ParachainPalletXcm = pallet_xcm::Pallet; + +#[cfg(test)] +mod tests { + use super::*; + + use codec::Encode; + use frame_support::{assert_ok, weights::Weight}; + use xcm::latest::QueryResponseInfo; + use xcm_simulator::TestExt; + + // Helper function for forming buy execution message + fn buy_execution(fees: impl Into) -> Instruction { + BuyExecution { fees: fees.into(), weight_limit: Unlimited } + } + + #[test] + fn remote_account_ids_work() { + child_account_account_id(1, ALICE); + sibling_account_account_id(1, ALICE); + parent_account_account_id(ALICE); + } + + #[test] + fn dmp() { + MockNet::reset(); + + let remark = parachain::RuntimeCall::System( + frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }, + ); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::send_xcm( + Here, + Parachain(1), + Xcm(vec![Transact { + origin_kind: OriginKind::SovereignAccount, + require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), + call: remark.encode().into(), + }]), + )); + }); + + ParaA::execute_with(|| { + use parachain::{RuntimeEvent, System}; + assert!(System::events().iter().any(|r| matches!( + r.event, + RuntimeEvent::System(frame_system::Event::Remarked { .. }) + ))); + }); + } + + #[test] + fn ump() { + MockNet::reset(); + + let remark = relay_chain::RuntimeCall::System( + frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }, + ); + ParaA::execute_with(|| { + assert_ok!(ParachainPalletXcm::send_xcm( + Here, + Parent, + Xcm(vec![Transact { + origin_kind: OriginKind::SovereignAccount, + require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), + call: remark.encode().into(), + }]), + )); + }); + + Relay::execute_with(|| { + use relay_chain::{RuntimeEvent, System}; + assert!(System::events().iter().any(|r| matches!( + r.event, + RuntimeEvent::System(frame_system::Event::Remarked { .. }) + ))); + }); + } + + #[test] + fn xcmp() { + MockNet::reset(); + + let remark = parachain::RuntimeCall::System( + frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }, + ); + ParaA::execute_with(|| { + assert_ok!(ParachainPalletXcm::send_xcm( + Here, + (Parent, Parachain(2)), + Xcm(vec![Transact { + origin_kind: OriginKind::SovereignAccount, + require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), + call: remark.encode().into(), + }]), + )); + }); + + ParaB::execute_with(|| { + use parachain::{RuntimeEvent, System}; + assert!(System::events().iter().any(|r| matches!( + r.event, + RuntimeEvent::System(frame_system::Event::Remarked { .. }) + ))); + }); + } + + #[test] + fn reserve_transfer() { + MockNet::reset(); + + let withdraw_amount = 123; + + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(ALICE), + Box::new(Parachain(1).into()), + Box::new(AccountId32 { network: None, id: ALICE.into() }.into()), + Box::new((Here, withdraw_amount).into()), + 0, + )); + assert_eq!( + relay_chain::Balances::free_balance(&child_account_id(1)), + INITIAL_BALANCE + withdraw_amount + ); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!( + pallet_balances::Pallet::::free_balance(&ALICE), + INITIAL_BALANCE + withdraw_amount + ); + }); + } + + #[test] + fn remote_locking_and_unlocking() { + MockNet::reset(); + + let locked_amount = 100; + + ParaB::execute_with(|| { + let message = Xcm(vec![LockAsset { + asset: (Here, locked_amount).into(), + unlocker: Parachain(1).into(), + }]); + assert_ok!(ParachainPalletXcm::send_xcm(Here, Parent, message.clone())); + }); + + Relay::execute_with(|| { + use pallet_balances::{BalanceLock, Reasons}; + assert_eq!( + relay_chain::Balances::locks(&child_account_id(2)), + vec![BalanceLock { + id: *b"py/xcmlk", + amount: locked_amount, + reasons: Reasons::All + }] + ); + }); + + ParaA::execute_with(|| { + assert_eq!( + parachain::MsgQueue::received_dmp(), + vec![Xcm(vec![NoteUnlockable { + owner: (Parent, Parachain(2)).into(), + asset: (Parent, locked_amount).into() + }])] + ); + }); + + ParaB::execute_with(|| { + // Request unlocking part of the funds on the relay chain + let message = Xcm(vec![RequestUnlock { + asset: (Parent, locked_amount - 50).into(), + locker: Parent.into(), + }]); + assert_ok!(ParachainPalletXcm::send_xcm(Here, (Parent, Parachain(1)), message)); + }); + + Relay::execute_with(|| { + use pallet_balances::{BalanceLock, Reasons}; + // Lock is reduced + assert_eq!( + relay_chain::Balances::locks(&child_account_id(2)), + vec![BalanceLock { + id: *b"py/xcmlk", + amount: locked_amount - 50, + reasons: Reasons::All + }] + ); + }); + } + + /// Scenario: + /// A parachain transfers an NFT resident on the relay chain to another parachain account. + /// + /// Asserts that the parachain accounts are updated as expected. + #[test] + fn withdraw_and_deposit_nft() { + MockNet::reset(); + + Relay::execute_with(|| { + assert_eq!(relay_chain::Uniques::owner(1, 42), Some(child_account_id(1))); + }); + + ParaA::execute_with(|| { + let message = Xcm(vec![TransferAsset { + assets: (GeneralIndex(1), 42u32).into(), + beneficiary: Parachain(2).into(), + }]); + // Send withdraw and deposit + assert_ok!(ParachainPalletXcm::send_xcm(Here, Parent, message)); + }); + + Relay::execute_with(|| { + assert_eq!(relay_chain::Uniques::owner(1, 42), Some(child_account_id(2))); + }); + } + + /// Scenario: + /// The relay-chain teleports an NFT to a parachain. + /// + /// Asserts that the parachain accounts are updated as expected. + #[test] + fn teleport_nft() { + MockNet::reset(); + + Relay::execute_with(|| { + // Mint the NFT (1, 69) and give it to our "parachain#1 alias". + assert_ok!(relay_chain::Uniques::mint( + relay_chain::RuntimeOrigin::signed(ALICE), + 1, + 69, + child_account_account_id(1, ALICE), + )); + // The parachain#1 alias of Alice is what must hold it on the Relay-chain for it to be + // withdrawable by Alice on the parachain. + assert_eq!( + relay_chain::Uniques::owner(1, 69), + Some(child_account_account_id(1, ALICE)) + ); + }); + ParaA::execute_with(|| { + assert_ok!(parachain::ForeignUniques::force_create( + parachain::RuntimeOrigin::root(), + (Parent, GeneralIndex(1)).into(), + ALICE, + false, + )); + assert_eq!( + parachain::ForeignUniques::owner((Parent, GeneralIndex(1)).into(), 69u32.into()), + None, + ); + assert_eq!(parachain::Balances::reserved_balance(&ALICE), 0); + + // IRL Alice would probably just execute this locally on the Relay-chain, but we can't + // easily do that here since we only send between chains. + let message = Xcm(vec![ + WithdrawAsset((GeneralIndex(1), 69u32).into()), + InitiateTeleport { + assets: AllCounted(1).into(), + dest: Parachain(1).into(), + xcm: Xcm(vec![DepositAsset { + assets: AllCounted(1).into(), + beneficiary: (AccountId32 { id: ALICE.into(), network: None },).into(), + }]), + }, + ]); + // Send teleport + let alice = AccountId32 { id: ALICE.into(), network: None }; + assert_ok!(ParachainPalletXcm::send_xcm(alice, Parent, message)); + }); + ParaA::execute_with(|| { + assert_eq!( + parachain::ForeignUniques::owner((Parent, GeneralIndex(1)).into(), 69u32.into()), + Some(ALICE), + ); + assert_eq!(parachain::Balances::reserved_balance(&ALICE), 1000); + }); + Relay::execute_with(|| { + assert_eq!(relay_chain::Uniques::owner(1, 69), None); + }); + } + + /// Scenario: + /// The relay-chain transfers an NFT into a parachain's sovereign account, who then mints a + /// trustless-backed-derivated locally. + /// + /// Asserts that the parachain accounts are updated as expected. + #[test] + fn reserve_asset_transfer_nft() { + sp_tracing::init_for_tests(); + MockNet::reset(); + + Relay::execute_with(|| { + assert_ok!(relay_chain::Uniques::force_create( + relay_chain::RuntimeOrigin::root(), + 2, + ALICE, + false + )); + assert_ok!(relay_chain::Uniques::mint( + relay_chain::RuntimeOrigin::signed(ALICE), + 2, + 69, + child_account_account_id(1, ALICE) + )); + assert_eq!( + relay_chain::Uniques::owner(2, 69), + Some(child_account_account_id(1, ALICE)) + ); + }); + ParaA::execute_with(|| { + assert_ok!(parachain::ForeignUniques::force_create( + parachain::RuntimeOrigin::root(), + (Parent, GeneralIndex(2)).into(), + ALICE, + false, + )); + assert_eq!( + parachain::ForeignUniques::owner((Parent, GeneralIndex(2)).into(), 69u32.into()), + None, + ); + assert_eq!(parachain::Balances::reserved_balance(&ALICE), 0); + + let message = Xcm(vec![ + WithdrawAsset((GeneralIndex(2), 69u32).into()), + DepositReserveAsset { + assets: AllCounted(1).into(), + dest: Parachain(1).into(), + xcm: Xcm(vec![DepositAsset { + assets: AllCounted(1).into(), + beneficiary: (AccountId32 { id: ALICE.into(), network: None },).into(), + }]), + }, + ]); + // Send transfer + let alice = AccountId32 { id: ALICE.into(), network: None }; + assert_ok!(ParachainPalletXcm::send_xcm(alice, Parent, message)); + }); + ParaA::execute_with(|| { + log::debug!(target: "xcm-exceutor", "Hello"); + assert_eq!( + parachain::ForeignUniques::owner((Parent, GeneralIndex(2)).into(), 69u32.into()), + Some(ALICE), + ); + assert_eq!(parachain::Balances::reserved_balance(&ALICE), 1000); + }); + + Relay::execute_with(|| { + assert_eq!(relay_chain::Uniques::owner(2, 69), Some(child_account_id(1))); + }); + } + + /// Scenario: + /// The relay-chain creates an asset class on a parachain and then Alice transfers her NFT into + /// that parachain's sovereign account, who then mints a trustless-backed-derivative locally. + /// + /// Asserts that the parachain accounts are updated as expected. + #[test] + fn reserve_asset_class_create_and_reserve_transfer() { + MockNet::reset(); + + Relay::execute_with(|| { + assert_ok!(relay_chain::Uniques::force_create( + relay_chain::RuntimeOrigin::root(), + 2, + ALICE, + false + )); + assert_ok!(relay_chain::Uniques::mint( + relay_chain::RuntimeOrigin::signed(ALICE), + 2, + 69, + child_account_account_id(1, ALICE) + )); + assert_eq!( + relay_chain::Uniques::owner(2, 69), + Some(child_account_account_id(1, ALICE)) + ); + + let message = Xcm(vec![Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: Weight::from_parts(1_000_000_000, 1024 * 1024), + call: parachain::RuntimeCall::from( + pallet_uniques::Call::::create { + collection: (Parent, 2u64).into(), + admin: parent_account_id(), + }, + ) + .encode() + .into(), + }]); + // Send creation. + assert_ok!(RelayChainPalletXcm::send_xcm(Here, Parachain(1), message)); + }); + ParaA::execute_with(|| { + // Then transfer + let message = Xcm(vec![ + WithdrawAsset((GeneralIndex(2), 69u32).into()), + DepositReserveAsset { + assets: AllCounted(1).into(), + dest: Parachain(1).into(), + xcm: Xcm(vec![DepositAsset { + assets: AllCounted(1).into(), + beneficiary: (AccountId32 { id: ALICE.into(), network: None },).into(), + }]), + }, + ]); + let alice = AccountId32 { id: ALICE.into(), network: None }; + assert_ok!(ParachainPalletXcm::send_xcm(alice, Parent, message)); + }); + ParaA::execute_with(|| { + assert_eq!(parachain::Balances::reserved_balance(&parent_account_id()), 1000); + assert_eq!( + parachain::ForeignUniques::collection_owner((Parent, 2u64).into()), + Some(parent_account_id()) + ); + }); + } + + /// Scenario: + /// A parachain transfers funds on the relay chain to another parachain account. + /// + /// Asserts that the parachain accounts are updated as expected. + #[test] + fn withdraw_and_deposit() { + MockNet::reset(); + + let send_amount = 10; + + ParaA::execute_with(|| { + let message = Xcm(vec![ + WithdrawAsset((Here, send_amount).into()), + buy_execution((Here, send_amount)), + DepositAsset { assets: AllCounted(1).into(), beneficiary: Parachain(2).into() }, + ]); + // Send withdraw and deposit + assert_ok!(ParachainPalletXcm::send_xcm(Here, Parent, message.clone())); + }); + + Relay::execute_with(|| { + assert_eq!( + relay_chain::Balances::free_balance(child_account_id(1)), + INITIAL_BALANCE - send_amount + ); + assert_eq!( + relay_chain::Balances::free_balance(child_account_id(2)), + INITIAL_BALANCE + send_amount + ); + }); + } + + /// Scenario: + /// A parachain wants to be notified that a transfer worked correctly. + /// It sends a `QueryHolding` after the deposit to get notified on success. + /// + /// Asserts that the balances are updated correctly and the expected XCM is sent. + #[test] + fn query_holding() { + MockNet::reset(); + + let send_amount = 10; + let query_id_set = 1234; + + // Send a message which fully succeeds on the relay chain + ParaA::execute_with(|| { + let message = Xcm(vec![ + WithdrawAsset((Here, send_amount).into()), + buy_execution((Here, send_amount)), + DepositAsset { assets: AllCounted(1).into(), beneficiary: Parachain(2).into() }, + ReportHolding { + response_info: QueryResponseInfo { + destination: Parachain(1).into(), + query_id: query_id_set, + max_weight: Weight::from_parts(1_000_000_000, 1024 * 1024), + }, + assets: All.into(), + }, + ]); + // Send withdraw and deposit with query holding + assert_ok!(ParachainPalletXcm::send_xcm(Here, Parent, message.clone(),)); + }); + + // Check that transfer was executed + Relay::execute_with(|| { + // Withdraw executed + assert_eq!( + relay_chain::Balances::free_balance(child_account_id(1)), + INITIAL_BALANCE - send_amount + ); + // Deposit executed + assert_eq!( + relay_chain::Balances::free_balance(child_account_id(2)), + INITIAL_BALANCE + send_amount + ); + }); + + // Check that QueryResponse message was received + ParaA::execute_with(|| { + assert_eq!( + parachain::MsgQueue::received_dmp(), + vec![Xcm(vec![QueryResponse { + query_id: query_id_set, + response: Response::Assets(MultiAssets::new()), + max_weight: Weight::from_parts(1_000_000_000, 1024 * 1024), + querier: Some(Here.into()), + }])], + ); + }); + } +} diff --git a/polkadex-xcm-simulator/src/parachain.rs b/polkadex-xcm-simulator/src/parachain.rs new file mode 100644 index 000000000..6ec8c22ec --- /dev/null +++ b/polkadex-xcm-simulator/src/parachain.rs @@ -0,0 +1,462 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Parachain runtime mock. + +use codec::{Decode, Encode}; +use core::marker::PhantomData; +use frame_support::{ + construct_runtime, parameter_types, + traits::{ContainsPair, EnsureOrigin, EnsureOriginWithArg, Everything, EverythingBut, Nothing}, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, +}; + +use frame_system::EnsureRoot; +use sp_core::{ConstU32, H256}; +use sp_runtime::{ + traits::{Get, Hash, IdentityLookup}, + AccountId32, +}; +use sp_std::prelude::*; + +use pallet_xcm::XcmPassthrough; +use polkadot_core_primitives::BlockNumber as RelayBlockNumber; +use polkadot_parachain_primitives::primitives::{ + DmpMessageHandler, Id as ParaId, Sibling, XcmpMessageFormat, XcmpMessageHandler, +}; +use xcm::{latest::prelude::*, VersionedXcm}; +use xcm_builder::{ + Account32Hash, AccountId32Aliases, AllowUnpaidExecutionFrom, ConvertedConcreteId, + CurrencyAdapter as XcmCurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, + IsConcrete, NativeAsset, NoChecking, NonFungiblesAdapter, ParentIsPreset, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, +}; +use xcm_executor::{ + traits::{ConvertLocation, JustTry}, + Config, XcmExecutor, +}; + +pub type SovereignAccountOf = ( + SiblingParachainConvertsVia, + AccountId32Aliases, + ParentIsPreset, +); + +pub type AccountId = AccountId32; +pub type Balance = u128; + +parameter_types! { + pub const BlockHashCount: u64 = 250; +} + +impl frame_system::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Block = Block; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type BlockWeights = (); + type BlockLength = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type DbWeight = (); + type BaseCallFilter = Everything; + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +parameter_types! { + pub ExistentialDeposit: Balance = 1; + pub const MaxLocks: u32 = 50; + pub const MaxReserves: u32 = 50; +} + +impl pallet_balances::Config for Runtime { + type MaxLocks = MaxLocks; + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type MaxReserves = MaxReserves; + type ReserveIdentifier = [u8; 8]; + type RuntimeHoldReason = RuntimeHoldReason; + type FreezeIdentifier = (); + type MaxHolds = ConstU32<0>; + type MaxFreezes = ConstU32<0>; +} + +#[cfg(feature = "runtime-benchmarks")] +pub struct UniquesHelper; +#[cfg(feature = "runtime-benchmarks")] +impl pallet_uniques::BenchmarkHelper for UniquesHelper { + fn collection(i: u16) -> MultiLocation { + GeneralIndex(i as u128).into() + } + fn item(i: u16) -> AssetInstance { + AssetInstance::Index(i as u128) + } +} + +impl pallet_uniques::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type CollectionId = MultiLocation; + type ItemId = AssetInstance; + type Currency = Balances; + type CreateOrigin = ForeignCreators; + type ForceOrigin = frame_system::EnsureRoot; + type CollectionDeposit = frame_support::traits::ConstU128<1_000>; + type ItemDeposit = frame_support::traits::ConstU128<1_000>; + type MetadataDepositBase = frame_support::traits::ConstU128<1_000>; + type AttributeDepositBase = frame_support::traits::ConstU128<1_000>; + type DepositPerByte = frame_support::traits::ConstU128<1>; + type StringLimit = ConstU32<64>; + type KeyLimit = ConstU32<64>; + type ValueLimit = ConstU32<128>; + type Locker = (); + type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type Helper = UniquesHelper; +} + +// `EnsureOriginWithArg` impl for `CreateOrigin` which allows only XCM origins +// which are locations containing the class location. +pub struct ForeignCreators; +impl EnsureOriginWithArg for ForeignCreators { + type Success = AccountId; + + fn try_origin( + o: RuntimeOrigin, + a: &MultiLocation, + ) -> sp_std::result::Result { + let origin_location = pallet_xcm::EnsureXcm::::try_origin(o.clone())?; + if !a.starts_with(&origin_location) { + return Err(o); + } + SovereignAccountOf::convert_location(&origin_location).ok_or(o) + } + + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin(a: &MultiLocation) -> Result { + Ok(pallet_xcm::Origin::Xcm(a.clone()).into()) + } +} + +parameter_types! { + pub const ReservedXcmpWeight: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_div(4), 0); + pub const ReservedDmpWeight: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_div(4), 0); +} + +parameter_types! { + pub const KsmLocation: MultiLocation = MultiLocation::parent(); + pub const RelayNetwork: NetworkId = NetworkId::Kusama; + pub UniversalLocation: InteriorMultiLocation = Parachain(MsgQueue::parachain_id().into()).into(); +} + +pub type LocationToAccountId = ( + ParentIsPreset, + SiblingParachainConvertsVia, + AccountId32Aliases, + Account32Hash<(), AccountId>, +); + +pub type XcmOriginToCallOrigin = ( + SovereignSignedViaLocation, + SignedAccountId32AsNative, + XcmPassthrough, +); + +parameter_types! { + pub const UnitWeightCost: Weight = Weight::from_parts(1, 1); + pub KsmPerSecondPerByte: (AssetId, u128, u128) = (Concrete(Parent.into()), 1, 1); + pub const MaxInstructions: u32 = 100; + pub const MaxAssetsIntoHolding: u32 = 64; + pub ForeignPrefix: MultiLocation = (Parent,).into(); +} + +pub type LocalAssetTransactor = ( + XcmCurrencyAdapter, LocationToAccountId, AccountId, ()>, + NonFungiblesAdapter< + ForeignUniques, + ConvertedConcreteId, + SovereignAccountOf, + AccountId, + NoChecking, + (), + >, +); + +pub type XcmRouter = super::ParachainXcmRouter; +pub type Barrier = AllowUnpaidExecutionFrom; + +parameter_types! { + pub NftCollectionOne: MultiAssetFilter + = Wild(AllOf { fun: WildNonFungible, id: Concrete((Parent, GeneralIndex(1)).into()) }); + pub NftCollectionOneForRelay: (MultiAssetFilter, MultiLocation) + = (NftCollectionOne::get(), (Parent,).into()); +} +pub type TrustedTeleporters = xcm_builder::Case; +pub type TrustedReserves = EverythingBut>; + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = LocalAssetTransactor; + type OriginConverter = XcmOriginToCallOrigin; + type IsReserve = (NativeAsset, TrustedReserves); + type IsTeleporter = TrustedTeleporters; + type UniversalLocation = UniversalLocation; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = FixedRateOfFungible; + type ResponseHandler = (); + type AssetTrap = (); + type AssetLocker = PolkadotXcm; + type AssetExchanger = (); + type AssetClaims = (); + type SubscriptionService = (); + type PalletInstancesInfo = (); + type FeeManager = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type MessageExporter = (); + type UniversalAliases = Nothing; + type CallDispatcher = RuntimeCall; + type SafeCallFilter = Everything; + type Aliasers = Nothing; +} + +#[frame_support::pallet] +#[allow(unused_imports)] +pub mod mock_msg_queue { + use super::*; + use frame_support::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type XcmExecutor: ExecuteXcm; + } + + // #[pallet::call] + impl Pallet {} + + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn parachain_id)] + pub(super) type ParachainId = StorageValue<_, ParaId, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn received_dmp)] + /// A queue of received DMP messages + pub(super) type ReceivedDmp = StorageValue<_, Vec>, ValueQuery>; + + impl Get for Pallet { + fn get() -> ParaId { + Self::parachain_id() + } + } + + pub type MessageId = [u8; 32]; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + // XCMP + /// Some XCM was executed OK. + Success(Option), + /// Some XCM failed. + Fail(Option, XcmError), + /// Bad XCM version used. + BadVersion(Option), + /// Bad XCM format used. + BadFormat(Option), + + // DMP + /// Downward message is invalid XCM. + InvalidFormat(MessageId), + /// Downward message is unsupported version of XCM. + UnsupportedVersion(MessageId), + /// Downward message executed with the given outcome. + ExecutedDownward(MessageId, Outcome), + } + + impl Pallet { + pub fn set_para_id(para_id: ParaId) { + ParachainId::::put(para_id); + } + + fn handle_xcmp_message( + sender: ParaId, + _sent_at: RelayBlockNumber, + xcm: VersionedXcm, + max_weight: Weight, + ) -> Result { + let hash = Encode::using_encoded(&xcm, T::Hashing::hash); + let message_hash = Encode::using_encoded(&xcm, sp_io::hashing::blake2_256); + let (result, event) = match Xcm::::try_from(xcm) { + Ok(xcm) => { + let location = (Parent, Parachain(sender.into())); + match T::XcmExecutor::execute_xcm(location, xcm, message_hash, max_weight) { + Outcome::Error(e) => (Err(e), Event::Fail(Some(hash), e)), + Outcome::Complete(w) => (Ok(w), Event::Success(Some(hash))), + // As far as the caller is concerned, this was dispatched without error, so + // we just report the weight used. + Outcome::Incomplete(w, e) => (Ok(w), Event::Fail(Some(hash), e)), + } + }, + Err(()) => (Err(XcmError::UnhandledXcmVersion), Event::BadVersion(Some(hash))), + }; + Self::deposit_event(event); + result + } + } + + impl XcmpMessageHandler for Pallet { + fn handle_xcmp_messages<'a, I: Iterator>( + iter: I, + max_weight: Weight, + ) -> Weight { + for (sender, sent_at, data) in iter { + let mut data_ref = data; + let _ = XcmpMessageFormat::decode(&mut data_ref) + .expect("Simulator encodes with versioned xcm format; qed"); + + let mut remaining_fragments = data_ref; + while !remaining_fragments.is_empty() { + if let Ok(xcm) = + VersionedXcm::::decode(&mut remaining_fragments) + { + let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight); + } else { + debug_assert!(false, "Invalid incoming XCMP message data"); + } + } + } + max_weight + } + } + + impl DmpMessageHandler for Pallet { + fn handle_dmp_messages( + iter: impl Iterator)>, + limit: Weight, + ) -> Weight { + for (_sent_at, data) in iter { + let id = sp_io::hashing::blake2_256(&data[..]); + let maybe_versioned = VersionedXcm::::decode(&mut &data[..]); + match maybe_versioned { + Err(_) => { + Self::deposit_event(Event::InvalidFormat(id)); + }, + Ok(versioned) => match Xcm::try_from(versioned) { + Err(()) => Self::deposit_event(Event::UnsupportedVersion(id)), + Ok(x) => { + let outcome = T::XcmExecutor::execute_xcm(Parent, x.clone(), id, limit); + >::append(x); + Self::deposit_event(Event::ExecutedDownward(id, outcome)); + }, + }, + } + } + limit + } + } +} + +impl mock_msg_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +pub type LocalOriginToLocation = SignedToAccountId32; + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parent.into()); +} + +pub struct TrustedLockerCase(PhantomData); +impl> ContainsPair + for TrustedLockerCase +{ + fn contains(origin: &MultiLocation, asset: &MultiAsset) -> bool { + let (o, a) = T::get(); + a.matches(asset) && &o == origin + } +} + +parameter_types! { + pub RelayTokenForRelay: (MultiLocation, MultiAssetFilter) = (Parent.into(), Wild(AllOf { id: Concrete(Parent.into()), fun: WildFungible })); +} + +pub type TrustedLockers = TrustedLockerCase; + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = Everything; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = Nothing; + type XcmReserveTransferFilter = Everything; + type Weigher = FixedWeightBounds; + type UniversalLocation = UniversalLocation; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = (); + type TrustedLockers = TrustedLockers; + type SovereignAccountOf = LocationToAccountId; + type MaxLockers = ConstU32<8>; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type WeightInfo = pallet_xcm::TestWeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + type AdminOrigin = EnsureRoot; +} + +type Block = frame_system::mocking::MockBlock; + +construct_runtime!( + pub enum Runtime + { + System: frame_system::{Pallet, Call, Storage, Config, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + MsgQueue: mock_msg_queue::{Pallet, Storage, Event}, + PolkadotXcm: pallet_xcm::{Pallet, Call, Event, Origin}, + ForeignUniques: pallet_uniques::{Pallet, Call, Storage, Event}, + } +); diff --git a/polkadex-xcm-simulator/src/relay_chain.rs b/polkadex-xcm-simulator/src/relay_chain.rs new file mode 100644 index 000000000..4e9195a84 --- /dev/null +++ b/polkadex-xcm-simulator/src/relay_chain.rs @@ -0,0 +1,294 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Relay chain runtime mock. + +use frame_support::{ + construct_runtime, parameter_types, + traits::{AsEnsureOriginWithArg, Everything, Nothing, ProcessMessage, ProcessMessageError}, + weights::{Weight, WeightMeter}, +}; + +use frame_system::EnsureRoot; +use sp_core::{ConstU32, H256}; +use sp_runtime::{traits::IdentityLookup, AccountId32}; + +use polkadot_parachain_primitives::primitives::Id as ParaId; +use polkadot_runtime_parachains::{ + configuration, + inclusion::{AggregateMessageOrigin, UmpQueueId}, + origin, shared, +}; +use xcm::latest::prelude::*; +use xcm_builder::{ + Account32Hash, AccountId32Aliases, AllowUnpaidExecutionFrom, AsPrefixedGeneralIndex, + ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, + ConvertedConcreteId, CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible, + FixedWeightBounds, IsConcrete, NoChecking, NonFungiblesAdapter, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, +}; +use xcm_executor::{traits::JustTry, Config, XcmExecutor}; + +pub type AccountId = AccountId32; +pub type Balance = u128; + +parameter_types! { + pub const BlockHashCount: u64 = 250; +} + +impl frame_system::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Block = Block; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type BlockWeights = (); + type BlockLength = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type DbWeight = (); + type BaseCallFilter = Everything; + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +parameter_types! { + pub ExistentialDeposit: Balance = 1; + pub const MaxLocks: u32 = 50; + pub const MaxReserves: u32 = 50; +} + +impl pallet_balances::Config for Runtime { + type MaxLocks = MaxLocks; + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type MaxReserves = MaxReserves; + type ReserveIdentifier = [u8; 8]; + type RuntimeHoldReason = RuntimeHoldReason; + type FreezeIdentifier = (); + type MaxHolds = ConstU32<0>; + type MaxFreezes = ConstU32<0>; +} + +impl pallet_uniques::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type CollectionId = u32; + type ItemId = u32; + type Currency = Balances; + type CreateOrigin = AsEnsureOriginWithArg>; + type ForceOrigin = frame_system::EnsureRoot; + type CollectionDeposit = frame_support::traits::ConstU128<1_000>; + type ItemDeposit = frame_support::traits::ConstU128<1_000>; + type MetadataDepositBase = frame_support::traits::ConstU128<1_000>; + type AttributeDepositBase = frame_support::traits::ConstU128<1_000>; + type DepositPerByte = frame_support::traits::ConstU128<1>; + type StringLimit = ConstU32<64>; + type KeyLimit = ConstU32<64>; + type ValueLimit = ConstU32<128>; + type Locker = (); + type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); +} + +impl shared::Config for Runtime {} + +impl configuration::Config for Runtime { + type WeightInfo = configuration::TestWeightInfo; +} + +parameter_types! { + pub const TokenLocation: MultiLocation = Here.into_location(); + pub RelayNetwork: NetworkId = ByGenesis([0; 32]); + pub const AnyNetwork: Option = None; + pub UniversalLocation: InteriorMultiLocation = Here; + pub UnitWeightCost: u64 = 1_000; +} + +pub type LocationToAccountId = ( + ChildParachainConvertsVia, + AccountId32Aliases, + Account32Hash<(), AccountId>, +); + +pub type LocalAssetTransactor = ( + XcmCurrencyAdapter, LocationToAccountId, AccountId, ()>, + NonFungiblesAdapter< + Uniques, + ConvertedConcreteId, JustTry>, + LocationToAccountId, + AccountId, + NoChecking, + (), + >, +); + +type LocalOriginConverter = ( + SovereignSignedViaLocation, + ChildParachainAsNative, + SignedAccountId32AsNative, + ChildSystemParachainAsSuperuser, +); + +parameter_types! { + pub const BaseXcmWeight: Weight = Weight::from_parts(1_000, 1_000); + pub TokensPerSecondPerByte: (AssetId, u128, u128) = + (Concrete(TokenLocation::get()), 1_000_000_000_000, 1024 * 1024); + pub const MaxInstructions: u32 = 100; + pub const MaxAssetsIntoHolding: u32 = 64; +} + +pub type XcmRouter = super::RelayChainXcmRouter; +pub type Barrier = AllowUnpaidExecutionFrom; + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = LocalAssetTransactor; + type OriginConverter = LocalOriginConverter; + type IsReserve = (); + type IsTeleporter = (); + type UniversalLocation = UniversalLocation; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = FixedRateOfFungible; + type ResponseHandler = (); + type AssetTrap = (); + type AssetLocker = XcmPallet; + type AssetExchanger = (); + type AssetClaims = (); + type SubscriptionService = (); + type PalletInstancesInfo = (); + type FeeManager = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type MessageExporter = (); + type UniversalAliases = Nothing; + type CallDispatcher = RuntimeCall; + type SafeCallFilter = Everything; + type Aliasers = Nothing; +} + +pub type LocalOriginToLocation = SignedToAccountId32; + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parachain(1).into()); +} + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + type XcmRouter = XcmRouter; + // Anyone can execute XCM messages locally... + type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; + type XcmExecuteFilter = Nothing; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = Everything; + type XcmReserveTransferFilter = Everything; + type Weigher = FixedWeightBounds; + type UniversalLocation = UniversalLocation; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = IsConcrete; + type TrustedLockers = (); + type SovereignAccountOf = LocationToAccountId; + type MaxLockers = ConstU32<8>; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type WeightInfo = pallet_xcm::TestWeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + type AdminOrigin = EnsureRoot; +} + +parameter_types! { + pub const FirstMessageFactorPercent: u64 = 100; +} + +impl origin::Config for Runtime {} + +type Block = frame_system::mocking::MockBlock; + +parameter_types! { + /// Amount of weight that can be spent per block to service messages. + pub MessageQueueServiceWeight: Weight = Weight::from_parts(1_000_000_000, 1_000_000); + pub const MessageQueueHeapSize: u32 = 65_536; + pub const MessageQueueMaxStale: u32 = 16; +} + +/// Message processor to handle any messages that were enqueued into the `MessageQueue` pallet. +pub struct MessageProcessor; +impl ProcessMessage for MessageProcessor { + type Origin = AggregateMessageOrigin; + + fn process_message( + message: &[u8], + origin: Self::Origin, + meter: &mut WeightMeter, + id: &mut [u8; 32], + ) -> Result { + let para = match origin { + AggregateMessageOrigin::Ump(UmpQueueId::Para(para)) => para, + }; + xcm_builder::ProcessXcmMessage::< + Junction, + xcm_executor::XcmExecutor, + RuntimeCall, + >::process_message(message, Junction::Parachain(para.into()), meter, id) + } +} + +impl pallet_message_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Size = u32; + type HeapSize = MessageQueueHeapSize; + type MaxStale = MessageQueueMaxStale; + type ServiceWeight = MessageQueueServiceWeight; + type MessageProcessor = MessageProcessor; + type QueueChangeHandler = (); + type QueuePausedQuery = (); + type WeightInfo = (); +} + +construct_runtime!( + pub enum Runtime + { + System: frame_system::{Pallet, Call, Storage, Config, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + ParasOrigin: origin::{Pallet, Origin}, + XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin}, + Uniques: pallet_uniques::{Pallet, Call, Storage, Event}, + MessageQueue: pallet_message_queue::{Pallet, Event}, + } +); diff --git a/primitives/orderbook/src/ingress.rs b/primitives/orderbook/src/ingress.rs index ababf8f81..cc163cc8b 100644 --- a/primitives/orderbook/src/ingress.rs +++ b/primitives/orderbook/src/ingress.rs @@ -21,6 +21,7 @@ use crate::lmp::LMPEpochConfig; use crate::{ocex::TradingPairConfig, AssetId}; use parity_scale_codec::{Decode, Encode}; +use primitive_types::H160; use rust_decimal::Decimal; use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; @@ -39,8 +40,8 @@ pub enum IngressMessages { UpdateTradingPair(TradingPairConfig), /// Register User ( main, proxy). RegisterUser(AccountId, AccountId), - /// Main Acc, Assetid, Amount. - Deposit(AccountId, AssetId, Decimal), + /// Unique ID, Main Acc, Assetid, Amount. + Deposit(H160, AccountId, AssetId, Decimal), /// Main Acc, Proxy Account. AddProxy(AccountId, AccountId), /// Main Acc, Proxy Account. diff --git a/primitives/orderbook/src/lib.rs b/primitives/orderbook/src/lib.rs index ee11f2e43..1a250f132 100644 --- a/primitives/orderbook/src/lib.rs +++ b/primitives/orderbook/src/lib.rs @@ -24,7 +24,6 @@ #![cfg_attr(not(feature = "std"), no_std)] use crate::ingress::EgressMessages; -use crate::lmp::LMPConfig; #[cfg(feature = "std")] use crate::recovery::ObCheckpoint; use crate::types::{AccountAsset, TradingPair}; @@ -36,7 +35,6 @@ use rust_decimal::prelude::ToPrimitive; use rust_decimal::Decimal; use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; -use sp_core::crypto::AccountId32; use sp_core::H256; use sp_std::{collections::btree_map::BTreeMap, vec::Vec}; @@ -170,13 +168,6 @@ pub struct ObCheckpointRaw { pub last_processed_block_number: BlockNumber, /// State change id pub state_change_id: u64, - /// LMPConfig - pub config: LMPConfig, - pub q_scores_uptime_map: BTreeMap<(u16, TradingPair, AccountId32), BTreeMap>, - pub maker_volume_map: BTreeMap<(u16, TradingPair, AccountId32), Decimal>, - pub taker_volume_map: BTreeMap<(u16, TradingPair, AccountId32), Decimal>, - pub fees_paid_map: BTreeMap<(u16, TradingPair, AccountId32), Decimal>, - pub total_maker_volume_map: BTreeMap<(u16, TradingPair), Decimal>, } impl ObCheckpointRaw { @@ -190,12 +181,6 @@ impl ObCheckpointRaw { balances: self.balances, last_processed_block_number: self.last_processed_block_number, state_change_id: self.state_change_id, - config: self.config, - q_scores_uptime_map: self.q_scores_uptime_map, - maker_volume_map: self.maker_volume_map, - taker_volume_map: self.taker_volume_map, - fees_paid_map: self.fees_paid_map, - total_maker_volume_map: self.total_maker_volume_map, } } } diff --git a/primitives/orderbook/src/lmp.rs b/primitives/orderbook/src/lmp.rs index 2853581e6..1f70737cf 100644 --- a/primitives/orderbook/src/lmp.rs +++ b/primitives/orderbook/src/lmp.rs @@ -90,7 +90,10 @@ pub struct LMPMarketConfig { // refer: https://en.wikipedia.org/wiki/Bid–ask_spread pub max_spread: Decimal, // Minimum depth an Order must have to be eligible for LMP - // In Quote asset. ( it is basically volume of that order ) + // In Base asset. ( it is basically (qty-filled_qty) of that order ) + // For example, if the order book shows that at a price of $10,000 (quote asset), + // there are 5 BTC (base asset) available to buy or sell, + // the order depth at that price level is 5 BTC. pub min_depth: Decimal, } diff --git a/primitives/orderbook/src/recovery.rs b/primitives/orderbook/src/recovery.rs index b8aa00041..2f151f22d 100644 --- a/primitives/orderbook/src/recovery.rs +++ b/primitives/orderbook/src/recovery.rs @@ -16,15 +16,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::lmp::LMPConfig; -use crate::types::TradingPair; use crate::{types::AccountAsset, ObCheckpointRaw}; use parity_scale_codec::{Decode, Encode}; use polkadex_primitives::{AccountId, AssetId, BlockNumber}; use rust_decimal::Decimal; use scale_info::TypeInfo; use serde_with::{json::JsonString, serde_as}; -use sp_core::crypto::AccountId32; use std::collections::BTreeMap; /// A struct representing the recovery state of an Order Book. @@ -59,18 +56,6 @@ pub struct ObCheckpoint { pub last_processed_block_number: BlockNumber, /// State change id pub state_change_id: u64, - /// LMP COnfig - pub config: LMPConfig, - #[serde_as(as = "JsonString>")] - pub q_scores_uptime_map: BTreeMap<(u16, TradingPair, AccountId32), BTreeMap>, - #[serde_as(as = "JsonString>")] - pub maker_volume_map: BTreeMap<(u16, TradingPair, AccountId32), Decimal>, - #[serde_as(as = "JsonString>")] - pub taker_volume_map: BTreeMap<(u16, TradingPair, AccountId32), Decimal>, - #[serde_as(as = "JsonString>")] - pub fees_paid_map: BTreeMap<(u16, TradingPair, AccountId32), Decimal>, - #[serde_as(as = "JsonString>")] - pub total_maker_volume_map: BTreeMap<(u16, TradingPair), Decimal>, } impl ObCheckpoint { @@ -81,12 +66,6 @@ impl ObCheckpoint { balances: self.balances.clone(), last_processed_block_number: self.last_processed_block_number, state_change_id: self.state_change_id, - config: self.config, - q_scores_uptime_map: self.q_scores_uptime_map.clone(), - maker_volume_map: self.maker_volume_map.clone(), - taker_volume_map: self.taker_volume_map.clone(), - fees_paid_map: self.fees_paid_map.clone(), - total_maker_volume_map: self.total_maker_volume_map.clone(), } } } diff --git a/primitives/orderbook/src/traits.rs b/primitives/orderbook/src/traits.rs index 2b3fe2f6e..de2afc891 100644 --- a/primitives/orderbook/src/traits.rs +++ b/primitives/orderbook/src/traits.rs @@ -18,6 +18,8 @@ use crate::types::TradingPair; use frame_support::dispatch::DispatchResult; +use polkadex_primitives::AssetId; +use primitive_types::H160; use rust_decimal::Decimal; pub trait LiquidityMiningCrowdSourcePallet { @@ -115,3 +117,15 @@ impl LiquidityMiningCrowdSourcePallet for () { pub trait VerifyExtensionSignature { fn verify_extension_signature(&self, payload: &str, account_id: &AccountId) -> bool; } + +pub trait OrderbookOperations { + /// Tries to deposit funds to orderbook + fn deposit(id: H160, main: AccountId, asset: AssetId, amount: u128) -> DispatchResult; +} + +// Stub for Orderbook trait +impl OrderbookOperations for () { + fn deposit(_id: H160, _main: AccountId, _asset: AssetId, _amount: u128) -> DispatchResult { + Ok(()) + } +} diff --git a/primitives/orderbook/src/types.rs b/primitives/orderbook/src/types.rs index 5be6d8557..8bb36f87f 100644 --- a/primitives/orderbook/src/types.rs +++ b/primitives/orderbook/src/types.rs @@ -31,6 +31,7 @@ use sp_core::H256; use sp_runtime::traits::Verify; use sp_std::cmp::Ordering; +use sp_core::H160; #[cfg(not(feature = "std"))] use sp_std::fmt::{Display, Formatter}; #[cfg(not(feature = "std"))] @@ -270,6 +271,8 @@ pub enum UserActions { /// Defines withdraw request DTO. #[derive(Clone, Debug, Decode, Encode, TypeInfo, PartialEq, Serialize, Deserialize)] pub struct WithdrawalRequest { + /// Withdrawal ID + pub id: H160, /// Signature. pub signature: Signature, /// Payload. @@ -283,11 +286,13 @@ pub struct WithdrawalRequest { impl WithdrawalRequest { pub fn convert(&self, stid: u64) -> Result, rust_decimal::Error> { Ok(Withdrawal { + id: self.id, main_account: self.main.clone(), amount: self.amount()?, asset: self.payload.asset_id, fees: Default::default(), stid, + destination: self.payload.destination_network.clone(), }) } } @@ -344,6 +349,7 @@ use core::{ }; use frame_support::{Deserialize, Serialize}; use parity_scale_codec::alloc::string::ToString; +use polkadex_primitives::withdrawal::WithdrawalDestination; use scale_info::prelude::string::String; use sp_runtime::MultiSignature; use sp_std::collections::btree_map::BTreeMap; @@ -357,6 +363,8 @@ pub struct WithdrawPayloadCallByUser { pub amount: String, /// Timestamp of the request. pub timestamp: i64, + /// Cross-chain destination ( this field is set for direct withdrawal ) + pub destination_network: Option, } /// Defines possible order sides variants. @@ -1025,6 +1033,7 @@ mod tests { }; use polkadex_primitives::{AccountId, AssetId}; use rust_decimal::Decimal; + use sp_core::H160; use sp_runtime::MultiSignature; use std::collections::BTreeMap; use std::str::FromStr; @@ -1035,7 +1044,12 @@ mod tests { let action = UserActions::BlockImport( 0, BTreeMap::from([( - IngressMessages::Deposit(alice.clone(), AssetId::Asset(u128::MAX), Decimal::MAX), + IngressMessages::Deposit( + H160::zero(), + alice.clone(), + AssetId::Asset(u128::MAX), + Decimal::MAX, + ), EgressMessages::PriceOracle(Default::default()), )]), BTreeMap::from([(((AssetId::Polkadex, AssetId::Asset(u128::MAX)), Decimal::MAX))]), @@ -1073,6 +1087,7 @@ mod tests { } #[test] + #[ignore] pub fn verify_withdrawal_request_signed_by_extension() { let withdraw_payload_str = "{\"asset_id\":{\"asset\":\"PDEX\"},\"amount\":\"1.11111111\",\"timestamp\":1714229288928}"; @@ -1083,6 +1098,7 @@ mod tests { let signature = serde_json::from_str::(signature_payload_str).unwrap(); const MAIN_ACCOUNT: &str = "5FYr5g1maSsAAw6w98xdAytZ6MEQ8sNPgp3PNLgy9o79kMug"; let request = WithdrawalRequest { + id: Default::default(), payload: payload.clone(), main: AccountId::from_str(MAIN_ACCOUNT).unwrap(), proxy: AccountId::from_str(MAIN_ACCOUNT).unwrap(), diff --git a/primitives/polkadex/src/assets.rs b/primitives/polkadex/src/assets.rs index e51084e31..c4be5e631 100644 --- a/primitives/polkadex/src/assets.rs +++ b/primitives/polkadex/src/assets.rs @@ -204,6 +204,15 @@ impl From for AssetId { } } +impl From for u128 { + fn from(value: AssetId) -> Self { + match value { + AssetId::Asset(id) => id, + AssetId::Polkadex => 0u128, + } + } +} + pub struct AssetIdConverter; impl MultiAssetIdConverter for AssetIdConverter { @@ -287,8 +296,11 @@ impl<'de> Visitor<'de> for AssetId { } } -pub fn generate_asset_id_for_parachain(asset: sp_std::boxed::Box) -> u128 { - u128::from_be_bytes(sp_io::hashing::blake2_128(&asset.encode()[..])) +pub fn generate_asset_id_for_parachain( + asset: sp_std::boxed::Box, +) -> crate::AssetId { + // TODO: @zktony handle PDEX multi asset + AssetId::Asset(u128::from_be_bytes(sp_io::hashing::blake2_128(&asset.encode()[..]))) } #[cfg(feature = "std")] diff --git a/primitives/polkadex/src/lib.rs b/primitives/polkadex/src/lib.rs index 1f2573ba8..abbe26bda 100644 --- a/primitives/polkadex/src/lib.rs +++ b/primitives/polkadex/src/lib.rs @@ -26,6 +26,7 @@ pub mod assets; pub mod auction; pub mod fees; pub mod rewards; +pub mod traits; pub mod withdrawal; pub use frame_support::storage::bounded_vec::BoundedVec; diff --git a/primitives/polkadex/src/traits.rs b/primitives/polkadex/src/traits.rs new file mode 100644 index 000000000..2f8547fbe --- /dev/null +++ b/primitives/polkadex/src/traits.rs @@ -0,0 +1,50 @@ +// This file is part of Polkadex. +// +// Copyright (c) 2023 Polkadex oü. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Common traits and its stub implementation. +use crate::AssetId; +use frame_support::dispatch::DispatchResult; +use primitive_types::H160; +use xcm::latest::MultiLocation; + +pub trait CrossChainWithdraw { + fn parachain_withdraw( + user: AccountId, + asset_id: AssetId, + amount: u128, + beneficiary: xcm::latest::MultiLocation, + fee_asset_id: Option, + fee_amount: Option, + id: H160, + ) -> DispatchResult; +} + +// Stub for CrossChainWithdraw +impl CrossChainWithdraw for () { + fn parachain_withdraw( + _user: AccountId, + _asset_id: AssetId, + _amount: u128, + _beneficiary: MultiLocation, + _fee_asset_id: Option, + _fee_amount: Option, + _id: H160, + ) -> DispatchResult { + Ok(()) + } +} diff --git a/primitives/polkadex/src/withdrawal.rs b/primitives/polkadex/src/withdrawal.rs index df73c44ea..880155684 100644 --- a/primitives/polkadex/src/withdrawal.rs +++ b/primitives/polkadex/src/withdrawal.rs @@ -22,15 +22,26 @@ use crate::assets::AssetId; use codec::{Decode, Encode, MaxEncodedLen}; use rust_decimal::Decimal; use scale_info::TypeInfo; +use sp_core::H160; -use crate::AccountId; +use crate::{AccountId, Balance}; use serde::{Deserialize, Serialize}; +use xcm::latest::MultiLocation; + +#[derive( + Encode, Decode, Clone, MaxEncodedLen, Debug, PartialEq, Eq, TypeInfo, Serialize, Deserialize, +)] +pub enum WithdrawalDestination { + Polkadot(MultiLocation, Option<(AssetId, Balance)>), +} /// Defines withdrawal structure. #[derive( Clone, Encode, Decode, MaxEncodedLen, TypeInfo, Debug, PartialEq, Serialize, Deserialize, )] pub struct Withdrawal { + /// Withdrawal ID + pub id: H160, /// Main account identifier. pub main_account: AccountId, /// Amount of withdrawal. @@ -41,6 +52,8 @@ pub struct Withdrawal { pub fees: Decimal, /// State change identifier. pub stid: u64, + /// Cross-chain withdrawal destination + pub destination: Option, } /// Defines payload item structure collected in `Withdrawals` structure. diff --git a/primitives/thea/src/extras.rs b/primitives/thea/src/extras.rs new file mode 100644 index 000000000..8eb01d489 --- /dev/null +++ b/primitives/thea/src/extras.rs @@ -0,0 +1,41 @@ +use frame_support::pallet_prelude::TypeInfo; +use parity_scale_codec::{Decode, Encode}; +use xcm::latest::MultiLocation; +use xcm::prelude::{AccountId32, PalletInstance, X1, X2}; +use xcm::v3::NetworkId; + +/// Extra data fields in Thea message, this can be extended +/// with new variants for future features +/// WARNING!: Don't change the order of variants +#[derive(Encode, Decode, Clone, TypeInfo, PartialEq, Debug)] +pub enum ExtraData { + None, + DirectDeposit, +} + +pub fn extract_data_from_multilocation( + multi_location: xcm::latest::MultiLocation, +) -> Option<([u8; 32], ExtraData)> { + match multi_location { + // Normal deposit + MultiLocation { parents: 0, interior: X1(AccountId32 { id, network }) } => { + if network == Some(NetworkId::Polkadot) || network.is_none() { + Some((id, ExtraData::None)) + } else { + None + } + }, + // Direct deposit + MultiLocation { + parents: 0, + interior: X2(AccountId32 { id, network }, PalletInstance(_index)), + } => { + if network == Some(NetworkId::Polkadot) || network.is_none() { + Some((id, ExtraData::DirectDeposit)) + } else { + None + } + }, + _ => None, + } +} diff --git a/primitives/thea/src/lib.rs b/primitives/thea/src/lib.rs index c2c5e3e3c..7538f4f41 100644 --- a/primitives/thea/src/lib.rs +++ b/primitives/thea/src/lib.rs @@ -23,6 +23,7 @@ #![cfg_attr(not(feature = "std"), no_std)] +pub mod extras; pub mod types; pub use crate::types::Message; diff --git a/primitives/thea/src/types.rs b/primitives/thea/src/types.rs index e1f7208c4..5defeb958 100644 --- a/primitives/thea/src/types.rs +++ b/primitives/thea/src/types.rs @@ -20,14 +20,16 @@ use frame_support::__private::log; use parity_scale_codec::{Decode, Encode}; -use polkadex_primitives::UNIT_BALANCE; +use polkadex_primitives::{AssetId, UNIT_BALANCE}; use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; +use sp_core::H160; use sp_runtime::Percent; #[cfg(not(feature = "std"))] use sp_std::vec::Vec; use sp_std::{cmp::Ordering, collections::btree_map::BTreeMap}; +use crate::extras::ExtraData; use crate::{Network, ValidatorSetId}; /// Defines the message structure. @@ -228,15 +230,15 @@ pub enum Destination { #[derive(Encode, Decode, Clone, TypeInfo, PartialEq, Debug)] pub struct Deposit { /// Identifier of the deposit. - pub id: Vec, // Unique identifier + pub id: H160, // Unique identifier /// Receiver of the deposit. pub recipient: AccountId, /// Asset identifier. - pub asset_id: u128, + pub asset_id: AssetId, /// Amount of the deposit. pub amount: u128, /// Extra data. - pub extra: Vec, + pub extra: ExtraData, } impl Deposit { @@ -255,58 +257,28 @@ impl Deposit { #[derive(Encode, Decode, Clone, TypeInfo, PartialEq, Debug)] pub struct Withdraw { /// Identifier of the withdrawal. - pub id: Vec, + pub id: H160, // Unique identifier /// Asset identifier. - pub asset_id: u128, - /// Amount of the withdrawal. - pub amount: u128, - /// Receiver of the withdrawal. - pub destination: Vec, - /// Defines if withdraw operation is blocked. - pub is_blocked: bool, - /// Extra data. - pub extra: Vec, -} - -impl From for Withdraw { - fn from(value: NewWithdraw) -> Self { - Self { - id: value.id, - asset_id: value.asset_id, - amount: value.amount, - destination: value.destination, - is_blocked: value.is_blocked, - extra: value.extra, - } - } -} - -#[derive(Encode, Decode, Clone, TypeInfo, PartialEq, Debug)] -pub struct NewWithdraw { - /// Identifier of the withdrawal. - pub id: Vec, - // Unique identifier - /// Asset identifier. - pub asset_id: u128, + pub asset_id: AssetId, /// Amount of the withdrawal. pub amount: u128, /// Receiver of the withdrawal. pub destination: Vec, /// Fee Asset Id - pub fee_asset_id: Option, + pub fee_asset_id: Option, /// Fee Amount pub fee_amount: Option, /// Defines if withdraw operation is blocked. pub is_blocked: bool, /// Extra data. - pub extra: Vec, + pub extra: ExtraData, } /// Metadata of asset's decimals #[derive(Encode, Decode, Clone, TypeInfo, PartialEq, Debug, Copy)] pub struct AssetMetadata { - decimal: u8, + pub decimal: u8, } impl AssetMetadata { diff --git a/runtimes/mainnet/src/lib.rs b/runtimes/mainnet/src/lib.rs index 2e707e21e..0b21ea717 100644 --- a/runtimes/mainnet/src/lib.rs +++ b/runtimes/mainnet/src/lib.rs @@ -122,7 +122,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to 0. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 351, + spec_version: 358, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 2, @@ -1300,6 +1300,7 @@ impl pallet_ocex_lmp::Config for Runtime { type CrowdSourceLiqudityMining = (); type OBWithdrawalLimit = OBWithdrawalLimit; type WeightInfo = pallet_ocex_lmp::weights::WeightInfo; + type CrossChainGadget = TheaExecutor; } //Install rewards Pallet @@ -1359,7 +1360,7 @@ impl thea_executor::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type Assets = Assets; - type AssetId = u128; + type AssetId = polkadex_primitives::AssetId; type AssetCreateUpdateOrigin = EnsureRootOrHalfCouncil; type Executor = Thea; type NativeAssetId = PolkadexAssetId; @@ -1372,6 +1373,7 @@ impl thea_executor::Config for Runtime { type AssetBalanceAdapter = u128; type GovernanceOrigin = EnsureRootOrHalfCouncil; type ExistentialDeposit = AutoSwapInitialNativeDeposit; + type Orderbook = OCEX; } #[cfg(feature = "runtime-benchmarks")] diff --git a/runtimes/parachain/src/lib.rs b/runtimes/parachain/src/lib.rs index 768814b30..c53ba6b00 100644 --- a/runtimes/parachain/src/lib.rs +++ b/runtimes/parachain/src/lib.rs @@ -179,7 +179,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("polkadex-parachain"), impl_name: create_runtime_str!("polkadex-parachain"), authoring_version: 1, - spec_version: 13, + spec_version: 14, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -480,7 +480,7 @@ impl xcm_helper::Config for Runtime { type RuntimeEvent = RuntimeEvent; type AccountIdConvert = LocationToAccountId; type Assets = Assets; - type AssetId = u128; + type AssetId = polkadex_primitives::AssetId; type Currency = Balances; type AssetCreateUpdateOrigin = EnsureRoot; type Executor = TheaMessageHandler; diff --git a/runtimes/parachain/src/xcm_config.rs b/runtimes/parachain/src/xcm_config.rs index 521965ba8..54ff3ed25 100644 --- a/runtimes/parachain/src/xcm_config.rs +++ b/runtimes/parachain/src/xcm_config.rs @@ -17,7 +17,7 @@ use super::{ AccountId, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, }; -use crate::{AllPalletsWithSystem, Balance, PolkadexAssetid, XcmHelper}; +use crate::{AllPalletsWithSystem, Balance, XcmHelper}; use core::marker::PhantomData; use frame_support::{ match_types, parameter_types, @@ -272,7 +272,7 @@ parameter_type_with_key! { impl orml_xtokens::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; - type CurrencyId = u128; + type CurrencyId = polkadex_primitives::AssetId; type CurrencyIdConvert = XcmHelper; type AccountIdToMultiLocation = AccountIdToMultiLocation; type SelfLocation = SelfLocation; @@ -330,9 +330,9 @@ where let _fee_in_native_token = T::weight_to_fee(&weight); let payment_asset = payment.fungible_assets_iter().next().ok_or(XcmError::Trap(1000))?; if let AssetId::Concrete(location) = payment_asset.id { - let foreign_currency_asset_id = - AC::convert_location_to_asset_id(location).ok_or(XcmError::Trap(1001))?; - let _path = [PolkadexAssetid::get(), foreign_currency_asset_id]; + // let foreign_currency_asset_id = + // AC::convert_location_to_asset_id(location).ok_or(XcmError::Trap(1001))?; + // let _path = [PolkadexAssetid::get(), foreign_currency_asset_id.into()]; //WILL BE RESTORED LATER // let (unused, expected_fee_in_foreign_currency) = // if WH::check_whitelisted_token(foreign_currency_asset_id) {