From c234652837c0b5eeaa8f8b807918e75a4cef1db1 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 13 Nov 2023 09:18:02 -0800 Subject: [PATCH 01/11] add generated tracing runtime 2601 --- tracing/2601/Cargo.lock | 13205 ++++++++++++++++ tracing/2601/Cargo.toml | 423 + tracing/2601/runtime/common/Cargo.toml | 134 + tracing/2601/runtime/common/src/apis.rs | 810 + .../common/src/impl_moonbeam_xcm_call.rs | 51 + .../src/impl_moonbeam_xcm_call_tracing.rs | 112 + .../src/impl_on_charge_evm_transaction.rs | 68 + .../common/src/impl_self_contained_call.rs | 78 + .../runtime/common/src/impl_xcm_evm_runner.rs | 188 + tracing/2601/runtime/common/src/lib.rs | 26 + tracing/2601/runtime/common/src/migrations.rs | 307 + .../src/weights/cumulus_pallet_xcmp_queue.rs | 72 + .../2601/runtime/common/src/weights/mod.rs | 47 + ...moonbeam_xcm_benchmarks_weights_generic.rs | 447 + .../src/weights/pallet_asset_manager.rs | 168 + .../common/src/weights/pallet_assets.rs | 512 + .../src/weights/pallet_author_inherent.rs | 70 + .../src/weights/pallet_author_mapping.rs | 126 + .../src/weights/pallet_author_slot_filter.rs | 59 + .../common/src/weights/pallet_balances.rs | 148 + .../common/src/weights/pallet_collective.rs | 308 + .../src/weights/pallet_conviction_voting.rs | 190 + .../src/weights/pallet_crowdloan_rewards.rs | 168 + .../common/src/weights/pallet_democracy.rs | 523 + .../runtime/common/src/weights/pallet_evm.rs | 79 + .../common/src/weights/pallet_identity.rs | 354 + .../src/weights/pallet_moonbeam_orbiters.rs | 212 + .../common/src/weights/pallet_multisig.rs | 166 + .../src/weights/pallet_parachain_staking.rs | 903 ++ .../common/src/weights/pallet_preimage.rs | 213 + .../common/src/weights/pallet_proxy.rs | 226 + .../common/src/weights/pallet_randomness.rs | 168 + .../common/src/weights/pallet_referenda.rs | 496 + .../common/src/weights/pallet_scheduler.rs | 205 + .../runtime/common/src/weights/pallet_sudo.rs | 82 + .../common/src/weights/pallet_timestamp.rs | 68 + .../common/src/weights/pallet_treasury.rs | 136 + .../common/src/weights/pallet_utility.rs | 109 + .../common/src/weights/pallet_whitelist.rs | 113 + .../runtime/common/src/weights/pallet_xcm.rs | 282 + .../src/weights/pallet_xcm_transactor.rs | 196 + tracing/2601/runtime/moonbase/Cargo.toml | 364 + tracing/2601/runtime/moonbase/build.rs | 25 + .../2601/runtime/moonbase/src/asset_config.rs | 343 + .../moonbase/src/governance/councils.rs | 98 + .../moonbase/src/governance/democracy.rs | 76 + .../runtime/moonbase/src/governance/mod.rs | 30 + .../moonbase/src/governance/origins.rs | 80 + .../moonbase/src/governance/referenda.rs | 98 + .../runtime/moonbase/src/governance/tracks.rs | 179 + tracing/2601/runtime/moonbase/src/lib.rs | 1807 +++ .../2601/runtime/moonbase/src/precompiles.rs | 271 + .../2601/runtime/moonbase/src/xcm_config.rs | 702 + .../2601/runtime/moonbase/tests/common/mod.rs | 384 + .../runtime/moonbase/tests/evm_tracing.rs | 94 + .../moonbase/tests/integration_test.rs | 3086 ++++ .../runtime/moonbase/tests/runtime_apis.rs | 397 + .../runtime/moonbase/tests/xcm_mock/mod.rs | 274 + .../moonbase/tests/xcm_mock/parachain.rs | 1229 ++ .../moonbase/tests/xcm_mock/relay_chain.rs | 406 + .../moonbase/tests/xcm_mock/statemint_like.rs | 552 + .../2601/runtime/moonbase/tests/xcm_tests.rs | 4054 +++++ tracing/2601/runtime/moonbeam/Cargo.toml | 351 + tracing/2601/runtime/moonbeam/build.rs | 25 + .../2601/runtime/moonbeam/src/asset_config.rs | 342 + .../moonbeam/src/governance/councils.rs | 97 + .../moonbeam/src/governance/democracy.rs | 77 + .../runtime/moonbeam/src/governance/mod.rs | 30 + .../moonbeam/src/governance/origins.rs | 82 + .../moonbeam/src/governance/referenda.rs | 98 + .../runtime/moonbeam/src/governance/tracks.rs | 179 + tracing/2601/runtime/moonbeam/src/lib.rs | 1808 +++ .../2601/runtime/moonbeam/src/precompiles.rs | 268 + .../2601/runtime/moonbeam/src/xcm_config.rs | 691 + .../2601/runtime/moonbeam/tests/common/mod.rs | 387 + .../runtime/moonbeam/tests/evm_tracing.rs | 94 + .../moonbeam/tests/integration_test.rs | 2823 ++++ .../runtime/moonbeam/tests/runtime_apis.rs | 393 + .../runtime/moonbeam/tests/xcm_mock/mod.rs | 272 + .../moonbeam/tests/xcm_mock/parachain.rs | 1210 ++ .../moonbeam/tests/xcm_mock/relay_chain.rs | 406 + .../moonbeam/tests/xcm_mock/statemint_like.rs | 551 + .../2601/runtime/moonbeam/tests/xcm_tests.rs | 3786 +++++ tracing/2601/runtime/moonriver/Cargo.toml | 355 + tracing/2601/runtime/moonriver/build.rs | 25 + .../runtime/moonriver/src/asset_config.rs | 343 + .../moonriver/src/governance/councils.rs | 97 + .../moonriver/src/governance/democracy.rs | 77 + .../runtime/moonriver/src/governance/mod.rs | 30 + .../moonriver/src/governance/origins.rs | 82 + .../moonriver/src/governance/referenda.rs | 98 + .../moonriver/src/governance/tracks.rs | 179 + tracing/2601/runtime/moonriver/src/lib.rs | 1830 +++ .../2601/runtime/moonriver/src/precompiles.rs | 267 + .../2601/runtime/moonriver/src/xcm_config.rs | 704 + .../runtime/moonriver/tests/common/mod.rs | 394 + .../runtime/moonriver/tests/evm_tracing.rs | 94 + .../moonriver/tests/integration_test.rs | 2726 ++++ .../runtime/moonriver/tests/runtime_apis.rs | 396 + .../runtime/moonriver/tests/xcm_mock/mod.rs | 275 + .../moonriver/tests/xcm_mock/parachain.rs | 1220 ++ .../moonriver/tests/xcm_mock/relay_chain.rs | 406 + .../tests/xcm_mock/statemine_like.rs | 552 + .../2601/runtime/moonriver/tests/xcm_tests.rs | 4092 +++++ tracing/2601/rust-toolchain | 5 + 105 files changed, 65014 insertions(+) create mode 100644 tracing/2601/Cargo.lock create mode 100644 tracing/2601/Cargo.toml create mode 100644 tracing/2601/runtime/common/Cargo.toml create mode 100644 tracing/2601/runtime/common/src/apis.rs create mode 100644 tracing/2601/runtime/common/src/impl_moonbeam_xcm_call.rs create mode 100644 tracing/2601/runtime/common/src/impl_moonbeam_xcm_call_tracing.rs create mode 100644 tracing/2601/runtime/common/src/impl_on_charge_evm_transaction.rs create mode 100644 tracing/2601/runtime/common/src/impl_self_contained_call.rs create mode 100644 tracing/2601/runtime/common/src/impl_xcm_evm_runner.rs create mode 100644 tracing/2601/runtime/common/src/lib.rs create mode 100644 tracing/2601/runtime/common/src/migrations.rs create mode 100644 tracing/2601/runtime/common/src/weights/cumulus_pallet_xcmp_queue.rs create mode 100644 tracing/2601/runtime/common/src/weights/mod.rs create mode 100644 tracing/2601/runtime/common/src/weights/moonbeam_xcm_benchmarks_weights_generic.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_asset_manager.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_assets.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_author_inherent.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_author_mapping.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_author_slot_filter.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_balances.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_collective.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_conviction_voting.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_crowdloan_rewards.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_democracy.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_evm.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_identity.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_moonbeam_orbiters.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_multisig.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_parachain_staking.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_preimage.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_proxy.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_randomness.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_referenda.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_scheduler.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_sudo.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_timestamp.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_treasury.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_utility.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_whitelist.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_xcm.rs create mode 100644 tracing/2601/runtime/common/src/weights/pallet_xcm_transactor.rs create mode 100644 tracing/2601/runtime/moonbase/Cargo.toml create mode 100644 tracing/2601/runtime/moonbase/build.rs create mode 100644 tracing/2601/runtime/moonbase/src/asset_config.rs create mode 100644 tracing/2601/runtime/moonbase/src/governance/councils.rs create mode 100644 tracing/2601/runtime/moonbase/src/governance/democracy.rs create mode 100644 tracing/2601/runtime/moonbase/src/governance/mod.rs create mode 100644 tracing/2601/runtime/moonbase/src/governance/origins.rs create mode 100644 tracing/2601/runtime/moonbase/src/governance/referenda.rs create mode 100644 tracing/2601/runtime/moonbase/src/governance/tracks.rs create mode 100644 tracing/2601/runtime/moonbase/src/lib.rs create mode 100644 tracing/2601/runtime/moonbase/src/precompiles.rs create mode 100644 tracing/2601/runtime/moonbase/src/xcm_config.rs create mode 100644 tracing/2601/runtime/moonbase/tests/common/mod.rs create mode 100644 tracing/2601/runtime/moonbase/tests/evm_tracing.rs create mode 100644 tracing/2601/runtime/moonbase/tests/integration_test.rs create mode 100644 tracing/2601/runtime/moonbase/tests/runtime_apis.rs create mode 100644 tracing/2601/runtime/moonbase/tests/xcm_mock/mod.rs create mode 100644 tracing/2601/runtime/moonbase/tests/xcm_mock/parachain.rs create mode 100644 tracing/2601/runtime/moonbase/tests/xcm_mock/relay_chain.rs create mode 100644 tracing/2601/runtime/moonbase/tests/xcm_mock/statemint_like.rs create mode 100644 tracing/2601/runtime/moonbase/tests/xcm_tests.rs create mode 100644 tracing/2601/runtime/moonbeam/Cargo.toml create mode 100644 tracing/2601/runtime/moonbeam/build.rs create mode 100644 tracing/2601/runtime/moonbeam/src/asset_config.rs create mode 100644 tracing/2601/runtime/moonbeam/src/governance/councils.rs create mode 100644 tracing/2601/runtime/moonbeam/src/governance/democracy.rs create mode 100644 tracing/2601/runtime/moonbeam/src/governance/mod.rs create mode 100644 tracing/2601/runtime/moonbeam/src/governance/origins.rs create mode 100644 tracing/2601/runtime/moonbeam/src/governance/referenda.rs create mode 100644 tracing/2601/runtime/moonbeam/src/governance/tracks.rs create mode 100644 tracing/2601/runtime/moonbeam/src/lib.rs create mode 100644 tracing/2601/runtime/moonbeam/src/precompiles.rs create mode 100644 tracing/2601/runtime/moonbeam/src/xcm_config.rs create mode 100644 tracing/2601/runtime/moonbeam/tests/common/mod.rs create mode 100644 tracing/2601/runtime/moonbeam/tests/evm_tracing.rs create mode 100644 tracing/2601/runtime/moonbeam/tests/integration_test.rs create mode 100644 tracing/2601/runtime/moonbeam/tests/runtime_apis.rs create mode 100644 tracing/2601/runtime/moonbeam/tests/xcm_mock/mod.rs create mode 100644 tracing/2601/runtime/moonbeam/tests/xcm_mock/parachain.rs create mode 100644 tracing/2601/runtime/moonbeam/tests/xcm_mock/relay_chain.rs create mode 100644 tracing/2601/runtime/moonbeam/tests/xcm_mock/statemint_like.rs create mode 100644 tracing/2601/runtime/moonbeam/tests/xcm_tests.rs create mode 100644 tracing/2601/runtime/moonriver/Cargo.toml create mode 100644 tracing/2601/runtime/moonriver/build.rs create mode 100644 tracing/2601/runtime/moonriver/src/asset_config.rs create mode 100644 tracing/2601/runtime/moonriver/src/governance/councils.rs create mode 100644 tracing/2601/runtime/moonriver/src/governance/democracy.rs create mode 100644 tracing/2601/runtime/moonriver/src/governance/mod.rs create mode 100644 tracing/2601/runtime/moonriver/src/governance/origins.rs create mode 100644 tracing/2601/runtime/moonriver/src/governance/referenda.rs create mode 100644 tracing/2601/runtime/moonriver/src/governance/tracks.rs create mode 100644 tracing/2601/runtime/moonriver/src/lib.rs create mode 100644 tracing/2601/runtime/moonriver/src/precompiles.rs create mode 100644 tracing/2601/runtime/moonriver/src/xcm_config.rs create mode 100644 tracing/2601/runtime/moonriver/tests/common/mod.rs create mode 100644 tracing/2601/runtime/moonriver/tests/evm_tracing.rs create mode 100644 tracing/2601/runtime/moonriver/tests/integration_test.rs create mode 100644 tracing/2601/runtime/moonriver/tests/runtime_apis.rs create mode 100644 tracing/2601/runtime/moonriver/tests/xcm_mock/mod.rs create mode 100644 tracing/2601/runtime/moonriver/tests/xcm_mock/parachain.rs create mode 100644 tracing/2601/runtime/moonriver/tests/xcm_mock/relay_chain.rs create mode 100644 tracing/2601/runtime/moonriver/tests/xcm_mock/statemine_like.rs create mode 100644 tracing/2601/runtime/moonriver/tests/xcm_tests.rs create mode 100644 tracing/2601/rust-toolchain diff --git a/tracing/2601/Cargo.lock b/tracing/2601/Cargo.lock new file mode 100644 index 00000000..26053dee --- /dev/null +++ b/tracing/2601/Cargo.lock @@ -0,0 +1,13205 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "account" +version = "0.1.1" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "blake2-rfc", + "impl-serde 0.3.2", + "libsecp256k1", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sha3", + "sp-core", + "sp-io", + "sp-runtime", + "sp-runtime-interface", + "sp-std", +] + +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli 0.27.3", +] + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli 0.28.0", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aead" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", +] + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array 0.14.7", +] + +[[package]] +name = "aes" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" +dependencies = [ + "aes-soft", + "aesni", + "cipher 0.2.5", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher 0.3.0", + "cpufeatures", + "opaque-debug 0.3.0", +] + +[[package]] +name = "aes" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +dependencies = [ + "cfg-if", + "cipher 0.4.4", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" +dependencies = [ + "aead 0.4.3", + "aes 0.7.5", + "cipher 0.3.0", + "ctr 0.8.0", + "ghash 0.4.4", + "subtle", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead 0.5.2", + "aes 0.8.3", + "cipher 0.4.4", + "ctr 0.9.2", + "ghash 0.5.0", + "subtle", +] + +[[package]] +name = "aes-soft" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" +dependencies = [ + "cipher 0.2.5", + "opaque-debug 0.3.0", +] + +[[package]] +name = "aesni" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" +dependencies = [ + "cipher 0.2.5", + "opaque-debug 0.3.0", +] + +[[package]] +name = "affix" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e7ea84d3fa2009f355f8429a0b418a96849135a4188fadf384f59127d5d4bc" +dependencies = [ + "convert_case 0.5.0", +] + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.10", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "getrandom 0.2.10", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anstream" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "aquamarine" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df752953c49ce90719c7bf1fc587bc8227aed04732ea0c0f85e5397d7fdbd1a1" +dependencies = [ + "include_dir", + "itertools", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "arc-swap" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" + +[[package]] +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ed-on-bls12-381-bandersnatch" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9cde0f2aa063a2a5c28d39b47761aa102bda7c13c84fc118a61b87c7b2f785c" +dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-scale" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b08346a3e38e2be792ef53ee168623c9244d968ff00cd70fb9932f6fe36393" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", + "parity-scale-codec", +] + +[[package]] +name = "ark-scale" +version = "0.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bd73bb6ddb72630987d37fa963e99196896c0d0ea81b7c894567e74a2f83af" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "ark-secret-scalar" +version = "0.0.2" +source = "git+https://github.com/w3f/ring-vrf?rev=3119f51#3119f51b54b69308abfb0671f6176cb125ae1bf1" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", + "ark-transcript", + "digest 0.10.7", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "ark-transcript" +version = "0.0.2" +source = "git+https://github.com/w3f/ring-vrf?rev=3119f51#3119f51b54b69308abfb0671f6176cb125ae1bf1" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "digest 0.10.7", + "rand_core 0.6.4", + "sha3", +] + +[[package]] +name = "array-bytes" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b1c5a481ec30a5abd8dfbd94ab5cf1bb4e9a66be7f1b3b322f2f1170c200fd" + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "asn1-rs" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ff05a702273012438132f449575dbc804e27b2f3cbe3069aa237d26c98fa33" +dependencies = [ + "asn1-rs-derive 0.1.0", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "asn1-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" +dependencies = [ + "asn1-rs-derive 0.4.0", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8b7511298d5b7784b40b092d9e9dcd3a627a5707e4b5e507931ab0d44eeebf" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite", + "log", + "parking", + "polling", + "rustix 0.37.25", + "slab", + "socket2 0.4.9", + "waker-fn", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-trait" +version = "0.1.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "asynchronous-codec" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4057f2c32adbb2fc158e22fb38433c8e9bbf76b75a4732c7c0cbaf695fb65568" +dependencies = [ + "bytes", + "futures-sink", + "futures-util", + "memchr", + "pin-project-lite 0.2.13", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "auto_impl" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line 0.21.0", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object 0.32.1", + "rustc-demangle", +] + +[[package]] +name = "bandersnatch_vrfs" +version = "0.0.1" +source = "git+https://github.com/w3f/ring-vrf?rev=3119f51#3119f51b54b69308abfb0671f6176cb125ae1bf1" +dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ed-on-bls12-381-bandersnatch", + "ark-ff", + "ark-scale 0.0.11", + "ark-serialize", + "ark-std", + "dleq_vrf", + "fflonk", + "merlin 3.0.0", + "rand_chacha 0.3.1", + "rand_core 0.6.4", + "ring 0.1.0", + "sha2 0.10.8", + "zeroize", +] + +[[package]] +name = "base-x" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" + +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +dependencies = [ + "serde", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bindgen" +version = "0.65.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "prettyplease 0.2.15", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.38", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +dependencies = [ + "arrayvec 0.4.12", + "constant_time_eq 0.1.5", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "constant_time_eq 0.3.0", +] + +[[package]] +name = "blake2s_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94230421e395b9920d23df13ea5d77a20e1725331f90fbbf6df6040b33f756ae" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "constant_time_eq 0.3.0", +] + +[[package]] +name = "blake3" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "cc", + "cfg-if", + "constant_time_eq 0.3.0", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding 0.1.5", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "block-modes" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0" +dependencies = [ + "block-padding 0.2.1", + "cipher 0.2.5", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + +[[package]] +name = "bounded-collections" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca548b6163b872067dc5eb82fd130c56881435e30367d2073594a3d9744120dd" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "bounded-vec" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68534a48cbf63a4b1323c433cf21238c9ec23711e0df13b08c33e5c2082663ce" +dependencies = [ + "thiserror", +] + +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + +[[package]] +name = "bs58" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "bstr" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "build-helper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdce191bf3fa4995ce948c8c83b4640a1745457a149e73c6db75b4ffe36aad5f" +dependencies = [ + "semver 0.6.0", +] + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "bytemuck" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "camino" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.20", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "case" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6c0e7b807d60291f42f33f58480c0bfafe28ed08286446f45e463728cf9c1c" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "jobserver", + "libc", +] + +[[package]] +name = "ccm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aca1a8fbc20b50ac9673ff014abfb2b5f4085ee1a850d408f14a159c5853ac7" +dependencies = [ + "aead 0.3.2", + "cipher 0.2.5", + "subtle", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-expr" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03915af431787e6ffdcc74c645077518c6b6e01f80b761e0fbbfa288536311b3" +dependencies = [ + "smallvec", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "chacha20" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" +dependencies = [ + "cfg-if", + "cipher 0.3.0", + "cpufeatures", + "zeroize", +] + +[[package]] +name = "chacha20poly1305" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5" +dependencies = [ + "aead 0.4.3", + "chacha20", + "cipher 0.3.0", + "poly1305", + "zeroize", +] + +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.48.5", +] + +[[package]] +name = "cid" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9b68e3193982cd54187d71afdb2a271ad4cf8af157858e9cb911b91321de143" +dependencies = [ + "core2", + "multibase", + "multihash", + "serde", + "unsigned-varint", +] + +[[package]] +name = "cipher" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "clang-sys" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "clap_lex" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" + +[[package]] +name = "coarsetime" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a73ef0d00d14301df35d0f13f5ea32344de6b00837485c358458f1e7f2d27db4" +dependencies = [ + "libc", + "once_cell", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "common" +version = "0.1.0" +source = "git+https://github.com/w3f/ring-proof?rev=0e948f3#0e948f3c28cbacecdd3020403c4841c0eb339213" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "fflonk", + "merlin 3.0.0", +] + +[[package]] +name = "common-path" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" + +[[package]] +name = "concurrent-queue" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-oid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" + +[[package]] +name = "const-random" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368a7a772ead6ce7e1de82bfb04c485f3db8ec744f72925af5735e29a22cc18e" +dependencies = [ + "const-random-macro", + "proc-macro-hack", +] + +[[package]] +name = "const-random-macro" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d7d6ab3c3a2282db210df5f02c4dab6e0a7057af0fb7ebd4070f30fe05c0ddb" +dependencies = [ + "getrandom 0.2.10", + "once_cell", + "proc-macro-hack", + "tiny-keccak", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "convert_case" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb4a24b1aaf0fd0ce8b45161144d6f42cd91677fd5940fd431183eb023b3a2b8" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + +[[package]] +name = "cpp_demangle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "cranelift-bforest" +version = "0.95.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1277fbfa94bc82c8ec4af2ded3e639d49ca5f7f3c7eeab2c66accd135ece4e70" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-codegen" +version = "0.95.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6e8c31ad3b2270e9aeec38723888fe1b0ace3bea2b06b3f749ccf46661d3220" +dependencies = [ + "bumpalo", + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-entity", + "cranelift-isle", + "gimli 0.27.3", + "hashbrown 0.13.2", + "log", + "regalloc2", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.95.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ac5ac30d62b2d66f12651f6b606dbdfd9c2cfd0908de6b387560a277c5c9da" +dependencies = [ + "cranelift-codegen-shared", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.95.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd82b8b376247834b59ed9bdc0ddeb50f517452827d4a11bccf5937b213748b8" + +[[package]] +name = "cranelift-entity" +version = "0.95.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40099d38061b37e505e63f89bab52199037a72b931ad4868d9089ff7268660b0" +dependencies = [ + "serde", +] + +[[package]] +name = "cranelift-frontend" +version = "0.95.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a25d9d0a0ae3079c463c34115ec59507b4707175454f0eee0891e83e30e82d" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.95.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80de6a7d0486e4acbd5f9f87ec49912bf4c8fb6aea00087b989685460d4469ba" + +[[package]] +name = "cranelift-native" +version = "0.95.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6b03e0e03801c4b3fd8ce0758a94750c07a44e7944cc0ffbf0d3f2e7c79b00" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "cranelift-wasm" +version = "0.95.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff3220489a3d928ad91e59dd7aeaa8b3de18afb554a6211213673a71c90737ac" +dependencies = [ + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "itertools", + "log", + "smallvec", + "wasmparser", + "wasmtime-types", +] + +[[package]] +name = "crc" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset 0.9.0", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "typenum 1.17.0", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher 0.3.0", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher 0.4.4", +] + +[[package]] +name = "cumulus-pallet-dmp-queue" +version = "0.1.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", +] + +[[package]] +name = "cumulus-pallet-parachain-system" +version = "0.1.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "bytes", + "cumulus-pallet-parachain-system-proc-macro", + "cumulus-primitives-core", + "cumulus-primitives-parachain-inherent", + "environmental", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "polkadot-parachain-primitives", + "scale-info", + "sp-core", + "sp-externalities", + "sp-inherents", + "sp-io", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-trie", + "sp-version", + "staging-xcm", + "trie-db", +] + +[[package]] +name = "cumulus-pallet-parachain-system-proc-macro" +version = "0.1.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "cumulus-pallet-xcm" +version = "0.1.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", +] + +[[package]] +name = "cumulus-pallet-xcmp-queue" +version = "0.1.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "cumulus-primitives-core", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "polkadot-runtime-common", + "rand_chacha 0.3.1", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-executor", +] + +[[package]] +name = "cumulus-primitives-core" +version = "0.1.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "polkadot-primitives", + "scale-info", + "sp-api", + "sp-runtime", + "sp-std", + "sp-trie", + "staging-xcm", +] + +[[package]] +name = "cumulus-primitives-parachain-inherent" +version = "0.1.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "cumulus-primitives-core", + "cumulus-relay-chain-interface", + "cumulus-test-relay-sproof-builder", + "parity-scale-codec", + "sc-client-api", + "scale-info", + "sp-api", + "sp-core", + "sp-inherents", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-storage", + "sp-trie", + "tracing", +] + +[[package]] +name = "cumulus-primitives-timestamp" +version = "0.1.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "cumulus-primitives-core", + "futures", + "parity-scale-codec", + "sp-inherents", + "sp-std", + "sp-timestamp", +] + +[[package]] +name = "cumulus-primitives-utility" +version = "0.1.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "log", + "parity-scale-codec", + "polkadot-runtime-common", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", +] + +[[package]] +name = "cumulus-relay-chain-interface" +version = "0.1.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "cumulus-primitives-core", + "futures", + "jsonrpsee-core", + "parity-scale-codec", + "polkadot-overseer", + "sc-client-api", + "sp-api", + "sp-blockchain", + "sp-state-machine", + "thiserror", +] + +[[package]] +name = "cumulus-test-relay-sproof-builder" +version = "0.1.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "cumulus-primitives-core", + "parity-scale-codec", + "polkadot-primitives", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-trie", +] + +[[package]] +name = "curve25519-dalek" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b85542f99a2dfa2a1b8e192662741c9859a846b296bef1c92ef9b58b5a216" +dependencies = [ + "byteorder", + "digest 0.8.1", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "cxx" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c390c123d671cc547244943ecad81bdaab756c6ea332d9ca9c1f48d952a24895" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00d3d3ac9ffb900304edf51ca719187c779f4001bb544f26c4511d621de905cf" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn 2.0.38", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94415827ecfea0f0c74c8cad7d1a86ddb3f05354d6a6ddeda0adee5e875d2939" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33dbbe9f5621c9247f97ec14213b04f350bff4b6cebefe834c60055db266ecf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + +[[package]] +name = "data-encoding-macro" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c904b33cc60130e1aeea4956ab803d08a3f4a0ca82d64ed757afac3891f2bb99" +dependencies = [ + "data-encoding", + "data-encoding-macro-internal", +] + +[[package]] +name = "data-encoding-macro-internal" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fdf3fce3ce863539ec1d7fd1b6dcc3c645663376b43ed376bbf887733e4f772" +dependencies = [ + "data-encoding", + "syn 1.0.109", +] + +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "der-parser" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe398ac75057914d7d07307bf67dc7f3f574a26783b4fc7805a20ffa9f506e82" +dependencies = [ + "asn1-rs 0.3.1", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "der-parser" +version = "8.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" +dependencies = [ + "asn1-rs 0.5.2", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "deranged" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive-syn-parse" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79116f119dd1dba1abf1f3405f03b9b0e79a27a3883864bfebded8a3dc768cd" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07adf7be193b71cc36b193d0f5fe60b918a3a9db4dad0449f57bcfd519704a3" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_macro" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68" +dependencies = [ + "derive_builder_core", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case 0.4.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "directories" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "directories-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "dleq_vrf" +version = "0.0.2" +source = "git+https://github.com/w3f/ring-vrf?rev=3119f51#3119f51b54b69308abfb0671f6176cb125ae1bf1" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-scale 0.0.10", + "ark-secret-scalar", + "ark-serialize", + "ark-std", + "ark-transcript", + "arrayvec 0.7.4", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "docify" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee528c501ddd15d5181997e9518e59024844eac44fd1e40cb20ddb2a8562fa" +dependencies = [ + "docify_macros", +] + +[[package]] +name = "docify_macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca01728ab2679c464242eca99f94e2ce0514b52ac9ad950e2ed03fca991231c" +dependencies = [ + "common-path", + "derive-syn-parse", + "once_cell", + "proc-macro2", + "quote", + "regex", + "syn 2.0.38", + "termcolor", + "toml 0.7.8", + "walkdir", +] + +[[package]] +name = "downcast" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dyn-clonable" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +dependencies = [ + "dyn-clonable-impl", + "dyn-clone", +] + +[[package]] +name = "dyn-clonable-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dyn-clone" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" + +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der 0.6.1", + "elliptic-curve 0.12.3", + "rfc6979 0.3.1", + "signature 1.6.4", +] + +[[package]] +name = "ecdsa" +version = "0.16.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" +dependencies = [ + "der 0.7.8", + "digest 0.10.7", + "elliptic-curve 0.13.6", + "rfc6979 0.4.0", + "signature 2.1.0", + "spki 0.7.2", +] + +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "signature 1.6.4", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8 0.10.2", + "signature 2.1.0", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek 3.2.0", + "ed25519 1.5.3", + "rand 0.7.3", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "ed25519-dalek" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" +dependencies = [ + "curve25519-dalek 4.1.1", + "ed25519 2.2.3", + "rand_core 0.6.4", + "serde", + "sha2 0.10.8", + "zeroize", +] + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek 3.2.0", + "hashbrown 0.12.3", + "hex", + "rand_core 0.6.4", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct 0.1.1", + "crypto-bigint 0.4.9", + "der 0.6.1", + "digest 0.10.7", + "ff 0.12.1", + "generic-array 0.14.7", + "group 0.12.1", + "hkdf", + "pem-rfc7468", + "pkcs8 0.9.0", + "rand_core 0.6.4", + "sec1 0.3.0", + "subtle", + "zeroize", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d97ca172ae9dc9f9b779a6e3a65d308f2af74e5b8c921299075bdb4a0370e914" +dependencies = [ + "base16ct 0.2.0", + "crypto-bigint 0.5.3", + "digest 0.10.7", + "ff 0.13.0", + "generic-array 0.14.7", + "group 0.13.0", + "pkcs8 0.10.2", + "rand_core 0.6.4", + "sec1 0.7.3", + "subtle", + "zeroize", +] + +[[package]] +name = "enum-as-inner" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "enumflags2" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5998b4f30320c9d93aed72f63af821bfdac50465b75428fce77b48ec482c3939" +dependencies = [ + "enumflags2_derive", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "enumn" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "environmental" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde 0.4.0", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethereum" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a89fb87a9e103f71b903b80b670200b54cc67a07578f070681f1fffb7396fb7" +dependencies = [ + "bytes", + "ethereum-types", + "hash-db 0.15.2", + "hash256-std-hasher", + "parity-scale-codec", + "rlp", + "scale-info", + "serde", + "sha3", + "triehash", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde 0.4.0", + "primitive-types", + "scale-info", + "uint", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "evm" +version = "0.39.1" +source = "git+https://github.com/moonbeam-foundation/evm?rev=a33ac87ad7462b7e7029d12c385492b2a8311d1c#a33ac87ad7462b7e7029d12c385492b2a8311d1c" +dependencies = [ + "auto_impl", + "environmental", + "ethereum", + "evm-core", + "evm-gasometer", + "evm-runtime", + "log", + "parity-scale-codec", + "primitive-types", + "rlp", + "scale-info", + "serde", + "sha3", +] + +[[package]] +name = "evm-core" +version = "0.39.0" +source = "git+https://github.com/moonbeam-foundation/evm?rev=a33ac87ad7462b7e7029d12c385492b2a8311d1c#a33ac87ad7462b7e7029d12c385492b2a8311d1c" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-info", + "serde", +] + +[[package]] +name = "evm-gasometer" +version = "0.39.0" +source = "git+https://github.com/moonbeam-foundation/evm?rev=a33ac87ad7462b7e7029d12c385492b2a8311d1c#a33ac87ad7462b7e7029d12c385492b2a8311d1c" +dependencies = [ + "environmental", + "evm-core", + "evm-runtime", + "primitive-types", +] + +[[package]] +name = "evm-runtime" +version = "0.39.0" +source = "git+https://github.com/moonbeam-foundation/evm?rev=a33ac87ad7462b7e7029d12c385492b2a8311d1c#a33ac87ad7462b7e7029d12c385492b2a8311d1c" +dependencies = [ + "auto_impl", + "environmental", + "evm-core", + "primitive-types", + "sha3", +] + +[[package]] +name = "evm-tracing-events" +version = "0.1.0" +dependencies = [ + "environmental", + "ethereum", + "ethereum-types", + "evm", + "evm-gasometer", + "evm-runtime", + "parity-scale-codec", + "sp-runtime-interface", +] + +[[package]] +name = "exit-future" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" +dependencies = [ + "futures", +] + +[[package]] +name = "expander" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a718c0675c555c5f976fff4ea9e2c150fa06cefa201cadef87cfbf9324075881" +dependencies = [ + "blake3", + "fs-err", + "proc-macro2", + "quote", +] + +[[package]] +name = "expander" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3774182a5df13c3d1690311ad32fbe913feef26baba609fa2dd5f72042bd2ab6" +dependencies = [ + "blake2", + "fs-err", + "proc-macro2", + "quote", +] + +[[package]] +name = "expander" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f86a749cf851891866c10515ef6c299b5c69661465e9c3bbe7e07a2b77fb0f7" +dependencies = [ + "blake2", + "fs-err", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "faster-hex" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e2ce894d53b295cf97b05685aa077950ff3e8541af83217fc720a6437169f8" + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "fatality" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ad875162843b0d046276327afe0136e9ed3a23d5a754210fb6f1f33610d39ab" +dependencies = [ + "fatality-proc-macro", + "thiserror", +] + +[[package]] +name = "fatality-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" +dependencies = [ + "expander 0.0.4", + "indexmap 1.9.3", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", + "thiserror", +] + +[[package]] +name = "fdlimit" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4c9e43643f5a3be4ca5b67d26b98031ff9db6806c3440ae32e02e3ceac3f1b" +dependencies = [ + "libc", +] + +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fflonk" +version = "0.1.0" +source = "git+https://github.com/w3f/fflonk#26a5045b24e169cffc1f9328ca83d71061145c40" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "merlin 3.0.0", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" + +[[package]] +name = "file-per-thread-logger" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84f2e425d9790201ba4af4630191feac6dcc98765b118d4d18e91d23c2353866" +dependencies = [ + "env_logger", + "log", +] + +[[package]] +name = "filetime" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.3.5", + "windows-sys 0.48.0", +] + +[[package]] +name = "finality-grandpa" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36530797b9bf31cd4ff126dcfee8170f86b00cfdcea3269d73133cc0415945c3" +dependencies = [ + "either", + "futures", + "futures-timer", + "log", + "num-traits", + "parity-scale-codec", + "parking_lot 0.12.1", + "scale-info", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "libz-sys", + "miniz_oxide", +] + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fork-tree" +version = "3.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fp-account" +version = "1.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "hex", + "impl-serde 0.4.0", + "libsecp256k1", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-runtime-interface", + "sp-std", +] + +[[package]] +name = "fp-consensus" +version = "2.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "ethereum", + "parity-scale-codec", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "fp-ethereum" +version = "1.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "ethereum", + "ethereum-types", + "fp-evm", + "frame-support", + "num_enum 0.6.1", + "parity-scale-codec", + "sp-std", +] + +[[package]] +name = "fp-evm" +version = "3.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "evm", + "frame-support", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "fp-rpc" +version = "3.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "ethereum", + "ethereum-types", + "fp-evm", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-core", + "sp-runtime", + "sp-state-machine", + "sp-std", +] + +[[package]] +name = "fp-self-contained" +version = "1.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "frame-support", + "parity-scale-codec", + "scale-info", + "serde", + "sp-runtime", +] + +[[package]] +name = "fp-storage" +version = "2.0.0" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "parity-scale-codec", + "serde", +] + +[[package]] +name = "fragile" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" + +[[package]] +name = "frame-benchmarking" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-support", + "frame-support-procedural", + "frame-system", + "linregress", + "log", + "parity-scale-codec", + "paste", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-core", + "sp-io", + "sp-runtime", + "sp-runtime-interface", + "sp-std", + "sp-storage", + "static_assertions", +] + +[[package]] +name = "frame-election-provider-solution-type" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "frame-election-provider-support" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-election-provider-solution-type", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-npos-elections", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "frame-executive" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-support", + "frame-system", + "frame-try-runtime", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-tracing", +] + +[[package]] +name = "frame-metadata" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cf1549fba25a6fcac22785b61698317d958e96cac72a59102ea45b9ae64692" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "frame-support" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "aquamarine", + "bitflags 1.3.2", + "docify", + "environmental", + "frame-metadata", + "frame-support-procedural", + "impl-trait-for-tuples", + "k256", + "log", + "macro_magic", + "parity-scale-codec", + "paste", + "scale-info", + "serde", + "serde_json", + "smallvec", + "sp-api", + "sp-arithmetic", + "sp-core", + "sp-core-hashing-proc-macro", + "sp-debug-derive", + "sp-genesis-builder", + "sp-inherents", + "sp-io", + "sp-metadata-ir", + "sp-runtime", + "sp-staking", + "sp-state-machine", + "sp-std", + "sp-tracing", + "sp-weights", + "static_assertions", + "tt-call", +] + +[[package]] +name = "frame-support-procedural" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "Inflector", + "cfg-expr", + "derive-syn-parse", + "expander 2.0.0", + "frame-support-procedural-tools", + "itertools", + "macro_magic", + "proc-macro-warning", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "frame-support-procedural-tools" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-support-procedural-tools-derive", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "frame-support-procedural-tools-derive" +version = "3.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "frame-system" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "cfg-if", + "frame-support", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-version", + "sp-weights", +] + +[[package]] +name = "frame-system-benchmarking" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "frame-system-rpc-runtime-api" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "sp-api", +] + +[[package]] +name = "frame-try-runtime" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-support", + "parity-scale-codec", + "sp-api", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "fs-err" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" + +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite 0.2.13", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "futures-rustls" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2411eed028cdf8c8034eaf21f9915f956b6c3abec4d4c7949ee67f0721127bd" +dependencies = [ + "futures-io", + "rustls 0.20.9", + "webpki 0.22.4", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite 0.2.13", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum 1.17.0", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum 1.17.0", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "ghash" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +dependencies = [ + "opaque-debug 0.3.0", + "polyval 0.5.3", +] + +[[package]] +name = "ghash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +dependencies = [ + "opaque-debug 0.3.0", + "polyval 0.6.1", +] + +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +dependencies = [ + "fallible-iterator", + "indexmap 1.9.3", + "stable_deref_trait", +] + +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "globset" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff 0.12.1", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff 0.13.0", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 1.9.3", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hash-db" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" + +[[package]] +name = "hash-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.6", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] + +[[package]] +name = "hashbrown" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac 0.12.1", +] + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac 0.8.0", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.1", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array 0.14.7", + "hmac 0.8.1", +] + +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite 0.2.13", +] + +[[package]] +name = "http-range-header" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite 0.2.13", + "socket2 0.4.9", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows 0.48.0", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "if-addrs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc0fa01ffc752e9dbc72818cdb072cd028b86be5e09dd04c5a643704fe101a9" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "if-watch" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb892e5777fe09e16f3d44de7802f4daa7267ecbe8c466f19d94e25bb0c303e" +dependencies = [ + "async-io", + "core-foundation", + "fnv", + "futures", + "if-addrs", + "ipnet", + "log", + "rtnetlink", + "system-configuration", + "tokio", + "windows 0.51.1", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "include_dir" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" +dependencies = [ + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +dependencies = [ + "equivalent", + "hashbrown 0.14.1", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "integer-encoding" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + +[[package]] +name = "interceptor" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e8a11ae2da61704edada656798b61c94b35ecac2c58eb955156987d5e6be90b" +dependencies = [ + "async-trait", + "bytes", + "log", + "rand 0.8.5", + "rtcp", + "rtp", + "thiserror", + "tokio", + "waitgroup", + "webrtc-srtp", + "webrtc-util", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.3", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "ip_network" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" + +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2 0.5.4", + "widestring", + "windows-sys 0.48.0", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi 0.3.3", + "rustix 0.38.19", + "windows-sys 0.48.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "jobserver" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonrpsee" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "367a292944c07385839818bb71c8d76611138e2dedb0677d035b8da21d29c78b" +dependencies = [ + "jsonrpsee-core", + "jsonrpsee-proc-macros", + "jsonrpsee-server", + "jsonrpsee-types", + "tracing", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5dde66c53d6dcdc8caea1874a45632ec0fcf5b437789f1e45766a1512ce803" +dependencies = [ + "anyhow", + "arrayvec 0.7.4", + "async-trait", + "beef", + "futures-channel", + "futures-util", + "globset", + "hyper", + "jsonrpsee-types", + "parking_lot 0.12.1", + "rand 0.8.5", + "rustc-hash", + "serde", + "serde_json", + "soketto", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-proc-macros" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44e8ab85614a08792b9bff6c8feee23be78c98d0182d4c622c05256ab553892a" +dependencies = [ + "heck", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "jsonrpsee-server" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4d945a6008c9b03db3354fb3c83ee02d2faa9f2e755ec1dfb69c3551b8f4ba" +dependencies = [ + "futures-channel", + "futures-util", + "http", + "hyper", + "jsonrpsee-core", + "jsonrpsee-types", + "serde", + "serde_json", + "soketto", + "tokio", + "tokio-stream", + "tokio-util", + "tower", + "tracing", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245ba8e5aa633dd1c1e4fae72bce06e71f42d34c14a2767c6b4d173b57bee5e5" +dependencies = [ + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "k256" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +dependencies = [ + "cfg-if", + "ecdsa 0.16.8", + "elliptic-curve 0.13.6", + "once_cell", + "sha2 0.10.8", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "kvdb" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7d770dcb02bf6835887c3a979b5107a04ff4bbde97a5f0928d27404a155add9" +dependencies = [ + "smallvec", +] + +[[package]] +name = "kvdb-memorydb" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7a85fe66f9ff9cd74e169fdd2c94c6e1e74c412c99a73b4df3200b5d3760b2" +dependencies = [ + "kvdb", + "parking_lot 0.12.1", +] + +[[package]] +name = "kvdb-rocksdb" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b644c70b92285f66bfc2032922a79000ea30af7bc2ab31902992a5dcb9b434f6" +dependencies = [ + "kvdb", + "num_cpus", + "parking_lot 0.12.1", + "regex", + "rocksdb", + "smallvec", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libp2p" +version = "0.51.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f210d259724eae82005b5c48078619b7745edb7b76de370b03f8ba59ea103097" +dependencies = [ + "bytes", + "futures", + "futures-timer", + "getrandom 0.2.10", + "instant", + "libp2p-allow-block-list", + "libp2p-connection-limits", + "libp2p-core", + "libp2p-dns", + "libp2p-identify", + "libp2p-identity", + "libp2p-kad", + "libp2p-mdns", + "libp2p-metrics", + "libp2p-noise", + "libp2p-ping", + "libp2p-quic", + "libp2p-request-response", + "libp2p-swarm", + "libp2p-tcp", + "libp2p-wasm-ext", + "libp2p-webrtc", + "libp2p-websocket", + "libp2p-yamux", + "multiaddr", + "pin-project", +] + +[[package]] +name = "libp2p-allow-block-list" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "510daa05efbc25184458db837f6f9a5143888f1caa742426d92e1833ddd38a50" +dependencies = [ + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "void", +] + +[[package]] +name = "libp2p-connection-limits" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4caa33f1d26ed664c4fe2cca81a08c8e07d4c1c04f2f4ac7655c2dd85467fda0" +dependencies = [ + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "void", +] + +[[package]] +name = "libp2p-core" +version = "0.39.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c1df63c0b582aa434fb09b2d86897fa2b419ffeccf934b36f87fcedc8e835c2" +dependencies = [ + "either", + "fnv", + "futures", + "futures-timer", + "instant", + "libp2p-identity", + "log", + "multiaddr", + "multihash", + "multistream-select", + "once_cell", + "parking_lot 0.12.1", + "pin-project", + "quick-protobuf", + "rand 0.8.5", + "rw-stream-sink", + "smallvec", + "thiserror", + "unsigned-varint", + "void", +] + +[[package]] +name = "libp2p-dns" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146ff7034daae62077c415c2376b8057368042df6ab95f5432ad5e88568b1554" +dependencies = [ + "futures", + "libp2p-core", + "log", + "parking_lot 0.12.1", + "smallvec", + "trust-dns-resolver", +] + +[[package]] +name = "libp2p-identify" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5455f472243e63b9c497ff320ded0314254a9eb751799a39c283c6f20b793f3c" +dependencies = [ + "asynchronous-codec", + "either", + "futures", + "futures-timer", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "log", + "lru", + "quick-protobuf", + "quick-protobuf-codec", + "smallvec", + "thiserror", + "void", +] + +[[package]] +name = "libp2p-identity" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276bb57e7af15d8f100d3c11cbdd32c6752b7eef4ba7a18ecf464972c07abcce" +dependencies = [ + "bs58 0.4.0", + "ed25519-dalek 2.0.0", + "log", + "multiaddr", + "multihash", + "quick-protobuf", + "rand 0.8.5", + "sha2 0.10.8", + "thiserror", + "zeroize", +] + +[[package]] +name = "libp2p-kad" +version = "0.43.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39d5ef876a2b2323d63c258e63c2f8e36f205fe5a11f0b3095d59635650790ff" +dependencies = [ + "arrayvec 0.7.4", + "asynchronous-codec", + "bytes", + "either", + "fnv", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "log", + "quick-protobuf", + "rand 0.8.5", + "sha2 0.10.8", + "smallvec", + "thiserror", + "uint", + "unsigned-varint", + "void", +] + +[[package]] +name = "libp2p-mdns" +version = "0.43.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19983e1f949f979a928f2c603de1cf180cc0dc23e4ac93a62651ccb18341460b" +dependencies = [ + "data-encoding", + "futures", + "if-watch", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "log", + "rand 0.8.5", + "smallvec", + "socket2 0.4.9", + "tokio", + "trust-dns-proto", + "void", +] + +[[package]] +name = "libp2p-metrics" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a42ec91e227d7d0dafa4ce88b333cdf5f277253873ab087555c92798db2ddd46" +dependencies = [ + "libp2p-core", + "libp2p-identify", + "libp2p-kad", + "libp2p-ping", + "libp2p-swarm", + "prometheus-client", +] + +[[package]] +name = "libp2p-noise" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3673da89d29936bc6435bafc638e2f184180d554ce844db65915113f86ec5e" +dependencies = [ + "bytes", + "curve25519-dalek 3.2.0", + "futures", + "libp2p-core", + "libp2p-identity", + "log", + "once_cell", + "quick-protobuf", + "rand 0.8.5", + "sha2 0.10.8", + "snow", + "static_assertions", + "thiserror", + "x25519-dalek 1.1.1", + "zeroize", +] + +[[package]] +name = "libp2p-ping" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e57759c19c28a73ef1eb3585ca410cefb72c1a709fcf6de1612a378e4219202" +dependencies = [ + "either", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-swarm", + "log", + "rand 0.8.5", + "void", +] + +[[package]] +name = "libp2p-quic" +version = "0.7.0-alpha.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6b26abd81cd2398382a1edfe739b539775be8a90fa6914f39b2ab49571ec735" +dependencies = [ + "bytes", + "futures", + "futures-timer", + "if-watch", + "libp2p-core", + "libp2p-identity", + "libp2p-tls", + "log", + "parking_lot 0.12.1", + "quinn-proto", + "rand 0.8.5", + "rustls 0.20.9", + "thiserror", + "tokio", +] + +[[package]] +name = "libp2p-request-response" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffdb374267d42dc5ed5bc53f6e601d4a64ac5964779c6e40bb9e4f14c1e30d5" +dependencies = [ + "async-trait", + "futures", + "instant", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "rand 0.8.5", + "smallvec", +] + +[[package]] +name = "libp2p-swarm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "903b3d592d7694e56204d211f29d31bc004be99386644ba8731fc3e3ef27b296" +dependencies = [ + "either", + "fnv", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm-derive", + "log", + "rand 0.8.5", + "smallvec", + "tokio", + "void", +] + +[[package]] +name = "libp2p-swarm-derive" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fba456131824ab6acd4c7bf61e9c0f0a3014b5fc9868ccb8e10d344594cdc4f" +dependencies = [ + "heck", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "libp2p-tcp" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d33698596d7722d85d3ab0c86c2c322254fce1241e91208e3679b4eb3026cf" +dependencies = [ + "futures", + "futures-timer", + "if-watch", + "libc", + "libp2p-core", + "log", + "socket2 0.4.9", + "tokio", +] + +[[package]] +name = "libp2p-tls" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff08d13d0dc66e5e9ba6279c1de417b84fa0d0adc3b03e5732928c180ec02781" +dependencies = [ + "futures", + "futures-rustls", + "libp2p-core", + "libp2p-identity", + "rcgen 0.10.0", + "ring 0.16.20", + "rustls 0.20.9", + "thiserror", + "webpki 0.22.4", + "x509-parser 0.14.0", + "yasna", +] + +[[package]] +name = "libp2p-wasm-ext" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77dff9d32353a5887adb86c8afc1de1a94d9e8c3bc6df8b2201d7cdf5c848f43" +dependencies = [ + "futures", + "js-sys", + "libp2p-core", + "parity-send-wrapper", + "wasm-bindgen", + "wasm-bindgen-futures", +] + +[[package]] +name = "libp2p-webrtc" +version = "0.4.0-alpha.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dba48592edbc2f60b4bc7c10d65445b0c3964c07df26fdf493b6880d33be36f8" +dependencies = [ + "async-trait", + "asynchronous-codec", + "bytes", + "futures", + "futures-timer", + "hex", + "if-watch", + "libp2p-core", + "libp2p-identity", + "libp2p-noise", + "log", + "multihash", + "quick-protobuf", + "quick-protobuf-codec", + "rand 0.8.5", + "rcgen 0.9.3", + "serde", + "stun", + "thiserror", + "tinytemplate", + "tokio", + "tokio-util", + "webrtc", +] + +[[package]] +name = "libp2p-websocket" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "111273f7b3d3510524c752e8b7a5314b7f7a1fee7e68161c01a7d72cbb06db9f" +dependencies = [ + "either", + "futures", + "futures-rustls", + "libp2p-core", + "log", + "parking_lot 0.12.1", + "quicksink", + "rw-stream-sink", + "soketto", + "url", + "webpki-roots", +] + +[[package]] +name = "libp2p-yamux" +version = "0.43.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd21d950662700a385d4c6d68e2f5f54d778e97068cdd718522222ef513bda" +dependencies = [ + "futures", + "libp2p-core", + "log", + "thiserror", + "yamux", +] + +[[package]] +name = "librocksdb-sys" +version = "0.11.0+8.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3386f101bcb4bd252d8e9d2fb41ec3b0862a15a62b478c355b2982efa469e3e" +dependencies = [ + "bindgen", + "bzip2-sys", + "cc", + "glob", + "libc", + "libz-sys", + "tikv-jemalloc-sys", +] + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64 0.13.1", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.5", + "serde", + "sha2 0.9.9", + "typenum 1.17.0", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libz-sys" +version = "1.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "link-cplusplus" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" +dependencies = [ + "cc", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linked_hash_set" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47186c6da4d81ca383c7c47c1bfc80f4b95f4720514d860a5407aaf4233f9588" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "linregress" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4de04dcecc58d366391f9920245b85ffa684558a5ef6e7736e754347c3aea9c2" +dependencies = [ + "nalgebra", +] + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "lru" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670" +dependencies = [ + "hashbrown 0.13.2", +] + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "lz4" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" +dependencies = [ + "libc", + "lz4-sys", +] + +[[package]] +name = "lz4-sys" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + +[[package]] +name = "macro_magic" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aee866bfee30d2d7e83835a4574aad5b45adba4cc807f2a3bbba974e5d4383c9" +dependencies = [ + "macro_magic_core", + "macro_magic_macros", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "macro_magic_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e766a20fd9c72bab3e1e64ed63f36bd08410e75803813df210d1ce297d7ad00" +dependencies = [ + "const-random", + "derive-syn-parse", + "macro_magic_core_macros", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "macro_magic_core_macros" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d710e1214dffbab3b5dacb21475dde7d6ed84c69ff722b3a47a782668d44fbac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "macro_magic_macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fb85ec1620619edf2984a7693497d4ec88a9665d8b87e942856884c92dbf2a" +dependencies = [ + "macro_magic_core", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + +[[package]] +name = "matchers" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "matrixmultiply" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2" +dependencies = [ + "autocfg", + "rawpointer", +] + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest 0.10.7", +] + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "memfd" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" +dependencies = [ + "rustix 0.38.19", +] + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memory-db" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +dependencies = [ + "hash-db 0.16.0", +] + +[[package]] +name = "merlin" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.5.1", + "zeroize", +] + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "mick-jaeger" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69672161530e8aeca1d1400fbf3f1a1747ff60ea604265a4e906c2442df20532" +dependencies = [ + "futures", + "rand 0.8.5", + "thrift", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", +] + +[[package]] +name = "mockall" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c84490118f2ee2d74570d114f3d0493cbf02790df303d2707606c3e14e07c96" +dependencies = [ + "cfg-if", + "downcast", + "fragile", + "lazy_static", + "mockall_derive", + "predicates", + "predicates-tree", +] + +[[package]] +name = "mockall_derive" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "moonbase-runtime" +version = "0.8.4" +dependencies = [ + "account", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "evm-tracing-events", + "fp-evm", + "fp-rpc", + "fp-self-contained", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "hex-literal 0.3.4", + "log", + "moonbeam-core-primitives", + "moonbeam-evm-tracer", + "moonbeam-relay-encoder", + "moonbeam-rpc-primitives-debug", + "moonbeam-rpc-primitives-txpool", + "moonbeam-runtime-common", + "moonbeam-xcm-benchmarks", + "nimbus-primitives", + "num_enum 0.5.11", + "orml-traits", + "orml-xcm-support", + "orml-xtokens", + "pallet-asset-manager", + "pallet-assets", + "pallet-author-inherent", + "pallet-author-mapping", + "pallet-author-slot-filter", + "pallet-balances", + "pallet-base-fee", + "pallet-collective", + "pallet-conviction-voting", + "pallet-crowdloan-rewards", + "pallet-democracy", + "pallet-erc20-xcm-bridge", + "pallet-ethereum", + "pallet-ethereum-xcm", + "pallet-evm", + "pallet-evm-chain-id", + "pallet-evm-precompile-author-mapping", + "pallet-evm-precompile-balances-erc20", + "pallet-evm-precompile-batch", + "pallet-evm-precompile-blake2", + "pallet-evm-precompile-bn128", + "pallet-evm-precompile-call-permit", + "pallet-evm-precompile-collective", + "pallet-evm-precompile-conviction-voting", + "pallet-evm-precompile-crowdloan-rewards", + "pallet-evm-precompile-democracy", + "pallet-evm-precompile-dispatch", + "pallet-evm-precompile-gmp", + "pallet-evm-precompile-identity", + "pallet-evm-precompile-modexp", + "pallet-evm-precompile-parachain-staking", + "pallet-evm-precompile-preimage", + "pallet-evm-precompile-proxy", + "pallet-evm-precompile-randomness", + "pallet-evm-precompile-referenda", + "pallet-evm-precompile-registry", + "pallet-evm-precompile-relay-encoder", + "pallet-evm-precompile-sha3fips", + "pallet-evm-precompile-simple", + "pallet-evm-precompile-xcm-transactor", + "pallet-evm-precompile-xcm-utils", + "pallet-evm-precompile-xtokens", + "pallet-evm-precompileset-assets-erc20", + "pallet-identity", + "pallet-maintenance-mode", + "pallet-migrations", + "pallet-moonbeam-orbiters", + "pallet-multisig", + "pallet-parachain-staking", + "pallet-preimage", + "pallet-proxy", + "pallet-proxy-genesis-companion", + "pallet-randomness", + "pallet-referenda", + "pallet-root-testing", + "pallet-scheduler", + "pallet-society", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-treasury", + "pallet-utility", + "pallet-whitelist", + "pallet-xcm", + "pallet-xcm-benchmarks", + "pallet-xcm-transactor", + "parachain-info", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "precompile-utils", + "rlp", + "scale-info", + "serde", + "session-keys-primitives", + "sha3", + "smallvec", + "sp-api", + "sp-block-builder", + "sp-core", + "sp-debug-derive", + "sp-inherents", + "sp-io", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "sp-weights", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "strum", + "strum_macros", + "substrate-wasm-builder", + "xcm-primitives 0.1.0", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "moonbeam-core-primitives" +version = "0.1.1" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "account", + "fp-self-contained", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "moonbeam-evm-tracer" +version = "0.1.0" +dependencies = [ + "ethereum-types", + "evm", + "evm-gasometer", + "evm-runtime", + "evm-tracing-events", + "fp-evm", + "moonbeam-primitives-ext", + "pallet-evm", + "parity-scale-codec", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "moonbeam-primitives-ext" +version = "0.1.0" +dependencies = [ + "ethereum-types", + "evm-tracing-events", + "parity-scale-codec", + "sp-externalities", + "sp-runtime-interface", + "sp-std", +] + +[[package]] +name = "moonbeam-relay-encoder" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "cumulus-primitives-core", + "frame-system", + "pallet-evm-precompile-relay-encoder", + "pallet-staking", + "pallet-xcm-transactor", + "parity-scale-codec", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "moonbeam-rpc-primitives-debug" +version = "0.1.0" +dependencies = [ + "environmental", + "ethereum", + "ethereum-types", + "hex", + "parity-scale-codec", + "serde", + "sp-api", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "moonbeam-rpc-primitives-txpool" +version = "0.6.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "ethereum", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "moonbeam-runtime" +version = "0.8.4" +dependencies = [ + "account", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "evm-tracing-events", + "fp-evm", + "fp-rpc", + "fp-self-contained", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "hex-literal 0.3.4", + "log", + "moonbeam-core-primitives", + "moonbeam-evm-tracer", + "moonbeam-relay-encoder", + "moonbeam-rpc-primitives-debug", + "moonbeam-rpc-primitives-txpool", + "moonbeam-runtime-common", + "moonbeam-xcm-benchmarks", + "nimbus-primitives", + "num_enum 0.5.11", + "orml-traits", + "orml-xcm-support", + "orml-xtokens", + "pallet-asset-manager", + "pallet-assets", + "pallet-author-inherent", + "pallet-author-mapping", + "pallet-author-slot-filter", + "pallet-balances", + "pallet-base-fee", + "pallet-collective", + "pallet-conviction-voting", + "pallet-crowdloan-rewards", + "pallet-democracy", + "pallet-erc20-xcm-bridge", + "pallet-ethereum", + "pallet-ethereum-xcm", + "pallet-evm", + "pallet-evm-chain-id", + "pallet-evm-precompile-author-mapping", + "pallet-evm-precompile-balances-erc20", + "pallet-evm-precompile-batch", + "pallet-evm-precompile-blake2", + "pallet-evm-precompile-bn128", + "pallet-evm-precompile-call-permit", + "pallet-evm-precompile-collective", + "pallet-evm-precompile-conviction-voting", + "pallet-evm-precompile-crowdloan-rewards", + "pallet-evm-precompile-democracy", + "pallet-evm-precompile-dispatch", + "pallet-evm-precompile-gmp", + "pallet-evm-precompile-modexp", + "pallet-evm-precompile-parachain-staking", + "pallet-evm-precompile-preimage", + "pallet-evm-precompile-proxy", + "pallet-evm-precompile-randomness", + "pallet-evm-precompile-referenda", + "pallet-evm-precompile-registry", + "pallet-evm-precompile-relay-encoder", + "pallet-evm-precompile-sha3fips", + "pallet-evm-precompile-simple", + "pallet-evm-precompile-xcm-transactor", + "pallet-evm-precompile-xcm-utils", + "pallet-evm-precompile-xtokens", + "pallet-evm-precompileset-assets-erc20", + "pallet-identity", + "pallet-maintenance-mode", + "pallet-migrations", + "pallet-moonbeam-orbiters", + "pallet-multisig", + "pallet-parachain-staking", + "pallet-preimage", + "pallet-proxy", + "pallet-proxy-genesis-companion", + "pallet-randomness", + "pallet-referenda", + "pallet-root-testing", + "pallet-scheduler", + "pallet-society", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-treasury", + "pallet-utility", + "pallet-whitelist", + "pallet-xcm", + "pallet-xcm-benchmarks", + "pallet-xcm-transactor", + "parachain-info", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "precompile-utils", + "rlp", + "scale-info", + "serde", + "session-keys-primitives", + "sha3", + "smallvec", + "sp-api", + "sp-block-builder", + "sp-core", + "sp-inherents", + "sp-io", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "sp-weights", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "strum", + "strum_macros", + "substrate-wasm-builder", + "xcm-primitives 0.1.0", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "moonbeam-runtime-common" +version = "0.8.0-dev" +dependencies = [ + "cumulus-pallet-xcmp-queue", + "fp-ethereum", + "fp-evm", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex-literal 0.3.4", + "impl-trait-for-tuples", + "log", + "moonbeam-xcm-benchmarks", + "nimbus-primitives", + "pallet-asset-manager", + "pallet-assets", + "pallet-author-inherent", + "pallet-author-mapping", + "pallet-author-slot-filter", + "pallet-balances", + "pallet-base-fee", + "pallet-collective", + "pallet-conviction-voting", + "pallet-crowdloan-rewards", + "pallet-democracy", + "pallet-ethereum-xcm", + "pallet-evm", + "pallet-evm-chain-id", + "pallet-identity", + "pallet-migrations", + "pallet-moonbeam-orbiters", + "pallet-multisig", + "pallet-parachain-staking", + "pallet-preimage", + "pallet-proxy", + "pallet-randomness", + "pallet-referenda", + "pallet-scheduler", + "pallet-sudo", + "pallet-timestamp", + "pallet-treasury", + "pallet-utility", + "pallet-whitelist", + "pallet-xcm", + "pallet-xcm-transactor", + "precompile-utils", + "sp-api", + "sp-core", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "moonbeam-xcm-benchmarks" +version = "0.2.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-erc20-xcm-bridge", + "pallet-xcm-benchmarks", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std", + "staging-xcm", + "staging-xcm-executor", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "moonriver-runtime" +version = "0.8.4" +dependencies = [ + "account", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "evm-tracing-events", + "fp-evm", + "fp-rpc", + "fp-self-contained", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "hex-literal 0.3.4", + "log", + "moonbeam-core-primitives", + "moonbeam-evm-tracer", + "moonbeam-relay-encoder", + "moonbeam-rpc-primitives-debug", + "moonbeam-rpc-primitives-txpool", + "moonbeam-runtime-common", + "moonbeam-xcm-benchmarks", + "nimbus-primitives", + "num_enum 0.5.11", + "orml-traits", + "orml-xcm-support", + "orml-xtokens", + "pallet-asset-manager", + "pallet-assets", + "pallet-author-inherent", + "pallet-author-mapping", + "pallet-author-slot-filter", + "pallet-balances", + "pallet-base-fee", + "pallet-collective", + "pallet-conviction-voting", + "pallet-crowdloan-rewards", + "pallet-democracy", + "pallet-erc20-xcm-bridge", + "pallet-ethereum", + "pallet-ethereum-xcm", + "pallet-evm", + "pallet-evm-chain-id", + "pallet-evm-precompile-author-mapping", + "pallet-evm-precompile-balances-erc20", + "pallet-evm-precompile-batch", + "pallet-evm-precompile-blake2", + "pallet-evm-precompile-bn128", + "pallet-evm-precompile-call-permit", + "pallet-evm-precompile-collective", + "pallet-evm-precompile-conviction-voting", + "pallet-evm-precompile-crowdloan-rewards", + "pallet-evm-precompile-democracy", + "pallet-evm-precompile-dispatch", + "pallet-evm-precompile-gmp", + "pallet-evm-precompile-modexp", + "pallet-evm-precompile-parachain-staking", + "pallet-evm-precompile-preimage", + "pallet-evm-precompile-proxy", + "pallet-evm-precompile-randomness", + "pallet-evm-precompile-referenda", + "pallet-evm-precompile-registry", + "pallet-evm-precompile-relay-encoder", + "pallet-evm-precompile-sha3fips", + "pallet-evm-precompile-simple", + "pallet-evm-precompile-xcm-transactor", + "pallet-evm-precompile-xcm-utils", + "pallet-evm-precompile-xtokens", + "pallet-evm-precompileset-assets-erc20", + "pallet-identity", + "pallet-maintenance-mode", + "pallet-migrations", + "pallet-moonbeam-orbiters", + "pallet-multisig", + "pallet-parachain-staking", + "pallet-preimage", + "pallet-proxy", + "pallet-proxy-genesis-companion", + "pallet-randomness", + "pallet-referenda", + "pallet-root-testing", + "pallet-scheduler", + "pallet-society", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-treasury", + "pallet-utility", + "pallet-whitelist", + "pallet-xcm", + "pallet-xcm-benchmarks", + "pallet-xcm-transactor", + "parachain-info", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "precompile-utils", + "rlp", + "scale-info", + "serde", + "session-keys-primitives", + "sha3", + "smallvec", + "sp-api", + "sp-block-builder", + "sp-core", + "sp-debug-derive", + "sp-inherents", + "sp-io", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "sp-weights", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "strum", + "strum_macros", + "substrate-wasm-builder", + "xcm-primitives 0.1.0", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "multiaddr" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b36f567c7099511fa8612bbbb52dda2419ce0bdbacf31714e3a5ffdb766d3bd" +dependencies = [ + "arrayref", + "byteorder", + "data-encoding", + "log", + "multibase", + "multihash", + "percent-encoding", + "serde", + "static_assertions", + "unsigned-varint", + "url", +] + +[[package]] +name = "multibase" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b3539ec3c1f04ac9748a260728e855f261b4977f5c3406612c884564f329404" +dependencies = [ + "base-x", + "data-encoding", + "data-encoding-macro", +] + +[[package]] +name = "multihash" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835d6ff01d610179fbce3de1694d007e500bf33a7f29689838941d6bf783ae40" +dependencies = [ + "blake2b_simd", + "blake2s_simd", + "blake3", + "core2", + "digest 0.10.7", + "multihash-derive", + "sha2 0.10.8", + "sha3", + "unsigned-varint", +] + +[[package]] +name = "multihash-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" +dependencies = [ + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "multistream-select" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8552ab875c1313b97b8d20cb857b9fd63e2d1d6a0a1b53ce9821e575405f27a" +dependencies = [ + "bytes", + "futures", + "log", + "pin-project", + "smallvec", + "unsigned-varint", +] + +[[package]] +name = "nalgebra" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "307ed9b18cc2423f29e83f84fd23a8e73628727990181f18641a8b5dc2ab1caa" +dependencies = [ + "approx", + "matrixmultiply", + "nalgebra-macros", + "num-complex", + "num-rational", + "num-traits", + "simba", + "typenum 1.17.0", +] + +[[package]] +name = "nalgebra-macros" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91761aed67d03ad966ef783ae962ef9bbaca728d2dd7ceb7939ec110fffad998" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "names" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7d66043b25d4a6cccb23619d10c19c25304b355a7dccd4a8e11423dd2382146" +dependencies = [ + "rand 0.8.5", +] + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" + +[[package]] +name = "netlink-packet-core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345b8ab5bd4e71a2986663e88c56856699d060e78e152e6e9d7966fcd5491297" +dependencies = [ + "anyhow", + "byteorder", + "libc", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-route" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9ea4302b9759a7a88242299225ea3688e63c85ea136371bb6cf94fd674efaab" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "byteorder", + "libc", + "netlink-packet-core", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-utils" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" +dependencies = [ + "anyhow", + "byteorder", + "paste", + "thiserror", +] + +[[package]] +name = "netlink-proto" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65b4b14489ab424703c092062176d52ba55485a89c076b4f9db05092b7223aa6" +dependencies = [ + "bytes", + "futures", + "log", + "netlink-packet-core", + "netlink-sys", + "thiserror", + "tokio", +] + +[[package]] +name = "netlink-sys" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" +dependencies = [ + "bytes", + "futures", + "libc", + "log", + "tokio", +] + +[[package]] +name = "nimbus-primitives" +version = "0.9.0" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-v1.1.0#caa31fa405387f445a3265a108310e63a1f83efe" +dependencies = [ + "async-trait", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-application-crypto", + "sp-inherents", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "nix" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.6.5", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec 0.7.4", + "itoa", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.3", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive 0.5.11", +] + +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive 0.6.1", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "object" +version = "0.30.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +dependencies = [ + "crc32fast", + "hashbrown 0.13.2", + "indexmap 1.9.3", + "memchr", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + +[[package]] +name = "oid-registry" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e20717fa0541f39bd146692035c37bedfa532b3e5071b35761082407546b2a" +dependencies = [ + "asn1-rs 0.3.1", +] + +[[package]] +name = "oid-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +dependencies = [ + "asn1-rs 0.5.2", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "orchestra" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "227585216d05ba65c7ab0a0450a3cf2cbd81a98862a54c4df8e14d5ac6adb015" +dependencies = [ + "async-trait", + "dyn-clonable", + "futures", + "futures-timer", + "orchestra-proc-macro", + "pin-project", + "prioritized-metered-channel", + "thiserror", + "tracing", +] + +[[package]] +name = "orchestra-proc-macro" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2871aadd82a2c216ee68a69837a526dfe788ecbe74c4c5038a6acdbff6653066" +dependencies = [ + "expander 0.0.6", + "itertools", + "petgraph", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ordered-float" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3305af35278dd29f46fcdd139e0b1fbfae2153f0e5928b39b035542dd31e37b7" +dependencies = [ + "num-traits", +] + +[[package]] +name = "orml-traits" +version = "0.4.1-dev" +source = "git+https://github.com/moonbeam-foundation/open-runtime-module-library?branch=moonbeam-polkadot-v1.1.0#0044e8dba2799cf0ddef3465ba901fa03ee1135f" +dependencies = [ + "frame-support", + "impl-trait-for-tuples", + "num-traits", + "orml-utilities", + "parity-scale-codec", + "paste", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", +] + +[[package]] +name = "orml-utilities" +version = "0.4.1-dev" +source = "git+https://github.com/moonbeam-foundation/open-runtime-module-library?branch=moonbeam-polkadot-v1.1.0#0044e8dba2799cf0ddef3465ba901fa03ee1135f" +dependencies = [ + "frame-support", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "orml-xcm-support" +version = "0.4.1-dev" +source = "git+https://github.com/moonbeam-foundation/open-runtime-module-library?branch=moonbeam-polkadot-v1.1.0#0044e8dba2799cf0ddef3465ba901fa03ee1135f" +dependencies = [ + "frame-support", + "orml-traits", + "parity-scale-codec", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-executor", +] + +[[package]] +name = "orml-xtokens" +version = "0.4.1-dev" +source = "git+https://github.com/moonbeam-foundation/open-runtime-module-library?branch=moonbeam-polkadot-v1.1.0#0044e8dba2799cf0ddef3465ba901fa03ee1135f" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "frame-system", + "log", + "orml-traits", + "orml-xcm-support", + "pallet-xcm", + "parity-scale-codec", + "scale-info", + "serde", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-executor", +] + +[[package]] +name = "p256" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +dependencies = [ + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", + "sha2 0.10.8", +] + +[[package]] +name = "p384" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" +dependencies = [ + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", + "sha2 0.10.8", +] + +[[package]] +name = "pallet-asset-manager" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "pallet-assets" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-author-inherent" +version = "0.9.0" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-v1.1.0#caa31fa405387f445a3265a108310e63a1f83efe" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "nimbus-primitives", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-application-crypto", + "sp-inherents", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-author-mapping" +version = "2.0.5" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-v1.1.0#caa31fa405387f445a3265a108310e63a1f83efe" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "nimbus-primitives", + "parity-scale-codec", + "scale-info", + "serde", + "session-keys-primitives", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-author-slot-filter" +version = "0.9.0" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-v1.1.0#caa31fa405387f445a3265a108310e63a1f83efe" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "nimbus-primitives", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-authority-discovery" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-support", + "frame-system", + "pallet-session", + "parity-scale-codec", + "scale-info", + "sp-application-crypto", + "sp-authority-discovery", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-authorship" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-babe" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-authorship", + "pallet-session", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-application-crypto", + "sp-consensus-babe", + "sp-core", + "sp-io", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std", +] + +[[package]] +name = "pallet-balances" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-base-fee" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "pallet-collective" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-conviction-voting" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "assert_matches", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "serde", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-crowdloan-rewards" +version = "0.6.0" +source = "git+https://github.com/moonbeam-foundation/crowdloan-rewards?branch=moonbeam-polkadot-v1.1.0#9539975524bb2792b77120788350875eb034d997" +dependencies = [ + "ed25519-dalek 1.0.1", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-balances", + "pallet-utility", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-trie", +] + +[[package]] +name = "pallet-democracy" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-election-provider-multi-phase" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "log", + "pallet-election-provider-support-benchmarking", + "parity-scale-codec", + "rand 0.8.5", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-npos-elections", + "sp-runtime", + "sp-std", + "strum", +] + +[[package]] +name = "pallet-election-provider-support-benchmarking" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-election-provider-support", + "frame-system", + "parity-scale-codec", + "sp-npos-elections", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-erc20-xcm-bridge" +version = "1.0.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "environmental", + "ethereum-types", + "fp-evm", + "frame-support", + "frame-system", + "pallet-evm", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-executor", +] + +[[package]] +name = "pallet-ethereum" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "environmental", + "ethereum", + "ethereum-types", + "evm", + "fp-consensus", + "fp-ethereum", + "fp-evm", + "fp-rpc", + "fp-storage", + "frame-support", + "frame-system", + "pallet-evm", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-ethereum-xcm" +version = "1.0.0-dev" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "ethereum", + "ethereum-types", + "fp-ethereum", + "fp-evm", + "fp-rpc", + "fp-self-contained", + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-evm", + "pallet-timestamp", + "parity-scale-codec", + "rlp", + "scale-info", + "serde", + "sp-io", + "sp-runtime", + "sp-std", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "pallet-evm" +version = "6.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "environmental", + "evm", + "fp-account", + "fp-evm", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex", + "hex-literal 0.4.1", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "rlp", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-evm-chain-id" +version = "1.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-runtime", +] + +[[package]] +name = "pallet-evm-precompile-author-mapping" +version = "0.2.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "log", + "nimbus-primitives", + "num_enum 0.5.11", + "pallet-author-mapping", + "pallet-evm", + "parity-scale-codec", + "precompile-utils", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-evm-precompile-balances-erc20" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "pallet-balances", + "pallet-evm", + "pallet-timestamp", + "parity-scale-codec", + "paste", + "precompile-utils", + "slices", + "sp-core", + "sp-io", + "sp-std", +] + +[[package]] +name = "pallet-evm-precompile-batch" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "evm", + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "pallet-evm", + "parity-scale-codec", + "paste", + "precompile-utils", + "slices", + "sp-core", + "sp-io", + "sp-std", +] + +[[package]] +name = "pallet-evm-precompile-blake2" +version = "2.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "fp-evm", +] + +[[package]] +name = "pallet-evm-precompile-bn128" +version = "2.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "fp-evm", + "sp-core", + "substrate-bn", +] + +[[package]] +name = "pallet-evm-precompile-call-permit" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "evm", + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "pallet-evm", + "pallet-timestamp", + "parity-scale-codec", + "paste", + "precompile-utils", + "slices", + "sp-core", + "sp-io", + "sp-std", +] + +[[package]] +name = "pallet-evm-precompile-collective" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "evm", + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "pallet-collective", + "pallet-evm", + "parity-scale-codec", + "paste", + "precompile-utils", + "slices", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "pallet-evm-precompile-conviction-voting" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "pallet-conviction-voting", + "pallet-evm", + "parity-scale-codec", + "precompile-utils", + "rustc-hex", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-evm-precompile-crowdloan-rewards" +version = "0.6.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "pallet-crowdloan-rewards", + "pallet-evm", + "precompile-utils", + "rustc-hex", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-evm-precompile-democracy" +version = "0.2.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "pallet-democracy", + "pallet-evm", + "pallet-preimage", + "parity-scale-codec", + "precompile-utils", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-evm-precompile-dispatch" +version = "2.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "fp-evm", + "frame-support", + "pallet-evm", + "parity-scale-codec", + "sp-runtime", +] + +[[package]] +name = "pallet-evm-precompile-gmp" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "cumulus-primitives-core", + "evm", + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "orml-traits", + "orml-xtokens", + "pallet-evm", + "pallet-xcm", + "parity-scale-codec", + "paste", + "precompile-utils", + "slices", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "pallet-evm-precompile-identity" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "enumflags2", + "evm", + "fp-evm", + "frame-support", + "frame-system", + "log", + "pallet-evm", + "pallet-identity", + "parity-scale-codec", + "precompile-utils", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-evm-precompile-modexp" +version = "2.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "fp-evm", + "num", +] + +[[package]] +name = "pallet-evm-precompile-parachain-staking" +version = "1.0.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "pallet-evm", + "pallet-parachain-staking", + "parity-scale-codec", + "precompile-utils", + "rustc-hex", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-evm-precompile-preimage" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "pallet-evm", + "pallet-preimage", + "parity-scale-codec", + "precompile-utils", + "rustc-hex", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-evm-precompile-proxy" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "evm", + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "pallet-balances", + "pallet-evm", + "pallet-proxy", + "parity-scale-codec", + "precompile-utils", + "rustc-hex", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-evm-precompile-randomness" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "log", + "nimbus-primitives", + "num_enum 0.5.11", + "pallet-base-fee", + "pallet-evm", + "pallet-randomness", + "parity-scale-codec", + "precompile-utils", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-evm-precompile-referenda" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "pallet-evm", + "pallet-referenda", + "parity-scale-codec", + "precompile-utils", + "rustc-hex", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-evm-precompile-registry" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "log", + "pallet-evm", + "parity-scale-codec", + "precompile-utils", + "sp-core", + "sp-io", + "sp-std", +] + +[[package]] +name = "pallet-evm-precompile-relay-encoder" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "cumulus-primitives-core", + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "pallet-evm", + "pallet-staking", + "pallet-xcm-transactor", + "parity-scale-codec", + "precompile-utils", + "rustc-hex", + "sp-core", + "sp-runtime", + "sp-std", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "pallet-evm-precompile-sha3fips" +version = "2.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "fp-evm", + "tiny-keccak", +] + +[[package]] +name = "pallet-evm-precompile-simple" +version = "2.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/frontier?branch=moonbeam-polkadot-v1.1.0#916a6c8bfe89a8696ffee32c850eda0ec4daa284" +dependencies = [ + "fp-evm", + "ripemd", + "sp-io", +] + +[[package]] +name = "pallet-evm-precompile-xcm-transactor" +version = "0.2.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "cumulus-primitives-core", + "evm", + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "pallet-evm", + "pallet-xcm-transactor", + "precompile-utils", + "rustc-hex", + "sp-core", + "sp-runtime", + "sp-std", + "sp-weights", + "staging-xcm", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "pallet-evm-precompile-xcm-utils" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "num_enum 0.5.11", + "pallet-evm", + "pallet-xcm", + "parity-scale-codec", + "precompile-utils", + "sp-core", + "sp-runtime", + "sp-std", + "sp-weights", + "staging-xcm", + "staging-xcm-executor", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "pallet-evm-precompile-xtokens" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "orml-xtokens", + "pallet-evm", + "precompile-utils", + "rustc-hex", + "sp-core", + "sp-runtime", + "sp-std", + "sp-weights", + "staging-xcm", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "pallet-evm-precompileset-assets-erc20" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "fp-evm", + "frame-support", + "frame-system", + "log", + "num_enum 0.5.11", + "pallet-assets", + "pallet-balances", + "pallet-evm", + "pallet-timestamp", + "parity-scale-codec", + "paste", + "precompile-utils", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-fast-unstake" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-std", +] + +[[package]] +name = "pallet-identity" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "enumflags2", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-maintenance-mode" +version = "0.1.0" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-v1.1.0#caa31fa405387f445a3265a108310e63a1f83efe" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", + "xcm-primitives 0.1.0", +] + +[[package]] +name = "pallet-message-queue" +version = "7.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", +] + +[[package]] +name = "pallet-migrations" +version = "0.1.0" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-v1.1.0#caa31fa405387f445a3265a108310e63a1f83efe" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "xcm-primitives 0.1.0", +] + +[[package]] +name = "pallet-moonbeam-orbiters" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "nimbus-primitives", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-multisig" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-parachain-staking" +version = "3.0.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "nimbus-primitives", + "parity-scale-codec", + "scale-info", + "serde", + "sp-runtime", + "sp-std", + "substrate-fixed", +] + +[[package]] +name = "pallet-preimage" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-proxy" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-proxy-genesis-companion" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "frame-support", + "frame-system", + "pallet-proxy", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-randomness" +version = "0.1.0" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-v1.1.0#caa31fa405387f445a3265a108310e63a1f83efe" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "hex", + "log", + "nimbus-primitives", + "parity-scale-codec", + "scale-info", + "schnorrkel", + "serde", + "session-keys-primitives", + "sp-consensus-babe", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-referenda" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "assert_matches", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-arithmetic", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-root-testing" +version = "1.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-scheduler" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", +] + +[[package]] +name = "pallet-session" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-state-machine", + "sp-std", + "sp-trie", +] + +[[package]] +name = "pallet-society" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "rand_chacha 0.2.2", + "scale-info", + "sp-arithmetic", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-staking" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "log", + "pallet-authorship", + "pallet-session", + "parity-scale-codec", + "rand_chacha 0.2.2", + "scale-info", + "serde", + "sp-application-crypto", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-std", +] + +[[package]] +name = "pallet-staking-reward-fn" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "log", + "sp-arithmetic", +] + +[[package]] +name = "pallet-sudo" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-timestamp" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-inherents", + "sp-io", + "sp-runtime", + "sp-std", + "sp-storage", + "sp-timestamp", +] + +[[package]] +name = "pallet-transaction-payment" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-transaction-payment-rpc-runtime-api" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "pallet-transaction-payment", + "parity-scale-codec", + "sp-api", + "sp-runtime", + "sp-weights", +] + +[[package]] +name = "pallet-treasury" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "serde", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-utility" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-vesting" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-whitelist" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-xcm" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "bounded-collections", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-executor", +] + +[[package]] +name = "pallet-xcm-benchmarks" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", +] + +[[package]] +name = "pallet-xcm-transactor" +version = "0.2.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "cumulus-primitives-core", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "orml-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "xcm-primitives 0.1.1", +] + +[[package]] +name = "parachain-info" +version = "0.1.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "parity-db" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59e9ab494af9e6e813c72170f0d3c1de1500990d62c97cc05cc7576f91aa402f" +dependencies = [ + "blake2", + "crc32fast", + "fs2", + "hex", + "libc", + "log", + "lz4", + "memmap2", + "parking_lot 0.12.1", + "rand 0.8.5", + "siphasher", + "snap", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" +dependencies = [ + "arrayvec 0.7.4", + "bitvec", + "byte-slice-cast", + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parity-send-wrapper" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" + +[[package]] +name = "parity-wasm" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" + +[[package]] +name = "parking" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.8", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.3.5", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "partial_sort" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7924d1d0ad836f665c9065e26d016c673ece3993f30d340068b16f282afc1156" + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pbkdf2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +dependencies = [ + "crypto-mac 0.11.1", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + +[[package]] +name = "pem-rfc7468" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "petgraph" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +dependencies = [ + "fixedbitset", + "indexmap 2.0.2", +] + +[[package]] +name = "pin-project" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "pin-project-lite" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der 0.6.1", + "spki 0.6.0", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.8", + "spki 0.7.2", +] + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "platforms" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" + +[[package]] +name = "polkadot-core-primitives" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "polkadot-node-jaeger" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "lazy_static", + "log", + "mick-jaeger", + "parity-scale-codec", + "parking_lot 0.12.1", + "polkadot-node-primitives", + "polkadot-primitives", + "sc-network", + "sp-core", + "thiserror", + "tokio", +] + +[[package]] +name = "polkadot-node-metrics" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "bs58 0.5.0", + "futures", + "futures-timer", + "log", + "parity-scale-codec", + "polkadot-primitives", + "prioritized-metered-channel", + "sc-cli", + "sc-service", + "sc-tracing", + "substrate-prometheus-endpoint", + "tracing-gum", +] + +[[package]] +name = "polkadot-node-network-protocol" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-channel", + "async-trait", + "bitvec", + "derive_more", + "fatality", + "futures", + "hex", + "parity-scale-codec", + "polkadot-node-jaeger", + "polkadot-node-primitives", + "polkadot-primitives", + "rand 0.8.5", + "sc-authority-discovery", + "sc-network", + "strum", + "thiserror", + "tracing-gum", +] + +[[package]] +name = "polkadot-node-primitives" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "bounded-vec", + "futures", + "parity-scale-codec", + "polkadot-parachain-primitives", + "polkadot-primitives", + "schnorrkel", + "serde", + "sp-application-crypto", + "sp-consensus-babe", + "sp-core", + "sp-keystore", + "sp-maybe-compressed-blob", + "sp-runtime", + "thiserror", + "zstd 0.12.4", +] + +[[package]] +name = "polkadot-node-subsystem-types" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "derive_more", + "futures", + "orchestra", + "polkadot-node-jaeger", + "polkadot-node-network-protocol", + "polkadot-node-primitives", + "polkadot-primitives", + "polkadot-statement-table", + "sc-network", + "sc-transaction-pool-api", + "smallvec", + "sp-api", + "sp-authority-discovery", + "sp-consensus-babe", + "substrate-prometheus-endpoint", + "thiserror", +] + +[[package]] +name = "polkadot-overseer" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "futures", + "futures-timer", + "orchestra", + "parking_lot 0.12.1", + "polkadot-node-metrics", + "polkadot-node-network-protocol", + "polkadot-node-primitives", + "polkadot-node-subsystem-types", + "polkadot-primitives", + "sc-client-api", + "schnellru", + "sp-api", + "sp-core", + "tikv-jemalloc-ctl", + "tracing-gum", +] + +[[package]] +name = "polkadot-parachain-primitives" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "bounded-collections", + "derive_more", + "frame-support", + "parity-scale-codec", + "polkadot-core-primitives", + "scale-info", + "serde", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "polkadot-primitives" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "bitvec", + "hex-literal 0.4.1", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain-primitives", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-authority-discovery", + "sp-consensus-slots", + "sp-core", + "sp-inherents", + "sp-io", + "sp-keystore", + "sp-runtime", + "sp-staking", + "sp-std", +] + +[[package]] +name = "polkadot-runtime-common" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "bitvec", + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "libsecp256k1", + "log", + "pallet-authorship", + "pallet-babe", + "pallet-balances", + "pallet-election-provider-multi-phase", + "pallet-fast-unstake", + "pallet-session", + "pallet-staking", + "pallet-staking-reward-fn", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-treasury", + "pallet-vesting", + "parity-scale-codec", + "polkadot-primitives", + "polkadot-runtime-parachains", + "rustc-hex", + "scale-info", + "serde", + "serde_derive", + "slot-range-helper", + "sp-api", + "sp-core", + "sp-inherents", + "sp-io", + "sp-npos-elections", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std", + "staging-xcm", + "static_assertions", +] + +[[package]] +name = "polkadot-runtime-metrics" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "bs58 0.5.0", + "frame-benchmarking", + "parity-scale-codec", + "polkadot-primitives", + "sp-std", + "sp-tracing", +] + +[[package]] +name = "polkadot-runtime-parachains" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "bitflags 1.3.2", + "bitvec", + "derive_more", + "frame-benchmarking", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "pallet-authority-discovery", + "pallet-authorship", + "pallet-babe", + "pallet-balances", + "pallet-message-queue", + "pallet-session", + "pallet-staking", + "pallet-timestamp", + "pallet-vesting", + "parity-scale-codec", + "polkadot-parachain-primitives", + "polkadot-primitives", + "polkadot-runtime-metrics", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rustc-hex", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-core", + "sp-inherents", + "sp-io", + "sp-keystore", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std", + "staging-xcm", + "staging-xcm-executor", + "static_assertions", +] + +[[package]] +name = "polkadot-statement-table" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "polkadot-primitives", + "sp-core", +] + +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite 0.2.13", + "windows-sys 0.48.0", +] + +[[package]] +name = "poly1305" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +dependencies = [ + "cpufeatures", + "opaque-debug 0.3.0", + "universal-hash 0.4.1", +] + +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug 0.3.0", + "universal-hash 0.4.1", +] + +[[package]] +name = "polyval" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug 0.3.0", + "universal-hash 0.5.1", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "precompile-utils" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "affix", + "environmental", + "evm", + "fp-evm", + "frame-support", + "frame-system", + "hex", + "impl-trait-for-tuples", + "log", + "num_enum 0.5.11", + "pallet-evm", + "parity-scale-codec", + "paste", + "precompile-utils-macro", + "sha3", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", + "staging-xcm", +] + +[[package]] +name = "precompile-utils-macro" +version = "0.1.0" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "case", + "num_enum 0.5.11", + "prettyplease 0.1.25", + "proc-macro2", + "quote", + "sha3", + "syn 1.0.109", +] + +[[package]] +name = "predicates" +version = "2.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" +dependencies = [ + "difflib", + "float-cmp", + "itertools", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" + +[[package]] +name = "predicates-tree" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2", + "syn 2.0.38", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde 0.4.0", + "scale-info", + "uint", +] + +[[package]] +name = "prioritized-metered-channel" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382698e48a268c832d0b181ed438374a6bb708a82a8ca273bb0f61c74cf209c4" +dependencies = [ + "coarsetime", + "crossbeam-queue", + "derive_more", + "futures", + "futures-timer", + "nanorand", + "thiserror", + "tracing", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro-warning" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prometheus" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +dependencies = [ + "cfg-if", + "fnv", + "lazy_static", + "memchr", + "parking_lot 0.12.1", + "thiserror", +] + +[[package]] +name = "prometheus-client" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6fa99d535dd930d1249e6c79cb3c2915f9172a540fe2b02a4c8f9ca954721e" +dependencies = [ + "dtoa", + "itoa", + "parking_lot 0.12.1", + "prometheus-client-derive-encode", +] + +[[package]] +name = "prometheus-client-derive-encode" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +dependencies = [ + "bytes", + "heck", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph", + "prettyplease 0.1.25", + "prost", + "prost-types", + "regex", + "syn 1.0.109", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost", +] + +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quick-protobuf" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6da84cc204722a989e01ba2f6e1e276e190f22263d0cb6ce8526fcdb0d2e1f" +dependencies = [ + "byteorder", +] + +[[package]] +name = "quick-protobuf-codec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1693116345026436eb2f10b677806169c1a1260c1c60eaaffe3fb5a29ae23d8b" +dependencies = [ + "asynchronous-codec", + "bytes", + "quick-protobuf", + "thiserror", + "unsigned-varint", +] + +[[package]] +name = "quicksink" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77de3c815e5a160b1539c6592796801df2043ae35e123b46d73380cfa57af858" +dependencies = [ + "futures-core", + "futures-sink", + "pin-project-lite 0.1.12", +] + +[[package]] +name = "quinn-proto" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" +dependencies = [ + "bytes", + "rand 0.8.5", + "ring 0.16.20", + "rustc-hash", + "rustls 0.20.9", + "slab", + "thiserror", + "tinyvec", + "tracing", + "webpki 0.22.4", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.10", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rcgen" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd" +dependencies = [ + "pem", + "ring 0.16.20", + "time", + "x509-parser 0.13.2", + "yasna", +] + +[[package]] +name = "rcgen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" +dependencies = [ + "pem", + "ring 0.16.20", + "time", + "yasna", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom 0.2.10", + "redox_syscall 0.2.16", + "thiserror", +] + +[[package]] +name = "ref-cast" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acde58d073e9c79da00f2b5b84eed919c8326832648a5b109b3fce1bb1175280" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7473c2cfcf90008193dd0e3e16599455cb601a9fce322b5bb55de799664925" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "regalloc2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80535183cae11b149d618fbd3c37e38d7cda589d82d7769e196ca9a9042d7621" +dependencies = [ + "fxhash", + "log", + "slice-group-by", + "smallvec", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint 0.4.9", + "hmac 0.12.1", + "zeroize", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + +[[package]] +name = "ring" +version = "0.1.0" +source = "git+https://github.com/w3f/ring-proof?rev=0e948f3#0e948f3c28cbacecdd3020403c4841c0eb339213" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "common", + "fflonk", + "merlin 3.0.0", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted 0.7.1", + "web-sys", + "winapi", +] + +[[package]] +name = "ring" +version = "0.17.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fce3045ffa7c981a6ee93f640b538952e155f1ae3a1a02b84547fc7a56b7059a" +dependencies = [ + "cc", + "getrandom 0.2.10", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.48.0", +] + +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rlp-derive", + "rustc-hex", +] + +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rocksdb" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6f170a4041d50a0ce04b0d2e14916d6ca863ea2e422689a5b694395d299ffe" +dependencies = [ + "libc", + "librocksdb-sys", +] + +[[package]] +name = "rpassword" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678cf63ab3491898c0d021b493c94c9b221d91295294a2a5746eacbe5928322" +dependencies = [ + "libc", + "rtoolbox", + "winapi", +] + +[[package]] +name = "rtcp" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1919efd6d4a6a85d13388f9487549bb8e359f17198cc03ffd72f79b553873691" +dependencies = [ + "bytes", + "thiserror", + "webrtc-util", +] + +[[package]] +name = "rtnetlink" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322c53fd76a18698f1c27381d58091de3a043d356aa5bd0d510608b565f469a0" +dependencies = [ + "futures", + "log", + "netlink-packet-route", + "netlink-proto", + "nix", + "thiserror", + "tokio", +] + +[[package]] +name = "rtoolbox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "034e22c514f5c0cb8a10ff341b9b048b5ceb21591f31c8f44c43b960f9b3524a" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "rtp" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a095411ff00eed7b12e4c6a118ba984d113e1079582570d56a5ee723f11f80" +dependencies = [ + "async-trait", + "bytes", + "rand 0.8.5", + "serde", + "thiserror", + "webrtc-util", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.20", +] + +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + +[[package]] +name = "rustix" +version = "0.36.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6da3636faa25820d8648e0e31c5d519bbb01f72fdf57131f0f5f7da5fed36eab" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.1.4", + "windows-sys 0.45.0", +] + +[[package]] +name = "rustix" +version = "0.37.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys 0.4.10", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustls" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +dependencies = [ + "base64 0.13.1", + "log", + "ring 0.16.20", + "sct 0.6.1", + "webpki 0.21.4", +] + +[[package]] +name = "rustls" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" +dependencies = [ + "log", + "ring 0.16.20", + "sct 0.7.0", + "webpki 0.22.4", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "rw-stream-sink" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26338f5e09bb721b85b135ea05af7767c90b52f6de4f087d4f4a3a9d64e7dc04" +dependencies = [ + "futures", + "pin-project", + "static_assertions", +] + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "safe_arch" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f398075ce1e6a179b46f51bd88d0598b92b00d3551f1a2d4ac49e771b56ac354" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "sc-allocator" +version = "4.1.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "log", + "sp-core", + "sp-wasm-interface", + "thiserror", +] + +[[package]] +name = "sc-authority-discovery" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "futures", + "futures-timer", + "ip_network", + "libp2p", + "log", + "multihash", + "parity-scale-codec", + "prost", + "prost-build", + "rand 0.8.5", + "sc-client-api", + "sc-network", + "sp-api", + "sp-authority-discovery", + "sp-blockchain", + "sp-core", + "sp-keystore", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror", +] + +[[package]] +name = "sc-block-builder" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "sc-client-api", + "sp-api", + "sp-block-builder", + "sp-blockchain", + "sp-core", + "sp-inherents", + "sp-runtime", +] + +[[package]] +name = "sc-chain-spec" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "memmap2", + "sc-chain-spec-derive", + "sc-client-api", + "sc-executor", + "sc-network", + "sc-telemetry", + "serde", + "serde_json", + "sp-blockchain", + "sp-core", + "sp-runtime", + "sp-state-machine", +] + +[[package]] +name = "sc-chain-spec-derive" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "sc-cli" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "array-bytes", + "chrono", + "clap", + "fdlimit", + "futures", + "libp2p-identity", + "log", + "names", + "parity-scale-codec", + "rand 0.8.5", + "regex", + "rpassword", + "sc-client-api", + "sc-client-db", + "sc-executor", + "sc-keystore", + "sc-network", + "sc-service", + "sc-telemetry", + "sc-tracing", + "sc-utils", + "serde", + "serde_json", + "sp-blockchain", + "sp-core", + "sp-keyring", + "sp-keystore", + "sp-panic-handler", + "sp-runtime", + "sp-state-machine", + "sp-storage", + "sp-version", + "thiserror", + "tiny-bip39", + "tokio", +] + +[[package]] +name = "sc-client-api" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "fnv", + "futures", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-executor", + "sc-transaction-pool-api", + "sc-utils", + "sp-api", + "sp-blockchain", + "sp-consensus", + "sp-core", + "sp-database", + "sp-externalities", + "sp-runtime", + "sp-state-machine", + "sp-statement-store", + "sp-storage", + "substrate-prometheus-endpoint", +] + +[[package]] +name = "sc-client-db" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "hash-db 0.16.0", + "kvdb", + "kvdb-memorydb", + "kvdb-rocksdb", + "linked-hash-map", + "log", + "parity-db", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-client-api", + "sc-state-db", + "schnellru", + "sp-arithmetic", + "sp-blockchain", + "sp-core", + "sp-database", + "sp-runtime", + "sp-state-machine", + "sp-trie", +] + +[[package]] +name = "sc-consensus" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "futures", + "futures-timer", + "libp2p-identity", + "log", + "mockall", + "parking_lot 0.12.1", + "sc-client-api", + "sc-utils", + "serde", + "sp-api", + "sp-blockchain", + "sp-consensus", + "sp-core", + "sp-runtime", + "sp-state-machine", + "substrate-prometheus-endpoint", + "thiserror", +] + +[[package]] +name = "sc-executor" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-executor-common", + "sc-executor-wasmtime", + "schnellru", + "sp-api", + "sp-core", + "sp-externalities", + "sp-io", + "sp-panic-handler", + "sp-runtime-interface", + "sp-trie", + "sp-version", + "sp-wasm-interface", + "tracing", +] + +[[package]] +name = "sc-executor-common" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "sc-allocator", + "sp-maybe-compressed-blob", + "sp-wasm-interface", + "thiserror", + "wasm-instrument", +] + +[[package]] +name = "sc-executor-wasmtime" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "anyhow", + "cfg-if", + "libc", + "log", + "parity-scale-codec", + "rustix 0.36.16", + "sc-allocator", + "sc-executor-common", + "sp-core", + "sp-runtime-interface", + "sp-wasm-interface", + "wasmtime", +] + +[[package]] +name = "sc-informant" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "ansi_term", + "futures", + "futures-timer", + "log", + "sc-client-api", + "sc-network", + "sc-network-common", + "sp-blockchain", + "sp-runtime", +] + +[[package]] +name = "sc-keystore" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "array-bytes", + "parking_lot 0.12.1", + "serde_json", + "sp-application-crypto", + "sp-core", + "sp-keystore", + "thiserror", +] + +[[package]] +name = "sc-network" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "array-bytes", + "async-channel", + "async-trait", + "asynchronous-codec", + "bytes", + "either", + "fnv", + "futures", + "futures-timer", + "ip_network", + "libp2p", + "linked_hash_set", + "log", + "mockall", + "parity-scale-codec", + "parking_lot 0.12.1", + "partial_sort", + "pin-project", + "rand 0.8.5", + "sc-client-api", + "sc-network-common", + "sc-utils", + "serde", + "serde_json", + "smallvec", + "sp-arithmetic", + "sp-blockchain", + "sp-core", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror", + "unsigned-varint", + "wasm-timer", + "zeroize", +] + +[[package]] +name = "sc-network-bitswap" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-channel", + "cid", + "futures", + "libp2p-identity", + "log", + "prost", + "prost-build", + "sc-client-api", + "sc-network", + "sp-blockchain", + "sp-runtime", + "thiserror", + "unsigned-varint", +] + +[[package]] +name = "sc-network-common" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "bitflags 1.3.2", + "futures", + "libp2p-identity", + "parity-scale-codec", + "prost-build", + "sc-consensus", + "sp-consensus", + "sp-consensus-grandpa", + "sp-runtime", +] + +[[package]] +name = "sc-network-light" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "array-bytes", + "async-channel", + "futures", + "libp2p-identity", + "log", + "parity-scale-codec", + "prost", + "prost-build", + "sc-client-api", + "sc-network", + "sp-blockchain", + "sp-core", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "sc-network-sync" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "array-bytes", + "async-channel", + "async-trait", + "fork-tree", + "futures", + "futures-timer", + "libp2p", + "log", + "mockall", + "parity-scale-codec", + "prost", + "prost-build", + "sc-client-api", + "sc-consensus", + "sc-network", + "sc-network-common", + "sc-utils", + "schnellru", + "smallvec", + "sp-arithmetic", + "sp-blockchain", + "sp-consensus", + "sp-consensus-grandpa", + "sp-core", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror", +] + +[[package]] +name = "sc-network-transactions" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "array-bytes", + "futures", + "libp2p", + "log", + "parity-scale-codec", + "sc-network", + "sc-network-common", + "sc-utils", + "sp-consensus", + "sp-runtime", + "substrate-prometheus-endpoint", +] + +[[package]] +name = "sc-rpc" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "futures", + "jsonrpsee", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-block-builder", + "sc-chain-spec", + "sc-client-api", + "sc-rpc-api", + "sc-tracing", + "sc-transaction-pool-api", + "sc-utils", + "serde_json", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-keystore", + "sp-offchain", + "sp-rpc", + "sp-runtime", + "sp-session", + "sp-statement-store", + "sp-version", + "tokio", +] + +[[package]] +name = "sc-rpc-api" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "jsonrpsee", + "parity-scale-codec", + "sc-chain-spec", + "sc-transaction-pool-api", + "scale-info", + "serde", + "serde_json", + "sp-core", + "sp-rpc", + "sp-runtime", + "sp-version", + "thiserror", +] + +[[package]] +name = "sc-rpc-server" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "http", + "jsonrpsee", + "log", + "serde_json", + "substrate-prometheus-endpoint", + "tokio", + "tower", + "tower-http", +] + +[[package]] +name = "sc-rpc-spec-v2" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "array-bytes", + "futures", + "futures-util", + "hex", + "jsonrpsee", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-chain-spec", + "sc-client-api", + "sc-transaction-pool-api", + "sc-utils", + "serde", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-runtime", + "sp-version", + "thiserror", + "tokio", + "tokio-stream", +] + +[[package]] +name = "sc-service" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "directories", + "exit-future", + "futures", + "futures-timer", + "jsonrpsee", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "pin-project", + "rand 0.8.5", + "sc-block-builder", + "sc-chain-spec", + "sc-client-api", + "sc-client-db", + "sc-consensus", + "sc-executor", + "sc-informant", + "sc-keystore", + "sc-network", + "sc-network-bitswap", + "sc-network-common", + "sc-network-light", + "sc-network-sync", + "sc-network-transactions", + "sc-rpc", + "sc-rpc-server", + "sc-rpc-spec-v2", + "sc-sysinfo", + "sc-telemetry", + "sc-tracing", + "sc-transaction-pool", + "sc-transaction-pool-api", + "sc-utils", + "serde", + "serde_json", + "sp-api", + "sp-blockchain", + "sp-consensus", + "sp-core", + "sp-externalities", + "sp-keystore", + "sp-runtime", + "sp-session", + "sp-state-machine", + "sp-storage", + "sp-transaction-pool", + "sp-transaction-storage-proof", + "sp-trie", + "sp-version", + "static_init", + "substrate-prometheus-endpoint", + "tempfile", + "thiserror", + "tokio", + "tracing", + "tracing-futures", +] + +[[package]] +name = "sc-state-db" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "sp-core", +] + +[[package]] +name = "sc-sysinfo" +version = "6.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "futures", + "libc", + "log", + "rand 0.8.5", + "rand_pcg", + "regex", + "sc-telemetry", + "serde", + "serde_json", + "sp-core", + "sp-io", + "sp-std", +] + +[[package]] +name = "sc-telemetry" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "chrono", + "futures", + "libp2p", + "log", + "parking_lot 0.12.1", + "pin-project", + "rand 0.8.5", + "sc-utils", + "serde", + "serde_json", + "thiserror", + "wasm-timer", +] + +[[package]] +name = "sc-tracing" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "ansi_term", + "atty", + "chrono", + "lazy_static", + "libc", + "log", + "parking_lot 0.12.1", + "regex", + "rustc-hash", + "sc-client-api", + "sc-tracing-proc-macro", + "serde", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-rpc", + "sp-runtime", + "sp-tracing", + "thiserror", + "tracing", + "tracing-log", + "tracing-subscriber", +] + +[[package]] +name = "sc-tracing-proc-macro" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "sc-transaction-pool" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "futures", + "futures-timer", + "linked-hash-map", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-client-api", + "sc-transaction-pool-api", + "sc-utils", + "serde", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-runtime", + "sp-tracing", + "sp-transaction-pool", + "substrate-prometheus-endpoint", + "thiserror", +] + +[[package]] +name = "sc-transaction-pool-api" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "futures", + "log", + "parity-scale-codec", + "serde", + "sp-blockchain", + "sp-core", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "sc-utils" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-channel", + "futures", + "futures-timer", + "lazy_static", + "log", + "parking_lot 0.12.1", + "prometheus", + "sp-arithmetic", +] + +[[package]] +name = "scale-info" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0a159d0c45c12b20c5a844feb1fe4bea86e28f17b92a5f0c42193634d3782" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", + "serde", +] + +[[package]] +name = "scale-info-derive" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "912e55f6d20e0e80d63733872b40e1227c0bce1e1ab81ba67d696339bfd7fd29" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "schnellru" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d" +dependencies = [ + "ahash 0.8.3", + "cfg-if", + "hashbrown 0.13.2", +] + +[[package]] +name = "schnorrkel" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "curve25519-dalek 2.1.3", + "getrandom 0.1.16", + "merlin 2.0.1", + "rand 0.7.3", + "rand_core 0.5.1", + "sha2 0.8.2", + "subtle", + "zeroize", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scratch" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" + +[[package]] +name = "sct" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +dependencies = [ + "ring 0.16.20", + "untrusted 0.7.1", +] + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring 0.16.20", + "untrusted 0.7.1", +] + +[[package]] +name = "sdp" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d22a5ef407871893fd72b4562ee15e4742269b173959db4b8df6f538c414e13" +dependencies = [ + "rand 0.8.5", + "substring", + "thiserror", + "url", +] + +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct 0.1.1", + "der 0.6.1", + "generic-array 0.14.7", + "pkcs8 0.9.0", + "subtle", + "zeroize", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct 0.2.0", + "der 0.7.8", + "generic-array 0.14.7", + "pkcs8 0.10.2", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +dependencies = [ + "cc", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "semver" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +dependencies = [ + "serde", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "serde_json" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde", +] + +[[package]] +name = "session-keys-primitives" +version = "0.1.0" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-v1.1.0#caa31fa405387f445a3265a108310e63a1f83efe" +dependencies = [ + "async-trait", + "frame-support", + "nimbus-primitives", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-application-crypto", + "sp-consensus-babe", + "sp-core", + "sp-inherents", + "sp-keystore", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "simba" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae" +dependencies = [ + "approx", + "num-complex", + "num-traits", + "paste", + "wide", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + +[[package]] +name = "slices" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2086e458a369cdca838e9f6ed04b4cc2e3ce636d99abb80c9e2eada107749cf" +dependencies = [ + "faster-hex", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "slot-range-helper" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "enumn", + "parity-scale-codec", + "paste", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "smallvec" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" + +[[package]] +name = "snap" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831" + +[[package]] +name = "snow" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9d1425eb528a21de2755c75af4c9b5d57f50a0d4c3b7f1828a4cd03f8ba155" +dependencies = [ + "aes-gcm 0.9.4", + "blake2", + "chacha20poly1305", + "curve25519-dalek 4.1.1", + "rand_core 0.6.4", + "ring 0.16.20", + "rustc_version", + "sha2 0.10.8", + "subtle", +] + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "soketto" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" +dependencies = [ + "base64 0.13.1", + "bytes", + "flate2", + "futures", + "http", + "httparse", + "log", + "rand 0.8.5", + "sha-1", +] + +[[package]] +name = "sp-api" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "hash-db 0.16.0", + "log", + "parity-scale-codec", + "scale-info", + "sp-api-proc-macro", + "sp-core", + "sp-externalities", + "sp-metadata-ir", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-trie", + "sp-version", + "thiserror", +] + +[[package]] +name = "sp-api-proc-macro" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "Inflector", + "blake2", + "expander 2.0.0", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "sp-application-crypto" +version = "23.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-std", +] + +[[package]] +name = "sp-arithmetic" +version = "16.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std", + "static_assertions", +] + +[[package]] +name = "sp-authority-discovery" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-application-crypto", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "sp-block-builder" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "sp-api", + "sp-inherents", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "sp-blockchain" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "futures", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "schnellru", + "sp-api", + "sp-consensus", + "sp-database", + "sp-runtime", + "sp-state-machine", + "thiserror", +] + +[[package]] +name = "sp-consensus" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "futures", + "log", + "sp-core", + "sp-inherents", + "sp-runtime", + "sp-state-machine", + "thiserror", +] + +[[package]] +name = "sp-consensus-babe" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "parity-scale-codec", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-consensus-slots", + "sp-core", + "sp-inherents", + "sp-runtime", + "sp-std", + "sp-timestamp", +] + +[[package]] +name = "sp-consensus-grandpa" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "finality-grandpa", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-core", + "sp-keystore", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "sp-consensus-slots" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-std", + "sp-timestamp", +] + +[[package]] +name = "sp-core" +version = "21.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "array-bytes", + "arrayvec 0.7.4", + "bandersnatch_vrfs", + "bitflags 1.3.2", + "blake2", + "bounded-collections", + "bs58 0.5.0", + "dyn-clonable", + "ed25519-zebra", + "futures", + "hash-db 0.16.0", + "hash256-std-hasher", + "impl-serde 0.4.0", + "lazy_static", + "libsecp256k1", + "log", + "merlin 2.0.1", + "parity-scale-codec", + "parking_lot 0.12.1", + "paste", + "primitive-types", + "rand 0.8.5", + "regex", + "scale-info", + "schnorrkel", + "secp256k1", + "secrecy", + "serde", + "sp-core-hashing", + "sp-debug-derive", + "sp-externalities", + "sp-runtime-interface", + "sp-std", + "sp-storage", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tiny-bip39", + "tracing", + "zeroize", +] + +[[package]] +name = "sp-core-hashing" +version = "9.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.7", + "sha2 0.10.8", + "sha3", + "twox-hash", +] + +[[package]] +name = "sp-core-hashing-proc-macro" +version = "9.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "quote", + "sp-core-hashing", + "syn 2.0.38", +] + +[[package]] +name = "sp-database" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "kvdb", + "parking_lot 0.12.1", +] + +[[package]] +name = "sp-debug-derive" +version = "8.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "sp-externalities" +version = "0.19.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-std", + "sp-storage", +] + +[[package]] +name = "sp-genesis-builder" +version = "0.1.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "serde_json", + "sp-api", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "sp-inherents" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", + "thiserror", +] + +[[package]] +name = "sp-io" +version = "23.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "bytes", + "ed25519-dalek 2.0.0", + "libsecp256k1", + "log", + "parity-scale-codec", + "rustversion", + "secp256k1", + "sp-core", + "sp-externalities", + "sp-keystore", + "sp-runtime-interface", + "sp-state-machine", + "sp-std", + "sp-tracing", + "sp-trie", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-keyring" +version = "24.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "lazy_static", + "sp-core", + "sp-runtime", + "strum", +] + +[[package]] +name = "sp-keystore" +version = "0.27.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "parking_lot 0.12.1", + "sp-core", + "sp-externalities", + "thiserror", +] + +[[package]] +name = "sp-maybe-compressed-blob" +version = "4.1.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "thiserror", + "zstd 0.12.4", +] + +[[package]] +name = "sp-metadata-ir" +version = "0.1.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-metadata", + "parity-scale-codec", + "scale-info", + "sp-std", +] + +[[package]] +name = "sp-npos-elections" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-arithmetic", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "sp-offchain" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "sp-api", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "sp-panic-handler" +version = "8.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "backtrace", + "lazy_static", + "regex", +] + +[[package]] +name = "sp-rpc" +version = "6.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "rustc-hash", + "serde", + "sp-core", +] + +[[package]] +name = "sp-runtime" +version = "24.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "paste", + "rand 0.8.5", + "scale-info", + "serde", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-std", + "sp-weights", +] + +[[package]] +name = "sp-runtime-interface" +version = "17.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "primitive-types", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "11.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "Inflector", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "sp-session" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-core", + "sp-keystore", + "sp-runtime", + "sp-staking", + "sp-std", +] + +[[package]] +name = "sp-staking" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "sp-state-machine" +version = "0.28.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "hash-db 0.16.0", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "rand 0.8.5", + "smallvec", + "sp-core", + "sp-externalities", + "sp-panic-handler", + "sp-std", + "sp-trie", + "thiserror", + "tracing", + "trie-db", +] + +[[package]] +name = "sp-statement-store" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "aes-gcm 0.10.3", + "curve25519-dalek 4.1.1", + "ed25519-dalek 2.0.0", + "hkdf", + "parity-scale-codec", + "rand 0.8.5", + "scale-info", + "sha2 0.10.8", + "sp-api", + "sp-application-crypto", + "sp-core", + "sp-externalities", + "sp-runtime", + "sp-runtime-interface", + "sp-std", + "thiserror", + "x25519-dalek 2.0.0", +] + +[[package]] +name = "sp-std" +version = "8.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" + +[[package]] +name = "sp-storage" +version = "13.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "impl-serde 0.4.0", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive", + "sp-std", +] + +[[package]] +name = "sp-timestamp" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "parity-scale-codec", + "sp-inherents", + "sp-runtime", + "sp-std", + "thiserror", +] + +[[package]] +name = "sp-tracing" +version = "10.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "sp-std", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sp-transaction-pool" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "sp-api", + "sp-runtime", +] + +[[package]] +name = "sp-transaction-storage-proof" +version = "4.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "async-trait", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-inherents", + "sp-runtime", + "sp-std", + "sp-trie", +] + +[[package]] +name = "sp-trie" +version = "22.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "ahash 0.8.3", + "hash-db 0.16.0", + "hashbrown 0.13.2", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot 0.12.1", + "scale-info", + "schnellru", + "sp-core", + "sp-std", + "thiserror", + "tracing", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-version" +version = "22.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "impl-serde 0.4.0", + "parity-scale-codec", + "parity-wasm", + "scale-info", + "serde", + "sp-core-hashing-proc-macro", + "sp-runtime", + "sp-std", + "sp-version-proc-macro", + "thiserror", +] + +[[package]] +name = "sp-version-proc-macro" +version = "8.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "sp-wasm-interface" +version = "14.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "anyhow", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "sp-std", + "wasmtime", +] + +[[package]] +name = "sp-weights" +version = "20.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-core", + "sp-debug-derive", + "sp-std", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der 0.6.1", +] + +[[package]] +name = "spki" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +dependencies = [ + "base64ct", + "der 0.7.8", +] + +[[package]] +name = "ss58-registry" +version = "1.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6915280e2d0db8911e5032a5c275571af6bdded2916abd691a659be25d3439" +dependencies = [ + "Inflector", + "num-format", + "proc-macro2", + "quote", + "serde", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "staging-xcm" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "bounded-collections", + "derivative", + "environmental", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-weights", + "xcm-procedural", +] + +[[package]] +name = "staging-xcm-builder" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "pallet-transaction-payment", + "parity-scale-codec", + "polkadot-parachain-primitives", + "scale-info", + "sp-arithmetic", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", + "staging-xcm", + "staging-xcm-executor", +] + +[[package]] +name = "staging-xcm-executor" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "environmental", + "frame-benchmarking", + "frame-support", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", + "staging-xcm", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "static_init" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a2a1c578e98c1c16fc3b8ec1328f7659a500737d7a0c6d625e73e830ff9c1f6" +dependencies = [ + "bitflags 1.3.2", + "cfg_aliases", + "libc", + "parking_lot 0.11.2", + "parking_lot_core 0.8.6", + "static_init_macro", + "winapi", +] + +[[package]] +name = "static_init_macro" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a2595fc3aa78f2d0e45dd425b22282dd863273761cc77780914b2cf3003acf" +dependencies = [ + "cfg_aliases", + "memchr", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.109", +] + +[[package]] +name = "stun" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7e94b1ec00bad60e6410e058b52f1c66de3dc5fe4d62d09b3e52bb7d3b73e25" +dependencies = [ + "base64 0.13.1", + "crc", + "lazy_static", + "md-5", + "rand 0.8.5", + "ring 0.16.20", + "subtle", + "thiserror", + "tokio", + "url", + "webrtc-util", +] + +[[package]] +name = "substrate-bip39" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49eee6965196b32f882dd2ee85a92b1dbead41b04e53907f269de3b0dc04733c" +dependencies = [ + "hmac 0.11.0", + "pbkdf2 0.8.0", + "schnorrkel", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "substrate-bn" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" +dependencies = [ + "byteorder", + "crunchy", + "lazy_static", + "rand 0.8.5", + "rustc-hex", +] + +[[package]] +name = "substrate-fixed" +version = "0.5.9" +source = "git+https://github.com/encointer/substrate-fixed#df67f97a6db9b40215f105613b381ca82f1e2ff4" +dependencies = [ + "parity-scale-codec", + "scale-info", + "typenum 1.16.0", +] + +[[package]] +name = "substrate-prometheus-endpoint" +version = "0.10.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "hyper", + "log", + "prometheus", + "thiserror", + "tokio", +] + +[[package]] +name = "substrate-wasm-builder" +version = "5.0.0-dev" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "ansi_term", + "build-helper", + "cargo_metadata", + "filetime", + "parity-wasm", + "sp-maybe-compressed-blob", + "strum", + "tempfile", + "toml 0.7.8", + "walkdir", + "wasm-opt", +] + +[[package]] +name = "substring" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ee6433ecef213b2e72f587ef64a2f5943e7cd16fbd82dbe8bc07486c534c86" +dependencies = [ + "autocfg", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "target-lexicon" +version = "0.12.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" + +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if", + "fastrand 2.0.1", + "redox_syscall 0.3.5", + "rustix 0.38.19", + "windows-sys 0.48.0", +] + +[[package]] +name = "termcolor" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + +[[package]] +name = "thiserror" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "thrift" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b82ca8f46f95b3ce96081fe3dd89160fdea970c254bb72925255d1b62aae692e" +dependencies = [ + "byteorder", + "integer-encoding", + "log", + "ordered-float", + "threadpool", +] + +[[package]] +name = "tikv-jemalloc-ctl" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "619bfed27d807b54f7f776b9430d4f8060e66ee138a28632ca898584d462c31c" +dependencies = [ + "libc", + "paste", + "tikv-jemalloc-sys", +] + +[[package]] +name = "tikv-jemalloc-sys" +version = "0.5.4+5.3.0-patched" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9402443cb8fd499b6f327e40565234ff34dbda27460c5b47db0db77443dd85d1" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "time" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +dependencies = [ + "deranged", + "itoa", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +dependencies = [ + "time-core", +] + +[[package]] +name = "tiny-bip39" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62cc94d358b5a1e84a5cb9109f559aa3c4d634d2b1b4de3d0fa4adc7c78e2861" +dependencies = [ + "anyhow", + "hmac 0.12.1", + "once_cell", + "pbkdf2 0.11.0", + "rand 0.8.5", + "rustc-hash", + "sha2 0.10.8", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot 0.12.1", + "pin-project-lite 0.2.13", + "signal-hook-registry", + "socket2 0.5.4", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite 0.2.13", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "pin-project-lite 0.2.13", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.0.2", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" +dependencies = [ + "bitflags 2.4.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "pin-project-lite 0.2.13", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2ef2af84856a50c1d430afce2fdded0a4ec7eda868db86409b4543df0797f9" +dependencies = [ + "log", + "pin-project-lite 0.2.13", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "tracing-gum" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "coarsetime", + "polkadot-node-jaeger", + "polkadot-primitives", + "tracing", + "tracing-gum-proc-macro", +] + +[[package]] +name = "tracing-gum-proc-macro" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "expander 2.0.0", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "ansi_term", + "chrono", + "lazy_static", + "matchers", + "parking_lot 0.11.2", + "regex", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", +] + +[[package]] +name = "trie-db" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "767abe6ffed88a1889671a102c2861ae742726f52e0a5a425b92c9fbfa7e9c85" +dependencies = [ + "hash-db 0.16.0", + "hashbrown 0.13.2", + "log", + "rustc-hex", + "smallvec", +] + +[[package]] +name = "trie-root" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +dependencies = [ + "hash-db 0.16.0", +] + +[[package]] +name = "triehash" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1631b201eb031b563d2e85ca18ec8092508e262a3196ce9bd10a67ec87b9f5c" +dependencies = [ + "hash-db 0.15.2", + "rlp", +] + +[[package]] +name = "trust-dns-proto" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.2.3", + "ipnet", + "lazy_static", + "rand 0.8.5", + "smallvec", + "socket2 0.4.9", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aff21aa4dcefb0a1afbfac26deb0adc93888c7d295fb63ab273ef276ba2b7cfe" +dependencies = [ + "cfg-if", + "futures-util", + "ipconfig", + "lazy_static", + "lru-cache", + "parking_lot 0.12.1", + "resolv-conf", + "smallvec", + "thiserror", + "tokio", + "tracing", + "trust-dns-proto", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "tt-call" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f195fd851901624eee5a58c4bb2b4f06399148fcd0ed336e6f1cb60a9881df" + +[[package]] +name = "turn" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4712ee30d123ec7ae26d1e1b218395a16c87cdbaf4b3925d170d684af62ea5e8" +dependencies = [ + "async-trait", + "base64 0.13.1", + "futures", + "log", + "md-5", + "rand 0.8.5", + "ring 0.16.20", + "stun", + "thiserror", + "tokio", + "webrtc-util", +] + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "digest 0.10.7", + "rand 0.8.5", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "git+https://github.com/encointer/typenum?tag=polkadot-v1.0.0#4cba9a73f7e94ba38c824616efab93f177c9a556" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "unsigned-varint" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" +dependencies = [ + "asynchronous-codec", + "bytes", + "futures-io", + "futures-util", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +dependencies = [ + "form_urlencoded", + "idna 0.4.0", + "percent-encoding", +] + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "uuid" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +dependencies = [ + "getrandom 0.2.10", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "waitgroup" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1f50000a783467e6c0200f9d10642f4bc424e39efc1b770203e88b488f79292" +dependencies = [ + "atomic-waker", +] + +[[package]] +name = "waker-fn" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" + +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.38", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "wasm-instrument" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa1dafb3e60065305741e83db35c6c2584bb3725b692b5b66148a38d72ace6cd" +dependencies = [ + "parity-wasm", +] + +[[package]] +name = "wasm-opt" +version = "0.114.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d005a95f934878a1fb446a816d51c3601a0120ff929005ba3bab3c749cfd1c7" +dependencies = [ + "anyhow", + "libc", + "strum", + "strum_macros", + "tempfile", + "thiserror", + "wasm-opt-cxx-sys", + "wasm-opt-sys", +] + +[[package]] +name = "wasm-opt-cxx-sys" +version = "0.114.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d04e240598162810fad3b2e96fa0dec6dba1eb65a03f3bd99a9248ab8b56caa" +dependencies = [ + "anyhow", + "cxx", + "cxx-build", + "wasm-opt-sys", +] + +[[package]] +name = "wasm-opt-sys" +version = "0.114.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2efd2aaca519d64098c4faefc8b7433a97ed511caf4c9e516384eb6aef1ff4f9" +dependencies = [ + "anyhow", + "cc", + "cxx", + "cxx-build", +] + +[[package]] +name = "wasm-timer" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" +dependencies = [ + "futures", + "js-sys", + "parking_lot 0.11.2", + "pin-utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.102.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48134de3d7598219ab9eaf6b91b15d8e50d31da76b8519fe4ecfcec2cf35104b" +dependencies = [ + "indexmap 1.9.3", + "url", +] + +[[package]] +name = "wasmtime" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f907fdead3153cb9bfb7a93bbd5b62629472dc06dee83605358c64c52ed3dda9" +dependencies = [ + "anyhow", + "bincode", + "cfg-if", + "indexmap 1.9.3", + "libc", + "log", + "object 0.30.4", + "once_cell", + "paste", + "psm", + "rayon", + "serde", + "target-lexicon", + "wasmparser", + "wasmtime-cache", + "wasmtime-cranelift", + "wasmtime-environ", + "wasmtime-jit", + "wasmtime-runtime", + "windows-sys 0.45.0", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b9daa7c14cd4fa3edbf69de994408d5f4b7b0959ac13fa69d465f6597f810d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "wasmtime-cache" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86437fa68626fe896e5afc69234bb2b5894949083586535f200385adfd71213" +dependencies = [ + "anyhow", + "base64 0.21.4", + "bincode", + "directories-next", + "file-per-thread-logger", + "log", + "rustix 0.36.16", + "serde", + "sha2 0.10.8", + "toml 0.5.11", + "windows-sys 0.45.0", + "zstd 0.11.2+zstd.1.5.2", +] + +[[package]] +name = "wasmtime-cranelift" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1cefde0cce8cb700b1b21b6298a3837dba46521affd7b8c38a9ee2c869eee04" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "cranelift-wasm", + "gimli 0.27.3", + "log", + "object 0.30.4", + "target-lexicon", + "thiserror", + "wasmparser", + "wasmtime-cranelift-shared", + "wasmtime-environ", +] + +[[package]] +name = "wasmtime-cranelift-shared" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd041e382ef5aea1b9fc78442394f1a4f6d676ce457e7076ca4cb3f397882f8b" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-native", + "gimli 0.27.3", + "object 0.30.4", + "target-lexicon", + "wasmtime-environ", +] + +[[package]] +name = "wasmtime-environ" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a990198cee4197423045235bf89d3359e69bd2ea031005f4c2d901125955c949" +dependencies = [ + "anyhow", + "cranelift-entity", + "gimli 0.27.3", + "indexmap 1.9.3", + "log", + "object 0.30.4", + "serde", + "target-lexicon", + "thiserror", + "wasmparser", + "wasmtime-types", +] + +[[package]] +name = "wasmtime-jit" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de48df552cfca1c9b750002d3e07b45772dd033b0b206d5c0968496abf31244" +dependencies = [ + "addr2line 0.19.0", + "anyhow", + "bincode", + "cfg-if", + "cpp_demangle", + "gimli 0.27.3", + "log", + "object 0.30.4", + "rustc-demangle", + "serde", + "target-lexicon", + "wasmtime-environ", + "wasmtime-jit-debug", + "wasmtime-jit-icache-coherence", + "wasmtime-runtime", + "windows-sys 0.45.0", +] + +[[package]] +name = "wasmtime-jit-debug" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0554b84c15a27d76281d06838aed94e13a77d7bf604bbbaf548aa20eb93846" +dependencies = [ + "object 0.30.4", + "once_cell", + "rustix 0.36.16", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aecae978b13f7f67efb23bd827373ace4578f2137ec110bbf6a4a7cde4121bbd" +dependencies = [ + "cfg-if", + "libc", + "windows-sys 0.45.0", +] + +[[package]] +name = "wasmtime-runtime" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658cf6f325232b6760e202e5255d823da5e348fdea827eff0a2a22319000b441" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "indexmap 1.9.3", + "libc", + "log", + "mach", + "memfd", + "memoffset 0.8.0", + "paste", + "rand 0.8.5", + "rustix 0.36.16", + "wasmtime-asm-macros", + "wasmtime-environ", + "wasmtime-jit-debug", + "windows-sys 0.45.0", +] + +[[package]] +name = "wasmtime-types" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f6fffd2a1011887d57f07654dd112791e872e3ff4a2e626aee8059ee17f06f" +dependencies = [ + "cranelift-entity", + "serde", + "thiserror", + "wasmparser", +] + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +dependencies = [ + "ring 0.16.20", + "untrusted 0.7.1", +] + +[[package]] +name = "webpki" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +dependencies = [ + "ring 0.17.4", + "untrusted 0.9.0", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki 0.22.4", +] + +[[package]] +name = "webrtc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3bc9049bdb2cea52f5fd4f6f728184225bdb867ed0dc2410eab6df5bdd67bb" +dependencies = [ + "arc-swap", + "async-trait", + "bytes", + "hex", + "interceptor", + "lazy_static", + "log", + "rand 0.8.5", + "rcgen 0.9.3", + "regex", + "ring 0.16.20", + "rtcp", + "rtp", + "rustls 0.19.1", + "sdp", + "serde", + "serde_json", + "sha2 0.10.8", + "stun", + "thiserror", + "time", + "tokio", + "turn", + "url", + "waitgroup", + "webrtc-data", + "webrtc-dtls", + "webrtc-ice", + "webrtc-mdns", + "webrtc-media", + "webrtc-sctp", + "webrtc-srtp", + "webrtc-util", +] + +[[package]] +name = "webrtc-data" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef36a4d12baa6e842582fe9ec16a57184ba35e1a09308307b67d43ec8883100" +dependencies = [ + "bytes", + "derive_builder", + "log", + "thiserror", + "tokio", + "webrtc-sctp", + "webrtc-util", +] + +[[package]] +name = "webrtc-dtls" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a00f4242f2db33307347bd5be53263c52a0331c96c14292118c9a6bb48d267" +dependencies = [ + "aes 0.6.0", + "aes-gcm 0.10.3", + "async-trait", + "bincode", + "block-modes", + "byteorder", + "ccm", + "curve25519-dalek 3.2.0", + "der-parser 8.2.0", + "elliptic-curve 0.12.3", + "hkdf", + "hmac 0.12.1", + "log", + "p256", + "p384", + "rand 0.8.5", + "rand_core 0.6.4", + "rcgen 0.10.0", + "ring 0.16.20", + "rustls 0.19.1", + "sec1 0.3.0", + "serde", + "sha1", + "sha2 0.10.8", + "signature 1.6.4", + "subtle", + "thiserror", + "tokio", + "webpki 0.21.4", + "webrtc-util", + "x25519-dalek 2.0.0", + "x509-parser 0.13.2", +] + +[[package]] +name = "webrtc-ice" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "465a03cc11e9a7d7b4f9f99870558fe37a102b65b93f8045392fef7c67b39e80" +dependencies = [ + "arc-swap", + "async-trait", + "crc", + "log", + "rand 0.8.5", + "serde", + "serde_json", + "stun", + "thiserror", + "tokio", + "turn", + "url", + "uuid", + "waitgroup", + "webrtc-mdns", + "webrtc-util", +] + +[[package]] +name = "webrtc-mdns" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f08dfd7a6e3987e255c4dbe710dde5d94d0f0574f8a21afa95d171376c143106" +dependencies = [ + "log", + "socket2 0.4.9", + "thiserror", + "tokio", + "webrtc-util", +] + +[[package]] +name = "webrtc-media" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f72e1650a8ae006017d1a5280efb49e2610c19ccc3c0905b03b648aee9554991" +dependencies = [ + "byteorder", + "bytes", + "rand 0.8.5", + "rtp", + "thiserror", +] + +[[package]] +name = "webrtc-sctp" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d47adcd9427eb3ede33d5a7f3424038f63c965491beafcc20bc650a2f6679c0" +dependencies = [ + "arc-swap", + "async-trait", + "bytes", + "crc", + "log", + "rand 0.8.5", + "thiserror", + "tokio", + "webrtc-util", +] + +[[package]] +name = "webrtc-srtp" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6183edc4c1c6c0175f8812eefdce84dfa0aea9c3ece71c2bf6ddd3c964de3da5" +dependencies = [ + "aead 0.4.3", + "aes 0.7.5", + "aes-gcm 0.9.4", + "async-trait", + "byteorder", + "bytes", + "ctr 0.8.0", + "hmac 0.11.0", + "log", + "rtcp", + "rtp", + "sha-1", + "subtle", + "thiserror", + "tokio", + "webrtc-util", +] + +[[package]] +name = "webrtc-util" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f1db1727772c05cf7a2cfece52c3aca8045ca1e176cd517d323489aa3c6d87" +dependencies = [ + "async-trait", + "bitflags 1.3.2", + "bytes", + "cc", + "ipnet", + "lazy_static", + "libc", + "log", + "nix", + "rand 0.8.5", + "thiserror", + "tokio", + "winapi", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.19", +] + +[[package]] +name = "wide" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68938b57b33da363195412cfc5fc37c9ed49aa9cfe2156fde64b8d2c9498242" +dependencies = [ + "bytemuck", + "safe_arch", +] + +[[package]] +name = "widestring" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "winnow" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x25519-dalek" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" +dependencies = [ + "curve25519-dalek 3.2.0", + "rand_core 0.5.1", + "zeroize", +] + +[[package]] +name = "x25519-dalek" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96" +dependencies = [ + "curve25519-dalek 4.1.1", + "rand_core 0.6.4", + "serde", + "zeroize", +] + +[[package]] +name = "x509-parser" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb9bace5b5589ffead1afb76e43e34cff39cd0f3ce7e170ae0c29e53b88eb1c" +dependencies = [ + "asn1-rs 0.3.1", + "base64 0.13.1", + "data-encoding", + "der-parser 7.0.0", + "lazy_static", + "nom", + "oid-registry 0.4.0", + "ring 0.16.20", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "x509-parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" +dependencies = [ + "asn1-rs 0.5.2", + "base64 0.13.1", + "data-encoding", + "der-parser 8.2.0", + "lazy_static", + "nom", + "oid-registry 0.6.1", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "xcm-primitives" +version = "0.1.0" +source = "git+https://github.com/Moonsong-Labs/moonkit?branch=moonbeam-polkadot-v1.1.0#caa31fa405387f445a3265a108310e63a1f83efe" +dependencies = [ + "sp-runtime", +] + +[[package]] +name = "xcm-primitives" +version = "0.1.1" +source = "git+https://github.com/PureStake/moonbeam?rev=runtime-2601#ac6aee3c3beec560a9266e63c1b389ca9c521505" +dependencies = [ + "cumulus-primitives-core", + "ethereum", + "ethereum-types", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex", + "impl-trait-for-tuples", + "log", + "orml-traits", + "pallet-staking", + "parity-scale-codec", + "scale-info", + "serde", + "sha3", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", +] + +[[package]] +name = "xcm-procedural" +version = "1.0.0" +source = "git+https://github.com/moonbeam-foundation/polkadot-sdk?branch=moonbeam-polkadot-v1.1.0#87b160e8f60c171862f471a390a78ec03b4f7358" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "yamux" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d9ba232399af1783a58d8eb26f6b5006fbefe2dc9ef36bd283324792d03ea5" +dependencies = [ + "futures", + "log", + "nohash-hasher", + "parking_lot 0.12.1", + "rand 0.8.5", + "static_assertions", +] + +[[package]] +name = "yasna" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time", +] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe 5.0.2+zstd.1.5.2", +] + +[[package]] +name = "zstd" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a27595e173641171fc74a1232b7b1c7a7cb6e18222c11e9dfb9888fa424c53c" +dependencies = [ + "zstd-safe 6.0.6", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-safe" +version = "6.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee98ffd0b48ee95e6c5168188e44a54550b1564d9d530ee21d5f0eaed1069581" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.9+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/tracing/2601/Cargo.toml b/tracing/2601/Cargo.toml new file mode 100644 index 00000000..d41fcca8 --- /dev/null +++ b/tracing/2601/Cargo.toml @@ -0,0 +1,423 @@ +[workspace] +members = [ + "runtime/moonbase", + "runtime/moonbeam", + "runtime/moonriver", +] +resolver = "2" + +[workspace.package] +authors = [ "PureStake" ] +repository = "https://github.com/PureStake/moonbeam" + +[workspace.dependencies] +# Dependencies are split into 2 groups: wasm and client. +# - "wasm" dependencies requires to be no_std compatible, which often requires +# `default-features = false`. When used in a client-side crate the "std" feature should be enabled +# there if it exists. +# - "client" dependencies are only used in the client, and thus don't need to be no_std compatible. + +# Moonbeam (wasm) +account = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +evm-tracing-events = { path = "shared/primitives/rpc/evm-tracing-events", default-features = false , features = ["runtime-1600"] } +moonbeam-core-primitives = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +moonbeam-primitives-ext = { path = "shared/primitives/ext", default-features = false } +moonbeam-rpc-primitives-debug = { path = "shared/primitives/rpc/debug", default-features = false } +moonbeam-rpc-primitives-txpool = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } + +moonbeam-evm-tracer = { path = "shared/runtime/evm_tracer", default-features = false } +moonbeam-relay-encoder = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +moonbeam-runtime-common = { path = "runtime/common", default-features = false } + +moonbeam-xcm-benchmarks = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-asset-manager = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-erc20-xcm-bridge = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-ethereum-xcm = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } + +pallet-evm-precompile-author-mapping = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-balances-erc20 = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-batch = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-call-permit = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-collective = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-conviction-voting = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-crowdloan-rewards = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-democracy = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-gmp = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-identity = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-parachain-staking = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-preimage = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-proxy = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-randomness = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-referenda = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-registry = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-relay-encoder = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-xcm-transactor = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-xcm-utils = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompile-xtokens = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-evm-precompileset-assets-erc20 = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-moonbeam-orbiters = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-parachain-staking = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-proxy-genesis-companion = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +pallet-xcm-transactor = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +precompile-utils = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +xcm-primitives = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } + +pallet-crowdloan-rewards = { git = "https://github.com/moonbeam-foundation/crowdloan-rewards", branch = "moonbeam-polkadot-v1.1.0", default-features = false } + +# Moonbeam (client) +moonbeam-cli = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +moonbeam-cli-opt = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +moonbeam-service = { default-features = false , git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } + +manual-xcm-rpc = { git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +moonbeam-client-evm-tracing = { git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +moonbeam-finality-rpc = { git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +moonbeam-rpc-core-debug = { git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +moonbeam-rpc-core-trace = { git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +moonbeam-rpc-core-txpool = { git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +moonbeam-rpc-core-types = { git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +moonbeam-rpc-debug = { git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +moonbeam-rpc-trace = { git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +moonbeam-rpc-txpool = { git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } +moonbeam-vrf = { git = "https://github.com/PureStake/moonbeam", rev = "runtime-2601" } + +moonbase-runtime = { path = "runtime/moonbase" } +moonbeam-runtime = { path = "runtime/moonbeam" } +moonriver-runtime = { path = "runtime/moonriver" } + +# Substrate (wasm) +frame-benchmarking = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +frame-executive = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +frame-support = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +frame-system = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +frame-system-benchmarking = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +frame-try-runtime = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-assets = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-balances = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-collective = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-conviction-voting = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-democracy = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-identity = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-message-queue = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +pallet-multisig = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-preimage = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-proxy = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-referenda = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-root-testing = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-scheduler = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-society = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-staking = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-sudo = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-timestamp = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-transaction-payment = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-treasury = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-utility = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-whitelist = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +parity-scale-codec = { version = "3.2.2", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.0", default-features = false, features = [ + "derive", +] } +sp-api = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-application-crypto = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-block-builder = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-consensus-babe = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-core = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-debug-derive = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-externalities = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-inherents = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-io = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-keystore = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-offchain = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-runtime = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-runtime-interface = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-session = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-std = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-transaction-pool = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-version = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +sp-weights = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +substrate-fixed = { git = "https://github.com/encointer/substrate-fixed", default-features = false } + +# Substrate (client) +frame-benchmarking-cli = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +pallet-transaction-payment-rpc = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-basic-authorship = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-block-builder = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-chain-spec = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-cli = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-client-api = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-client-db = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-consensus = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-consensus-grandpa = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-consensus-manual-seal = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-executor = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-informant = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-network = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-network-common = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-network-sync = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-offchain = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-rpc = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-rpc-api = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-service = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-sysinfo = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-telemetry = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-tracing = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-transaction-pool = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-transaction-pool-api = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sc-utils = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sp-blockchain = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sp-consensus = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sp-storage = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sp-timestamp = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sp-trie = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +sp-wasm-interface = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +substrate-build-script-utils = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +substrate-frame-rpc-system = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +substrate-prometheus-endpoint = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +substrate-test-client = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +substrate-test-runtime = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +substrate-test-runtime-client = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +substrate-wasm-builder = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +try-runtime-cli = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } + +# Frontier (wasm) +ethereum = { version = "0.14.0", default-features = false, features = [ + "with-codec", +] } +ethereum-types = { version = "0.14", default-features = false } +evm = { git = "https://github.com/moonbeam-foundation/evm", rev = "a33ac87ad7462b7e7029d12c385492b2a8311d1c", default-features = false } +evm-gasometer = { git = "https://github.com/moonbeam-foundation/evm", rev = "a33ac87ad7462b7e7029d12c385492b2a8311d1c", default-features = false } +evm-runtime = { git = "https://github.com/moonbeam-foundation/evm", rev = "a33ac87ad7462b7e7029d12c385492b2a8311d1c", default-features = false } +fp-ethereum = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +fp-evm = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +fp-rpc = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +fp-self-contained = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-base-fee = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-ethereum = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", default-features = false, features = [ + "forbid-evm-reentrancy", +] } +pallet-evm = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", default-features = false, features = [ + "forbid-evm-reentrancy", +] } +pallet-evm-chain-id = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-evm-precompile-blake2 = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-evm-precompile-bn128 = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-evm-precompile-dispatch = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-evm-precompile-modexp = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-evm-precompile-sha3fips = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-evm-precompile-simple = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", default-features = false } + +# Frontier (client) +fc-consensus = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0" } +fc-db = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0" } +fc-mapping-sync = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0" } +fc-rpc = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0", features = [ + "rpc-binary-search-estimate", +] } +fc-rpc-core = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0" } +fc-storage = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0" } +fp-consensus = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0" } +fp-storage = { git = "https://github.com/moonbeam-foundation/frontier", branch = "moonbeam-polkadot-v1.1.0" } + +# Cumulus (wasm) +cumulus-pallet-dmp-queue = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +cumulus-pallet-parachain-system = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +cumulus-pallet-xcm = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +cumulus-pallet-xcmp-queue = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +cumulus-primitives-core = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +cumulus-primitives-parachain-inherent = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +cumulus-primitives-timestamp = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +cumulus-primitives-utility = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +cumulus-test-relay-sproof-builder = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +parachain-info = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } + +# Cumulus (client) +cumulus-client-cli = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +cumulus-client-collator = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +cumulus-client-consensus-common = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +cumulus-client-consensus-relay-chain = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +cumulus-client-network = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +cumulus-client-service = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +cumulus-relay-chain-inprocess-interface = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +cumulus-relay-chain-interface = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +cumulus-relay-chain-minimal-node = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +cumulus-relay-chain-rpc-interface = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } + +# Polkadot / XCM (wasm) +orml-traits = { git = "https://github.com/moonbeam-foundation/open-runtime-module-library", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +orml-xcm-support = { git = "https://github.com/moonbeam-foundation/open-runtime-module-library", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +orml-xtokens = { git = "https://github.com/moonbeam-foundation/open-runtime-module-library", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-xcm = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-xcm-benchmarks = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +polkadot-core-primitives = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +polkadot-parachain = { package = "polkadot-parachain-primitives", git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +xcm = { package = "staging-xcm", git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0", default-features = false } + +# Polkadot / XCM (client) +kusama-runtime = { package = "staging-kusama-runtime", git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +polkadot-cli = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +polkadot-primitives = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +polkadot-runtime = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +polkadot-runtime-common = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +polkadot-runtime-parachains = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +polkadot-service = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +rococo-runtime = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +westend-runtime = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } +xcm-simulator = { git = "https://github.com/moonbeam-foundation/polkadot-sdk", branch = "moonbeam-polkadot-v1.1.0" } + +# Moonkit (wasm) +moonkit-xcm-primitives = { package = "xcm-primitives", git = "https://github.com/Moonsong-Labs/moonkit", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +nimbus-primitives = { git = "https://github.com/Moonsong-Labs/moonkit", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-author-inherent = { git = "https://github.com/Moonsong-Labs/moonkit", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-author-mapping = { git = "https://github.com/Moonsong-Labs/moonkit", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-author-slot-filter = { git = "https://github.com/Moonsong-Labs/moonkit", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-maintenance-mode = { git = "https://github.com/Moonsong-Labs/moonkit", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-migrations = { git = "https://github.com/Moonsong-Labs/moonkit", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +pallet-randomness = { git = "https://github.com/Moonsong-Labs/moonkit", branch = "moonbeam-polkadot-v1.1.0", default-features = false } +session-keys-primitives = { git = "https://github.com/Moonsong-Labs/moonkit", branch = "moonbeam-polkadot-v1.1.0", default-features = false } + +# Moonkit (client) +nimbus-consensus = { git = "https://github.com/Moonsong-Labs/moonkit", branch = "moonbeam-polkadot-v1.1.0" } + +# Other (wasm) +affix = "0.1.2" +async-trait = { version = "0.1.42" } +blake2-rfc = { version = "0.2.18", default-features = false } +derive_more = "0.99" +environmental = { version = "1.1.2", default-features = false } +frame-metadata = { version = "16.0.0", default-features = false, features = ["current"] } +hex = { version = "0.4.3", default-features = false } +hex-literal = { version = "0.3.4" } +impl-serde = { version = "0.3.1", default-features = false } +impl-trait-for-tuples = "0.2.1" +libsecp256k1 = { version = "0.7", default-features = false } +log = { version = "0.4", default-features = false } +num_enum = { version = "0.5.3", default-features = false } +paste = "1.0.6" +rlp = { version = "0.5", default-features = false } +rustc-hex = { version = "2.0.1", default-features = false } +serde = { version = "1.0.101", default-features = false } +sha3 = { version = "0.10", default-features = false } +slices = "0.2.0" +smallvec = "1.8.0" +strum = { version = "0.24", default-features = false, features = [ "derive" ] } +strum_macros = "0.24" + +# Other (client) +ansi_term = "0.12.1" +assert_cmd = "2.0.10" +async-io = "1.3" +bip32 = { version = "0.5.1", default-features = false, features = [ + "bip39", +] } +clap = { version = "4.0.9", features = [ "derive" ] } +exit-future = "0.2" +flume = "0.10.9" +futures = { version = "0.3.21" } +jsonrpsee = { version = "0.16.2", default-features = false } +maplit = "1.0.2" +nix = "0.23" +parking_lot = "0.12.0" +primitive-types = "0.12.0" +prometheus = { version = "0.13.0", default-features = false } +rand = "0.7.3" +schnorrkel = { version = "0.9.1", default-features = false, features = [ + "preaudit_deprecated", + "u64_backend", +] } +serde_json = { version = "1.0" } +similar-asserts = "1.1.0" +tempfile = "3.2.0" +tiny-bip39 = { version = "0.8", default-features = false } +tokio = { version = "1.13" } +tracing = "0.1.34" +tracing-core = "0.1.29" +trie-root = "0.15.2" +url = "2.2.2" + +# The list of dependencies below (which can be both direct and indirect dependencies) are crates +# that are suspected to be CPU-intensive, and that are unlikely to require debugging (as some of +# their debug info might be missing) or to require to be frequently recompiled. We compile these +# dependencies with `opt-level=3` even in "dev" mode in order to make "dev" mode more usable. +# The majority of these crates are cryptographic libraries. +# +# Note that this does **not** affect crates that depend on Moonbeam. In other words, if you add +# a dependency on Moonbeam, you have to copy-paste this list in your own `Cargo.toml` (assuming +# that you want the same list). This list is only relevant when running `cargo build` from within +# the Moonbeam workspace. +# +# If you see an error mentioning "profile package spec ... did not match any packages", it +# probably concerns this list. +# +# This list is ordered alphabetically. +[profile.dev.package] +blake2 = { opt-level = 3 } +blake2b_simd = { opt-level = 3 } +chacha20poly1305 = { opt-level = 3 } +cranelift-codegen = { opt-level = 3 } +cranelift-wasm = { opt-level = 3 } +crc32fast = { opt-level = 3 } +crossbeam-deque = { opt-level = 3 } +crypto-mac = { opt-level = 3 } +curve25519-dalek = { opt-level = 3 } +ed25519-zebra = { opt-level = 3 } +flate2 = { opt-level = 3 } +futures-channel = { opt-level = 3 } +hash-db = { opt-level = 3 } +hashbrown = { opt-level = 3 } +hmac = { opt-level = 3 } +httparse = { opt-level = 3 } +integer-sqrt = { opt-level = 3 } +k256 = { opt-level = 3 } +keccak = { opt-level = 3 } +libm = { opt-level = 3 } +librocksdb-sys = { opt-level = 3 } +libsecp256k1 = { opt-level = 3 } +libz-sys = { opt-level = 3 } +mio = { opt-level = 3 } +nalgebra = { opt-level = 3 } +num-bigint = { opt-level = 3 } +parking_lot = { opt-level = 3 } +parking_lot_core = { opt-level = 3 } +percent-encoding = { opt-level = 3 } +primitive-types = { opt-level = 3 } +ring = { opt-level = 3 } +rustls = { opt-level = 3 } +secp256k1 = { opt-level = 3 } +sha2 = { opt-level = 3 } +sha3 = { opt-level = 3 } +smallvec = { opt-level = 3 } +snow = { opt-level = 3 } +twox-hash = { opt-level = 3 } +uint = { opt-level = 3 } +wasmi = { opt-level = 3 } +x25519-dalek = { opt-level = 3 } +yamux = { opt-level = 3 } +zeroize = { opt-level = 3 } + +# make sure dev builds with backtrace do +# not slow us down +[profile.dev.package.backtrace] +inherits = "release" + +[profile.production] +codegen-units = 1 +incremental = false +inherits = "release" +lto = true + +[profile.release] +# Moonbeam runtime requires unwinding. +opt-level = 3 +panic = "unwind" + +[profile.testnet] +debug = 1 # debug symbols are useful for profilers +debug-assertions = true +inherits = "release" +overflow-checks = true diff --git a/tracing/2601/runtime/common/Cargo.toml b/tracing/2601/runtime/common/Cargo.toml new file mode 100644 index 00000000..005f1e13 --- /dev/null +++ b/tracing/2601/runtime/common/Cargo.toml @@ -0,0 +1,134 @@ +[package] +name = "moonbeam-runtime-common" +authors = { workspace = true } +description = "Common code shared between runtimes" +edition = "2021" +homepage = "https://moonbeam.network" +license = "GPL-3.0-only" +version = "0.8.0-dev" + +[dependencies] +hex-literal = "0.3.4" +impl-trait-for-tuples = "0.2.1" +log = "0.4" + +# Moonbeam +moonbeam-xcm-benchmarks = { workspace = true } +pallet-asset-manager = { workspace = true } +pallet-author-mapping = { workspace = true } +pallet-conviction-voting = { workspace = true } +pallet-ethereum-xcm = { workspace = true } +pallet-migrations = { workspace = true } +pallet-parachain-staking = { workspace = true } +pallet-randomness = { workspace = true } +pallet-xcm-transactor = { workspace = true } +precompile-utils = { workspace = true } +xcm-primitives = { workspace = true } + +# Substrate +cumulus-pallet-xcmp-queue = { workspace = true } +frame-benchmarking = { workspace = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +pallet-assets = { workspace = true } +pallet-balances = { workspace = true } +pallet-collective = { workspace = true } +pallet-crowdloan-rewards = { workspace = true } +pallet-democracy = { workspace = true } +pallet-identity = { workspace = true } +pallet-moonbeam-orbiters = { workspace = true } +pallet-multisig = { workspace = true } +pallet-preimage = { workspace = true } +pallet-proxy = { workspace = true } +pallet-referenda = { workspace = true } +pallet-scheduler = { workspace = true } +pallet-sudo = { workspace = true } +pallet-timestamp = { workspace = true } +pallet-treasury = { workspace = true } +pallet-utility = { workspace = true } +pallet-whitelist = { workspace = true } +pallet-xcm = { workspace = true } +sp-api = { workspace = true } +sp-core = { workspace = true } +sp-runtime = { workspace = true } +sp-std = { workspace = true } + + +# Frontier +fp-ethereum = { workspace = true } +fp-evm = { workspace = true } +pallet-base-fee = { workspace = true } +pallet-evm = { workspace = true, features = [ "forbid-evm-reentrancy" ] } +pallet-evm-chain-id = { workspace = true } + +# Nimbus +nimbus-primitives = { workspace = true } +pallet-author-inherent = { workspace = true } +pallet-author-slot-filter = { workspace = true } + +# Polkadot +xcm = { workspace = true } +xcm-builder = { workspace = true } +xcm-executor = { workspace = true } + +[features] +std = [ + "fp-ethereum/std", + "fp-evm/std", + "frame-support/std", + "pallet-asset-manager/std", + "pallet-author-inherent/std", + "pallet-author-mapping/std", + "pallet-base-fee/std", + "pallet-ethereum-xcm/std", + "pallet-evm/std", + "pallet-migrations/std", + "pallet-parachain-staking/std", + "pallet-randomness/std", + "pallet-referenda/std", + "pallet-scheduler/std", + "pallet-xcm-transactor/std", + "precompile-utils/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", + "xcm-executor/std", + "xcm/std", +] +runtime-benchmarks = [ + "cumulus-pallet-xcmp-queue/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "pallet-asset-manager/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pallet-author-inherent/runtime-benchmarks", + "pallet-author-mapping/runtime-benchmarks", + "pallet-author-slot-filter/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-conviction-voting/runtime-benchmarks", + "pallet-crowdloan-rewards/runtime-benchmarks", + "pallet-democracy/runtime-benchmarks", + "pallet-ethereum-xcm/runtime-benchmarks", + "pallet-evm/runtime-benchmarks", + "pallet-identity/runtime-benchmarks", + "pallet-moonbeam-orbiters/runtime-benchmarks", + "pallet-multisig/runtime-benchmarks", + "pallet-parachain-staking/runtime-benchmarks", + "pallet-preimage/runtime-benchmarks", + "pallet-proxy/runtime-benchmarks", + "pallet-randomness/runtime-benchmarks", + "pallet-referenda/runtime-benchmarks", + "pallet-referenda/runtime-benchmarks", + "pallet-scheduler/runtime-benchmarks", + "pallet-sudo/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "pallet-treasury/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "pallet-whitelist/runtime-benchmarks", + "pallet-xcm-transactor/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "moonbeam-xcm-benchmarks/runtime-benchmarks", +] +try-runtime = [ + "frame-support/try-runtime", + "pallet-migrations/try-runtime", +] diff --git a/tracing/2601/runtime/common/src/apis.rs b/tracing/2601/runtime/common/src/apis.rs new file mode 100644 index 00000000..81d831fc --- /dev/null +++ b/tracing/2601/runtime/common/src/apis.rs @@ -0,0 +1,810 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +#[macro_export] +macro_rules! impl_runtime_apis_plus_common { + {$($custom:tt)*} => { + impl_runtime_apis! { + $($custom)* + + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + OpaqueMetadata::new(Runtime::metadata().into()) + } + + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) + } + + fn metadata_versions() -> Vec { + Runtime::metadata_versions() + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalize_block() -> ::Header { + Executive::finalize_block() + } + + fn inherent_extrinsics( + data: sp_inherents::InherentData, + ) -> Vec<::Extrinsic> { + data.create_extrinsics() + } + + fn check_inherents( + block: Block, + data: sp_inherents::InherentData, + ) -> sp_inherents::CheckInherentsResult { + data.check_extrinsics(&block) + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + Executive::offchain_worker(header) + } + } + + impl sp_session::SessionKeys for Runtime { + fn decode_session_keys( + encoded: Vec, + ) -> Option, sp_core::crypto::KeyTypeId)>> { + opaque::SessionKeys::decode_into_raw_public_keys(&encoded) + } + + fn generate_session_keys(seed: Option>) -> Vec { + opaque::SessionKeys::generate(seed) + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Index { + System::account_nonce(account) + } + } + + impl moonbeam_rpc_primitives_debug::DebugRuntimeApi for Runtime { + fn trace_transaction( + extrinsics: Vec<::Extrinsic>, + traced_transaction: &EthereumTransaction, + ) -> Result< + (), + sp_runtime::DispatchError, + > { + #[cfg(feature = "evm-tracing")] + { + use moonbeam_evm_tracer::tracer::EvmTracer; + use xcm_primitives::{ + ETHEREUM_XCM_TRACING_STORAGE_KEY, + EthereumXcmTracingStatus + }; + use frame_support::storage::unhashed; + + // Tell the CallDispatcher we are tracing a specific Transaction. + unhashed::put::( + ETHEREUM_XCM_TRACING_STORAGE_KEY, + &EthereumXcmTracingStatus::Transaction(traced_transaction.hash()), + ); + + // Apply the a subset of extrinsics: all the substrate-specific or ethereum + // transactions that preceded the requested transaction. + for ext in extrinsics.into_iter() { + let _ = match &ext.0.function { + RuntimeCall::Ethereum(transact { transaction }) => { + if transaction == traced_transaction { + EvmTracer::new().trace(|| Executive::apply_extrinsic(ext)); + return Ok(()); + } else { + Executive::apply_extrinsic(ext) + } + } + _ => Executive::apply_extrinsic(ext), + }; + if let Some(EthereumXcmTracingStatus::TransactionExited) = unhashed::get( + ETHEREUM_XCM_TRACING_STORAGE_KEY + ) { + return Ok(()); + } + } + Err(sp_runtime::DispatchError::Other( + "Failed to find Ethereum transaction among the extrinsics.", + )) + } + #[cfg(not(feature = "evm-tracing"))] + Err(sp_runtime::DispatchError::Other( + "Missing `evm-tracing` compile time feature flag.", + )) + } + + fn trace_block( + extrinsics: Vec<::Extrinsic>, + known_transactions: Vec, + ) -> Result< + (), + sp_runtime::DispatchError, + > { + #[cfg(feature = "evm-tracing")] + { + use moonbeam_evm_tracer::tracer::EvmTracer; + use xcm_primitives::EthereumXcmTracingStatus; + + // Tell the CallDispatcher we are tracing a full Block. + frame_support::storage::unhashed::put::( + xcm_primitives::ETHEREUM_XCM_TRACING_STORAGE_KEY, + &EthereumXcmTracingStatus::Block, + ); + + let mut config = ::config().clone(); + config.estimate = true; + + // Apply all extrinsics. Ethereum extrinsics are traced. + for ext in extrinsics.into_iter() { + match &ext.0.function { + RuntimeCall::Ethereum(transact { transaction }) => { + if known_transactions.contains(&transaction.hash()) { + // Each known extrinsic is a new call stack. + EvmTracer::emit_new(); + EvmTracer::new().trace(|| Executive::apply_extrinsic(ext)); + } else { + let _ = Executive::apply_extrinsic(ext); + } + } + _ => { + let _ = Executive::apply_extrinsic(ext); + } + }; + } + + Ok(()) + } + #[cfg(not(feature = "evm-tracing"))] + Err(sp_runtime::DispatchError::Other( + "Missing `evm-tracing` compile time feature flag.", + )) + } + } + + impl moonbeam_rpc_primitives_txpool::TxPoolRuntimeApi for Runtime { + fn extrinsic_filter( + xts_ready: Vec<::Extrinsic>, + xts_future: Vec<::Extrinsic>, + ) -> TxPoolResponse { + TxPoolResponse { + ready: xts_ready + .into_iter() + .filter_map(|xt| match xt.0.function { + RuntimeCall::Ethereum(transact { transaction }) => Some(transaction), + _ => None, + }) + .collect(), + future: xts_future + .into_iter() + .filter_map(|xt| match xt.0.function { + RuntimeCall::Ethereum(transact { transaction }) => Some(transaction), + _ => None, + }) + .collect(), + } + } + } + + impl fp_rpc::EthereumRuntimeRPCApi for Runtime { + fn chain_id() -> u64 { + ::ChainId::get() + } + + fn account_basic(address: H160) -> EVMAccount { + let (account, _) = EVM::account_basic(&address); + account + } + + fn gas_price() -> U256 { + let (gas_price, _) = ::FeeCalculator::min_gas_price(); + gas_price + } + + fn account_code_at(address: H160) -> Vec { + pallet_evm::AccountCodes::::get(address) + } + + fn author() -> H160 { + >::find_author() + } + + fn storage_at(address: H160, index: U256) -> H256 { + let mut tmp = [0u8; 32]; + index.to_big_endian(&mut tmp); + pallet_evm::AccountStorages::::get(address, H256::from_slice(&tmp[..])) + } + + fn call( + from: H160, + to: H160, + data: Vec, + value: U256, + gas_limit: U256, + max_fee_per_gas: Option, + max_priority_fee_per_gas: Option, + nonce: Option, + estimate: bool, + access_list: Option)>>, + ) -> Result { + let config = if estimate { + let mut config = ::config().clone(); + config.estimate = true; + Some(config) + } else { + None + }; + let is_transactional = false; + let validate = true; + + // Estimated encoded transaction size must be based on the heaviest transaction + // type (EIP1559Transaction) to be compatible with all transaction types. + let mut estimated_transaction_len = data.len() + + // pallet ethereum index: 1 + // transact call index: 1 + // Transaction enum variant: 1 + // chain_id 8 bytes + // nonce: 32 + // max_priority_fee_per_gas: 32 + // max_fee_per_gas: 32 + // gas_limit: 32 + // action: 21 (enum varianrt + call address) + // value: 32 + // access_list: 1 (empty vec size) + // 65 bytes signature + 258; + + if access_list.is_some() { + estimated_transaction_len += access_list.encoded_size(); + } + + let gas_limit = gas_limit.min(u64::MAX.into()).low_u64(); + let without_base_extrinsic_weight = true; + + let (weight_limit, proof_size_base_cost) = + match ::GasWeightMapping::gas_to_weight( + gas_limit, + without_base_extrinsic_weight + ) { + weight_limit if weight_limit.proof_size() > 0 => { + (Some(weight_limit), Some(estimated_transaction_len as u64)) + } + _ => (None, None), + }; + + ::Runner::call( + from, + to, + data, + value, + gas_limit, + max_fee_per_gas, + max_priority_fee_per_gas, + nonce, + access_list.unwrap_or_default(), + is_transactional, + validate, + weight_limit, + proof_size_base_cost, + config.as_ref().unwrap_or(::config()), + ).map_err(|err| err.error.into()) + } + + fn create( + from: H160, + data: Vec, + value: U256, + gas_limit: U256, + max_fee_per_gas: Option, + max_priority_fee_per_gas: Option, + nonce: Option, + estimate: bool, + access_list: Option)>>, + ) -> Result { + let config = if estimate { + let mut config = ::config().clone(); + config.estimate = true; + Some(config) + } else { + None + }; + let is_transactional = false; + let validate = true; + + let mut estimated_transaction_len = data.len() + + // from: 20 + // value: 32 + // gas_limit: 32 + // nonce: 32 + // 1 byte transaction action variant + // chain id 8 bytes + // 65 bytes signature + 190; + + if max_fee_per_gas.is_some() { + estimated_transaction_len += 32; + } + if max_priority_fee_per_gas.is_some() { + estimated_transaction_len += 32; + } + if access_list.is_some() { + estimated_transaction_len += access_list.encoded_size(); + } + + let gas_limit = if gas_limit > U256::from(u64::MAX) { + u64::MAX + } else { + gas_limit.low_u64() + }; + let without_base_extrinsic_weight = true; + + let (weight_limit, proof_size_base_cost) = + match ::GasWeightMapping::gas_to_weight( + gas_limit, + without_base_extrinsic_weight + ) { + weight_limit if weight_limit.proof_size() > 0 => { + (Some(weight_limit), Some(estimated_transaction_len as u64)) + } + _ => (None, None), + }; + + #[allow(clippy::or_fun_call)] // suggestion not helpful here + ::Runner::create( + from, + data, + value, + gas_limit, + max_fee_per_gas, + max_priority_fee_per_gas, + nonce, + access_list.unwrap_or_default(), + is_transactional, + validate, + weight_limit, + proof_size_base_cost, + config.as_ref().unwrap_or(::config()), + ).map_err(|err| err.error.into()) + } + + fn current_transaction_statuses() -> Option> { + pallet_ethereum::CurrentTransactionStatuses::::get() + } + + fn current_block() -> Option { + pallet_ethereum::CurrentBlock::::get() + } + + fn current_receipts() -> Option> { + pallet_ethereum::CurrentReceipts::::get() + } + + fn current_all() -> ( + Option, + Option>, + Option>, + ) { + ( + pallet_ethereum::CurrentBlock::::get(), + pallet_ethereum::CurrentReceipts::::get(), + pallet_ethereum::CurrentTransactionStatuses::::get(), + ) + } + + fn extrinsic_filter( + xts: Vec<::Extrinsic>, + ) -> Vec { + xts.into_iter().filter_map(|xt| match xt.0.function { + RuntimeCall::Ethereum(transact { transaction }) => Some(transaction), + _ => None + }).collect::>() + } + + fn elasticity() -> Option { + None + } + + fn gas_limit_multiplier_support() {} + + fn pending_block( + xts: Vec<::Extrinsic> + ) -> ( + Option, Option> + ) { + for ext in xts.into_iter() { + let _ = Executive::apply_extrinsic(ext); + } + + Ethereum::on_finalize(System::block_number() + 1); + + ( + pallet_ethereum::CurrentBlock::::get(), + pallet_ethereum::CurrentTransactionStatuses::::get() + ) + } + } + + impl fp_rpc::ConvertTransactionRuntimeApi for Runtime { + fn convert_transaction( + transaction: pallet_ethereum::Transaction + ) -> ::Extrinsic { + UncheckedExtrinsic::new_unsigned( + pallet_ethereum::Call::::transact { transaction }.into(), + ) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + for Runtime { + fn query_info( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) + } + + fn query_fee_details( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment::FeeDetails { + TransactionPayment::query_fee_details(uxt, len) + } + + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } + } + + impl nimbus_primitives::NimbusApi for Runtime { + fn can_author( + author: nimbus_primitives::NimbusId, + slot: u32, + parent_header: &::Header + ) -> bool { + let block_number = parent_header.number + 1; + + // The Moonbeam runtimes use an entropy source that needs to do some accounting + // work during block initialization. Therefore we initialize it here to match + // the state it will be in when the next block is being executed. + use frame_support::traits::OnInitialize; + System::initialize( + &block_number, + &parent_header.hash(), + &parent_header.digest, + ); + + // Because the staking solution calculates the next staking set at the beginning + // of the first block in the new round, the only way to accurately predict the + // authors is to compute the selection during prediction. + if pallet_parachain_staking::Pallet::::round().should_update(block_number) { + // get author account id + use nimbus_primitives::AccountLookup; + let author_account_id = if let Some(account) = + pallet_author_mapping::Pallet::::lookup_account(&author) { + account + } else { + // return false if author mapping not registered like in can_author impl + return false + }; + let candidates = pallet_parachain_staking::Pallet::::compute_top_candidates(); + if candidates.is_empty() { + // If there are zero selected candidates, we use the same eligibility + // as the previous round + return AuthorInherent::can_author(&author, &slot); + } + + // predict eligibility post-selection by computing selection results now + let (eligible, _) = + pallet_author_slot_filter::compute_pseudo_random_subset::( + candidates, + &slot + ); + eligible.contains(&author_account_id) + } else { + AuthorInherent::can_author(&author, &slot) + } + } + } + + impl cumulus_primitives_core::CollectCollationInfo for Runtime { + fn collect_collation_info( + header: &::Header + ) -> cumulus_primitives_core::CollationInfo { + ParachainSystem::collect_collation_info(header) + } + } + + impl session_keys_primitives::VrfApi for Runtime { + fn get_last_vrf_output() -> Option<::Hash> { + // TODO: remove in future runtime upgrade along with storage item + if pallet_randomness::Pallet::::not_first_block().is_none() { + return None; + } + pallet_randomness::Pallet::::local_vrf_output() + } + fn vrf_key_lookup( + nimbus_id: nimbus_primitives::NimbusId + ) -> Option { + use session_keys_primitives::KeysLookup; + AuthorMapping::lookup_keys(&nimbus_id) + } + } + + #[cfg(feature = "runtime-benchmarks")] + impl frame_benchmarking::Benchmark for Runtime { + + fn benchmark_metadata(extra: bool) -> ( + Vec, + Vec, + ) { + use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; + use moonbeam_xcm_benchmarks::generic::benchmarking as MoonbeamXcmBenchmarks; + use frame_support::traits::StorageInfoTrait; + use MoonbeamXcmBenchmarks::XcmGenericBenchmarks as MoonbeamXcmGenericBench; + + let mut list = Vec::::new(); + list_benchmarks!(list, extra); + + let storage_info = AllPalletsWithSystem::storage_info(); + + return (list, storage_info) + } + + fn dispatch_benchmark( + config: frame_benchmarking::BenchmarkConfig, + ) -> Result, sp_runtime::RuntimeString> { + use frame_benchmarking::{add_benchmark, BenchmarkBatch, Benchmarking}; + use frame_support::traits::TrackedStorageKey; + + use xcm::latest::prelude::*; + use frame_benchmarking::BenchmarkError; + + use frame_system_benchmarking::Pallet as SystemBench; + impl frame_system_benchmarking::Config for Runtime {} + + impl moonbeam_xcm_benchmarks::Config for Runtime {} + impl moonbeam_xcm_benchmarks::generic::Config for Runtime {} + + use pallet_asset_manager::Config as PalletAssetManagerConfig; + impl pallet_xcm_benchmarks::Config for Runtime { + type XcmConfig = xcm_config::XcmExecutorConfig; + type AccountIdConverter = xcm_config::LocationToAccountId; + fn valid_destination() -> Result { + Ok(MultiLocation::parent()) + } + fn worst_case_holding(_depositable_count: u32) -> MultiAssets { + // 100 fungibles + const HOLDING_FUNGIBLES: u32 = 100; + let fungibles_amount: u128 = 100; + let assets = (0..HOLDING_FUNGIBLES).map(|i| { + let location: MultiLocation = GeneralIndex(i as u128).into(); + MultiAsset { + id: Concrete(location), + fun: Fungible(fungibles_amount * i as u128), + } + .into() + }) + .chain( + core::iter::once( + MultiAsset { + id: Concrete(MultiLocation::parent()), + fun: Fungible(u128::MAX) + } + ) + ) + .collect::>(); + + + for (i, asset) in assets.iter().enumerate() { + if let MultiAsset { + id: Concrete(location), + fun: Fungible(_) + } = asset { + ::AssetId, + ::ForeignAssetType> + >::set_asset_type_asset_id( + location.clone().into(), + i as u128 + ); + // set 1-1 + ::ForeignAssetType> + >::set_units_per_second( + location.clone().into(), + 1_000_000_000_000u128 + ); + } + } + assets.into() + } + } + + impl pallet_xcm_benchmarks::generic::Config for Runtime { + type RuntimeCall = RuntimeCall; + + fn worst_case_response() -> (u64, Response) { + (0u64, Response::Version(Default::default())) + } + + fn worst_case_asset_exchange() + -> Result<(MultiAssets, MultiAssets), BenchmarkError> { + Err(BenchmarkError::Skip) + } + + fn universal_alias() -> Result<(MultiLocation, Junction), BenchmarkError> { + Err(BenchmarkError::Skip) + } + + fn export_message_origin_and_destination() + -> Result<(MultiLocation, NetworkId, Junctions), BenchmarkError> { + Err(BenchmarkError::Skip) + } + + fn transact_origin_and_runtime_call() + -> Result<(MultiLocation, RuntimeCall), BenchmarkError> { + Ok((MultiLocation::parent(), frame_system::Call::remark_with_event { + remark: vec![] + }.into())) + } + + fn subscribe_origin() -> Result { + Ok(MultiLocation::parent()) + } + + fn claimable_asset() + -> Result<(MultiLocation, MultiLocation, MultiAssets), BenchmarkError> { + let origin = MultiLocation::parent(); + let assets: MultiAssets = (Concrete(MultiLocation::parent()), 1_000u128) + .into(); + let ticket = MultiLocation { parents: 0, interior: Here }; + Ok((origin, ticket, assets)) + } + + fn unlockable_asset() + -> Result<(MultiLocation, MultiLocation, MultiAsset), BenchmarkError> { + Err(BenchmarkError::Skip) + } + + fn alias_origin() -> Result<(MultiLocation, MultiLocation), BenchmarkError> { + Err(BenchmarkError::Skip) + } + } + + let whitelist: Vec = vec![ + // Block Number + hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7" + "02a5c1b19ab7a04f536c519aca4983ac") + .to_vec().into(), + // Total Issuance + hex_literal::hex!( "c2261276cc9d1f8598ea4b6a74b15c2f" + "57c875e4cff74148e4628f264b974c80") + .to_vec().into(), + // Execution Phase + hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7" + "ff553b5a9862a516939d82b3d3d8661a") + .to_vec().into(), + // Event Count + hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7" + "0a98fdbe9ce6c55837576c60c7af3850") + .to_vec().into(), + // System Events + hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7" + "80d41e5e16056765bc8461851072c9d7") + .to_vec().into(), + // System BlockWeight + hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7" + "34abf5cb34d6244378cddbf18e849d96") + .to_vec().into(), + // ParachainStaking Round + hex_literal::hex!( "a686a3043d0adcf2fa655e57bc595a78" + "13792e785168f725b60e2969c7fc2552") + .to_vec().into(), + // Treasury Account (py/trsry) + hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7" + "b99d880ec681799c0cf30e8886371da9" + "7be2919ac397ba499ea5e57132180ec6" + "6d6f646c70792f747273727900000000" + "00000000" + ).to_vec().into(), + // Treasury Account (pc/trsry) + hex_literal::hex!( "26aa394eea5630e07c48ae0c9558cef7" + "b99d880ec681799c0cf30e8886371da9" + "7be2919ac397ba499ea5e57132180ec6" + "6d6f646c70632f747273727900000000" + "00000000" + ).to_vec().into(), + // ParachainInfo ParachainId + hex_literal::hex!( "0d715f2646c8f85767b5d2764bb27826" + "04a74d81251e398fd8a0a4d55023bb3f") + .to_vec().into(), + + ]; + + let mut batches = Vec::::new(); + let params = (&config, &whitelist); + + add_benchmarks!(params, batches); + + if batches.is_empty() { + return Err("Benchmark not found for this pallet.".into()); + } + Ok(batches) + } + } + + #[cfg(feature = "try-runtime")] + impl frame_try_runtime::TryRuntime for Runtime { + fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { + log::info!("try-runtime::on_runtime_upgrade()"); + // NOTE: intentional expect: we don't want to propagate the error backwards, + // and want to have a backtrace here. If any of the pre/post migration checks + // fail, we shall stop right here and right now. + let weight = Executive::try_runtime_upgrade(checks) + .expect("runtime upgrade logic *must* be infallible"); + (weight, RuntimeBlockWeights::get().max_block) + } + + fn execute_block( + block: Block, + state_root_check: bool, + signature_check: bool, + select: frame_try_runtime::TryStateSelect + ) -> Weight { + log::info!( + "try-runtime: executing block {:?} / root checks: {:?} / try-state-select: {:?}", + block.header.hash(), + state_root_check, + select, + ); + // NOTE: intentional unwrap: we don't want to propagate the error backwards, + // and want to have a backtrace here. + Executive::try_execute_block( + block, + state_root_check, + signature_check, + select, + ).expect("execute-block failed") + } + } + } + }; +} diff --git a/tracing/2601/runtime/common/src/impl_moonbeam_xcm_call.rs b/tracing/2601/runtime/common/src/impl_moonbeam_xcm_call.rs new file mode 100644 index 00000000..112c457c --- /dev/null +++ b/tracing/2601/runtime/common/src/impl_moonbeam_xcm_call.rs @@ -0,0 +1,51 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +#[macro_export] +macro_rules! impl_moonbeam_xcm_call { + {} => { + + pub struct MoonbeamCall; + impl CallDispatcher for MoonbeamCall { + fn dispatch( + call: RuntimeCall, + origin: RuntimeOrigin, + ) -> Result< + PostDispatchInfoOf, + DispatchErrorWithPostInfo> + > { + if let Ok(raw_origin) = TryInto::>::try_into(origin.clone().caller) { + match (call.clone(), raw_origin) { + ( + RuntimeCall::EthereumXcm(pallet_ethereum_xcm::Call::transact { .. }) | + RuntimeCall::EthereumXcm(pallet_ethereum_xcm::Call::transact_through_proxy { .. }), + RawOrigin::Signed(account_id) + ) => { + return RuntimeCall::dispatch( + call, + pallet_ethereum_xcm::Origin::XcmEthereumTransaction( + account_id.into() + ).into() + ); + }, + _ => {} + } + } + RuntimeCall::dispatch(call, origin) + } + } + } +} diff --git a/tracing/2601/runtime/common/src/impl_moonbeam_xcm_call_tracing.rs b/tracing/2601/runtime/common/src/impl_moonbeam_xcm_call_tracing.rs new file mode 100644 index 00000000..87b1c94e --- /dev/null +++ b/tracing/2601/runtime/common/src/impl_moonbeam_xcm_call_tracing.rs @@ -0,0 +1,112 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +#[macro_export] +macro_rules! impl_moonbeam_xcm_call_tracing { + {} => { + + type CallResult = + Result< + PostDispatchInfoOf, + DispatchErrorWithPostInfo> + >; + + pub struct MoonbeamCall; + impl CallDispatcher for MoonbeamCall { + fn dispatch( + call: RuntimeCall, + origin: RuntimeOrigin, + ) -> CallResult { + if let Ok(raw_origin) = TryInto::>::try_into(origin.clone().caller) { + match (call.clone(), raw_origin) { + ( + RuntimeCall::EthereumXcm(pallet_ethereum_xcm::Call::transact { xcm_transaction }) | + RuntimeCall::EthereumXcm(pallet_ethereum_xcm::Call::transact_through_proxy { + xcm_transaction, .. + }), + RawOrigin::Signed(account_id) + ) => { + use crate::EthereumXcm; + use moonbeam_evm_tracer::tracer::EvmTracer; + use xcm_primitives::{ + XcmToEthereum, + EthereumXcmTracingStatus, + ETHEREUM_XCM_TRACING_STORAGE_KEY + }; + use frame_support::storage::unhashed; + use frame_support::traits::Get; + + let dispatch_call = || { + RuntimeCall::dispatch( + call, + pallet_ethereum_xcm::Origin::XcmEthereumTransaction( + account_id.into() + ).into() + ) + }; + + return match unhashed::get( + ETHEREUM_XCM_TRACING_STORAGE_KEY + ) { + // This runtime instance is used for tracing. + Some(transaction) => match transaction { + // Tracing a block, all calls are done using environmental. + EthereumXcmTracingStatus::Block => { + // Each known extrinsic is a new call stack. + EvmTracer::emit_new(); + let mut res: Option = None; + EvmTracer::new().trace(|| { + res = Some(dispatch_call()); + }); + res.expect("Invalid dispatch result") + }, + // Tracing a transaction, the one matching the trace request + // is done using environmental, the rest dispatched normally. + EthereumXcmTracingStatus::Transaction(traced_transaction_hash) => { + let transaction_hash = xcm_transaction.into_transaction_v2( + EthereumXcm::nonce(), + ::ChainId::get() + ) + .expect("Invalid transaction conversion") + .hash(); + if transaction_hash == traced_transaction_hash { + let mut res: Option = None; + EvmTracer::new().trace(|| { + res = Some(dispatch_call()); + }); + // Tracing runtime work is done, just signal instance exit. + unhashed::put::( + xcm_primitives::ETHEREUM_XCM_TRACING_STORAGE_KEY, + &EthereumXcmTracingStatus::TransactionExited, + ); + return res.expect("Invalid dispatch result"); + } + dispatch_call() + }, + _ => unreachable!() + }, + // This runtime instance is importing a block. + None => dispatch_call() + }; + }, + _ => {} + } + } + RuntimeCall::dispatch(call, origin) + } + } + } +} diff --git a/tracing/2601/runtime/common/src/impl_on_charge_evm_transaction.rs b/tracing/2601/runtime/common/src/impl_on_charge_evm_transaction.rs new file mode 100644 index 00000000..122d5afc --- /dev/null +++ b/tracing/2601/runtime/common/src/impl_on_charge_evm_transaction.rs @@ -0,0 +1,68 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +#[macro_export] +macro_rules! impl_on_charge_evm_transaction { + {} => { + type CurrencyAccountId = ::AccountId; + + type BalanceFor = + <::Currency as CurrencyT>>::Balance; + + type PositiveImbalanceFor = + <::Currency as CurrencyT>>::PositiveImbalance; + + type NegativeImbalanceFor = + <::Currency as CurrencyT>>::NegativeImbalance; + + pub struct OnChargeEVMTransaction(sp_std::marker::PhantomData); + impl OnChargeEVMTransactionT for OnChargeEVMTransaction + where + T: pallet_evm::Config, + PositiveImbalanceFor: Imbalance, Opposite = NegativeImbalanceFor>, + NegativeImbalanceFor: Imbalance, Opposite = PositiveImbalanceFor>, + OU: OnUnbalanced>, + U256: UniqueSaturatedInto> + { + type LiquidityInfo = Option>; + + fn withdraw_fee(who: &H160, fee: U256) -> Result> { + EVMCurrencyAdapter::<::Currency, ()>::withdraw_fee(who, fee) + } + + fn can_withdraw(who: &H160, amount: U256) -> Result<(), pallet_evm::Error> { + EVMCurrencyAdapter::<::Currency, ()>::can_withdraw(who, amount) + } + + fn correct_and_deposit_fee( + who: &H160, + corrected_fee: U256, + base_fee: U256, + already_withdrawn: Self::LiquidityInfo, + ) -> Self::LiquidityInfo { + ::Currency, OU> as OnChargeEVMTransactionT< + T, + >>::correct_and_deposit_fee(who, corrected_fee, base_fee, already_withdrawn) + } + + fn pay_priority_fee(tip: Self::LiquidityInfo) { + if let Some(tip) = tip { + OU::on_unbalanced(tip); + } + } + } + } +} diff --git a/tracing/2601/runtime/common/src/impl_self_contained_call.rs b/tracing/2601/runtime/common/src/impl_self_contained_call.rs new file mode 100644 index 00000000..0dbce052 --- /dev/null +++ b/tracing/2601/runtime/common/src/impl_self_contained_call.rs @@ -0,0 +1,78 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +#[macro_export] +macro_rules! impl_self_contained_call { + {} => { + impl fp_self_contained::SelfContainedCall for RuntimeCall { + type SignedInfo = H160; + + fn is_self_contained(&self) -> bool { + match self { + RuntimeCall::Ethereum(call) => call.is_self_contained(), + _ => false, + } + } + + fn check_self_contained( + &self + ) -> Option> { + match self { + RuntimeCall::Ethereum(call) => call.check_self_contained(), + _ => None, + } + } + + fn validate_self_contained( + &self, + signed_info: &Self::SignedInfo, + dispatch_info: &DispatchInfoOf, + len: usize, + ) -> Option { + match self { + RuntimeCall::Ethereum(call) => call.validate_self_contained(signed_info, dispatch_info, len), + _ => None, + } + } + + fn pre_dispatch_self_contained( + &self, + info: &Self::SignedInfo, + dispatch_info: &DispatchInfoOf, + len: usize, + ) -> Option> { + match self { + RuntimeCall::Ethereum(call) => call.pre_dispatch_self_contained(info, dispatch_info, len), + _ => None, + } + } + + fn apply_self_contained( + self, + info: Self::SignedInfo, + ) -> Option>> { + match self { + call @ RuntimeCall::Ethereum(pallet_ethereum::Call::transact { .. }) => Some( + call.dispatch(RuntimeOrigin::from( + pallet_ethereum::RawOrigin::EthereumTransaction(info) + )) + ), + _ => None, + } + } + } + } +} diff --git a/tracing/2601/runtime/common/src/impl_xcm_evm_runner.rs b/tracing/2601/runtime/common/src/impl_xcm_evm_runner.rs new file mode 100644 index 00000000..7eebe42d --- /dev/null +++ b/tracing/2601/runtime/common/src/impl_xcm_evm_runner.rs @@ -0,0 +1,188 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +#[macro_export] +macro_rules! impl_evm_runner_precompile_or_eth_xcm { + {} => { + use fp_evm::{CallInfo, CallOrCreateInfo, Context, Transfer}; + use frame_support::dispatch::CallableCallFor; + use pallet_evm::{Runner, RunnerError}; + use precompile_utils::{prelude::*, evm::handle::with_precompile_handle}; + use sp_core::U256; + use sp_runtime::DispatchError; + use sp_std::vec::Vec; + use xcm_primitives::{EthereumXcmTransaction, EthereumXcmTransactionV2}; + + pub struct EvmRunnerPrecompileOrEthXcm( + core::marker::PhantomData<(CallDispatcher, Runtime)>, + ); + + impl Runner + for EvmRunnerPrecompileOrEthXcm + where + CallDispatcher: xcm_executor::traits::CallDispatcher, + Runtime: pallet_evm::Config + pallet_ethereum_xcm::Config, + Runtime::RuntimeOrigin: From, + { + type Error = DispatchError; + + fn call( + source: H160, + target: H160, + input: Vec, + value: U256, + gas_limit: u64, + _max_fee_per_gas: Option, + _max_priority_fee_per_gas: Option, + _nonce: Option, + access_list: Vec<(H160, Vec)>, + _is_transactional: bool, + _validate: bool, + _weight_limit: Option, + _transaction_len: Option, + _config: &fp_evm::Config, + ) -> Result> { + // The `with_precompile_handle` function will execute the closure (and return the + // result in a Some) if and only if there is an available EVM context. Otherwise, + // it will return None. + if let Some((exit_reason, value)) = with_precompile_handle(|precompile_handle| { + let transfer = if value.is_zero() { + None + } else { + Some(Transfer { + source, + target, + value, + }) + }; + + precompile_handle.call( + target, + transfer, + input.clone(), + Some(gas_limit), + false, + &Context { + address: target, + caller: source, + apparent_value: value, + }, + ) + }) { + Ok(CallInfo { + exit_reason, + value, + used_gas: fp_evm::UsedGas { + standard: U256::default(), + effective: U256::default(), + }, + logs: Default::default(), + weight_info: None, + }) + } else { + let xcm_transaction = EthereumXcmTransaction::V2(EthereumXcmTransactionV2 { + gas_limit: gas_limit.into(), + action: pallet_ethereum_xcm::TransactionAction::Call(target), + value, + input: input.try_into().map_err(|_| RunnerError { + error: DispatchError::Exhausted, + weight: Default::default(), + })?, + access_list: Some(access_list), + }); + + let mut execution_info: Option = None; + pallet_ethereum::catch_exec_info(&mut execution_info, || { + CallDispatcher::dispatch( + RuntimeCall::EthereumXcm(pallet_ethereum_xcm::Call::transact { xcm_transaction }), + RawOrigin::Signed(source.into()).into(), + ) + .map_err(|DispatchErrorWithPostInfo { error, .. }| RunnerError { + error, + weight: Default::default(), + }) + })?; + + if let Some(CallOrCreateInfo::Call(call_info))= execution_info { + Ok(call_info) + } else { + // `execution_info` must have been filled in + Err(RunnerError { + error: DispatchError::Unavailable, + weight: Default::default(), + }) + } + } + } + + fn create( + _source: H160, + _init: Vec, + _value: U256, + _gas_limit: u64, + _max_fee_per_gas: Option, + _max_priority_fee_per_gas: Option, + _nonce: Option, + _access_list: Vec<(H160, Vec)>, + _is_transactional: bool, + _validate: bool, + _weight_limit: Option, + _transaction_len: Option, + _config: &fp_evm::Config, + ) -> Result> { + unimplemented!() + } + + fn create2( + _source: H160, + _init: Vec, + _salt: H256, + _value: U256, + _gas_limit: u64, + _max_fee_per_gas: Option, + _max_priority_fee_per_gas: Option, + _nonce: Option, + _access_list: Vec<(H160, Vec)>, + _is_transactional: bool, + _validate: bool, + _weight_limit: Option, + _transaction_len: Option, + _config: &fp_evm::Config, + ) -> Result> { + unimplemented!() + } + + fn validate( + _source: H160, + _target: Option, + _input: Vec, + _value: U256, + _gas_limit: u64, + _max_fee_per_gas: Option, + _max_priority_fee_per_gas: Option, + _nonce: Option, + _access_list: Vec<(H160, Vec)>, + _is_transactional: bool, + _weight_limit: Option, + _transaction_len: Option, + _evm_config: &fp_evm::Config, + ) -> Result<(), RunnerError> { + unimplemented!() + } + } + + } +} diff --git a/tracing/2601/runtime/common/src/lib.rs b/tracing/2601/runtime/common/src/lib.rs new file mode 100644 index 00000000..8688e54c --- /dev/null +++ b/tracing/2601/runtime/common/src/lib.rs @@ -0,0 +1,26 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +mod apis; +mod impl_moonbeam_xcm_call; +mod impl_moonbeam_xcm_call_tracing; +mod impl_on_charge_evm_transaction; +mod impl_self_contained_call; +mod impl_xcm_evm_runner; +pub mod migrations; +pub mod weights; diff --git a/tracing/2601/runtime/common/src/migrations.rs b/tracing/2601/runtime/common/src/migrations.rs new file mode 100644 index 00000000..e107fc4e --- /dev/null +++ b/tracing/2601/runtime/common/src/migrations.rs @@ -0,0 +1,307 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! # Migrations +//! +//! This module acts as a registry where each migration is defined. Each migration should implement +//! the "Migration" trait declared in the pallet-migrations crate. + +use frame_support::{ + pallet_prelude::GetStorageVersion, + traits::{Hash as PreimageHash, OnRuntimeUpgrade, PalletInfoAccess}, + weights::Weight, +}; +use pallet_author_slot_filter::Config as AuthorSlotFilterConfig; +use pallet_migrations::{GetMigrations, Migration}; +use pallet_moonbeam_orbiters::CollatorsPool; +#[cfg(feature = "try-runtime")] +use sp_runtime::traits::Zero; +use sp_std::{marker::PhantomData, prelude::*}; + +pub struct PreimageMigrationHashToBoundedCall(PhantomData); +impl Migration for PreimageMigrationHashToBoundedCall +where + T: pallet_preimage::Config + frame_system::Config, +{ + fn friendly_name(&self) -> &str { + "MM_PreimageMigrationHashToBoundedCall" + } + + fn migrate(&self, _available_weight: Weight) -> Weight { + pallet_preimage::migration::v1::Migration::::on_runtime_upgrade() + } + + /// Run a standard pre-runtime test. This works the same way as in a normal runtime upgrade. + #[cfg(feature = "try-runtime")] + fn pre_upgrade(&self) -> Result, sp_runtime::DispatchError> { + pallet_preimage::migration::v1::Migration::::pre_upgrade() + } + + /// Run a standard post-runtime test. This works the same way as in a normal runtime upgrade. + #[cfg(feature = "try-runtime")] + fn post_upgrade(&self, state: Vec) -> Result<(), sp_runtime::DispatchError> { + pallet_preimage::migration::v1::Migration::::post_upgrade(state) + } +} + +pub struct PalletReferendaMigrateV0ToV1(pub PhantomData); +impl Migration for PalletReferendaMigrateV0ToV1 +where + T: pallet_referenda::Config + frame_system::Config, +{ + fn friendly_name(&self) -> &str { + "MM_PalletReferendaMigrateV0ToV1" + } + + fn migrate(&self, _available_weight: Weight) -> Weight { + pallet_referenda::migration::v1::MigrateV0ToV1::::on_runtime_upgrade() + } + + /// Run a standard pre-runtime test. This works the same way as in a normal runtime upgrade. + #[cfg(feature = "try-runtime")] + fn pre_upgrade(&self) -> Result, sp_runtime::DispatchError> { + pallet_referenda::migration::v1::MigrateV0ToV1::::pre_upgrade() + } + + /// Run a standard post-runtime test. This works the same way as in a normal runtime upgrade. + #[cfg(feature = "try-runtime")] + fn post_upgrade(&self, state: Vec) -> Result<(), sp_runtime::DispatchError> { + pallet_referenda::migration::v1::MigrateV0ToV1::::post_upgrade(state) + } +} + +use pallet_xcm_transactor::{relay_indices::*, RelayIndices}; +use sp_core::Get; +pub struct PopulateRelayIndices(pub RelayChainIndices, pub PhantomData); +impl Migration for PopulateRelayIndices { + fn friendly_name(&self) -> &str { + "MM_PopulateRelayIndices" + } + + fn migrate(&self, _available_weight: Weight) -> Weight { + // insert input into storage + RelayIndices::::put(self.0); + T::DbWeight::get().writes(1) + } + + /// Run a standard pre-runtime test. This works the same way as in a normal runtime upgrade. + #[cfg(feature = "try-runtime")] + fn pre_upgrade(&self) -> Result, sp_runtime::DispatchError> { + // check storage is default pre migration + assert_eq!(RelayIndices::::get(), Default::default()); + Ok(Vec::new()) + } + + /// Run a standard post-runtime test. This works the same way as in a normal runtime upgrade. + #[cfg(feature = "try-runtime")] + fn post_upgrade(&self, _state: Vec) -> Result<(), sp_runtime::DispatchError> { + // check storage matches input post migration + assert_eq!(RelayIndices::::get(), self.0); + Ok(()) + } +} + +pub struct RemoveMinBondForOrbiterCollators(pub PhantomData); +impl Migration for RemoveMinBondForOrbiterCollators +where + T: pallet_moonbeam_orbiters::Config, + T: pallet_parachain_staking::Config, + T: frame_system::Config, +{ + fn friendly_name(&self) -> &str { + "MM_RemoveMinBondForOrbiterCollators" + } + + fn migrate(&self, _available_weight: Weight) -> Weight { + let mut weight = Weight::zero(); + CollatorsPool::::iter_keys().for_each(|collator| { + log::info!("Setting the bond for collator {:?} to zero", collator); + weight += >::set_candidate_bond_to_zero(&collator); + }); + weight + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade(&self) -> Result, sp_runtime::DispatchError> { + Ok(vec![]) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(&self, _state: Vec) -> Result<(), sp_runtime::DispatchError> { + CollatorsPool::::iter_keys().for_each(|collator| { + log::info!("Checking collator: {:?}", collator); + let state = >::candidate_info(&collator) + .expect("collator should have candidate info"); + assert!(state.bond.is_zero(), "collator bond should be zero"); + }); + Ok(()) + } +} + +pub struct ReferendaMigrations(PhantomData<(Runtime, Council, Tech)>); + +impl GetMigrations for ReferendaMigrations +where + Runtime: pallet_author_mapping::Config, + Runtime: pallet_parachain_staking::Config, + Runtime: pallet_scheduler::Config, + Runtime: AuthorSlotFilterConfig, + Council: GetStorageVersion + PalletInfoAccess + 'static, + Tech: GetStorageVersion + PalletInfoAccess + 'static, + Runtime: pallet_democracy::Config, + Runtime: pallet_preimage::Config, + Runtime: pallet_referenda::Config, +{ + fn get_migrations() -> Vec> { + let pallet_referenda_migrate_v0_to_v1 = + PalletReferendaMigrateV0ToV1::(Default::default()); + vec![Box::new(pallet_referenda_migrate_v0_to_v1)] + } +} + +pub struct CommonMigrations(PhantomData<(Runtime, Council, Tech)>); + +impl GetMigrations for CommonMigrations +where + Runtime: pallet_author_mapping::Config, + Runtime: pallet_parachain_staking::Config, + Runtime: pallet_scheduler::Config, + Runtime: AuthorSlotFilterConfig, + Council: GetStorageVersion + PalletInfoAccess + 'static, + Tech: GetStorageVersion + PalletInfoAccess + 'static, + Runtime: pallet_democracy::Config, + Runtime: pallet_preimage::Config, + Runtime: pallet_asset_manager::Config, + ::ForeignAssetType: From, + Runtime: pallet_xcm_transactor::Config, + Runtime: pallet_moonbeam_orbiters::Config, +{ + fn get_migrations() -> Vec> { + // let migration_author_mapping_twox_to_blake = AuthorMappingTwoXToBlake:: { + // 0: Default::default(), + // }; + + // let migration_parachain_staking_purge_stale_storage = + // ParachainStakingPurgeStaleStorage::(Default::default()); + // let migration_parachain_staking_manual_exits = + // ParachainStakingManualExits::(Default::default()); + // let migration_parachain_staking_increase_max_delegations_per_candidate = + // ParachainStakingIncreaseMaxDelegationsPerCandidate::(Default::default()); + // let migration_parachain_staking_split_candidate_state = + // ParachainStakingSplitCandidateState::(Default::default()); + // let migration_parachain_staking_patch_incorrect_delegation_sums = + // ParachainStakingPatchIncorrectDelegationSums::(Default::default()); + + // let migration_scheduler_v3 = SchedulerMigrationV3::(Default::default()); + + // let migration_base_fee = MigrateBaseFeePerGas::(Default::default()); + + // TODO: this is a lot of allocation to do upon every get() call. this *should* be avoided + // except when pallet_migrations undergoes a runtime upgrade -- but TODO: review + + // let migration_author_slot_filter_eligible_ratio_to_eligibility_count = + // AuthorSlotFilterEligibleRatioToEligiblityCount::(Default::default()); + // let migration_author_mapping_add_keys_to_registration_info = + // AuthorMappingAddKeysToRegistrationInfo::(Default::default()); + // let staking_delegator_state_requests = + // ParachainStakingSplitDelegatorStateIntoDelegationScheduledRequests::( + // Default::default(), + // ); + // let migration_author_mapping_add_account_id_to_nimbus_lookup = + // AuthorMappingAddAccountIdToNimbusLookup::(Default::default()); + + // let xcm_transactor_max_weight = + // XcmTransactorMaxTransactWeight::(Default::default()); + + // let asset_manager_units_with_asset_type = + // AssetManagerUnitsWithAssetType::(Default::default()); + + // let asset_manager_populate_asset_type_id_storage = + // AssetManagerPopulateAssetTypeIdStorage::(Default::default()); + + // let asset_manager_change_statemine_prefixes = AssetManagerChangeStateminePrefixes::< + // Runtime, + // StatemineParaIdInfo, + // StatemineAssetsInstanceInfo, + // >(Default::default()); + + // let xcm_supported_assets = XcmPaymentSupportedAssets::(Default::default()); + + // let migration_elasticity = MigrateBaseFeeElasticity::(Default::default()); + //let staking_at_stake_auto_compound = + // ParachainStakingMigrateAtStakeAutoCompound::(Default::default()); + + //let scheduler_to_v4 = SchedulerMigrationV4::(Default::default()); + //let democracy_migration_hash_to_bounded_call = + // DemocracryMigrationHashToBoundedCall::(Default::default()); + //let preimage_migration_hash_to_bounded_call = + // PreimageMigrationHashToBoundedCall::(Default::default()); + //let asset_manager_to_xcm_v3 = + // PalletAssetManagerMigrateXcmV2ToV3::(Default::default()); + //let xcm_transactor_to_xcm_v3 = + // PalletXcmTransactorMigrateXcmV2ToV3::(Default::default()); + let remove_min_bond_for_old_orbiter_collators = + RemoveMinBondForOrbiterCollators::(Default::default()); + vec![ + // completed in runtime 800 + // Box::new(migration_author_mapping_twox_to_blake), + // completed in runtime 900 + // completed in runtime 1000 + // Box::new(migration_parachain_staking_purge_stale_storage), + // completed in runtime 1000 + // Box::new(migration_parachain_staking_manual_exits), + // completed in runtime 1101 + // Box::new(migration_parachain_staking_increase_max_delegations_per_candidate), + // completed in runtime 1201 + // Box::new(migration_parachain_staking_split_candidate_state), + // completed in runtime 1201 + // Box::new(xcm_transactor_max_weight), + // completed in runtime 1201 + // Box::new(asset_manager_units_with_asset_type), + // completed in runtime 1201 + // Box::new(asset_manager_change_statemine_prefixes), + // completed in runtime 1201 + // Box::new(asset_manager_populate_asset_type_id_storage), + // completed in runtime 1300 + // Box::new(migration_scheduler_v3), + // completed in runtime 1300 + // Box::new(migration_parachain_staking_patch_incorrect_delegation_sums), + // completed in runtime 1300 + // Box::new(migration_base_fee), + // completed in runtime 1300 + // Box::new(xcm_supported_assets), + // completed in runtime 1500 + // Box::new(migration_author_slot_filter_eligible_ratio_to_eligibility_count), + // Box::new(migration_author_mapping_add_keys_to_registration_info), + // Box::new(staking_delegator_state_requests), + // completed in runtime 1600 + // Box::new(migration_author_mapping_add_account_id_to_nimbus_lookup), + // completed in runtime 1600 + // Box::new(xcm_transactor_transact_signed), + // completed in runtime 1700 + //Box::new(migration_elasticity), + // completed in runtime 1900 + //Box::new(staking_at_stake_auto_compound), + // completed in runtime 2000 + //Box::new(scheduler_to_v4), + //Box::new(democracy_migration_hash_to_bounded_call), + //Box::new(preimage_migration_hash_to_bounded_call), + //Box::new(asset_manager_to_xcm_v3), + //Box::new(xcm_transactor_to_xcm_v3), + Box::new(remove_min_bond_for_old_orbiter_collators), + ] + } +} diff --git a/tracing/2601/runtime/common/src/weights/cumulus_pallet_xcmp_queue.rs b/tracing/2601/runtime/common/src/weights/cumulus_pallet_xcmp_queue.rs new file mode 100644 index 00000000..92782d48 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/cumulus_pallet_xcmp_queue.rs @@ -0,0 +1,72 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `cumulus_pallet_xcmp_queue` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=cumulus_pallet_xcmp_queue +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `cumulus_pallet_xcmp_queue`. +pub struct WeightInfo(PhantomData); +impl cumulus_pallet_xcmp_queue::WeightInfo for WeightInfo { + /// Storage: XcmpQueue QueueConfig (r:1 w:1) + /// Proof Skipped: XcmpQueue QueueConfig (max_values: Some(1), max_size: None, mode: Measured) + fn set_config_with_u32() -> Weight { + // Proof Size summary in bytes: + // Measured: `142` + // Estimated: `1627` + // Minimum execution time: 3_683_000 picoseconds. + Weight::from_parts(3_779_000, 0) + .saturating_add(Weight::from_parts(0, 1627)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: XcmpQueue QueueConfig (r:1 w:1) + /// Proof Skipped: XcmpQueue QueueConfig (max_values: Some(1), max_size: None, mode: Measured) + fn set_config_with_weight() -> Weight { + // Proof Size summary in bytes: + // Measured: `142` + // Estimated: `1627` + // Minimum execution time: 3_832_000 picoseconds. + Weight::from_parts(3_976_000, 0) + .saturating_add(Weight::from_parts(0, 1627)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/mod.rs b/tracing/2601/runtime/common/src/weights/mod.rs new file mode 100644 index 00000000..98507489 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/mod.rs @@ -0,0 +1,47 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Moonbeam common weights. + +pub mod cumulus_pallet_xcmp_queue; +pub mod moonbeam_xcm_benchmarks_weights_generic; +pub mod pallet_asset_manager; +pub mod pallet_assets; +pub mod pallet_author_inherent; +pub mod pallet_author_mapping; +pub mod pallet_author_slot_filter; +pub mod pallet_balances; +pub mod pallet_collective; +pub mod pallet_conviction_voting; +pub mod pallet_crowdloan_rewards; +pub mod pallet_democracy; +pub mod pallet_evm; +pub mod pallet_identity; +pub mod pallet_moonbeam_orbiters; +pub mod pallet_multisig; +pub mod pallet_parachain_staking; +pub mod pallet_preimage; +pub mod pallet_proxy; +pub mod pallet_randomness; +pub mod pallet_referenda; +pub mod pallet_scheduler; +pub mod pallet_sudo; +pub mod pallet_timestamp; +pub mod pallet_treasury; +pub mod pallet_utility; +pub mod pallet_whitelist; +pub mod pallet_xcm; +pub mod pallet_xcm_transactor; diff --git a/tracing/2601/runtime/common/src/weights/moonbeam_xcm_benchmarks_weights_generic.rs b/tracing/2601/runtime/common/src/weights/moonbeam_xcm_benchmarks_weights_generic.rs new file mode 100644 index 00000000..f3831441 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/moonbeam_xcm_benchmarks_weights_generic.rs @@ -0,0 +1,447 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `moonbeam_xcm_benchmarks::weights::generic` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=moonbeam_xcm_benchmarks::weights::generic +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/moonbeam_xcm_benchmarks_weights_generic.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `moonbeam_xcm_benchmarks::weights::generic`. +pub struct WeightInfo(PhantomData); +impl moonbeam_xcm_benchmarks::weights::generic::WeightInfo for WeightInfo { + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn report_holding() -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `3610` + // Minimum execution time: 128_733_000 picoseconds. + Weight::from_parts(130_596_000, 0) + .saturating_add(Weight::from_parts(0, 3610)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: AssetManager SupportedFeePaymentAssets (r:1 w:0) + /// Proof Skipped: AssetManager SupportedFeePaymentAssets (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AssetManager AssetTypeUnitsPerSecond (r:1 w:0) + /// Proof Skipped: AssetManager AssetTypeUnitsPerSecond (max_values: None, max_size: None, mode: Measured) + /// Storage: AssetManager AssetTypeId (r:1 w:0) + /// Proof Skipped: AssetManager AssetTypeId (max_values: None, max_size: None, mode: Measured) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + fn buy_execution() -> Weight { + // Proof Size summary in bytes: + // Measured: `2334` + // Estimated: `5799` + // Minimum execution time: 52_670_000 picoseconds. + Weight::from_parts(54_209_000, 0) + .saturating_add(Weight::from_parts(0, 5799)) + .saturating_add(T::DbWeight::get().reads(4)) + } + /// Storage: PolkadotXcm Queries (r:1 w:0) + /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) + fn query_response() -> Weight { + // Proof Size summary in bytes: + // Measured: `69` + // Estimated: `3534` + // Minimum execution time: 6_292_000 picoseconds. + Weight::from_parts(6_546_000, 0) + .saturating_add(Weight::from_parts(0, 3534)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: MaintenanceMode MaintenanceMode (r:1 w:0) + /// Proof Skipped: MaintenanceMode MaintenanceMode (max_values: Some(1), max_size: None, mode: Measured) + fn transact() -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `1527` + // Minimum execution time: 8_026_000 picoseconds. + Weight::from_parts(8_174_000, 0) + .saturating_add(Weight::from_parts(0, 1527)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn refund_surplus() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_860_000 picoseconds. + Weight::from_parts(4_143_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn set_error_handler() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_034_000 picoseconds. + Weight::from_parts(1_070_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn set_appendix() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_012_000 picoseconds. + Weight::from_parts(1_108_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn clear_error() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 989_000 picoseconds. + Weight::from_parts(1_042_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn descend_origin() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_119_000 picoseconds. + Weight::from_parts(1_197_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn clear_origin() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 982_000 picoseconds. + Weight::from_parts(1_032_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn report_error() -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `3610` + // Minimum execution time: 13_075_000 picoseconds. + Weight::from_parts(13_413_000, 0) + .saturating_add(Weight::from_parts(0, 3610)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: PolkadotXcm AssetTraps (r:1 w:1) + /// Proof Skipped: PolkadotXcm AssetTraps (max_values: None, max_size: None, mode: Measured) + fn claim_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `126` + // Estimated: `3591` + // Minimum execution time: 8_585_000 picoseconds. + Weight::from_parts(8_854_000, 0) + .saturating_add(Weight::from_parts(0, 3591)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + fn trap() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 997_000 picoseconds. + Weight::from_parts(1_047_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn subscribe_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `3610` + // Minimum execution time: 15_051_000 picoseconds. + Weight::from_parts(15_510_000, 0) + .saturating_add(Weight::from_parts(0, 3610)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:0 w:1) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + fn unsubscribe_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_920_000 picoseconds. + Weight::from_parts(1_964_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn initiate_reserve_withdraw() -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `3610` + // Minimum execution time: 132_023_000 picoseconds. + Weight::from_parts(132_983_000, 0) + .saturating_add(Weight::from_parts(0, 3610)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + fn burn_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 45_907_000 picoseconds. + Weight::from_parts(46_696_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn expect_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 12_259_000 picoseconds. + Weight::from_parts(12_690_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn expect_origin() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_028_000 picoseconds. + Weight::from_parts(1_078_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn expect_error() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_032_000 picoseconds. + Weight::from_parts(1_065_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn expect_transact_status() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_055_000 picoseconds. + Weight::from_parts(1_099_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn query_pallet() -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `3610` + // Minimum execution time: 14_911_000 picoseconds. + Weight::from_parts(15_426_000, 0) + .saturating_add(Weight::from_parts(0, 3610)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + fn expect_pallet() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_060_000 picoseconds. + Weight::from_parts(2_184_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn report_transact_status() -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `3610` + // Minimum execution time: 12_907_000 picoseconds. + Weight::from_parts(13_306_000, 0) + .saturating_add(Weight::from_parts(0, 3610)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + fn clear_transact_status() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 955_000 picoseconds. + Weight::from_parts(1_018_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn set_topic() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 962_000 picoseconds. + Weight::from_parts(1_007_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn clear_topic() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 965_000 picoseconds. + Weight::from_parts(1_014_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + fn exchange_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + fn universal_origin() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[1, 1000]`. + fn export_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn set_fees_mode() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 971_000 picoseconds. + Weight::from_parts(1_025_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + fn lock_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + fn unlock_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + fn note_unlockable() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + fn request_unlock() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + fn unpaid_execution() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 976_000 picoseconds. + Weight::from_parts(1_025_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_asset_manager.rs b/tracing/2601/runtime/common/src/weights/pallet_asset_manager.rs new file mode 100644 index 00000000..8d822dfa --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_asset_manager.rs @@ -0,0 +1,168 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_asset_manager` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_asset_manager +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_asset_manager`. +pub struct WeightInfo(PhantomData); +impl pallet_asset_manager::WeightInfo for WeightInfo { + /// Storage: AssetManager AssetIdType (r:1 w:1) + /// Proof Skipped: AssetManager AssetIdType (max_values: None, max_size: None, mode: Measured) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(152), added: 2627, mode: MaxEncodedLen) + /// Storage: AssetManager AssetTypeId (r:0 w:1) + /// Proof Skipped: AssetManager AssetTypeId (max_values: None, max_size: None, mode: Measured) + fn register_foreign_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `82` + // Estimated: `3639` + // Minimum execution time: 18_671_000 picoseconds. + Weight::from_parts(19_426_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: AssetManager AssetTypeId (r:1 w:0) + /// Proof Skipped: AssetManager AssetTypeId (max_values: None, max_size: None, mode: Measured) + /// Storage: AssetManager SupportedFeePaymentAssets (r:1 w:1) + /// Proof Skipped: AssetManager SupportedFeePaymentAssets (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AssetManager AssetTypeUnitsPerSecond (r:0 w:1) + /// Proof Skipped: AssetManager AssetTypeUnitsPerSecond (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[5, 100]`. + fn set_asset_units_per_second(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `611 + x * (9 ±0)` + // Estimated: `4000 + x * (10 ±0)` + // Minimum execution time: 13_680_000 picoseconds. + Weight::from_parts(15_643_701, 0) + .saturating_add(Weight::from_parts(0, 4000)) + // Standard Error: 2_622 + .saturating_add(Weight::from_parts(274_621, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 10).saturating_mul(x.into())) + } + /// Storage: AssetManager SupportedFeePaymentAssets (r:1 w:1) + /// Proof Skipped: AssetManager SupportedFeePaymentAssets (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AssetManager AssetIdType (r:1 w:1) + /// Proof Skipped: AssetManager AssetIdType (max_values: None, max_size: None, mode: Measured) + /// Storage: AssetManager AssetTypeUnitsPerSecond (r:1 w:2) + /// Proof Skipped: AssetManager AssetTypeUnitsPerSecond (max_values: None, max_size: None, mode: Measured) + /// Storage: AssetManager AssetTypeId (r:0 w:2) + /// Proof Skipped: AssetManager AssetTypeId (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[5, 100]`. + fn change_existing_asset_type(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `926 + x * (13 ±0)` + // Estimated: `4309 + x * (15 ±0)` + // Minimum execution time: 19_784_000 picoseconds. + Weight::from_parts(23_095_890, 0) + .saturating_add(Weight::from_parts(0, 4309)) + // Standard Error: 4_344 + .saturating_add(Weight::from_parts(320_669, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(6)) + .saturating_add(Weight::from_parts(0, 15).saturating_mul(x.into())) + } + /// Storage: AssetManager SupportedFeePaymentAssets (r:1 w:1) + /// Proof Skipped: AssetManager SupportedFeePaymentAssets (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AssetManager AssetTypeUnitsPerSecond (r:0 w:1) + /// Proof Skipped: AssetManager AssetTypeUnitsPerSecond (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[5, 100]`. + fn remove_supported_asset(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `196 + x * (5 ±0)` + // Estimated: `1678 + x * (5 ±0)` + // Minimum execution time: 10_369_000 picoseconds. + Weight::from_parts(11_485_853, 0) + .saturating_add(Weight::from_parts(0, 1678)) + // Standard Error: 2_255 + .saturating_add(Weight::from_parts(259_454, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 5).saturating_mul(x.into())) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: AssetManager LocalAssetCounter (r:1 w:1) + /// Proof Skipped: AssetManager LocalAssetCounter (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: LocalAssets Asset (r:1 w:1) + /// Proof: LocalAssets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: EVM AccountCodes (r:0 w:1) + /// Proof Skipped: EVM AccountCodes (max_values: None, max_size: None, mode: Measured) + /// Storage: AssetManager LocalAssetDeposit (r:0 w:1) + /// Proof Skipped: AssetManager LocalAssetDeposit (max_values: None, max_size: None, mode: Measured) + fn register_local_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `310` + // Estimated: `3639` + // Minimum execution time: 24_699_000 picoseconds. + Weight::from_parts(25_397_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(5)) + } + /// Storage: AssetManager SupportedFeePaymentAssets (r:1 w:1) + /// Proof Skipped: AssetManager SupportedFeePaymentAssets (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AssetManager AssetIdType (r:1 w:1) + /// Proof Skipped: AssetManager AssetIdType (max_values: None, max_size: None, mode: Measured) + /// Storage: AssetManager AssetTypeUnitsPerSecond (r:0 w:1) + /// Proof Skipped: AssetManager AssetTypeUnitsPerSecond (max_values: None, max_size: None, mode: Measured) + /// Storage: AssetManager AssetTypeId (r:0 w:1) + /// Proof Skipped: AssetManager AssetTypeId (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[5, 100]`. + fn remove_existing_asset_type(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `482 + x * (10 ±0)` + // Estimated: `3955 + x * (10 ±0)` + // Minimum execution time: 15_040_000 picoseconds. + Weight::from_parts(17_158_622, 0) + .saturating_add(Weight::from_parts(0, 3955)) + // Standard Error: 2_614 + .saturating_add(Weight::from_parts(275_195, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(Weight::from_parts(0, 10).saturating_mul(x.into())) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_assets.rs b/tracing/2601/runtime/common/src/weights/pallet_assets.rs new file mode 100644 index 00000000..2da2a800 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_assets.rs @@ -0,0 +1,512 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_assets` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_assets +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_assets`. +pub struct WeightInfo(PhantomData); +impl pallet_assets::WeightInfo for WeightInfo { + fn create() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 0_000 picoseconds. + Weight::from_parts(0, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + fn force_create() -> Weight { + // Proof Size summary in bytes: + // Measured: `6` + // Estimated: `3639` + // Minimum execution time: 6_235_000 picoseconds. + Weight::from_parts(6_496_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + fn start_destroy() -> Weight { + // Proof Size summary in bytes: + // Measured: `241` + // Estimated: `3639` + // Minimum execution time: 8_286_000 picoseconds. + Weight::from_parts(8_499_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Account (r:657 w:656) + /// Proof: Assets Account (max_values: None, max_size: Some(122), added: 2597, mode: MaxEncodedLen) + /// Storage: System Account (r:656 w:656) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// The range of component `c` is `[0, 656]`. + fn destroy_accounts(c: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `846 + c * (183 ±0)` + // Estimated: `3639 + c * (2597 ±0)` + // Minimum execution time: 10_964_000 picoseconds. + Weight::from_parts(11_134_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + // Standard Error: 5_191 + .saturating_add(Weight::from_parts(9_291_791, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(c.into()))) + .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(c.into()))) + .saturating_add(Weight::from_parts(0, 2597).saturating_mul(c.into())) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Approvals (r:657 w:656) + /// Proof: Assets Approvals (max_values: None, max_size: Some(136), added: 2611, mode: MaxEncodedLen) + /// The range of component `a` is `[0, 656]`. + fn destroy_approvals(a: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `313 + a * (74 ±0)` + // Estimated: `3639 + a * (2611 ±0)` + // Minimum execution time: 11_340_000 picoseconds. + Weight::from_parts(11_551_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + // Standard Error: 3_544 + .saturating_add(Weight::from_parts(4_459_183, 0).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) + .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) + .saturating_add(Weight::from_parts(0, 2611).saturating_mul(a.into())) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:0) + /// Proof: Assets Metadata (max_values: None, max_size: Some(152), added: 2627, mode: MaxEncodedLen) + fn finish_destroy() -> Weight { + // Proof Size summary in bytes: + // Measured: `207` + // Estimated: `3639` + // Minimum execution time: 8_953_000 picoseconds. + Weight::from_parts(9_199_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(122), added: 2597, mode: MaxEncodedLen) + fn mint() -> Weight { + // Proof Size summary in bytes: + // Measured: `207` + // Estimated: `3639` + // Minimum execution time: 13_790_000 picoseconds. + Weight::from_parts(14_331_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(122), added: 2597, mode: MaxEncodedLen) + fn burn() -> Weight { + // Proof Size summary in bytes: + // Measured: `315` + // Estimated: `3639` + // Minimum execution time: 18_592_000 picoseconds. + Weight::from_parts(18_971_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Account (r:2 w:2) + /// Proof: Assets Account (max_values: None, max_size: Some(122), added: 2597, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `387` + // Estimated: `6184` + // Minimum execution time: 24_652_000 picoseconds. + Weight::from_parts(25_198_000, 0) + .saturating_add(Weight::from_parts(0, 6184)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Account (r:2 w:2) + /// Proof: Assets Account (max_values: None, max_size: Some(122), added: 2597, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn transfer_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `387` + // Estimated: `6184` + // Minimum execution time: 22_205_000 picoseconds. + Weight::from_parts(22_720_000, 0) + .saturating_add(Weight::from_parts(0, 6184)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Account (r:2 w:2) + /// Proof: Assets Account (max_values: None, max_size: Some(122), added: 2597, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn force_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `387` + // Estimated: `6184` + // Minimum execution time: 24_933_000 picoseconds. + Weight::from_parts(25_469_000, 0) + .saturating_add(Weight::from_parts(0, 6184)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(122), added: 2597, mode: MaxEncodedLen) + fn freeze() -> Weight { + // Proof Size summary in bytes: + // Measured: `315` + // Estimated: `3639` + // Minimum execution time: 10_913_000 picoseconds. + Weight::from_parts(11_393_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(122), added: 2597, mode: MaxEncodedLen) + fn thaw() -> Weight { + // Proof Size summary in bytes: + // Measured: `315` + // Estimated: `3639` + // Minimum execution time: 11_231_000 picoseconds. + Weight::from_parts(11_560_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + fn freeze_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `241` + // Estimated: `3639` + // Minimum execution time: 7_966_000 picoseconds. + Weight::from_parts(8_288_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + fn thaw_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `241` + // Estimated: `3639` + // Minimum execution time: 7_960_000 picoseconds. + Weight::from_parts(8_167_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:0) + /// Proof: Assets Metadata (max_values: None, max_size: Some(152), added: 2627, mode: MaxEncodedLen) + fn transfer_ownership() -> Weight { + // Proof Size summary in bytes: + // Measured: `207` + // Estimated: `3639` + // Minimum execution time: 9_052_000 picoseconds. + Weight::from_parts(9_269_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + fn set_team() -> Weight { + // Proof Size summary in bytes: + // Measured: `207` + // Estimated: `3639` + // Minimum execution time: 7_815_000 picoseconds. + Weight::from_parts(8_092_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(152), added: 2627, mode: MaxEncodedLen) + /// The range of component `n` is `[0, 50]`. + /// The range of component `s` is `[0, 50]`. + fn set_metadata(_n: u32, _s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `207` + // Estimated: `3639` + // Minimum execution time: 15_555_000 picoseconds. + Weight::from_parts(16_251_020, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(152), added: 2627, mode: MaxEncodedLen) + fn clear_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `383` + // Estimated: `3639` + // Minimum execution time: 16_736_000 picoseconds. + Weight::from_parts(17_244_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(152), added: 2627, mode: MaxEncodedLen) + /// The range of component `n` is `[0, 50]`. + /// The range of component `s` is `[0, 50]`. + fn force_set_metadata(n: u32, s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `94` + // Estimated: `3639` + // Minimum execution time: 7_857_000 picoseconds. + Weight::from_parts(8_300_312, 0) + .saturating_add(Weight::from_parts(0, 3639)) + // Standard Error: 253 + .saturating_add(Weight::from_parts(126, 0).saturating_mul(n.into())) + // Standard Error: 253 + .saturating_add(Weight::from_parts(154, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Metadata (r:1 w:1) + /// Proof: Assets Metadata (max_values: None, max_size: Some(152), added: 2627, mode: MaxEncodedLen) + fn force_clear_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `383` + // Estimated: `3639` + // Minimum execution time: 16_497_000 picoseconds. + Weight::from_parts(17_111_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + fn force_asset_status() -> Weight { + // Proof Size summary in bytes: + // Measured: `207` + // Estimated: `3639` + // Minimum execution time: 7_656_000 picoseconds. + Weight::from_parts(7_773_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Approvals (r:1 w:1) + /// Proof: Assets Approvals (max_values: None, max_size: Some(136), added: 2611, mode: MaxEncodedLen) + fn approve_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `241` + // Estimated: `3639` + // Minimum execution time: 11_014_000 picoseconds. + Weight::from_parts(11_360_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Approvals (r:1 w:1) + /// Proof: Assets Approvals (max_values: None, max_size: Some(136), added: 2611, mode: MaxEncodedLen) + /// Storage: Assets Account (r:2 w:2) + /// Proof: Assets Account (max_values: None, max_size: Some(122), added: 2597, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn transfer_approved() -> Weight { + // Proof Size summary in bytes: + // Measured: `513` + // Estimated: `6184` + // Minimum execution time: 29_960_000 picoseconds. + Weight::from_parts(30_884_000, 0) + .saturating_add(Weight::from_parts(0, 6184)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Approvals (r:1 w:1) + /// Proof: Assets Approvals (max_values: None, max_size: Some(136), added: 2611, mode: MaxEncodedLen) + fn cancel_approval() -> Weight { + // Proof Size summary in bytes: + // Measured: `399` + // Estimated: `3639` + // Minimum execution time: 13_267_000 picoseconds. + Weight::from_parts(13_605_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Approvals (r:1 w:1) + /// Proof: Assets Approvals (max_values: None, max_size: Some(136), added: 2611, mode: MaxEncodedLen) + fn force_cancel_approval() -> Weight { + // Proof Size summary in bytes: + // Measured: `399` + // Estimated: `3639` + // Minimum execution time: 13_425_000 picoseconds. + Weight::from_parts(14_001_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + fn set_min_balance() -> Weight { + // Proof Size summary in bytes: + // Measured: `207` + // Estimated: `3639` + // Minimum execution time: 7_958_000 picoseconds. + Weight::from_parts(8_381_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(122), added: 2597, mode: MaxEncodedLen) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn touch() -> Weight { + // Proof Size summary in bytes: + // Measured: `402` + // Estimated: `3639` + // Minimum execution time: 19_028_000 picoseconds. + Weight::from_parts(19_576_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(122), added: 2597, mode: MaxEncodedLen) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + fn touch_other() -> Weight { + // Proof Size summary in bytes: + // Measured: `207` + // Estimated: `3639` + // Minimum execution time: 16_799_000 picoseconds. + Weight::from_parts(17_268_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(122), added: 2597, mode: MaxEncodedLen) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn refund() -> Weight { + // Proof Size summary in bytes: + // Measured: `528` + // Estimated: `3639` + // Minimum execution time: 19_465_000 picoseconds. + Weight::from_parts(20_018_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(122), added: 2597, mode: MaxEncodedLen) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + fn refund_other() -> Weight { + // Proof Size summary in bytes: + // Measured: `353` + // Estimated: `3639` + // Minimum execution time: 17_017_000 picoseconds. + Weight::from_parts(17_603_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(122), added: 2597, mode: MaxEncodedLen) + fn block() -> Weight { + // Proof Size summary in bytes: + // Measured: `315` + // Estimated: `3639` + // Minimum execution time: 11_215_000 picoseconds. + Weight::from_parts(11_486_000, 0) + .saturating_add(Weight::from_parts(0, 3639)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_author_inherent.rs b/tracing/2601/runtime/common/src/weights/pallet_author_inherent.rs new file mode 100644 index 00000000..844d00a3 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_author_inherent.rs @@ -0,0 +1,70 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_author_inherent` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_author_inherent +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_author_inherent`. +pub struct WeightInfo(PhantomData); +impl pallet_author_inherent::WeightInfo for WeightInfo { + /// Storage: ParachainSystem ValidationData (r:1 w:0) + /// Proof Skipped: ParachainSystem ValidationData (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AuthorInherent HighestSlotSeen (r:1 w:1) + /// Proof: AuthorInherent HighestSlotSeen (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: AuthorInherent Author (r:1 w:0) + /// Proof: AuthorInherent Author (max_values: Some(1), max_size: Some(20), added: 515, mode: MaxEncodedLen) + /// Storage: ParachainStaking SelectedCandidates (r:1 w:0) + /// Proof Skipped: ParachainStaking SelectedCandidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AuthorFilter EligibleCount (r:1 w:0) + /// Proof Skipped: AuthorFilter EligibleCount (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Randomness PreviousLocalVrfOutput (r:1 w:0) + /// Proof Skipped: Randomness PreviousLocalVrfOutput (max_values: Some(1), max_size: None, mode: Measured) + fn kick_off_authorship_validation() -> Weight { + // Proof Size summary in bytes: + // Measured: `371` + // Estimated: `1856` + // Minimum execution time: 14_675_000 picoseconds. + Weight::from_parts(15_236_000, 0) + .saturating_add(Weight::from_parts(0, 1856)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_author_mapping.rs b/tracing/2601/runtime/common/src/weights/pallet_author_mapping.rs new file mode 100644 index 00000000..096abdae --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_author_mapping.rs @@ -0,0 +1,126 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_author_mapping` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_author_mapping +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_author_mapping`. +pub struct WeightInfo(PhantomData); +impl pallet_author_mapping::WeightInfo for WeightInfo { + /// Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + /// Proof Skipped: AuthorMapping MappingWithDeposit (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: AuthorMapping NimbusLookup (r:0 w:1) + /// Proof Skipped: AuthorMapping NimbusLookup (max_values: None, max_size: None, mode: Measured) + fn add_association() -> Weight { + // Proof Size summary in bytes: + // Measured: `376` + // Estimated: `3841` + // Minimum execution time: 17_903_000 picoseconds. + Weight::from_parts(18_427_000, 0) + .saturating_add(Weight::from_parts(0, 3841)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: AuthorMapping MappingWithDeposit (r:2 w:2) + /// Proof Skipped: AuthorMapping MappingWithDeposit (max_values: None, max_size: None, mode: Measured) + /// Storage: AuthorMapping NimbusLookup (r:0 w:1) + /// Proof Skipped: AuthorMapping NimbusLookup (max_values: None, max_size: None, mode: Measured) + fn update_association() -> Weight { + // Proof Size summary in bytes: + // Measured: `325` + // Estimated: `6265` + // Minimum execution time: 12_636_000 picoseconds. + Weight::from_parts(12_893_000, 0) + .saturating_add(Weight::from_parts(0, 6265)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + /// Proof Skipped: AuthorMapping MappingWithDeposit (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: AuthorMapping NimbusLookup (r:0 w:1) + /// Proof Skipped: AuthorMapping NimbusLookup (max_values: None, max_size: None, mode: Measured) + fn clear_association() -> Weight { + // Proof Size summary in bytes: + // Measured: `453` + // Estimated: `3918` + // Minimum execution time: 19_255_000 picoseconds. + Weight::from_parts(19_892_000, 0) + .saturating_add(Weight::from_parts(0, 3918)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: AuthorMapping NimbusLookup (r:1 w:1) + /// Proof Skipped: AuthorMapping NimbusLookup (max_values: None, max_size: None, mode: Measured) + /// Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + /// Proof Skipped: AuthorMapping MappingWithDeposit (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn remove_keys() -> Weight { + // Proof Size summary in bytes: + // Measured: `547` + // Estimated: `4012` + // Minimum execution time: 22_108_000 picoseconds. + Weight::from_parts(22_636_000, 0) + .saturating_add(Weight::from_parts(0, 4012)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: AuthorMapping NimbusLookup (r:1 w:1) + /// Proof Skipped: AuthorMapping NimbusLookup (max_values: None, max_size: None, mode: Measured) + /// Storage: AuthorMapping MappingWithDeposit (r:1 w:1) + /// Proof Skipped: AuthorMapping MappingWithDeposit (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn set_keys() -> Weight { + // Proof Size summary in bytes: + // Measured: `432` + // Estimated: `3897` + // Minimum execution time: 19_904_000 picoseconds. + Weight::from_parts(20_421_000, 0) + .saturating_add(Weight::from_parts(0, 3897)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_author_slot_filter.rs b/tracing/2601/runtime/common/src/weights/pallet_author_slot_filter.rs new file mode 100644 index 00000000..4047b4ca --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_author_slot_filter.rs @@ -0,0 +1,59 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_author_slot_filter` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_author_slot_filter +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_author_slot_filter`. +pub struct WeightInfo(PhantomData); +impl pallet_author_slot_filter::WeightInfo for WeightInfo { + /// Storage: AuthorFilter EligibleCount (r:0 w:1) + /// Proof Skipped: AuthorFilter EligibleCount (max_values: Some(1), max_size: None, mode: Measured) + fn set_eligible() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_628_000 picoseconds. + Weight::from_parts(3_777_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_balances.rs b/tracing/2601/runtime/common/src/weights/pallet_balances.rs new file mode 100644 index 00000000..f6ac64c5 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_balances.rs @@ -0,0 +1,148 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_balances` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_balances +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_balances`. +pub struct WeightInfo(PhantomData); +impl pallet_balances::WeightInfo for WeightInfo { + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn transfer_allow_death() -> Weight { + // Proof Size summary in bytes: + // Measured: `72` + // Estimated: `3581` + // Minimum execution time: 20_916_000 picoseconds. + Weight::from_parts(21_458_000, 0) + .saturating_add(Weight::from_parts(0, 3581)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn transfer_keep_alive() -> Weight { + // Proof Size summary in bytes: + // Measured: `72` + // Estimated: `3581` + // Minimum execution time: 20_547_000 picoseconds. + Weight::from_parts(21_033_000, 0) + .saturating_add(Weight::from_parts(0, 3581)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn force_set_balance_creating() -> Weight { + // Proof Size summary in bytes: + // Measured: `195` + // Estimated: `3581` + // Minimum execution time: 9_298_000 picoseconds. + Weight::from_parts(9_738_000, 0) + .saturating_add(Weight::from_parts(0, 3581)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn force_set_balance_killing() -> Weight { + // Proof Size summary in bytes: + // Measured: `195` + // Estimated: `3581` + // Minimum execution time: 10_243_000 picoseconds. + Weight::from_parts(10_523_000, 0) + .saturating_add(Weight::from_parts(0, 3581)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn force_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `267` + // Estimated: `6172` + // Minimum execution time: 23_572_000 picoseconds. + Weight::from_parts(24_097_000, 0) + .saturating_add(Weight::from_parts(0, 6172)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn transfer_all() -> Weight { + // Proof Size summary in bytes: + // Measured: `72` + // Estimated: `3581` + // Minimum execution time: 22_177_000 picoseconds. + Weight::from_parts(22_556_000, 0) + .saturating_add(Weight::from_parts(0, 3581)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn force_unreserve() -> Weight { + // Proof Size summary in bytes: + // Measured: `195` + // Estimated: `3581` + // Minimum execution time: 10_680_000 picoseconds. + Weight::from_parts(10_979_000, 0) + .saturating_add(Weight::from_parts(0, 3581)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: System Account (r:999 w:999) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// The range of component `u` is `[1, 1000]`. + fn upgrade_accounts(u: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `585 + u * (123 ±0)` + // Estimated: `990 + u * (2591 ±0)` + // Minimum execution time: 9_772_000 picoseconds. + Weight::from_parts(9_938_000, 0) + .saturating_add(Weight::from_parts(0, 990)) + // Standard Error: 9_375 + .saturating_add(Weight::from_parts(8_373_767, 0).saturating_mul(u.into())) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) + .saturating_add(Weight::from_parts(0, 2591).saturating_mul(u.into())) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_collective.rs b/tracing/2601/runtime/common/src/weights/pallet_collective.rs new file mode 100644 index 00000000..5c70e97f --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_collective.rs @@ -0,0 +1,308 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_collective` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_collective +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_collective`. +pub struct WeightInfo(PhantomData); +impl pallet_collective::WeightInfo for WeightInfo { + /// Storage: CouncilCollective Members (r:1 w:1) + /// Proof Skipped: CouncilCollective Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective Proposals (r:1 w:0) + /// Proof Skipped: CouncilCollective Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective Voting (r:100 w:100) + /// Proof Skipped: CouncilCollective Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: CouncilCollective Prime (r:0 w:1) + /// Proof Skipped: CouncilCollective Prime (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `m` is `[0, 100]`. + /// The range of component `n` is `[0, 100]`. + /// The range of component `p` is `[0, 100]`. + fn set_members(m: u32, _n: u32, p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0 + m * (2021 ±0) + p * (2026 ±0)` + // Estimated: `12238 + m * (1231 ±14) + p * (3660 ±14)` + // Minimum execution time: 13_785_000 picoseconds. + Weight::from_parts(14_085_000, 0) + .saturating_add(Weight::from_parts(0, 12238)) + // Standard Error: 34_315 + .saturating_add(Weight::from_parts(2_414_144, 0).saturating_mul(m.into())) + // Standard Error: 34_315 + .saturating_add(Weight::from_parts(5_345_562, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) + .saturating_add(Weight::from_parts(0, 1231).saturating_mul(m.into())) + .saturating_add(Weight::from_parts(0, 3660).saturating_mul(p.into())) + } + /// Storage: CouncilCollective Members (r:1 w:0) + /// Proof Skipped: CouncilCollective Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: MaintenanceMode MaintenanceMode (r:1 w:0) + /// Proof Skipped: MaintenanceMode MaintenanceMode (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `b` is `[2, 1024]`. + /// The range of component `m` is `[1, 100]`. + fn execute(b: u32, m: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `149 + m * (20 ±0)` + // Estimated: `1634 + m * (20 ±0)` + // Minimum execution time: 12_726_000 picoseconds. + Weight::from_parts(12_294_605, 0) + .saturating_add(Weight::from_parts(0, 1634)) + // Standard Error: 18 + .saturating_add(Weight::from_parts(910, 0).saturating_mul(b.into())) + // Standard Error: 192 + .saturating_add(Weight::from_parts(13_235, 0).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(Weight::from_parts(0, 20).saturating_mul(m.into())) + } + /// Storage: CouncilCollective Members (r:1 w:0) + /// Proof Skipped: CouncilCollective Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective ProposalOf (r:1 w:0) + /// Proof Skipped: CouncilCollective ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: MaintenanceMode MaintenanceMode (r:1 w:0) + /// Proof Skipped: MaintenanceMode MaintenanceMode (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `b` is `[2, 1024]`. + /// The range of component `m` is `[1, 100]`. + fn propose_execute(b: u32, m: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `149 + m * (20 ±0)` + // Estimated: `3614 + m * (20 ±0)` + // Minimum execution time: 14_722_000 picoseconds. + Weight::from_parts(14_487_427, 0) + .saturating_add(Weight::from_parts(0, 3614)) + // Standard Error: 20 + .saturating_add(Weight::from_parts(944, 0).saturating_mul(b.into())) + // Standard Error: 215 + .saturating_add(Weight::from_parts(25_619, 0).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(Weight::from_parts(0, 20).saturating_mul(m.into())) + } + /// Storage: CouncilCollective Members (r:1 w:0) + /// Proof Skipped: CouncilCollective Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective ProposalOf (r:1 w:1) + /// Proof Skipped: CouncilCollective ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: CouncilCollective Proposals (r:1 w:1) + /// Proof Skipped: CouncilCollective Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective ProposalCount (r:1 w:1) + /// Proof Skipped: CouncilCollective ProposalCount (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective Voting (r:0 w:1) + /// Proof Skipped: CouncilCollective Voting (max_values: None, max_size: None, mode: Measured) + /// The range of component `b` is `[2, 1024]`. + /// The range of component `m` is `[2, 100]`. + /// The range of component `p` is `[1, 100]`. + fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `395 + m * (20 ±0) + p * (36 ±0)` + // Estimated: `3789 + m * (21 ±0) + p * (36 ±0)` + // Minimum execution time: 17_107_000 picoseconds. + Weight::from_parts(15_172_014, 0) + .saturating_add(Weight::from_parts(0, 3789)) + // Standard Error: 104 + .saturating_add(Weight::from_parts(3_191, 0).saturating_mul(b.into())) + // Standard Error: 1_090 + .saturating_add(Weight::from_parts(31_145, 0).saturating_mul(m.into())) + // Standard Error: 1_077 + .saturating_add(Weight::from_parts(131_855, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(Weight::from_parts(0, 21).saturating_mul(m.into())) + .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) + } + /// Storage: CouncilCollective Members (r:1 w:0) + /// Proof Skipped: CouncilCollective Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective Voting (r:1 w:1) + /// Proof Skipped: CouncilCollective Voting (max_values: None, max_size: None, mode: Measured) + /// The range of component `m` is `[5, 100]`. + fn vote(m: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `870 + m * (40 ±0)` + // Estimated: `4334 + m * (40 ±0)` + // Minimum execution time: 21_423_000 picoseconds. + Weight::from_parts(22_311_906, 0) + .saturating_add(Weight::from_parts(0, 4334)) + // Standard Error: 415 + .saturating_add(Weight::from_parts(32_990, 0).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(Weight::from_parts(0, 40).saturating_mul(m.into())) + } + /// Storage: CouncilCollective Voting (r:1 w:1) + /// Proof Skipped: CouncilCollective Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: CouncilCollective Members (r:1 w:0) + /// Proof Skipped: CouncilCollective Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective Proposals (r:1 w:1) + /// Proof Skipped: CouncilCollective Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective ProposalOf (r:0 w:1) + /// Proof Skipped: CouncilCollective ProposalOf (max_values: None, max_size: None, mode: Measured) + /// The range of component `m` is `[4, 100]`. + /// The range of component `p` is `[1, 100]`. + fn close_early_disapproved(m: u32, p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `447 + m * (40 ±0) + p * (36 ±0)` + // Estimated: `3892 + m * (41 ±0) + p * (36 ±0)` + // Minimum execution time: 20_010_000 picoseconds. + Weight::from_parts(20_008_777, 0) + .saturating_add(Weight::from_parts(0, 3892)) + // Standard Error: 1_391 + .saturating_add(Weight::from_parts(39_960, 0).saturating_mul(m.into())) + // Standard Error: 1_356 + .saturating_add(Weight::from_parts(126_447, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(Weight::from_parts(0, 41).saturating_mul(m.into())) + .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) + } + /// Storage: CouncilCollective Voting (r:1 w:1) + /// Proof Skipped: CouncilCollective Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: CouncilCollective Members (r:1 w:0) + /// Proof Skipped: CouncilCollective Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective ProposalOf (r:1 w:1) + /// Proof Skipped: CouncilCollective ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: MaintenanceMode MaintenanceMode (r:1 w:0) + /// Proof Skipped: MaintenanceMode MaintenanceMode (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective Proposals (r:1 w:1) + /// Proof Skipped: CouncilCollective Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `b` is `[2, 1024]`. + /// The range of component `m` is `[4, 100]`. + /// The range of component `p` is `[1, 100]`. + fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `791 + b * (1 ±0) + m * (40 ±0) + p * (40 ±0)` + // Estimated: `4108 + b * (1 ±0) + m * (42 ±0) + p * (40 ±0)` + // Minimum execution time: 30_647_000 picoseconds. + Weight::from_parts(30_084_699, 0) + .saturating_add(Weight::from_parts(0, 4108)) + // Standard Error: 123 + .saturating_add(Weight::from_parts(2_876, 0).saturating_mul(b.into())) + // Standard Error: 1_307 + .saturating_add(Weight::from_parts(31_661, 0).saturating_mul(m.into())) + // Standard Error: 1_274 + .saturating_add(Weight::from_parts(154_567, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(Weight::from_parts(0, 1).saturating_mul(b.into())) + .saturating_add(Weight::from_parts(0, 42).saturating_mul(m.into())) + .saturating_add(Weight::from_parts(0, 40).saturating_mul(p.into())) + } + /// Storage: CouncilCollective Voting (r:1 w:1) + /// Proof Skipped: CouncilCollective Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: CouncilCollective Members (r:1 w:0) + /// Proof Skipped: CouncilCollective Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective Prime (r:1 w:0) + /// Proof Skipped: CouncilCollective Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective Proposals (r:1 w:1) + /// Proof Skipped: CouncilCollective Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective ProposalOf (r:0 w:1) + /// Proof Skipped: CouncilCollective ProposalOf (max_values: None, max_size: None, mode: Measured) + /// The range of component `m` is `[4, 100]`. + /// The range of component `p` is `[1, 100]`. + fn close_disapproved(m: u32, p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `516 + m * (30 ±0) + p * (36 ±0)` + // Estimated: `3958 + m * (31 ±0) + p * (36 ±0)` + // Minimum execution time: 20_735_000 picoseconds. + Weight::from_parts(22_649_363, 0) + .saturating_add(Weight::from_parts(0, 3958)) + // Standard Error: 1_082 + .saturating_add(Weight::from_parts(32_331, 0).saturating_mul(m.into())) + // Standard Error: 1_055 + .saturating_add(Weight::from_parts(122_034, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(Weight::from_parts(0, 31).saturating_mul(m.into())) + .saturating_add(Weight::from_parts(0, 36).saturating_mul(p.into())) + } + /// Storage: CouncilCollective Voting (r:1 w:1) + /// Proof Skipped: CouncilCollective Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: CouncilCollective Members (r:1 w:0) + /// Proof Skipped: CouncilCollective Members (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective Prime (r:1 w:0) + /// Proof Skipped: CouncilCollective Prime (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective ProposalOf (r:1 w:1) + /// Proof Skipped: CouncilCollective ProposalOf (max_values: None, max_size: None, mode: Measured) + /// Storage: MaintenanceMode MaintenanceMode (r:1 w:0) + /// Proof Skipped: MaintenanceMode MaintenanceMode (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective Proposals (r:1 w:1) + /// Proof Skipped: CouncilCollective Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `b` is `[2, 1024]`. + /// The range of component `m` is `[4, 100]`. + /// The range of component `p` is `[1, 100]`. + fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `811 + b * (1 ±0) + m * (40 ±0) + p * (40 ±0)` + // Estimated: `4128 + b * (1 ±0) + m * (42 ±0) + p * (40 ±0)` + // Minimum execution time: 32_927_000 picoseconds. + Weight::from_parts(32_086_367, 0) + .saturating_add(Weight::from_parts(0, 4128)) + // Standard Error: 122 + .saturating_add(Weight::from_parts(2_962, 0).saturating_mul(b.into())) + // Standard Error: 1_299 + .saturating_add(Weight::from_parts(32_167, 0).saturating_mul(m.into())) + // Standard Error: 1_266 + .saturating_add(Weight::from_parts(154_131, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(Weight::from_parts(0, 1).saturating_mul(b.into())) + .saturating_add(Weight::from_parts(0, 42).saturating_mul(m.into())) + .saturating_add(Weight::from_parts(0, 40).saturating_mul(p.into())) + } + /// Storage: CouncilCollective Proposals (r:1 w:1) + /// Proof Skipped: CouncilCollective Proposals (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CouncilCollective Voting (r:0 w:1) + /// Proof Skipped: CouncilCollective Voting (max_values: None, max_size: None, mode: Measured) + /// Storage: CouncilCollective ProposalOf (r:0 w:1) + /// Proof Skipped: CouncilCollective ProposalOf (max_values: None, max_size: None, mode: Measured) + /// The range of component `p` is `[1, 100]`. + fn disapprove_proposal(p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `264 + p * (32 ±0)` + // Estimated: `1749 + p * (32 ±0)` + // Minimum execution time: 10_334_000 picoseconds. + Weight::from_parts(11_413_201, 0) + .saturating_add(Weight::from_parts(0, 1749)) + // Standard Error: 1_033 + .saturating_add(Weight::from_parts(95_458, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(Weight::from_parts(0, 32).saturating_mul(p.into())) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_conviction_voting.rs b/tracing/2601/runtime/common/src/weights/pallet_conviction_voting.rs new file mode 100644 index 00000000..459fa565 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_conviction_voting.rs @@ -0,0 +1,190 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_conviction_voting` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_conviction_voting +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_conviction_voting`. +pub struct WeightInfo(PhantomData); +impl pallet_conviction_voting::WeightInfo for WeightInfo { + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(1152), added: 3627, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(119), added: 2594, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn vote_new() -> Weight { + // Proof Size summary in bytes: + // Measured: `1862` + // Estimated: `42428` + // Minimum execution time: 49_713_000 picoseconds. + Weight::from_parts(51_247_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(5)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(1152), added: 3627, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(119), added: 2594, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn vote_existing() -> Weight { + // Proof Size summary in bytes: + // Measured: `2163` + // Estimated: `83866` + // Minimum execution time: 66_644_000 picoseconds. + Weight::from_parts(68_298_000, 0) + .saturating_add(Weight::from_parts(0, 83866)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(6)) + } + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(1152), added: 3627, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn remove_vote() -> Weight { + // Proof Size summary in bytes: + // Measured: `1807` + // Estimated: `83866` + // Minimum execution time: 46_630_000 picoseconds. + Weight::from_parts(48_124_000, 0) + .saturating_add(Weight::from_parts(0, 83866)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(1152), added: 3627, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + fn remove_other_vote() -> Weight { + // Proof Size summary in bytes: + // Measured: `1351` + // Estimated: `4617` + // Minimum execution time: 17_086_000 picoseconds. + Weight::from_parts(17_574_000, 0) + .saturating_add(Weight::from_parts(0, 4617)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: ConvictionVoting VotingFor (r:2 w:2) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(1152), added: 3627, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:20 w:20) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(119), added: 2594, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// The range of component `r` is `[0, 20]`. + fn delegate(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1505 + r * (235 ±0)` + // Estimated: `83866 + r * (3387 ±0)` + // Minimum execution time: 31_288_000 picoseconds. + Weight::from_parts(26_953_858, 0) + .saturating_add(Weight::from_parts(0, 83866)) + // Standard Error: 86_677 + .saturating_add(Weight::from_parts(18_262_342, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(6)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) + .saturating_add(Weight::from_parts(0, 3387).saturating_mul(r.into())) + } + /// Storage: ConvictionVoting VotingFor (r:2 w:2) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(1152), added: 3627, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:20 w:20) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// The range of component `r` is `[0, 20]`. + fn undelegate(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1290 + r * (235 ±0)` + // Estimated: `83866 + r * (3387 ±0)` + // Minimum execution time: 17_054_000 picoseconds. + Weight::from_parts(8_013_322, 0) + .saturating_add(Weight::from_parts(0, 83866)) + // Standard Error: 92_600 + .saturating_add(Weight::from_parts(17_999_181, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) + .saturating_add(Weight::from_parts(0, 3387).saturating_mul(r.into())) + } + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(1152), added: 3627, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(119), added: 2594, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + fn unlock() -> Weight { + // Proof Size summary in bytes: + // Measured: `1111` + // Estimated: `4752` + // Minimum execution time: 36_667_000 picoseconds. + Weight::from_parts(37_471_000, 0) + .saturating_add(Weight::from_parts(0, 4752)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_crowdloan_rewards.rs b/tracing/2601/runtime/common/src/weights/pallet_crowdloan_rewards.rs new file mode 100644 index 00000000..f0691f66 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_crowdloan_rewards.rs @@ -0,0 +1,168 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_crowdloan_rewards` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_crowdloan_rewards +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_crowdloan_rewards`. +pub struct WeightInfo(PhantomData); +impl pallet_crowdloan_rewards::WeightInfo for WeightInfo { + /// Storage: CrowdloanRewards Initialized (r:1 w:0) + /// Proof Skipped: CrowdloanRewards Initialized (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CrowdloanRewards InitializedRewardAmount (r:1 w:1) + /// Proof Skipped: CrowdloanRewards InitializedRewardAmount (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CrowdloanRewards TotalContributors (r:1 w:1) + /// Proof Skipped: CrowdloanRewards TotalContributors (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:501 w:501) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: CrowdloanRewards ClaimedRelayChainIds (r:500 w:500) + /// Proof Skipped: CrowdloanRewards ClaimedRelayChainIds (max_values: None, max_size: None, mode: Measured) + /// Storage: CrowdloanRewards UnassociatedContributions (r:500 w:0) + /// Proof Skipped: CrowdloanRewards UnassociatedContributions (max_values: None, max_size: None, mode: Measured) + /// Storage: CrowdloanRewards AccountsPayable (r:500 w:500) + /// Proof Skipped: CrowdloanRewards AccountsPayable (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[1, 500]`. + fn initialize_reward_vec(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `75944 + x * (659 ±0)` + // Estimated: `66066 + x * (3161 ±5)` + // Minimum execution time: 87_730_000 picoseconds. + Weight::from_parts(54_129_335, 0) + .saturating_add(Weight::from_parts(0, 66066)) + // Standard Error: 24_625 + .saturating_add(Weight::from_parts(32_916_886, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 3161).saturating_mul(x.into())) + } + /// Storage: CrowdloanRewards Initialized (r:1 w:1) + /// Proof Skipped: CrowdloanRewards Initialized (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CrowdloanRewards InitRelayBlock (r:1 w:0) + /// Proof Skipped: CrowdloanRewards InitRelayBlock (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CrowdloanRewards InitializedRewardAmount (r:1 w:0) + /// Proof Skipped: CrowdloanRewards InitializedRewardAmount (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: CrowdloanRewards TotalContributors (r:1 w:0) + /// Proof Skipped: CrowdloanRewards TotalContributors (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CrowdloanRewards EndRelayBlock (r:0 w:1) + /// Proof Skipped: CrowdloanRewards EndRelayBlock (max_values: Some(1), max_size: None, mode: Measured) + fn complete_initialization() -> Weight { + // Proof Size summary in bytes: + // Measured: `513` + // Estimated: `3581` + // Minimum execution time: 13_253_000 picoseconds. + Weight::from_parts(13_416_000, 0) + .saturating_add(Weight::from_parts(0, 3581)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: CrowdloanRewards Initialized (r:1 w:0) + /// Proof Skipped: CrowdloanRewards Initialized (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CrowdloanRewards AccountsPayable (r:1 w:1) + /// Proof Skipped: CrowdloanRewards AccountsPayable (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainSystem ValidationData (r:1 w:0) + /// Proof Skipped: ParachainSystem ValidationData (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CrowdloanRewards InitRelayBlock (r:1 w:0) + /// Proof Skipped: CrowdloanRewards InitRelayBlock (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: CrowdloanRewards EndRelayBlock (r:1 w:0) + /// Proof Skipped: CrowdloanRewards EndRelayBlock (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn claim() -> Weight { + // Proof Size summary in bytes: + // Measured: `968` + // Estimated: `6172` + // Minimum execution time: 40_516_000 picoseconds. + Weight::from_parts(41_450_000, 0) + .saturating_add(Weight::from_parts(0, 6172)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: CrowdloanRewards AccountsPayable (r:2 w:2) + /// Proof Skipped: CrowdloanRewards AccountsPayable (max_values: None, max_size: None, mode: Measured) + fn update_reward_address() -> Weight { + // Proof Size summary in bytes: + // Measured: `397` + // Estimated: `6337` + // Minimum execution time: 13_569_000 picoseconds. + Weight::from_parts(13_940_000, 0) + .saturating_add(Weight::from_parts(0, 6337)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: CrowdloanRewards UnassociatedContributions (r:1 w:1) + /// Proof Skipped: CrowdloanRewards UnassociatedContributions (max_values: None, max_size: None, mode: Measured) + /// Storage: CrowdloanRewards ClaimedRelayChainIds (r:1 w:1) + /// Proof Skipped: CrowdloanRewards ClaimedRelayChainIds (max_values: None, max_size: None, mode: Measured) + /// Storage: CrowdloanRewards AccountsPayable (r:1 w:1) + /// Proof Skipped: CrowdloanRewards AccountsPayable (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn associate_native_identity() -> Weight { + // Proof Size summary in bytes: + // Measured: `802` + // Estimated: `6172` + // Minimum execution time: 90_788_000 picoseconds. + Weight::from_parts(91_822_000, 0) + .saturating_add(Weight::from_parts(0, 6172)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) + } + /// Storage: CrowdloanRewards AccountsPayable (r:2 w:2) + /// Proof Skipped: CrowdloanRewards AccountsPayable (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[1, 500]`. + fn change_association_with_relay_keys(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `366 + x * (32 ±0)` + // Estimated: `6306 + x * (32 ±0)` + // Minimum execution time: 68_841_000 picoseconds. + Weight::from_parts(6_018_178, 0) + .saturating_add(Weight::from_parts(0, 6306)) + // Standard Error: 2_074 + .saturating_add(Weight::from_parts(53_552_923, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 32).saturating_mul(x.into())) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_democracy.rs b/tracing/2601/runtime/common/src/weights/pallet_democracy.rs new file mode 100644 index 00000000..5ec69608 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_democracy.rs @@ -0,0 +1,523 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_democracy` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_democracy +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_democracy`. +pub struct WeightInfo(PhantomData); +impl pallet_democracy::WeightInfo for WeightInfo { + /// Storage: Democracy PublicPropCount (r:1 w:1) + /// Proof: Democracy PublicPropCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy PublicProps (r:1 w:1) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(15502), added: 15997, mode: MaxEncodedLen) + /// Storage: Democracy Blacklist (r:1 w:0) + /// Proof: Democracy Blacklist (max_values: None, max_size: Some(2038), added: 4513, mode: MaxEncodedLen) + /// Storage: Democracy DepositOf (r:0 w:1) + /// Proof: Democracy DepositOf (max_values: None, max_size: Some(2030), added: 4505, mode: MaxEncodedLen) + fn propose() -> Weight { + // Proof Size summary in bytes: + // Measured: `3843` + // Estimated: `16987` + // Minimum execution time: 32_118_000 picoseconds. + Weight::from_parts(33_567_000, 0) + .saturating_add(Weight::from_parts(0, 16987)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Democracy DepositOf (r:1 w:1) + /// Proof: Democracy DepositOf (max_values: None, max_size: Some(2030), added: 4505, mode: MaxEncodedLen) + fn second() -> Weight { + // Proof Size summary in bytes: + // Measured: `2559` + // Estimated: `5495` + // Minimum execution time: 26_988_000 picoseconds. + Weight::from_parts(28_730_000, 0) + .saturating_add(Weight::from_parts(0, 5495)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3783), added: 6258, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + fn vote_new() -> Weight { + // Proof Size summary in bytes: + // Measured: `3511` + // Estimated: `7248` + // Minimum execution time: 47_295_000 picoseconds. + Weight::from_parts(48_622_000, 0) + .saturating_add(Weight::from_parts(0, 7248)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3783), added: 6258, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + fn vote_existing() -> Weight { + // Proof Size summary in bytes: + // Measured: `3533` + // Estimated: `7248` + // Minimum execution time: 49_540_000 picoseconds. + Weight::from_parts(50_795_000, 0) + .saturating_add(Weight::from_parts(0, 7248)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy Cancellations (r:1 w:1) + /// Proof: Democracy Cancellations (max_values: None, max_size: Some(33), added: 2508, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + fn emergency_cancel() -> Weight { + // Proof Size summary in bytes: + // Measured: `299` + // Estimated: `3666` + // Minimum execution time: 16_745_000 picoseconds. + Weight::from_parts(17_100_000, 0) + .saturating_add(Weight::from_parts(0, 3666)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Democracy PublicProps (r:1 w:1) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(15502), added: 15997, mode: MaxEncodedLen) + /// Storage: Democracy DepositOf (r:1 w:1) + /// Proof: Democracy DepositOf (max_values: None, max_size: Some(2030), added: 4505, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:3 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: Democracy NextExternal (r:1 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy Blacklist (r:0 w:1) + /// Proof: Democracy Blacklist (max_values: None, max_size: Some(2038), added: 4513, mode: MaxEncodedLen) + fn blacklist() -> Weight { + // Proof Size summary in bytes: + // Measured: `4659` + // Estimated: `16987` + // Minimum execution time: 66_727_000 picoseconds. + Weight::from_parts(68_348_000, 0) + .saturating_add(Weight::from_parts(0, 16987)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) + } + /// Storage: Democracy NextExternal (r:1 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy Blacklist (r:1 w:0) + /// Proof: Democracy Blacklist (max_values: None, max_size: Some(2038), added: 4513, mode: MaxEncodedLen) + fn external_propose() -> Weight { + // Proof Size summary in bytes: + // Measured: `2161` + // Estimated: `5503` + // Minimum execution time: 10_276_000 picoseconds. + Weight::from_parts(10_506_000, 0) + .saturating_add(Weight::from_parts(0, 5503)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Democracy NextExternal (r:0 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + fn external_propose_majority() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_767_000 picoseconds. + Weight::from_parts(1_851_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Democracy NextExternal (r:0 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + fn external_propose_default() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_707_000 picoseconds. + Weight::from_parts(1_800_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Democracy NextExternal (r:1 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumCount (r:1 w:1) + /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:2) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:0 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + fn fast_track() -> Weight { + // Proof Size summary in bytes: + // Measured: `219` + // Estimated: `3518` + // Minimum execution time: 16_619_000 picoseconds. + Weight::from_parts(17_116_000, 0) + .saturating_add(Weight::from_parts(0, 3518)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(5)) + } + /// Storage: Democracy NextExternal (r:1 w:1) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy Blacklist (r:1 w:1) + /// Proof: Democracy Blacklist (max_values: None, max_size: Some(2038), added: 4513, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + fn veto_external() -> Weight { + // Proof Size summary in bytes: + // Measured: `2264` + // Estimated: `5503` + // Minimum execution time: 19_585_000 picoseconds. + Weight::from_parts(20_128_000, 0) + .saturating_add(Weight::from_parts(0, 5503)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Democracy PublicProps (r:1 w:1) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(15502), added: 15997, mode: MaxEncodedLen) + /// Storage: Democracy DepositOf (r:1 w:1) + /// Proof: Democracy DepositOf (max_values: None, max_size: Some(2030), added: 4505, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + fn cancel_proposal() -> Weight { + // Proof Size summary in bytes: + // Measured: `4558` + // Estimated: `16987` + // Minimum execution time: 51_975_000 picoseconds. + Weight::from_parts(53_193_000, 0) + .saturating_add(Weight::from_parts(0, 16987)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:0 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + fn cancel_referendum() -> Weight { + // Proof Size summary in bytes: + // Measured: `204` + // Estimated: `3518` + // Minimum execution time: 11_895_000 picoseconds. + Weight::from_parts(12_155_000, 0) + .saturating_add(Weight::from_parts(0, 3518)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Democracy LowestUnbaked (r:1 w:1) + /// Proof: Democracy LowestUnbaked (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumCount (r:1 w:0) + /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:99 w:0) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// The range of component `r` is `[0, 99]`. + fn on_initialize_base(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `177 + r * (86 ±0)` + // Estimated: `1489 + r * (2676 ±0)` + // Minimum execution time: 5_817_000 picoseconds. + Weight::from_parts(6_694_982, 0) + .saturating_add(Weight::from_parts(0, 1489)) + // Standard Error: 5_229 + .saturating_add(Weight::from_parts(2_542_238, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) + } + /// Storage: Democracy LowestUnbaked (r:1 w:1) + /// Proof: Democracy LowestUnbaked (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumCount (r:1 w:0) + /// Proof: Democracy ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Democracy LastTabledWasExternal (r:1 w:0) + /// Proof: Democracy LastTabledWasExternal (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: Democracy NextExternal (r:1 w:0) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy PublicProps (r:1 w:0) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(15502), added: 15997, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:99 w:0) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// The range of component `r` is `[0, 99]`. + fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `177 + r * (86 ±0)` + // Estimated: `16987 + r * (2676 ±0)` + // Minimum execution time: 7_465_000 picoseconds. + Weight::from_parts(9_080_556, 0) + .saturating_add(Weight::from_parts(0, 16987)) + // Standard Error: 6_001 + .saturating_add(Weight::from_parts(2_525_995, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) + } + /// Storage: Democracy VotingOf (r:3 w:3) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3783), added: 6258, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:99 w:99) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// The range of component `r` is `[0, 99]`. + fn delegate(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `832 + r * (108 ±0)` + // Estimated: `19764 + r * (2676 ±0)` + // Minimum execution time: 30_152_000 picoseconds. + Weight::from_parts(34_644_994, 0) + .saturating_add(Weight::from_parts(0, 19764)) + // Standard Error: 7_028 + .saturating_add(Weight::from_parts(3_219_569, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) + .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) + } + /// Storage: Democracy VotingOf (r:2 w:2) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3783), added: 6258, mode: MaxEncodedLen) + /// Storage: Democracy ReferendumInfoOf (r:99 w:99) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// The range of component `r` is `[0, 99]`. + fn undelegate(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `388 + r * (108 ±0)` + // Estimated: `13506 + r * (2676 ±0)` + // Minimum execution time: 14_558_000 picoseconds. + Weight::from_parts(16_381_184, 0) + .saturating_add(Weight::from_parts(0, 13506)) + // Standard Error: 6_251 + .saturating_add(Weight::from_parts(3_163_594, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) + .saturating_add(Weight::from_parts(0, 2676).saturating_mul(r.into())) + } + /// Storage: Democracy PublicProps (r:0 w:1) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(15502), added: 15997, mode: MaxEncodedLen) + fn clear_public_proposals() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_768_000 picoseconds. + Weight::from_parts(1_852_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3783), added: 6258, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// The range of component `r` is `[0, 99]`. + fn unlock_remove(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `421` + // Estimated: `7248` + // Minimum execution time: 15_205_000 picoseconds. + Weight::from_parts(24_689_085, 0) + .saturating_add(Weight::from_parts(0, 7248)) + // Standard Error: 2_518 + .saturating_add(Weight::from_parts(94_640, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3783), added: 6258, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// The range of component `r` is `[0, 99]`. + fn unlock_set(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `422 + r * (22 ±0)` + // Estimated: `7248` + // Minimum execution time: 22_237_000 picoseconds. + Weight::from_parts(24_475_537, 0) + .saturating_add(Weight::from_parts(0, 7248)) + // Standard Error: 1_587 + .saturating_add(Weight::from_parts(132_155, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3783), added: 6258, mode: MaxEncodedLen) + /// The range of component `r` is `[1, 100]`. + fn remove_vote(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `649 + r * (26 ±0)` + // Estimated: `7248` + // Minimum execution time: 11_279_000 picoseconds. + Weight::from_parts(13_755_338, 0) + .saturating_add(Weight::from_parts(0, 7248)) + // Standard Error: 2_321 + .saturating_add(Weight::from_parts(145_498, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Democracy ReferendumInfoOf (r:1 w:1) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy VotingOf (r:1 w:1) + /// Proof: Democracy VotingOf (max_values: None, max_size: Some(3783), added: 6258, mode: MaxEncodedLen) + /// The range of component `r` is `[1, 100]`. + fn remove_other_vote(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `649 + r * (26 ±0)` + // Estimated: `7248` + // Minimum execution time: 11_403_000 picoseconds. + Weight::from_parts(13_824_312, 0) + .saturating_add(Weight::from_parts(0, 7248)) + // Standard Error: 2_302 + .saturating_add(Weight::from_parts(145_629, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Democracy NextExternal (r:1 w:0) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:0) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:0 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + fn set_external_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `289` + // Estimated: `3544` + // Minimum execution time: 13_135_000 picoseconds. + Weight::from_parts(13_601_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Democracy NextExternal (r:1 w:0) + /// Proof: Democracy NextExternal (max_values: Some(1), max_size: Some(132), added: 627, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + fn clear_external_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `219` + // Estimated: `3518` + // Minimum execution time: 11_822_000 picoseconds. + Weight::from_parts(12_140_000, 0) + .saturating_add(Weight::from_parts(0, 3518)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Democracy PublicProps (r:1 w:0) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(15502), added: 15997, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:0) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:0 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + fn set_proposal_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `3621` + // Estimated: `16987` + // Minimum execution time: 33_453_000 picoseconds. + Weight::from_parts(34_665_000, 0) + .saturating_add(Weight::from_parts(0, 16987)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Democracy PublicProps (r:1 w:0) + /// Proof: Democracy PublicProps (max_values: Some(1), max_size: Some(15502), added: 15997, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + fn clear_proposal_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `3555` + // Estimated: `16987` + // Minimum execution time: 27_619_000 picoseconds. + Weight::from_parts(29_080_000, 0) + .saturating_add(Weight::from_parts(0, 16987)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Preimage StatusFor (r:1 w:0) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:0 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + fn set_referendum_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `144` + // Estimated: `3544` + // Minimum execution time: 8_981_000 picoseconds. + Weight::from_parts(9_243_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Democracy ReferendumInfoOf (r:1 w:0) + /// Proof: Democracy ReferendumInfoOf (max_values: None, max_size: Some(201), added: 2676, mode: MaxEncodedLen) + /// Storage: Democracy MetadataOf (r:1 w:1) + /// Proof: Democracy MetadataOf (max_values: None, max_size: Some(53), added: 2528, mode: MaxEncodedLen) + fn clear_referendum_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `235` + // Estimated: `3666` + // Minimum execution time: 13_020_000 picoseconds. + Weight::from_parts(13_684_000, 0) + .saturating_add(Weight::from_parts(0, 3666)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_evm.rs b/tracing/2601/runtime/common/src/weights/pallet_evm.rs new file mode 100644 index 00000000..e478c380 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_evm.rs @@ -0,0 +1,79 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_evm` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_evm +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_evm`. +pub struct WeightInfo(PhantomData); +impl pallet_evm::WeightInfo for WeightInfo { + /// Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) + /// Proof: TransactionPayment NextFeeMultiplier (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: EthereumChainId ChainId (r:1 w:0) + /// Proof: EthereumChainId ChainId (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: EVM AccountCodes (r:2 w:0) + /// Proof Skipped: EVM AccountCodes (max_values: None, max_size: None, mode: Measured) + /// Storage: System Digest (r:1 w:0) + /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: EVM AccountStorages (r:1 w:0) + /// Proof Skipped: EVM AccountStorages (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[1, 10000000]`. + fn runner_execute(_x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1501` + // Estimated: `7441` + // Minimum execution time: 8_971_188_000 picoseconds. + Weight::from_parts(9_104_793_824, 0) + .saturating_add(Weight::from_parts(0, 7441)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(2)) + } + fn withdraw() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 817_000 picoseconds. + Weight::from_parts(878_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_identity.rs b/tracing/2601/runtime/common/src/weights/pallet_identity.rs new file mode 100644 index 00000000..5d532b89 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_identity.rs @@ -0,0 +1,354 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_identity` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_identity +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_identity`. +pub struct WeightInfo(PhantomData); +impl pallet_identity::WeightInfo for WeightInfo { + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(901), added: 1396, mode: MaxEncodedLen) + /// The range of component `r` is `[1, 19]`. + fn add_registrar(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `32 + r * (45 ±0)` + // Estimated: `2386` + // Minimum execution time: 7_157_000 picoseconds. + Weight::from_parts(7_518_611, 0) + .saturating_add(Weight::from_parts(0, 2386)) + // Standard Error: 991 + .saturating_add(Weight::from_parts(100_030, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7526), added: 10001, mode: MaxEncodedLen) + /// The range of component `r` is `[1, 20]`. + /// The range of component `x` is `[0, 100]`. + fn set_identity(r: u32, x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `430 + r * (5 ±0)` + // Estimated: `10991` + // Minimum execution time: 18_174_000 picoseconds. + Weight::from_parts(15_674_240, 0) + .saturating_add(Weight::from_parts(0, 10991)) + // Standard Error: 2_987 + .saturating_add(Weight::from_parts(138_510, 0).saturating_mul(r.into())) + // Standard Error: 582 + .saturating_add(Weight::from_parts(130_131, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7526), added: 10001, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(2046), added: 4521, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:100 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(90), added: 2565, mode: MaxEncodedLen) + /// The range of component `s` is `[0, 100]`. + fn set_subs_new(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `89` + // Estimated: `10991 + s * (2565 ±0)` + // Minimum execution time: 6_059_000 picoseconds. + Weight::from_parts(12_820_827, 0) + .saturating_add(Weight::from_parts(0, 10991)) + // Standard Error: 1_998 + .saturating_add(Weight::from_parts(1_521_486, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(s.into()))) + .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) + .saturating_add(Weight::from_parts(0, 2565).saturating_mul(s.into())) + } + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7526), added: 10001, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(2046), added: 4521, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:0 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(90), added: 2565, mode: MaxEncodedLen) + /// The range of component `p` is `[0, 100]`. + fn set_subs_old(p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `169 + p * (20 ±0)` + // Estimated: `10991` + // Minimum execution time: 6_030_000 picoseconds. + Weight::from_parts(13_394_171, 0) + .saturating_add(Weight::from_parts(0, 10991)) + // Standard Error: 1_864 + .saturating_add(Weight::from_parts(718_549, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) + } + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(2046), added: 4521, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7526), added: 10001, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:0 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(90), added: 2565, mode: MaxEncodedLen) + /// The range of component `r` is `[1, 20]`. + /// The range of component `s` is `[0, 100]`. + /// The range of component `x` is `[0, 100]`. + fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `445 + r * (5 ±0) + s * (20 ±0) + x * (66 ±0)` + // Estimated: `10991` + // Minimum execution time: 30_009_000 picoseconds. + Weight::from_parts(19_908_009, 0) + .saturating_add(Weight::from_parts(0, 10991)) + // Standard Error: 9_160 + .saturating_add(Weight::from_parts(116_985, 0).saturating_mul(r.into())) + // Standard Error: 1_788 + .saturating_add(Weight::from_parts(728_921, 0).saturating_mul(s.into())) + // Standard Error: 1_788 + .saturating_add(Weight::from_parts(122_488, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) + } + /// Storage: Identity Registrars (r:1 w:0) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(901), added: 1396, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7526), added: 10001, mode: MaxEncodedLen) + /// The range of component `r` is `[1, 20]`. + /// The range of component `x` is `[0, 100]`. + fn request_judgement(r: u32, x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `355 + r * (45 ±0) + x * (66 ±0)` + // Estimated: `10991` + // Minimum execution time: 19_215_000 picoseconds. + Weight::from_parts(17_566_122, 0) + .saturating_add(Weight::from_parts(0, 10991)) + // Standard Error: 3_387 + .saturating_add(Weight::from_parts(103_336, 0).saturating_mul(r.into())) + // Standard Error: 660 + .saturating_add(Weight::from_parts(148_440, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7526), added: 10001, mode: MaxEncodedLen) + /// The range of component `r` is `[1, 20]`. + /// The range of component `x` is `[0, 100]`. + fn cancel_request(r: u32, x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `386 + x * (66 ±0)` + // Estimated: `10991` + // Minimum execution time: 16_100_000 picoseconds. + Weight::from_parts(15_271_614, 0) + .saturating_add(Weight::from_parts(0, 10991)) + // Standard Error: 2_865 + .saturating_add(Weight::from_parts(64_053, 0).saturating_mul(r.into())) + // Standard Error: 559 + .saturating_add(Weight::from_parts(144_144, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(901), added: 1396, mode: MaxEncodedLen) + /// The range of component `r` is `[1, 19]`. + fn set_fee(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `77 + r * (45 ±0)` + // Estimated: `2386` + // Minimum execution time: 4_963_000 picoseconds. + Weight::from_parts(5_207_820, 0) + .saturating_add(Weight::from_parts(0, 2386)) + // Standard Error: 817 + .saturating_add(Weight::from_parts(82_469, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(901), added: 1396, mode: MaxEncodedLen) + /// The range of component `r` is `[1, 19]`. + fn set_account_id(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `77 + r * (45 ±0)` + // Estimated: `2386` + // Minimum execution time: 4_912_000 picoseconds. + Weight::from_parts(5_187_188, 0) + .saturating_add(Weight::from_parts(0, 2386)) + // Standard Error: 807 + .saturating_add(Weight::from_parts(81_365, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Identity Registrars (r:1 w:1) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(901), added: 1396, mode: MaxEncodedLen) + /// The range of component `r` is `[1, 19]`. + fn set_fields(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `77 + r * (45 ±0)` + // Estimated: `2386` + // Minimum execution time: 4_889_000 picoseconds. + Weight::from_parts(5_229_571, 0) + .saturating_add(Weight::from_parts(0, 2386)) + // Standard Error: 758 + .saturating_add(Weight::from_parts(76_901, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Identity Registrars (r:1 w:0) + /// Proof: Identity Registrars (max_values: Some(1), max_size: Some(901), added: 1396, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7526), added: 10001, mode: MaxEncodedLen) + /// The range of component `r` is `[1, 19]`. + /// The range of component `x` is `[0, 100]`. + fn provide_judgement(r: u32, x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `421 + r * (45 ±0) + x * (66 ±0)` + // Estimated: `10991` + // Minimum execution time: 14_325_000 picoseconds. + Weight::from_parts(11_759_619, 0) + .saturating_add(Weight::from_parts(0, 10991)) + // Standard Error: 3_780 + .saturating_add(Weight::from_parts(131_885, 0).saturating_mul(r.into())) + // Standard Error: 699 + .saturating_add(Weight::from_parts(231_319, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(2046), added: 4521, mode: MaxEncodedLen) + /// Storage: Identity IdentityOf (r:1 w:1) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7526), added: 10001, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:0 w:100) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(90), added: 2565, mode: MaxEncodedLen) + /// The range of component `r` is `[1, 20]`. + /// The range of component `s` is `[0, 100]`. + /// The range of component `x` is `[0, 100]`. + fn kill_identity(r: u32, s: u32, x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `680 + r * (5 ±0) + s * (20 ±0) + x * (66 ±0)` + // Estimated: `10991` + // Minimum execution time: 45_060_000 picoseconds. + Weight::from_parts(30_044_300, 0) + .saturating_add(Weight::from_parts(0, 10991)) + // Standard Error: 8_943 + .saturating_add(Weight::from_parts(270_510, 0).saturating_mul(r.into())) + // Standard Error: 1_746 + .saturating_add(Weight::from_parts(747_775, 0).saturating_mul(s.into())) + // Standard Error: 1_746 + .saturating_add(Weight::from_parts(150_732, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) + } + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7526), added: 10001, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(90), added: 2565, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(2046), added: 4521, mode: MaxEncodedLen) + /// The range of component `s` is `[0, 99]`. + fn add_sub(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `536 + s * (23 ±0)` + // Estimated: `10991` + // Minimum execution time: 15_619_000 picoseconds. + Weight::from_parts(19_839_769, 0) + .saturating_add(Weight::from_parts(0, 10991)) + // Standard Error: 1_102 + .saturating_add(Weight::from_parts(73_705, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7526), added: 10001, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(90), added: 2565, mode: MaxEncodedLen) + /// The range of component `s` is `[1, 100]`. + fn rename_sub(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `615 + s * (4 ±0)` + // Estimated: `10991` + // Minimum execution time: 8_768_000 picoseconds. + Weight::from_parts(10_076_423, 0) + .saturating_add(Weight::from_parts(0, 10991)) + // Standard Error: 1_363 + .saturating_add(Weight::from_parts(68_020, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Identity IdentityOf (r:1 w:0) + /// Proof: Identity IdentityOf (max_values: None, max_size: Some(7526), added: 10001, mode: MaxEncodedLen) + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(90), added: 2565, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(2046), added: 4521, mode: MaxEncodedLen) + /// The range of component `s` is `[1, 100]`. + fn remove_sub(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `647 + s * (24 ±0)` + // Estimated: `10991` + // Minimum execution time: 19_137_000 picoseconds. + Weight::from_parts(23_700_395, 0) + .saturating_add(Weight::from_parts(0, 10991)) + // Standard Error: 1_375 + .saturating_add(Weight::from_parts(94_036, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Identity SuperOf (r:1 w:1) + /// Proof: Identity SuperOf (max_values: None, max_size: Some(90), added: 2565, mode: MaxEncodedLen) + /// Storage: Identity SubsOf (r:1 w:1) + /// Proof: Identity SubsOf (max_values: None, max_size: Some(2046), added: 4521, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// The range of component `s` is `[0, 99]`. + fn quit_sub(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `620 + s * (24 ±0)` + // Estimated: `5511` + // Minimum execution time: 15_642_000 picoseconds. + Weight::from_parts(17_017_310, 0) + .saturating_add(Weight::from_parts(0, 5511)) + // Standard Error: 571 + .saturating_add(Weight::from_parts(71_443, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_moonbeam_orbiters.rs b/tracing/2601/runtime/common/src/weights/pallet_moonbeam_orbiters.rs new file mode 100644 index 00000000..9ed4c451 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_moonbeam_orbiters.rs @@ -0,0 +1,212 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_moonbeam_orbiters` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_moonbeam_orbiters +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_moonbeam_orbiters`. +pub struct WeightInfo(PhantomData); +impl pallet_moonbeam_orbiters::WeightInfo for WeightInfo { + /// Storage: MoonbeamOrbiters CollatorsPool (r:1 w:1) + /// Proof Skipped: MoonbeamOrbiters CollatorsPool (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Reserves (r:1 w:0) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1037), added: 3512, mode: MaxEncodedLen) + fn collator_add_orbiter() -> Weight { + // Proof Size summary in bytes: + // Measured: `524` + // Estimated: `4502` + // Minimum execution time: 14_395_000 picoseconds. + Weight::from_parts(14_829_000, 0) + .saturating_add(Weight::from_parts(0, 4502)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: MoonbeamOrbiters CollatorsPool (r:1 w:1) + /// Proof Skipped: MoonbeamOrbiters CollatorsPool (max_values: None, max_size: None, mode: Measured) + fn collator_remove_orbiter() -> Weight { + // Proof Size summary in bytes: + // Measured: `328` + // Estimated: `3793` + // Minimum execution time: 10_794_000 picoseconds. + Weight::from_parts(11_251_000, 0) + .saturating_add(Weight::from_parts(0, 3793)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: MoonbeamOrbiters CollatorsPool (r:1 w:1) + /// Proof Skipped: MoonbeamOrbiters CollatorsPool (max_values: None, max_size: None, mode: Measured) + fn orbiter_leave_collator_pool() -> Weight { + // Proof Size summary in bytes: + // Measured: `328` + // Estimated: `3793` + // Minimum execution time: 10_874_000 picoseconds. + Weight::from_parts(11_386_000, 0) + .saturating_add(Weight::from_parts(0, 3793)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: MoonbeamOrbiters MinOrbiterDeposit (r:1 w:0) + /// Proof Skipped: MoonbeamOrbiters MinOrbiterDeposit (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Balances Reserves (r:1 w:1) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1037), added: 3512, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: MoonbeamOrbiters RegisteredOrbiter (r:0 w:1) + /// Proof Skipped: MoonbeamOrbiters RegisteredOrbiter (max_values: None, max_size: None, mode: Measured) + fn orbiter_register() -> Weight { + // Proof Size summary in bytes: + // Measured: `244` + // Estimated: `4502` + // Minimum execution time: 18_272_000 picoseconds. + Weight::from_parts(18_623_000, 0) + .saturating_add(Weight::from_parts(0, 4502)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: MoonbeamOrbiters CounterForCollatorsPool (r:1 w:0) + /// Proof: MoonbeamOrbiters CounterForCollatorsPool (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: MoonbeamOrbiters CollatorsPool (r:101 w:0) + /// Proof Skipped: MoonbeamOrbiters CollatorsPool (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Reserves (r:1 w:1) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1037), added: 3512, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: MoonbeamOrbiters RegisteredOrbiter (r:0 w:1) + /// Proof Skipped: MoonbeamOrbiters RegisteredOrbiter (max_values: None, max_size: None, mode: Measured) + /// The range of component `n` is `[0, 100]`. + fn orbiter_unregister(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `353 + n * (48 ±0)` + // Estimated: `4502 + n * (2524 ±0)` + // Minimum execution time: 23_194_000 picoseconds. + Weight::from_parts(26_994_916, 0) + .saturating_add(Weight::from_parts(0, 4502)) + // Standard Error: 3_856 + .saturating_add(Weight::from_parts(3_066_545, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(Weight::from_parts(0, 2524).saturating_mul(n.into())) + } + /// Storage: MoonbeamOrbiters CollatorsPool (r:1 w:1) + /// Proof Skipped: MoonbeamOrbiters CollatorsPool (max_values: None, max_size: None, mode: Measured) + /// Storage: MoonbeamOrbiters CounterForCollatorsPool (r:1 w:1) + /// Proof: MoonbeamOrbiters CounterForCollatorsPool (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn add_collator() -> Weight { + // Proof Size summary in bytes: + // Measured: `44` + // Estimated: `3509` + // Minimum execution time: 6_626_000 picoseconds. + Weight::from_parts(6_766_000, 0) + .saturating_add(Weight::from_parts(0, 3509)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: MoonbeamOrbiters CollatorsPool (r:1 w:1) + /// Proof Skipped: MoonbeamOrbiters CollatorsPool (max_values: None, max_size: None, mode: Measured) + /// Storage: MoonbeamOrbiters CounterForCollatorsPool (r:1 w:1) + /// Proof: MoonbeamOrbiters CounterForCollatorsPool (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: MoonbeamOrbiters AccountLookupOverride (r:0 w:9) + /// Proof Skipped: MoonbeamOrbiters AccountLookupOverride (max_values: None, max_size: None, mode: Measured) + fn remove_collator() -> Weight { + // Proof Size summary in bytes: + // Measured: `328` + // Estimated: `3793` + // Minimum execution time: 13_833_000 picoseconds. + Weight::from_parts(14_436_000, 0) + .saturating_add(Weight::from_parts(0, 3793)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(11)) + } + /// Storage: MoonbeamOrbiters CurrentRound (r:1 w:0) + /// Proof Skipped: MoonbeamOrbiters CurrentRound (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: MoonbeamOrbiters OrbiterPerRound (r:100 w:100) + /// Proof Skipped: MoonbeamOrbiters OrbiterPerRound (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[0, 100]`. + fn on_initialize(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `102 + x * (61 ±0)` + // Estimated: `1586 + x * (2537 ±0)` + // Minimum execution time: 4_838_000 picoseconds. + Weight::from_parts(3_934_897, 0) + .saturating_add(Weight::from_parts(0, 1586)) + // Standard Error: 1_450 + .saturating_add(Weight::from_parts(1_064_674, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 2537).saturating_mul(x.into())) + } + /// Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:1) + /// Proof Skipped: MoonbeamOrbiters OrbiterPerRound (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn distribute_rewards() -> Weight { + // Proof Size summary in bytes: + // Measured: `260` + // Estimated: `3725` + // Minimum execution time: 13_951_000 picoseconds. + Weight::from_parts(14_388_000, 0) + .saturating_add(Weight::from_parts(0, 3725)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: MoonbeamOrbiters ForceRotation (r:1 w:1) + /// Proof Skipped: MoonbeamOrbiters ForceRotation (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: MoonbeamOrbiters CollatorsPool (r:2 w:1) + /// Proof Skipped: MoonbeamOrbiters CollatorsPool (max_values: None, max_size: None, mode: Measured) + /// Storage: MoonbeamOrbiters OrbiterPerRound (r:0 w:3) + /// Proof Skipped: MoonbeamOrbiters OrbiterPerRound (max_values: None, max_size: None, mode: Measured) + /// Storage: MoonbeamOrbiters AccountLookupOverride (r:0 w:3) + /// Proof Skipped: MoonbeamOrbiters AccountLookupOverride (max_values: None, max_size: None, mode: Measured) + /// Storage: MoonbeamOrbiters CurrentRound (r:0 w:1) + /// Proof Skipped: MoonbeamOrbiters CurrentRound (max_values: Some(1), max_size: None, mode: Measured) + fn on_new_round() -> Weight { + // Proof Size summary in bytes: + // Measured: `218` + // Estimated: `6158` + // Minimum execution time: 16_367_000 picoseconds. + Weight::from_parts(17_229_000, 0) + .saturating_add(Weight::from_parts(0, 6158)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(9)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_multisig.rs b/tracing/2601/runtime/common/src/weights/pallet_multisig.rs new file mode 100644 index 00000000..62ac69c7 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_multisig.rs @@ -0,0 +1,166 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_multisig` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_multisig +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_multisig`. +pub struct WeightInfo(PhantomData); +impl pallet_multisig::WeightInfo for WeightInfo { + /// Storage: MaintenanceMode MaintenanceMode (r:1 w:0) + /// Proof Skipped: MaintenanceMode MaintenanceMode (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `z` is `[0, 10000]`. + fn as_multi_threshold_1(z: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `1527` + // Minimum execution time: 11_468_000 picoseconds. + Weight::from_parts(12_264_301, 0) + .saturating_add(Weight::from_parts(0, 1527)) + // Standard Error: 4 + .saturating_add(Weight::from_parts(99, 0).saturating_mul(z.into())) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(2122), added: 4597, mode: MaxEncodedLen) + /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. + fn as_multi_create(s: u32, z: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `304` + // Estimated: `5587` + // Minimum execution time: 27_229_000 picoseconds. + Weight::from_parts(17_646_947, 0) + .saturating_add(Weight::from_parts(0, 5587)) + // Standard Error: 650 + .saturating_add(Weight::from_parts(115_590, 0).saturating_mul(s.into())) + // Standard Error: 6 + .saturating_add(Weight::from_parts(1_008, 0).saturating_mul(z.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(2122), added: 4597, mode: MaxEncodedLen) + /// The range of component `s` is `[3, 100]`. + /// The range of component `z` is `[0, 10000]`. + fn as_multi_approve(s: u32, z: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `312` + // Estimated: `5587` + // Minimum execution time: 19_809_000 picoseconds. + Weight::from_parts(10_872_947, 0) + .saturating_add(Weight::from_parts(0, 5587)) + // Standard Error: 509 + .saturating_add(Weight::from_parts(100_638, 0).saturating_mul(s.into())) + // Standard Error: 4 + .saturating_add(Weight::from_parts(976, 0).saturating_mul(z.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(2122), added: 4597, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: MaintenanceMode MaintenanceMode (r:1 w:0) + /// Proof Skipped: MaintenanceMode MaintenanceMode (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. + fn as_multi_complete(s: u32, z: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `475 + s * (20 ±0)` + // Estimated: `5587 + s * (20 ±0)` + // Minimum execution time: 33_146_000 picoseconds. + Weight::from_parts(24_322_085, 0) + .saturating_add(Weight::from_parts(0, 5587)) + // Standard Error: 763 + .saturating_add(Weight::from_parts(156_521, 0).saturating_mul(s.into())) + // Standard Error: 7 + .saturating_add(Weight::from_parts(959, 0).saturating_mul(z.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 20).saturating_mul(s.into())) + } + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(2122), added: 4597, mode: MaxEncodedLen) + /// The range of component `s` is `[2, 100]`. + fn approve_as_multi_create(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `304` + // Estimated: `5587` + // Minimum execution time: 17_400_000 picoseconds. + Weight::from_parts(17_831_464, 0) + .saturating_add(Weight::from_parts(0, 5587)) + // Standard Error: 792 + .saturating_add(Weight::from_parts(111_017, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(2122), added: 4597, mode: MaxEncodedLen) + /// The range of component `s` is `[2, 100]`. + fn approve_as_multi_approve(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `312` + // Estimated: `5587` + // Minimum execution time: 10_697_000 picoseconds. + Weight::from_parts(10_842_736, 0) + .saturating_add(Weight::from_parts(0, 5587)) + // Standard Error: 606 + .saturating_add(Weight::from_parts(92_557, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Multisig Multisigs (r:1 w:1) + /// Proof: Multisig Multisigs (max_values: None, max_size: Some(2122), added: 4597, mode: MaxEncodedLen) + /// The range of component `s` is `[2, 100]`. + fn cancel_as_multi(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `474` + // Estimated: `5587` + // Minimum execution time: 19_175_000 picoseconds. + Weight::from_parts(19_433_900, 0) + .saturating_add(Weight::from_parts(0, 5587)) + // Standard Error: 626 + .saturating_add(Weight::from_parts(106_848, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_parachain_staking.rs b/tracing/2601/runtime/common/src/weights/pallet_parachain_staking.rs new file mode 100644 index 00000000..1fa08749 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_parachain_staking.rs @@ -0,0 +1,903 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_parachain_staking` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_parachain_staking +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_parachain_staking`. +pub struct WeightInfo(PhantomData); +impl pallet_parachain_staking::WeightInfo for WeightInfo { + /// Storage: ParachainStaking InflationConfig (r:1 w:1) + /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) + fn set_staking_expectations() -> Weight { + // Proof Size summary in bytes: + // Measured: `88` + // Estimated: `1573` + // Minimum execution time: 6_890_000 picoseconds. + Weight::from_parts(7_224_000, 0) + .saturating_add(Weight::from_parts(0, 1573)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: ParachainStaking InflationConfig (r:1 w:1) + /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) + fn set_inflation() -> Weight { + // Proof Size summary in bytes: + // Measured: `88` + // Estimated: `1573` + // Minimum execution time: 14_471_000 picoseconds. + Weight::from_parts(14_854_000, 0) + .saturating_add(Weight::from_parts(0, 1573)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: ParachainStaking ParachainBondInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) + fn set_parachain_bond_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `6` + // Estimated: `1491` + // Minimum execution time: 5_456_000 picoseconds. + Weight::from_parts(5_699_000, 0) + .saturating_add(Weight::from_parts(0, 1491)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: ParachainStaking ParachainBondInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) + fn set_parachain_bond_reserve_percent() -> Weight { + // Proof Size summary in bytes: + // Measured: `6` + // Estimated: `1491` + // Minimum execution time: 5_390_000 picoseconds. + Weight::from_parts(5_665_000, 0) + .saturating_add(Weight::from_parts(0, 1491)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: ParachainStaking TotalSelected (r:1 w:1) + /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) + fn set_total_selected() -> Weight { + // Proof Size summary in bytes: + // Measured: `28` + // Estimated: `1513` + // Minimum execution time: 6_141_000 picoseconds. + Weight::from_parts(6_387_000, 0) + .saturating_add(Weight::from_parts(0, 1513)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: ParachainStaking CollatorCommission (r:1 w:1) + /// Proof Skipped: ParachainStaking CollatorCommission (max_values: Some(1), max_size: None, mode: Measured) + fn set_collator_commission() -> Weight { + // Proof Size summary in bytes: + // Measured: `27` + // Estimated: `1512` + // Minimum execution time: 5_661_000 picoseconds. + Weight::from_parts(5_868_000, 0) + .saturating_add(Weight::from_parts(0, 1512)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: ParachainStaking TotalSelected (r:1 w:0) + /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking InflationConfig (r:1 w:1) + /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) + fn set_blocks_per_round() -> Weight { + // Proof Size summary in bytes: + // Measured: `116` + // Estimated: `1601` + // Minimum execution time: 16_971_000 picoseconds. + Weight::from_parts(17_437_000, 0) + .saturating_add(Weight::from_parts(0, 1601)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegatorState (r:1 w:0) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:0 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking BottomDelegations (r:0 w:1) + /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[3, 200]`. + fn join_candidates(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1421 + x * (38 ±0)` + // Estimated: `4752 + x * (41 ±0)` + // Minimum execution time: 31_867_000 picoseconds. + Weight::from_parts(41_892_922, 0) + .saturating_add(Weight::from_parts(0, 4752)) + // Standard Error: 1_749 + .saturating_add(Weight::from_parts(93_193, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(7)) + .saturating_add(Weight::from_parts(0, 41).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[3, 200]`. + fn schedule_leave_candidates(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `702 + x * (37 ±0)` + // Estimated: `4060 + x * (38 ±0)` + // Minimum execution time: 13_138_000 picoseconds. + Weight::from_parts(18_558_857, 0) + .saturating_add(Weight::from_parts(0, 4060)) + // Standard Error: 1_008 + .saturating_add(Weight::from_parts(66_693, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 38).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegatorState (r:349 w:349) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:350 w:350) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:350 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: System Account (r:350 w:350) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking BottomDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[2, 350]`. + fn execute_leave_candidates_worst_case(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1157 + x * (431 ±0)` + // Estimated: `4696 + x * (3762 ±0)` + // Minimum execution time: 65_656_000 picoseconds. + Weight::from_parts(66_996_000, 0) + .saturating_add(Weight::from_parts(0, 4696)) + // Standard Error: 107_183 + .saturating_add(Weight::from_parts(25_757_839, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 3762).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegatorState (r:349 w:349) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:350 w:350) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:350 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: System Account (r:350 w:350) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking BottomDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[2, 350]`. + /// The range of component `y` is `[2, 350]`. + fn execute_leave_candidates_ideal(x: u32, _y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1149 + x * (431 ±0)` + // Estimated: `4696 + x * (3762 ±0)` + // Minimum execution time: 61_023_000 picoseconds. + Weight::from_parts(61_779_000, 0) + .saturating_add(Weight::from_parts(0, 4696)) + // Standard Error: 49_414 + .saturating_add(Weight::from_parts(28_584_427, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 3762).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[3, 200]`. + fn cancel_leave_candidates(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `670 + x * (37 ±0)` + // Estimated: `4028 + x * (38 ±0)` + // Minimum execution time: 12_638_000 picoseconds. + Weight::from_parts(17_996_862, 0) + .saturating_add(Weight::from_parts(0, 4028)) + // Standard Error: 993 + .saturating_add(Weight::from_parts(67_486, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 38).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[1, 200]`. + fn go_offline(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `567 + x * (38 ±0)` + // Estimated: `3968 + x * (39 ±0)` + // Minimum execution time: 12_169_000 picoseconds. + Weight::from_parts(17_084_623, 0) + .saturating_add(Weight::from_parts(0, 3968)) + // Standard Error: 1_057 + .saturating_add(Weight::from_parts(69_599, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 39).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[1, 200]`. + fn go_online(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `531 + x * (38 ±0)` + // Estimated: `3932 + x * (39 ±0)` + // Minimum execution time: 11_837_000 picoseconds. + Weight::from_parts(16_851_802, 0) + .saturating_add(Weight::from_parts(0, 3932)) + // Standard Error: 1_027 + .saturating_add(Weight::from_parts(72_062, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 39).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// The range of component `x` is `[1, 200]`. + fn candidate_bond_more(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1270 + x * (42 ±0)` + // Estimated: `4752 + x * (44 ±0)` + // Minimum execution time: 30_904_000 picoseconds. + Weight::from_parts(39_948_520, 0) + .saturating_add(Weight::from_parts(0, 4752)) + // Standard Error: 1_831 + .saturating_add(Weight::from_parts(123_879, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(Weight::from_parts(0, 44).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + fn schedule_candidate_bond_less() -> Weight { + // Proof Size summary in bytes: + // Measured: `171` + // Estimated: `3636` + // Minimum execution time: 9_219_000 picoseconds. + Weight::from_parts(9_688_000, 0) + .saturating_add(Weight::from_parts(0, 3636)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// The range of component `x` is `[1, 200]`. + fn execute_candidate_bond_less(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1322 + x * (42 ±0)` + // Estimated: `4752 + x * (43 ±0)` + // Minimum execution time: 35_024_000 picoseconds. + Weight::from_parts(42_699_127, 0) + .saturating_add(Weight::from_parts(0, 4752)) + // Standard Error: 1_208 + .saturating_add(Weight::from_parts(105_143, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(Weight::from_parts(0, 43).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + fn cancel_candidate_bond_less() -> Weight { + // Proof Size summary in bytes: + // Measured: `191` + // Estimated: `3656` + // Minimum execution time: 8_552_000 picoseconds. + Weight::from_parts(8_881_000, 0) + .saturating_add(Weight::from_parts(0, 3656)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + fn set_candidate_bond_to_zero(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1322 + x * (42 ±0)` + // Estimated: `4752 + x * (43 ±0)` + // Minimum execution time: 34_969_000 picoseconds. + Weight::from_parts(43_183_234, 0) + .saturating_add(Weight::from_parts(0, 4752)) + // Standard Error: 1_377 + .saturating_add(Weight::from_parts(105_890, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(Weight::from_parts(0, 43).saturating_mul(x.into())) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[3, 100]`. + /// The range of component `y` is `[2, 300]`. + fn delegate(x: u32, y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `2479 + x * (79 ±0) + y * (38 ±0)` + // Estimated: `5723 + x * (81 ±0) + y * (39 ±0)` + // Minimum execution time: 70_929_000 picoseconds. + Weight::from_parts(59_788_434, 0) + .saturating_add(Weight::from_parts(0, 5723)) + // Standard Error: 1_596 + .saturating_add(Weight::from_parts(166_733, 0).saturating_mul(x.into())) + // Standard Error: 523 + .saturating_add(Weight::from_parts(52_733, 0).saturating_mul(y.into())) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) + .saturating_add(Weight::from_parts(0, 81).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 39).saturating_mul(y.into())) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[0, 349]`. + fn schedule_revoke_delegation(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `566 + x * (42 ±0)` + // Estimated: `4012 + x * (43 ±0)` + // Minimum execution time: 10_384_000 picoseconds. + Weight::from_parts(18_134_181, 0) + .saturating_add(Weight::from_parts(0, 4012)) + // Standard Error: 696 + .saturating_add(Weight::from_parts(69_714, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 43).saturating_mul(x.into())) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[0, 349]`. + fn delegator_bond_more(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1996 + x * (79 ±0)` + // Estimated: `5428 + x * (79 ±0)` + // Minimum execution time: 41_127_000 picoseconds. + Weight::from_parts(56_454_563, 0) + .saturating_add(Weight::from_parts(0, 5428)) + // Standard Error: 1_329 + .saturating_add(Weight::from_parts(155_463, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(7)) + .saturating_add(Weight::from_parts(0, 79).saturating_mul(x.into())) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[0, 349]`. + fn schedule_delegator_bond_less(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `566 + x * (42 ±0)` + // Estimated: `4012 + x * (43 ±0)` + // Minimum execution time: 10_304_000 picoseconds. + Weight::from_parts(18_044_389, 0) + .saturating_add(Weight::from_parts(0, 4012)) + // Standard Error: 682 + .saturating_add(Weight::from_parts(69_747, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 43).saturating_mul(x.into())) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + fn execute_revoke_delegation() -> Weight { + // Proof Size summary in bytes: + // Measured: `964` + // Estimated: `4752` + // Minimum execution time: 52_762_000 picoseconds. + Weight::from_parts(53_896_000, 0) + .saturating_add(Weight::from_parts(0, 4752)) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(8)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking BottomDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + fn execute_delegator_revoke_delegation_worst() -> Weight { + // Proof Size summary in bytes: + // Measured: `37308` + // Estimated: `40773` + // Minimum execution time: 121_863_000 picoseconds. + Weight::from_parts(125_957_000, 0) + .saturating_add(Weight::from_parts(0, 40773)) + .saturating_add(T::DbWeight::get().reads(11)) + .saturating_add(T::DbWeight::get().writes(10)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking BottomDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + fn execute_delegator_bond_less_worst() -> Weight { + // Proof Size summary in bytes: + // Measured: `29930` + // Estimated: `33395` + // Minimum execution time: 101_887_000 picoseconds. + Weight::from_parts(104_203_000, 0) + .saturating_add(Weight::from_parts(0, 33395)) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(9)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[0, 349]`. + fn cancel_delegation_request(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `663 + x * (42 ±0)` + // Estimated: `4092 + x * (43 ±0)` + // Minimum execution time: 13_580_000 picoseconds. + Weight::from_parts(20_161_730, 0) + .saturating_add(Weight::from_parts(0, 4092)) + // Standard Error: 748 + .saturating_add(Weight::from_parts(72_019, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 43).saturating_mul(x.into())) + } + /// Storage: ParachainStaking Points (r:1 w:0) + /// Proof Skipped: ParachainStaking Points (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking Staked (r:1 w:1) + /// Proof Skipped: ParachainStaking Staked (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking InflationConfig (r:1 w:0) + /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking ParachainBondInfo (r:1 w:0) + /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking CollatorCommission (r:1 w:0) + /// Proof Skipped: ParachainStaking CollatorCommission (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking DelayedPayouts (r:0 w:1) + /// Proof Skipped: ParachainStaking DelayedPayouts (max_values: None, max_size: None, mode: Measured) + fn prepare_staking_payouts() -> Weight { + // Proof Size summary in bytes: + // Measured: `380` + // Estimated: `3845` + // Minimum execution time: 21_509_000 picoseconds. + Weight::from_parts(22_210_000, 0) + .saturating_add(Weight::from_parts(0, 3845)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:0) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// The range of component `y` is `[0, 100]`. + fn get_rewardable_delegators(y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `73 + y * (36 ±0)` + // Estimated: `3537 + y * (36 ±0)` + // Minimum execution time: 4_225_000 picoseconds. + Weight::from_parts(5_236_159, 0) + .saturating_add(Weight::from_parts(0, 3537)) + // Standard Error: 565 + .saturating_add(Weight::from_parts(54_480, 0).saturating_mul(y.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(Weight::from_parts(0, 36).saturating_mul(y.into())) + } + /// Storage: ParachainStaking TotalSelected (r:1 w:0) + /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:0) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:51 w:0) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:51 w:0) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:51 w:0) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:51 w:0) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking SelectedCandidates (r:0 w:1) + /// Proof Skipped: ParachainStaking SelectedCandidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking AtStake (r:0 w:51) + /// Proof Skipped: ParachainStaking AtStake (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[0, 50]`. + /// The range of component `y` is `[0, 100]`. + fn select_top_candidates(x: u32, y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0 + x * (3816 ±0) + y * (1800 ±0)` + // Estimated: `3730 + x * (3975 ±39) + y * (639 ±19)` + // Minimum execution time: 14_650_000 picoseconds. + Weight::from_parts(14_993_000, 0) + .saturating_add(Weight::from_parts(0, 3730)) + // Standard Error: 86_614 + .saturating_add(Weight::from_parts(11_368_523, 0).saturating_mul(x.into())) + // Standard Error: 43_192 + .saturating_add(Weight::from_parts(1_335_158, 0).saturating_mul(y.into())) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 3975).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 639).saturating_mul(y.into())) + } + /// Storage: System Account (r:349 w:349) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking DelegatorState (r:349 w:349) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:349 w:349) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:349 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking BottomDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[0, 349]`. + /// The range of component `y` is `[0, 349]`. + /// The range of component `z` is `[0, 349]`. + fn pay_one_collator_reward_best(x: u32, y: u32, z: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0 + x * (395 ±0) + y * (156 ±0) + z * (41 ±0)` + // Estimated: `125757 + x * (2591 ±1) + y * (2234 ±1) + z * (28 ±0)` + // Minimum execution time: 84_000 picoseconds. + Weight::from_parts(89_000, 0) + .saturating_add(Weight::from_parts(0, 125757)) + // Standard Error: 586_928 + .saturating_add(Weight::from_parts(37_021_750, 0).saturating_mul(x.into())) + // Standard Error: 586_928 + .saturating_add(Weight::from_parts(20_024_306, 0).saturating_mul(y.into())) + .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(y.into()))) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(y.into()))) + .saturating_add(Weight::from_parts(0, 2591).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 2234).saturating_mul(y.into())) + .saturating_add(Weight::from_parts(0, 28).saturating_mul(z.into())) + } + /// Storage: ParachainStaking DelayedPayouts (r:1 w:0) + /// Proof Skipped: ParachainStaking DelayedPayouts (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking Points (r:1 w:0) + /// Proof Skipped: ParachainStaking Points (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AtStake (r:2 w:1) + /// Proof Skipped: ParachainStaking AtStake (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AwardedPts (r:1 w:1) + /// Proof Skipped: ParachainStaking AwardedPts (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:0) + /// Proof Skipped: MoonbeamOrbiters OrbiterPerRound (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:301 w:301) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// The range of component `y` is `[0, 300]`. + fn pay_one_collator_reward(y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1208 + y * (160 ±0)` + // Estimated: `6978 + y * (2591 ±0)` + // Minimum execution time: 32_493_000 picoseconds. + Weight::from_parts(29_439_933, 0) + .saturating_add(Weight::from_parts(0, 6978)) + // Standard Error: 4_122 + .saturating_add(Weight::from_parts(9_113_953, 0).saturating_mul(y.into())) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(y.into()))) + .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(y.into()))) + .saturating_add(Weight::from_parts(0, 2591).saturating_mul(y.into())) + } + fn base_on_initialize() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 646_000 picoseconds. + Weight::from_parts(696_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:0) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[0, 300]`. + /// The range of component `y` is `[0, 100]`. + fn set_auto_compound(x: u32, y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `671 + x * (22 ±0) + y * (36 ±0)` + // Estimated: `4027 + x * (23 ±0) + y * (36 ±0)` + // Minimum execution time: 19_844_000 picoseconds. + Weight::from_parts(18_132_368, 0) + .saturating_add(Weight::from_parts(0, 4027)) + // Standard Error: 390 + .saturating_add(Weight::from_parts(57_278, 0).saturating_mul(x.into())) + // Standard Error: 1_168 + .saturating_add(Weight::from_parts(51_455, 0).saturating_mul(y.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(Weight::from_parts(0, 23).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 36).saturating_mul(y.into())) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking BottomDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:1 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[0, 350]`. + /// The range of component `y` is `[0, 349]`. + /// The range of component `z` is `[0, 99]`. + fn delegate_with_auto_compound(x: u32, y: u32, z: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0 + x * (60 ±0) + y * (21 ±0) + z * (78 ±0)` + // Estimated: `26253 + x * (44 ±0) + y * (19 ±0) + z * (76 ±1)` + // Minimum execution time: 75_570_000 picoseconds. + Weight::from_parts(42_877_030, 0) + .saturating_add(Weight::from_parts(0, 26253)) + // Standard Error: 959 + .saturating_add(Weight::from_parts(145_930, 0).saturating_mul(x.into())) + // Standard Error: 962 + .saturating_add(Weight::from_parts(36_760, 0).saturating_mul(y.into())) + // Standard Error: 3_389 + .saturating_add(Weight::from_parts(236_052, 0).saturating_mul(z.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(8)) + .saturating_add(Weight::from_parts(0, 44).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 19).saturating_mul(y.into())) + .saturating_add(Weight::from_parts(0, 76).saturating_mul(z.into())) + } + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking DelegatorState (r:2 w:2) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking BottomDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:2 w:2) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Balances Freezes (r:2 w:0) + /// Proof: Balances Freezes (max_values: None, max_size: Some(37), added: 2512, mode: MaxEncodedLen) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + fn delegate_with_auto_compound_worst() -> Weight { + // Proof Size summary in bytes: + // Measured: `48167` + // Estimated: `54107` + // Minimum execution time: 198_472_000 picoseconds. + Weight::from_parts(201_828_000, 0) + .saturating_add(Weight::from_parts(0, 54107)) + .saturating_add(T::DbWeight::get().reads(15)) + .saturating_add(T::DbWeight::get().writes(13)) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn mint_collator_reward() -> Weight { + // Proof Size summary in bytes: + // Measured: `128` + // Estimated: `3581` + // Minimum execution time: 10_327_000 picoseconds. + Weight::from_parts(10_581_000, 0) + .saturating_add(Weight::from_parts(0, 3581)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: ParachainStaking EnableMarkingOffline (r:1 w:0) + /// Proof Skipped: ParachainStaking EnableMarkingOffline (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking TotalSelected (r:1 w:0) + /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking SelectedCandidates (r:1 w:0) + /// Proof Skipped: ParachainStaking SelectedCandidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking AtStake (r:2 w:0) + /// Proof Skipped: ParachainStaking AtStake (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AwardedPts (r:2 w:0) + /// Proof Skipped: ParachainStaking AwardedPts (max_values: None, max_size: None, mode: Measured) + /// Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:0) + /// Proof Skipped: MoonbeamOrbiters OrbiterPerRound (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + fn notify_inactive_collator() -> Weight { + // Proof Size summary in bytes: + // Measured: `11494` + // Estimated: `17434` + // Minimum execution time: 41_130_000 picoseconds. + Weight::from_parts(41_130_000, 0) + .saturating_add(Weight::from_parts(0, 17434)) + .saturating_add(T::DbWeight::get().reads(10_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_preimage.rs b/tracing/2601/runtime/common/src/weights/pallet_preimage.rs new file mode 100644 index 00000000..0b1c82f0 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_preimage.rs @@ -0,0 +1,213 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_preimage` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_preimage +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_preimage`. +pub struct WeightInfo(PhantomData); +impl pallet_preimage::WeightInfo for WeightInfo { + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:0 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) + /// The range of component `s` is `[0, 4194304]`. + fn note_preimage(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `275` + // Estimated: `3544` + // Minimum execution time: 17_326_000 picoseconds. + Weight::from_parts(17_614_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + // Standard Error: 8 + .saturating_add(Weight::from_parts(1_484, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:0 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) + /// The range of component `s` is `[0, 4194304]`. + fn note_requested_preimage(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `106` + // Estimated: `3544` + // Minimum execution time: 9_478_000 picoseconds. + Weight::from_parts(9_691_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + // Standard Error: 8 + .saturating_add(Weight::from_parts(1_484, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:0 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) + /// The range of component `s` is `[0, 4194304]`. + fn note_no_deposit_preimage(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `106` + // Estimated: `3544` + // Minimum execution time: 9_147_000 picoseconds. + Weight::from_parts(9_215_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + // Standard Error: 16 + .saturating_add(Weight::from_parts(1_668, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:0 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) + fn unnote_preimage() -> Weight { + // Proof Size summary in bytes: + // Measured: `409` + // Estimated: `3544` + // Minimum execution time: 26_789_000 picoseconds. + Weight::from_parts(27_732_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:0 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) + fn unnote_no_deposit_preimage() -> Weight { + // Proof Size summary in bytes: + // Measured: `144` + // Estimated: `3544` + // Minimum execution time: 15_405_000 picoseconds. + Weight::from_parts(15_973_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + fn request_preimage() -> Weight { + // Proof Size summary in bytes: + // Measured: `176` + // Estimated: `3544` + // Minimum execution time: 14_823_000 picoseconds. + Weight::from_parts(15_161_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + fn request_no_deposit_preimage() -> Weight { + // Proof Size summary in bytes: + // Measured: `144` + // Estimated: `3544` + // Minimum execution time: 9_102_000 picoseconds. + Weight::from_parts(9_530_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + fn request_unnoted_preimage() -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `3544` + // Minimum execution time: 9_581_000 picoseconds. + Weight::from_parts(10_026_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + fn request_requested_preimage() -> Weight { + // Proof Size summary in bytes: + // Measured: `106` + // Estimated: `3544` + // Minimum execution time: 6_347_000 picoseconds. + Weight::from_parts(6_669_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:0 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: MaxEncodedLen) + fn unrequest_preimage() -> Weight { + // Proof Size summary in bytes: + // Measured: `144` + // Estimated: `3544` + // Minimum execution time: 14_675_000 picoseconds. + Weight::from_parts(15_122_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + fn unrequest_unnoted_preimage() -> Weight { + // Proof Size summary in bytes: + // Measured: `106` + // Estimated: `3544` + // Minimum execution time: 6_368_000 picoseconds. + Weight::from_parts(6_576_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + fn unrequest_multi_referenced_preimage() -> Weight { + // Proof Size summary in bytes: + // Measured: `106` + // Estimated: `3544` + // Minimum execution time: 6_261_000 picoseconds. + Weight::from_parts(6_404_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_proxy.rs b/tracing/2601/runtime/common/src/weights/pallet_proxy.rs new file mode 100644 index 00000000..76a5d2d9 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_proxy.rs @@ -0,0 +1,226 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_proxy` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_proxy +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_proxy`. +pub struct WeightInfo(PhantomData); +impl pallet_proxy::WeightInfo for WeightInfo { + /// Storage: Proxy Proxies (r:1 w:0) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(845), added: 3320, mode: MaxEncodedLen) + /// Storage: MaintenanceMode MaintenanceMode (r:1 w:0) + /// Proof Skipped: MaintenanceMode MaintenanceMode (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `p` is `[1, 31]`. + fn proxy(p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `191 + p * (25 ±0)` + // Estimated: `4310 + p * (25 ±0)` + // Minimum execution time: 11_482_000 picoseconds. + Weight::from_parts(12_093_037, 0) + .saturating_add(Weight::from_parts(0, 4310)) + // Standard Error: 943 + .saturating_add(Weight::from_parts(40_718, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(2)) + // Manually adding 1 DB read that happen when filtering the proxy call transaction + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(Weight::from_parts(0, 25).saturating_mul(p.into())) + } + /// Storage: Proxy Proxies (r:1 w:0) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(845), added: 3320, mode: MaxEncodedLen) + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(1837), added: 4312, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: MaintenanceMode MaintenanceMode (r:1 w:0) + /// Proof Skipped: MaintenanceMode MaintenanceMode (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `a` is `[0, 31]`. + /// The range of component `p` is `[1, 31]`. + fn proxy_announced(a: u32, p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `443 + a * (56 ±0) + p * (25 ±0)` + // Estimated: `5302 + a * (59 ±0) + p * (23 ±0)` + // Minimum execution time: 26_926_000 picoseconds. + Weight::from_parts(27_170_528, 0) + .saturating_add(Weight::from_parts(0, 5302)) + // Standard Error: 2_005 + .saturating_add(Weight::from_parts(82_968, 0).saturating_mul(a.into())) + // Standard Error: 2_072 + .saturating_add(Weight::from_parts(20_197, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 59).saturating_mul(a.into())) + .saturating_add(Weight::from_parts(0, 23).saturating_mul(p.into())) + } + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(1837), added: 4312, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// The range of component `a` is `[0, 31]`. + /// The range of component `p` is `[1, 31]`. + fn remove_announcement(a: u32, _p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `329 + a * (56 ±0)` + // Estimated: `5302` + // Minimum execution time: 14_555_000 picoseconds. + Weight::from_parts(15_212_728, 0) + .saturating_add(Weight::from_parts(0, 5302)) + // Standard Error: 2_156 + .saturating_add(Weight::from_parts(75_335, 0).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(1837), added: 4312, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// The range of component `a` is `[0, 31]`. + /// The range of component `p` is `[1, 31]`. + fn reject_announcement(a: u32, _p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `329 + a * (56 ±0)` + // Estimated: `5302` + // Minimum execution time: 14_589_000 picoseconds. + Weight::from_parts(15_095_034, 0) + .saturating_add(Weight::from_parts(0, 5302)) + // Standard Error: 2_092 + .saturating_add(Weight::from_parts(79_740, 0).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Proxy Proxies (r:1 w:0) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(845), added: 3320, mode: MaxEncodedLen) + /// Storage: Proxy Announcements (r:1 w:1) + /// Proof: Proxy Announcements (max_values: None, max_size: Some(1837), added: 4312, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// The range of component `a` is `[0, 31]`. + /// The range of component `p` is `[1, 31]`. + fn announce(a: u32, p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `345 + a * (56 ±0) + p * (25 ±0)` + // Estimated: `5302` + // Minimum execution time: 19_613_000 picoseconds. + Weight::from_parts(22_016_278, 0) + .saturating_add(Weight::from_parts(0, 5302)) + // Standard Error: 2_419 + .saturating_add(Weight::from_parts(100_259, 0).saturating_mul(a.into())) + // Standard Error: 2_499 + .saturating_add(Weight::from_parts(26_733, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(845), added: 3320, mode: MaxEncodedLen) + /// The range of component `p` is `[1, 31]`. + fn add_proxy(p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `149 + p * (25 ±0)` + // Estimated: `4310` + // Minimum execution time: 13_603_000 picoseconds. + Weight::from_parts(14_296_527, 0) + .saturating_add(Weight::from_parts(0, 4310)) + // Standard Error: 808 + .saturating_add(Weight::from_parts(42_189, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(845), added: 3320, mode: MaxEncodedLen) + /// The range of component `p` is `[1, 31]`. + fn remove_proxy(p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `149 + p * (25 ±0)` + // Estimated: `4310` + // Minimum execution time: 13_627_000 picoseconds. + Weight::from_parts(14_289_242, 0) + .saturating_add(Weight::from_parts(0, 4310)) + // Standard Error: 915 + .saturating_add(Weight::from_parts(42_530, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(845), added: 3320, mode: MaxEncodedLen) + /// The range of component `p` is `[1, 31]`. + fn remove_proxies(p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `149 + p * (25 ±0)` + // Estimated: `4310` + // Minimum execution time: 12_681_000 picoseconds. + Weight::from_parts(13_132_149, 0) + .saturating_add(Weight::from_parts(0, 4310)) + // Standard Error: 815 + .saturating_add(Weight::from_parts(41_809, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(845), added: 3320, mode: MaxEncodedLen) + /// The range of component `p` is `[1, 31]`. + fn create_pure(p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `161` + // Estimated: `4310` + // Minimum execution time: 14_212_000 picoseconds. + Weight::from_parts(14_890_418, 0) + .saturating_add(Weight::from_parts(0, 4310)) + // Standard Error: 962 + .saturating_add(Weight::from_parts(3_235, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Proxy Proxies (r:1 w:1) + /// Proof: Proxy Proxies (max_values: None, max_size: Some(845), added: 3320, mode: MaxEncodedLen) + /// The range of component `p` is `[0, 30]`. + fn kill_pure(p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `174 + p * (25 ±0)` + // Estimated: `4310` + // Minimum execution time: 13_035_000 picoseconds. + Weight::from_parts(13_606_961, 0) + .saturating_add(Weight::from_parts(0, 4310)) + // Standard Error: 773 + .saturating_add(Weight::from_parts(38_899, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_randomness.rs b/tracing/2601/runtime/common/src/weights/pallet_randomness.rs new file mode 100644 index 00000000..af8ceb57 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_randomness.rs @@ -0,0 +1,168 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_randomness` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_randomness +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_randomness`. +pub struct WeightInfo(PhantomData); +impl pallet_randomness::WeightInfo for WeightInfo { + /// Storage: Randomness RelayEpoch (r:1 w:1) + /// Proof Skipped: Randomness RelayEpoch (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem ValidationData (r:1 w:0) + /// Proof Skipped: ParachainSystem ValidationData (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem RelayStateProof (r:1 w:0) + /// Proof Skipped: ParachainSystem RelayStateProof (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Randomness RandomnessResults (r:1 w:1) + /// Proof Skipped: Randomness RandomnessResults (max_values: None, max_size: None, mode: Measured) + /// Storage: Randomness InherentIncluded (r:0 w:1) + /// Proof Skipped: Randomness InherentIncluded (max_values: Some(1), max_size: None, mode: Measured) + fn set_babe_randomness_results() -> Weight { + // Proof Size summary in bytes: + // Measured: `297` + // Estimated: `3762` + // Minimum execution time: 10_513_000 picoseconds. + Weight::from_parts(10_834_000, 0) + .saturating_add(Weight::from_parts(0, 3762)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Randomness NotFirstBlock (r:1 w:0) + /// Proof Skipped: Randomness NotFirstBlock (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Digest (r:1 w:0) + /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: AuthorMapping MappingWithDeposit (r:1 w:0) + /// Proof Skipped: AuthorMapping MappingWithDeposit (max_values: None, max_size: None, mode: Measured) + /// Storage: Randomness LocalVrfOutput (r:1 w:1) + /// Proof Skipped: Randomness LocalVrfOutput (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Randomness RandomnessResults (r:1 w:1) + /// Proof Skipped: Randomness RandomnessResults (max_values: None, max_size: None, mode: Measured) + fn on_initialize() -> Weight { + // Proof Size summary in bytes: + // Measured: `719` + // Estimated: `4184` + // Minimum execution time: 169_944_000 picoseconds. + Weight::from_parts(171_082_000, 0) + .saturating_add(Weight::from_parts(0, 4184)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Randomness RequestCount (r:1 w:1) + /// Proof Skipped: Randomness RequestCount (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: Randomness RandomnessResults (r:1 w:1) + /// Proof Skipped: Randomness RandomnessResults (max_values: None, max_size: None, mode: Measured) + /// Storage: Randomness Requests (r:0 w:1) + /// Proof Skipped: Randomness Requests (max_values: None, max_size: None, mode: Measured) + fn request_randomness() -> Weight { + // Proof Size summary in bytes: + // Measured: `516` + // Estimated: `6172` + // Minimum execution time: 29_481_000 picoseconds. + Weight::from_parts(29_887_000, 0) + .saturating_add(Weight::from_parts(0, 6172)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(5)) + } + /// Storage: Randomness Requests (r:1 w:0) + /// Proof Skipped: Randomness Requests (max_values: None, max_size: None, mode: Measured) + /// Storage: Randomness RandomnessResults (r:1 w:0) + /// Proof Skipped: Randomness RandomnessResults (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[1, 100]`. + fn prepare_fulfillment(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `412` + // Estimated: `3877` + // Minimum execution time: 7_457_000 picoseconds. + Weight::from_parts(7_749_145, 0) + .saturating_add(Weight::from_parts(0, 3877)) + // Standard Error: 177 + .saturating_add(Weight::from_parts(144_131, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + } + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: Randomness RandomnessResults (r:1 w:1) + /// Proof Skipped: Randomness RandomnessResults (max_values: None, max_size: None, mode: Measured) + /// Storage: Randomness Requests (r:0 w:1) + /// Proof Skipped: Randomness Requests (max_values: None, max_size: None, mode: Measured) + fn finish_fulfillment() -> Weight { + // Proof Size summary in bytes: + // Measured: `706` + // Estimated: `6172` + // Minimum execution time: 27_108_000 picoseconds. + Weight::from_parts(27_748_000, 0) + .saturating_add(Weight::from_parts(0, 6172)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: Randomness Requests (r:1 w:1) + /// Proof Skipped: Randomness Requests (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn increase_fee() -> Weight { + // Proof Size summary in bytes: + // Measured: `792` + // Estimated: `6172` + // Minimum execution time: 25_726_000 picoseconds. + Weight::from_parts(26_475_000, 0) + .saturating_add(Weight::from_parts(0, 6172)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Randomness Requests (r:1 w:1) + /// Proof Skipped: Randomness Requests (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: Randomness RandomnessResults (r:1 w:1) + /// Proof Skipped: Randomness RandomnessResults (max_values: None, max_size: None, mode: Measured) + fn execute_request_expiration() -> Weight { + // Proof Size summary in bytes: + // Measured: `835` + // Estimated: `6172` + // Minimum execution time: 31_196_000 picoseconds. + Weight::from_parts(31_824_000, 0) + .saturating_add(Weight::from_parts(0, 6172)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_referenda.rs b/tracing/2601/runtime/common/src/weights/pallet_referenda.rs new file mode 100644 index 00000000..fe8eba23 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_referenda.rs @@ -0,0 +1,496 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_referenda` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_referenda +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_referenda`. +pub struct WeightInfo(PhantomData); +impl pallet_referenda::WeightInfo for WeightInfo { + /// Storage: Referenda ReferendumCount (r:1 w:1) + /// Proof: Referenda ReferendumCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:0 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + fn submit() -> Weight { + // Proof Size summary in bytes: + // Measured: `236` + // Estimated: `42428` + // Minimum execution time: 20_543_000 picoseconds. + Weight::from_parts(21_432_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn place_decision_deposit_preparing() -> Weight { + // Proof Size summary in bytes: + // Measured: `477` + // Estimated: `83866` + // Minimum execution time: 28_243_000 picoseconds. + Weight::from_parts(29_387_000, 0) + .saturating_add(Weight::from_parts(0, 83866)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:0) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn place_decision_deposit_queued() -> Weight { + // Proof Size summary in bytes: + // Measured: `3270` + // Estimated: `42428` + // Minimum execution time: 45_487_000 picoseconds. + Weight::from_parts(47_249_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:0) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn place_decision_deposit_not_queued() -> Weight { + // Proof Size summary in bytes: + // Measured: `3290` + // Estimated: `42428` + // Minimum execution time: 45_439_000 picoseconds. + Weight::from_parts(47_121_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn place_decision_deposit_passing() -> Weight { + // Proof Size summary in bytes: + // Measured: `477` + // Estimated: `83866` + // Minimum execution time: 33_247_000 picoseconds. + Weight::from_parts(34_212_000, 0) + .saturating_add(Weight::from_parts(0, 83866)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn place_decision_deposit_failing() -> Weight { + // Proof Size summary in bytes: + // Measured: `477` + // Estimated: `83866` + // Minimum execution time: 32_743_000 picoseconds. + Weight::from_parts(33_816_000, 0) + .saturating_add(Weight::from_parts(0, 83866)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + fn refund_decision_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `387` + // Estimated: `4377` + // Minimum execution time: 18_586_000 picoseconds. + Weight::from_parts(19_021_000, 0) + .saturating_add(Weight::from_parts(0, 4377)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + fn refund_submission_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `345` + // Estimated: `4377` + // Minimum execution time: 17_750_000 picoseconds. + Weight::from_parts(18_235_000, 0) + .saturating_add(Weight::from_parts(0, 4377)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn cancel() -> Weight { + // Proof Size summary in bytes: + // Measured: `285` + // Estimated: `83866` + // Minimum execution time: 20_371_000 picoseconds. + Weight::from_parts(21_004_000, 0) + .saturating_add(Weight::from_parts(0, 83866)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: Referenda MetadataOf (r:1 w:0) + /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + fn kill() -> Weight { + // Proof Size summary in bytes: + // Measured: `786` + // Estimated: `83866` + // Minimum execution time: 59_921_000 picoseconds. + Weight::from_parts(61_509_000, 0) + .saturating_add(Weight::from_parts(0, 83866)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: Referenda TrackQueue (r:1 w:0) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + fn one_fewer_deciding_queue_empty() -> Weight { + // Proof Size summary in bytes: + // Measured: `102` + // Estimated: `5477` + // Minimum execution time: 7_119_000 picoseconds. + Weight::from_parts(7_260_000, 0) + .saturating_add(Weight::from_parts(0, 5477)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn one_fewer_deciding_failing() -> Weight { + // Proof Size summary in bytes: + // Measured: `3104` + // Estimated: `42428` + // Minimum execution time: 35_136_000 picoseconds. + Weight::from_parts(36_654_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn one_fewer_deciding_passing() -> Weight { + // Proof Size summary in bytes: + // Measured: `3090` + // Estimated: `42428` + // Minimum execution time: 35_670_000 picoseconds. + Weight::from_parts(36_874_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + fn nudge_referendum_requeued_insertion() -> Weight { + // Proof Size summary in bytes: + // Measured: `2915` + // Estimated: `5477` + // Minimum execution time: 17_099_000 picoseconds. + Weight::from_parts(17_653_000, 0) + .saturating_add(Weight::from_parts(0, 5477)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + fn nudge_referendum_requeued_slide() -> Weight { + // Proof Size summary in bytes: + // Measured: `2915` + // Estimated: `5477` + // Minimum execution time: 16_765_000 picoseconds. + Weight::from_parts(17_615_000, 0) + .saturating_add(Weight::from_parts(0, 5477)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:0) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + fn nudge_referendum_queued() -> Weight { + // Proof Size summary in bytes: + // Measured: `2919` + // Estimated: `5477` + // Minimum execution time: 23_001_000 picoseconds. + Weight::from_parts(23_790_000, 0) + .saturating_add(Weight::from_parts(0, 5477)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:0) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Referenda TrackQueue (r:1 w:1) + /// Proof: Referenda TrackQueue (max_values: None, max_size: Some(2012), added: 4487, mode: MaxEncodedLen) + fn nudge_referendum_not_queued() -> Weight { + // Proof Size summary in bytes: + // Measured: `2939` + // Estimated: `5477` + // Minimum execution time: 22_839_000 picoseconds. + Weight::from_parts(23_722_000, 0) + .saturating_add(Weight::from_parts(0, 5477)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn nudge_referendum_no_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `249` + // Estimated: `42428` + // Minimum execution time: 14_689_000 picoseconds. + Weight::from_parts(15_311_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn nudge_referendum_preparing() -> Weight { + // Proof Size summary in bytes: + // Measured: `285` + // Estimated: `42428` + // Minimum execution time: 15_039_000 picoseconds. + Weight::from_parts(15_625_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + fn nudge_referendum_timed_out() -> Weight { + // Proof Size summary in bytes: + // Measured: `194` + // Estimated: `4377` + // Minimum execution time: 9_579_000 picoseconds. + Weight::from_parts(9_947_000, 0) + .saturating_add(Weight::from_parts(0, 4377)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn nudge_referendum_begin_deciding_failing() -> Weight { + // Proof Size summary in bytes: + // Measured: `285` + // Estimated: `42428` + // Minimum execution time: 19_107_000 picoseconds. + Weight::from_parts(19_573_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Referenda DecidingCount (r:1 w:1) + /// Proof: Referenda DecidingCount (max_values: None, max_size: Some(14), added: 2489, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn nudge_referendum_begin_deciding_passing() -> Weight { + // Proof Size summary in bytes: + // Measured: `285` + // Estimated: `42428` + // Minimum execution time: 20_042_000 picoseconds. + Weight::from_parts(20_480_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn nudge_referendum_begin_confirming() -> Weight { + // Proof Size summary in bytes: + // Measured: `338` + // Estimated: `42428` + // Minimum execution time: 17_651_000 picoseconds. + Weight::from_parts(18_258_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn nudge_referendum_end_confirming() -> Weight { + // Proof Size summary in bytes: + // Measured: `321` + // Estimated: `42428` + // Minimum execution time: 17_436_000 picoseconds. + Weight::from_parts(17_910_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn nudge_referendum_continue_not_confirming() -> Weight { + // Proof Size summary in bytes: + // Measured: `338` + // Estimated: `42428` + // Minimum execution time: 16_448_000 picoseconds. + Weight::from_parts(16_910_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn nudge_referendum_continue_confirming() -> Weight { + // Proof Size summary in bytes: + // Measured: `342` + // Estimated: `42428` + // Minimum execution time: 16_600_000 picoseconds. + Weight::from_parts(17_034_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// Storage: Scheduler Lookup (r:1 w:1) + /// Proof: Scheduler Lookup (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + fn nudge_referendum_approved() -> Weight { + // Proof Size summary in bytes: + // Measured: `342` + // Estimated: `83866` + // Minimum execution time: 23_193_000 picoseconds. + Weight::from_parts(23_606_000, 0) + .saturating_add(Weight::from_parts(0, 83866)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn nudge_referendum_rejected() -> Weight { + // Proof Size summary in bytes: + // Measured: `338` + // Estimated: `42428` + // Minimum execution time: 17_454_000 picoseconds. + Weight::from_parts(18_060_000, 0) + .saturating_add(Weight::from_parts(0, 42428)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:0) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + /// Storage: Referenda MetadataOf (r:0 w:1) + /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + fn set_some_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `338` + // Estimated: `4377` + // Minimum execution time: 13_651_000 picoseconds. + Weight::from_parts(14_428_000, 0) + .saturating_add(Weight::from_parts(0, 4377)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Referenda MetadataOf (r:1 w:1) + /// Proof: Referenda MetadataOf (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + fn clear_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `271` + // Estimated: `4377` + // Minimum execution time: 11_827_000 picoseconds. + Weight::from_parts(12_371_000, 0) + .saturating_add(Weight::from_parts(0, 4377)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_scheduler.rs b/tracing/2601/runtime/common/src/weights/pallet_scheduler.rs new file mode 100644 index 00000000..6a85baad --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_scheduler.rs @@ -0,0 +1,205 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_scheduler` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_scheduler +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_scheduler`. +pub struct WeightInfo(PhantomData); +impl pallet_scheduler::WeightInfo for WeightInfo { + /// Storage: Scheduler IncompleteSince (r:1 w:1) + /// Proof: Scheduler IncompleteSince (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn service_agendas_base() -> Weight { + // Proof Size summary in bytes: + // Measured: `31` + // Estimated: `1489` + // Minimum execution time: 2_877_000 picoseconds. + Weight::from_parts(2_990_000, 0) + .saturating_add(Weight::from_parts(0, 1489)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// The range of component `s` is `[0, 50]`. + fn service_agenda_base(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `78 + s * (177 ±0)` + // Estimated: `42428` + // Minimum execution time: 1_931_000 picoseconds. + Weight::from_parts(3_725_545, 0) + .saturating_add(Weight::from_parts(0, 42428)) + // Standard Error: 1_433 + .saturating_add(Weight::from_parts(317_299, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + fn service_task_base() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_319_000 picoseconds. + Weight::from_parts(2_385_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: Preimage PreimageFor (r:1 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: Measured) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + /// The range of component `s` is `[128, 4194304]`. + fn service_task_fetched(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `179 + s * (1 ±0)` + // Estimated: `3644 + s * (1 ±0)` + // Minimum execution time: 11_954_000 picoseconds. + Weight::from_parts(12_114_000, 0) + .saturating_add(Weight::from_parts(0, 3644)) + // Standard Error: 6 + .saturating_add(Weight::from_parts(1_099, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(Weight::from_parts(0, 1).saturating_mul(s.into())) + } + /// Storage: Scheduler Lookup (r:0 w:1) + /// Proof: Scheduler Lookup (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + fn service_task_named() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_893_000 picoseconds. + Weight::from_parts(3_012_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + fn service_task_periodic() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_257_000 picoseconds. + Weight::from_parts(2_333_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: MaintenanceMode MaintenanceMode (r:1 w:0) + /// Proof Skipped: MaintenanceMode MaintenanceMode (max_values: Some(1), max_size: None, mode: Measured) + fn execute_dispatch_signed() -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `1527` + // Minimum execution time: 3_422_000 picoseconds. + Weight::from_parts(3_493_000, 0) + .saturating_add(Weight::from_parts(0, 1527)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn execute_dispatch_unsigned() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_243_000 picoseconds. + Weight::from_parts(1_316_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// The range of component `s` is `[0, 49]`. + fn schedule(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `78 + s * (177 ±0)` + // Estimated: `42428` + // Minimum execution time: 6_376_000 picoseconds. + Weight::from_parts(8_258_368, 0) + .saturating_add(Weight::from_parts(0, 42428)) + // Standard Error: 1_696 + .saturating_add(Weight::from_parts(375_190, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// Storage: Scheduler Lookup (r:0 w:1) + /// Proof: Scheduler Lookup (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// The range of component `s` is `[1, 50]`. + fn cancel(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `78 + s * (177 ±0)` + // Estimated: `42428` + // Minimum execution time: 9_362_000 picoseconds. + Weight::from_parts(8_447_528, 0) + .saturating_add(Weight::from_parts(0, 42428)) + // Standard Error: 2_297 + .saturating_add(Weight::from_parts(599_518, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Scheduler Lookup (r:1 w:1) + /// Proof: Scheduler Lookup (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// The range of component `s` is `[0, 49]`. + fn schedule_named(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `255 + s * (185 ±0)` + // Estimated: `42428` + // Minimum execution time: 8_278_000 picoseconds. + Weight::from_parts(11_068_336, 0) + .saturating_add(Weight::from_parts(0, 42428)) + // Standard Error: 2_406 + .saturating_add(Weight::from_parts(412_321, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Scheduler Lookup (r:1 w:1) + /// Proof: Scheduler Lookup (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// The range of component `s` is `[1, 50]`. + fn cancel_named(s: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `281 + s * (185 ±0)` + // Estimated: `42428` + // Minimum execution time: 11_072_000 picoseconds. + Weight::from_parts(11_042_516, 0) + .saturating_add(Weight::from_parts(0, 42428)) + // Standard Error: 2_254 + .saturating_add(Weight::from_parts(623_730, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_sudo.rs b/tracing/2601/runtime/common/src/weights/pallet_sudo.rs new file mode 100644 index 00000000..a39d3191 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_sudo.rs @@ -0,0 +1,82 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_sudo` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_sudo +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_sudo`. +pub struct WeightInfo(PhantomData); +impl pallet_sudo::WeightInfo for WeightInfo { + /// Storage: Sudo Key (r:1 w:1) + /// Proof: Sudo Key (max_values: Some(1), max_size: Some(20), added: 515, mode: MaxEncodedLen) + fn set_key() -> Weight { + // Proof Size summary in bytes: + // Measured: `153` + // Estimated: `1505` + // Minimum execution time: 7_790_000 picoseconds. + Weight::from_parts(7_983_000, 0) + .saturating_add(Weight::from_parts(0, 1505)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Sudo Key (r:1 w:0) + /// Proof: Sudo Key (max_values: Some(1), max_size: Some(20), added: 515, mode: MaxEncodedLen) + fn sudo() -> Weight { + // Proof Size summary in bytes: + // Measured: `153` + // Estimated: `1505` + // Minimum execution time: 7_702_000 picoseconds. + Weight::from_parts(7_984_000, 0) + .saturating_add(Weight::from_parts(0, 1505)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: Sudo Key (r:1 w:0) + /// Proof: Sudo Key (max_values: Some(1), max_size: Some(20), added: 515, mode: MaxEncodedLen) + fn sudo_as() -> Weight { + // Proof Size summary in bytes: + // Measured: `153` + // Estimated: `1505` + // Minimum execution time: 7_791_000 picoseconds. + Weight::from_parts(8_005_000, 0) + .saturating_add(Weight::from_parts(0, 1505)) + .saturating_add(T::DbWeight::get().reads(1)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_timestamp.rs b/tracing/2601/runtime/common/src/weights/pallet_timestamp.rs new file mode 100644 index 00000000..514cd7be --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_timestamp.rs @@ -0,0 +1,68 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_timestamp` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_timestamp +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_timestamp`. +pub struct WeightInfo(PhantomData); +impl pallet_timestamp::WeightInfo for WeightInfo { + /// Storage: Timestamp Now (r:1 w:1) + /// Proof: Timestamp Now (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + fn set() -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `1493` + // Minimum execution time: 4_706_000 picoseconds. + Weight::from_parts(4_849_000, 0) + .saturating_add(Weight::from_parts(0, 1493)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + fn on_finalize() -> Weight { + // Proof Size summary in bytes: + // Measured: `94` + // Estimated: `0` + // Minimum execution time: 3_671_000 picoseconds. + Weight::from_parts(3_781_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_treasury.rs b/tracing/2601/runtime/common/src/weights/pallet_treasury.rs new file mode 100644 index 00000000..717d1616 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_treasury.rs @@ -0,0 +1,136 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_treasury` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_treasury +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_treasury`. +pub struct WeightInfo(PhantomData); +impl pallet_treasury::WeightInfo for WeightInfo { + fn spend() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 80_000 picoseconds. + Weight::from_parts(90_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: Treasury ProposalCount (r:1 w:1) + /// Proof: Treasury ProposalCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Treasury Proposals (r:0 w:1) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + fn propose_spend() -> Weight { + // Proof Size summary in bytes: + // Measured: `342` + // Estimated: `1489` + // Minimum execution time: 16_677_000 picoseconds. + Weight::from_parts(17_224_000, 0) + .saturating_add(Weight::from_parts(0, 1489)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Treasury Proposals (r:1 w:1) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn reject_proposal() -> Weight { + // Proof Size summary in bytes: + // Measured: `516` + // Estimated: `6172` + // Minimum execution time: 28_249_000 picoseconds. + Weight::from_parts(28_825_000, 0) + .saturating_add(Weight::from_parts(0, 6172)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: Treasury Proposals (r:1 w:0) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// The range of component `p` is `[0, 99]`. + fn approve_proposal(p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `537 + p * (8 ±0)` + // Estimated: `3549` + // Minimum execution time: 6_666_000 picoseconds. + Weight::from_parts(9_412_310, 0) + .saturating_add(Weight::from_parts(0, 3549)) + // Standard Error: 1_172 + .saturating_add(Weight::from_parts(75_315, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + fn remove_approval() -> Weight { + // Proof Size summary in bytes: + // Measured: `194` + // Estimated: `1887` + // Minimum execution time: 5_305_000 picoseconds. + Weight::from_parts(5_530_000, 0) + .saturating_add(Weight::from_parts(0, 1887)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: System Account (r:1 w:0) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: Treasury Deactivated (r:1 w:0) + /// Proof: Treasury Deactivated (max_values: Some(1), max_size: Some(16), added: 511, mode: MaxEncodedLen) + /// Storage: Treasury Approvals (r:1 w:1) + /// Proof: Treasury Approvals (max_values: Some(1), max_size: Some(402), added: 897, mode: MaxEncodedLen) + /// Storage: Treasury Proposals (r:100 w:0) + /// Proof: Treasury Proposals (max_values: None, max_size: Some(84), added: 2559, mode: MaxEncodedLen) + /// The range of component `p` is `[0, 100]`. + fn on_initialize_proposals(p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `277 + p * (97 ±0)` + // Estimated: `3581 + p * (2559 ±0)` + // Minimum execution time: 12_203_000 picoseconds. + Weight::from_parts(11_358_334, 0) + .saturating_add(Weight::from_parts(0, 3581)) + // Standard Error: 5_943 + .saturating_add(Weight::from_parts(2_475_040, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) + .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(Weight::from_parts(0, 2559).saturating_mul(p.into())) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_utility.rs b/tracing/2601/runtime/common/src/weights/pallet_utility.rs new file mode 100644 index 00000000..e50da7a9 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_utility.rs @@ -0,0 +1,109 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_utility` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_utility +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_utility`. +pub struct WeightInfo(PhantomData); +impl pallet_utility::WeightInfo for WeightInfo { + /// Storage: MaintenanceMode MaintenanceMode (r:1 w:0) + /// Proof Skipped: MaintenanceMode MaintenanceMode (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `c` is `[0, 1000]`. + fn batch(c: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `1527` + // Minimum execution time: 3_367_000 picoseconds. + Weight::from_parts(3_496_000, 0) + .saturating_add(Weight::from_parts(0, 1527)) + // Standard Error: 1_117 + .saturating_add(Weight::from_parts(2_472_089, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: MaintenanceMode MaintenanceMode (r:1 w:0) + /// Proof Skipped: MaintenanceMode MaintenanceMode (max_values: Some(1), max_size: None, mode: Measured) + fn as_derivative() -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `1527` + // Minimum execution time: 4_651_000 picoseconds. + Weight::from_parts(4_795_000, 0) + .saturating_add(Weight::from_parts(0, 1527)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: MaintenanceMode MaintenanceMode (r:1 w:0) + /// Proof Skipped: MaintenanceMode MaintenanceMode (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `c` is `[0, 1000]`. + fn batch_all(c: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `1527` + // Minimum execution time: 3_399_000 picoseconds. + Weight::from_parts(1_656_270, 0) + .saturating_add(Weight::from_parts(0, 1527)) + // Standard Error: 1_828 + .saturating_add(Weight::from_parts(2_506_503, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn dispatch_as() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 4_523_000 picoseconds. + Weight::from_parts(4_673_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: MaintenanceMode MaintenanceMode (r:1 w:0) + /// Proof Skipped: MaintenanceMode MaintenanceMode (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `c` is `[0, 1000]`. + fn force_batch(c: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `1527` + // Minimum execution time: 3_510_000 picoseconds. + Weight::from_parts(1_601_892, 0) + .saturating_add(Weight::from_parts(0, 1527)) + // Standard Error: 1_657 + .saturating_add(Weight::from_parts(2_465_423, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(1)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_whitelist.rs b/tracing/2601/runtime/common/src/weights/pallet_whitelist.rs new file mode 100644 index 00000000..a89a63b6 --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_whitelist.rs @@ -0,0 +1,113 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_whitelist` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_whitelist +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_whitelist`. +pub struct WeightInfo(PhantomData); +impl pallet_whitelist::WeightInfo for WeightInfo { + /// Storage: Whitelist WhitelistedCall (r:1 w:1) + /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + fn whitelist_call() -> Weight { + // Proof Size summary in bytes: + // Measured: `83` + // Estimated: `3544` + // Minimum execution time: 11_554_000 picoseconds. + Weight::from_parts(11_937_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Whitelist WhitelistedCall (r:1 w:1) + /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + fn remove_whitelisted_call() -> Weight { + // Proof Size summary in bytes: + // Measured: `212` + // Estimated: `3544` + // Minimum execution time: 12_621_000 picoseconds. + Weight::from_parts(12_927_000, 0) + .saturating_add(Weight::from_parts(0, 3544)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Whitelist WhitelistedCall (r:1 w:1) + /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: Preimage PreimageFor (r:1 w:1) + /// Proof: Preimage PreimageFor (max_values: None, max_size: Some(4194344), added: 4196819, mode: Measured) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + /// The range of component `n` is `[1, 4194294]`. + fn dispatch_whitelisted_call(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `288 + n * (1 ±0)` + // Estimated: `3752 + n * (1 ±0)` + // Minimum execution time: 19_476_000 picoseconds. + Weight::from_parts(19_650_000, 0) + .saturating_add(Weight::from_parts(0, 3752)) + // Standard Error: 7 + .saturating_add(Weight::from_parts(1_036, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) + } + /// Storage: Whitelist WhitelistedCall (r:1 w:1) + /// Proof: Whitelist WhitelistedCall (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: Preimage StatusFor (r:1 w:1) + /// Proof: Preimage StatusFor (max_values: None, max_size: Some(79), added: 2554, mode: MaxEncodedLen) + /// The range of component `n` is `[1, 10000]`. + fn dispatch_whitelisted_call_with_preimage(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `212` + // Estimated: `3544` + // Minimum execution time: 14_497_000 picoseconds. + Weight::from_parts(14_754_700, 0) + .saturating_add(Weight::from_parts(0, 3544)) + // Standard Error: 2 + .saturating_add(Weight::from_parts(948, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_xcm.rs b/tracing/2601/runtime/common/src/weights/pallet_xcm.rs new file mode 100644 index 00000000..9c9bd5aa --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_xcm.rs @@ -0,0 +1,282 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_xcm` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_xcm +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_xcm`. +pub struct WeightInfo(PhantomData); +impl pallet_xcm::WeightInfo for WeightInfo { + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn send() -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `3610` + // Minimum execution time: 15_397_000 picoseconds. + Weight::from_parts(15_791_000, 0) + .saturating_add(Weight::from_parts(0, 3610)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: Benchmark Override (r:0 w:0) + /// Proof Skipped: Benchmark Override (max_values: None, max_size: None, mode: Measured) + fn teleport_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: AssetManager AssetTypeId (r:1 w:0) + /// Proof Skipped: AssetManager AssetTypeId (max_values: None, max_size: None, mode: Measured) + fn reserve_transfer_assets() -> Weight { + // Proof Size summary in bytes: + // Measured: `76` + // Estimated: `3541` + // Minimum execution time: 12_181_000 picoseconds. + Weight::from_parts(12_556_000, 0) + .saturating_add(Weight::from_parts(0, 3541)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn execute() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 4_364_000 picoseconds. + Weight::from_parts(4_484_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: PolkadotXcm SupportedVersion (r:0 w:1) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + fn force_xcm_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 4_538_000 picoseconds. + Weight::from_parts(4_722_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: PolkadotXcm SafeXcmVersion (r:0 w:1) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + fn force_default_xcm_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_551_000 picoseconds. + Weight::from_parts(1_671_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm QueryCounter (r:1 w:1) + /// Proof Skipped: PolkadotXcm QueryCounter (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm Queries (r:0 w:1) + /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) + fn force_subscribe_version_notify() -> Weight { + // Proof Size summary in bytes: + // Measured: `145` + // Estimated: `3610` + // Minimum execution time: 18_013_000 picoseconds. + Weight::from_parts(18_604_000, 0) + .saturating_add(Weight::from_parts(0, 3610)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(5)) + } + /// Storage: PolkadotXcm VersionNotifiers (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm Queries (r:0 w:1) + /// Proof Skipped: PolkadotXcm Queries (max_values: None, max_size: None, mode: Measured) + fn force_unsubscribe_version_notify() -> Weight { + // Proof Size summary in bytes: + // Measured: `328` + // Estimated: `3793` + // Minimum execution time: 20_502_000 picoseconds. + Weight::from_parts(20_948_000, 0) + .saturating_add(Weight::from_parts(0, 3793)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: PolkadotXcm XcmExecutionSuspended (r:0 w:1) + /// Proof Skipped: PolkadotXcm XcmExecutionSuspended (max_values: Some(1), max_size: None, mode: Measured) + fn force_suspension() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 1_588_000 picoseconds. + Weight::from_parts(1_633_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: PolkadotXcm SupportedVersion (r:4 w:2) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + fn migrate_supported_version() -> Weight { + // Proof Size summary in bytes: + // Measured: `167` + // Estimated: `11057` + // Minimum execution time: 13_876_000 picoseconds. + Weight::from_parts(14_183_000, 0) + .saturating_add(Weight::from_parts(0, 11057)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: PolkadotXcm VersionNotifiers (r:4 w:2) + /// Proof Skipped: PolkadotXcm VersionNotifiers (max_values: None, max_size: None, mode: Measured) + fn migrate_version_notifiers() -> Weight { + // Proof Size summary in bytes: + // Measured: `171` + // Estimated: `11061` + // Minimum execution time: 13_695_000 picoseconds. + Weight::from_parts(14_351_000, 0) + .saturating_add(Weight::from_parts(0, 11061)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:5 w:0) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + fn already_notified_target() -> Weight { + // Proof Size summary in bytes: + // Measured: `178` + // Estimated: `13543` + // Minimum execution time: 15_535_000 picoseconds. + Weight::from_parts(15_823_000, 0) + .saturating_add(Weight::from_parts(0, 13543)) + .saturating_add(T::DbWeight::get().reads(5)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:2 w:1) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn notify_current_targets() -> Weight { + // Proof Size summary in bytes: + // Measured: `212` + // Estimated: `6152` + // Minimum execution time: 18_768_000 picoseconds. + Weight::from_parts(19_300_000, 0) + .saturating_add(Weight::from_parts(0, 6152)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:3 w:0) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + fn notify_target_migration_fail() -> Weight { + // Proof Size summary in bytes: + // Measured: `172` + // Estimated: `8587` + // Minimum execution time: 7_607_000 picoseconds. + Weight::from_parts(7_884_000, 0) + .saturating_add(Weight::from_parts(0, 8587)) + .saturating_add(T::DbWeight::get().reads(3)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + fn migrate_version_notify_targets() -> Weight { + // Proof Size summary in bytes: + // Measured: `178` + // Estimated: `11068` + // Minimum execution time: 13_923_000 picoseconds. + Weight::from_parts(14_349_000, 0) + .saturating_add(Weight::from_parts(0, 11068)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: PolkadotXcm VersionNotifyTargets (r:4 w:2) + /// Proof Skipped: PolkadotXcm VersionNotifyTargets (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn migrate_and_notify_old_targets() -> Weight { + // Proof Size summary in bytes: + // Measured: `254` + // Estimated: `11144` + // Minimum execution time: 24_934_000 picoseconds. + Weight::from_parts(25_495_000, 0) + .saturating_add(Weight::from_parts(0, 11144)) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/tracing/2601/runtime/common/src/weights/pallet_xcm_transactor.rs b/tracing/2601/runtime/common/src/weights/pallet_xcm_transactor.rs new file mode 100644 index 00000000..3b1b29fc --- /dev/null +++ b/tracing/2601/runtime/common/src/weights/pallet_xcm_transactor.rs @@ -0,0 +1,196 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . +//! Autogenerated weights for `pallet_xcm_transactor` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-11-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_xcm_transactor +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_xcm_transactor`. +pub struct WeightInfo(PhantomData); +impl pallet_xcm_transactor::WeightInfo for WeightInfo { + /// Storage: XcmTransactor IndexToAccount (r:1 w:1) + /// Proof Skipped: XcmTransactor IndexToAccount (max_values: None, max_size: None, mode: Measured) + fn register() -> Weight { + // Proof Size summary in bytes: + // Measured: `76` + // Estimated: `3541` + // Minimum execution time: 6_377_000 picoseconds. + Weight::from_parts(6_644_000, 0) + .saturating_add(Weight::from_parts(0, 3541)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: XcmTransactor IndexToAccount (r:0 w:1) + /// Proof Skipped: XcmTransactor IndexToAccount (max_values: None, max_size: None, mode: Measured) + fn deregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_881_000 picoseconds. + Weight::from_parts(4_077_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: XcmTransactor TransactInfoWithWeightLimit (r:0 w:1) + /// Proof Skipped: XcmTransactor TransactInfoWithWeightLimit (max_values: None, max_size: None, mode: Measured) + fn set_transact_info() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 4_652_000 picoseconds. + Weight::from_parts(4_896_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: XcmTransactor TransactInfoWithWeightLimit (r:0 w:1) + /// Proof Skipped: XcmTransactor TransactInfoWithWeightLimit (max_values: None, max_size: None, mode: Measured) + fn remove_transact_info() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 4_277_000 picoseconds. + Weight::from_parts(4_465_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: XcmTransactor DestinationAssetFeePerSecond (r:0 w:1) + /// Proof Skipped: XcmTransactor DestinationAssetFeePerSecond (max_values: None, max_size: None, mode: Measured) + fn set_fee_per_second() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 4_106_000 picoseconds. + Weight::from_parts(4_461_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: AssetManager AssetIdType (r:1 w:0) + /// Proof Skipped: AssetManager AssetIdType (max_values: None, max_size: None, mode: Measured) + /// Storage: XcmTransactor IndexToAccount (r:1 w:0) + /// Proof Skipped: XcmTransactor IndexToAccount (max_values: None, max_size: None, mode: Measured) + /// Storage: XcmTransactor TransactInfoWithWeightLimit (r:1 w:0) + /// Proof Skipped: XcmTransactor TransactInfoWithWeightLimit (max_values: None, max_size: None, mode: Measured) + /// Storage: XcmTransactor DestinationAssetFeePerSecond (r:1 w:0) + /// Proof Skipped: XcmTransactor DestinationAssetFeePerSecond (max_values: None, max_size: None, mode: Measured) + /// Storage: AssetManager AssetTypeId (r:1 w:0) + /// Proof Skipped: AssetManager AssetTypeId (max_values: None, max_size: None, mode: Measured) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + fn transact_through_derivative() -> Weight { + // Proof Size summary in bytes: + // Measured: `451` + // Estimated: `3916` + // Minimum execution time: 20_809_000 picoseconds. + Weight::from_parts(21_288_000, 0) + .saturating_add(Weight::from_parts(0, 3916)) + .saturating_add(T::DbWeight::get().reads(6)) + } + /// Storage: AssetManager AssetIdType (r:1 w:0) + /// Proof Skipped: AssetManager AssetIdType (max_values: None, max_size: None, mode: Measured) + /// Storage: XcmTransactor TransactInfoWithWeightLimit (r:1 w:0) + /// Proof Skipped: XcmTransactor TransactInfoWithWeightLimit (max_values: None, max_size: None, mode: Measured) + /// Storage: XcmTransactor DestinationAssetFeePerSecond (r:1 w:0) + /// Proof Skipped: XcmTransactor DestinationAssetFeePerSecond (max_values: None, max_size: None, mode: Measured) + /// Storage: AssetManager AssetTypeId (r:1 w:0) + /// Proof Skipped: AssetManager AssetTypeId (max_values: None, max_size: None, mode: Measured) + /// Storage: Assets Asset (r:1 w:0) + /// Proof: Assets Asset (max_values: None, max_size: Some(174), added: 2649, mode: MaxEncodedLen) + fn transact_through_sovereign() -> Weight { + // Proof Size summary in bytes: + // Measured: `389` + // Estimated: `3854` + // Minimum execution time: 15_641_000 picoseconds. + Weight::from_parts(16_101_000, 0) + .saturating_add(Weight::from_parts(0, 3854)) + .saturating_add(T::DbWeight::get().reads(5)) + } + /// Storage: AssetManager AssetIdType (r:1 w:0) + /// Proof Skipped: AssetManager AssetIdType (max_values: None, max_size: None, mode: Measured) + /// Storage: XcmTransactor TransactInfoWithWeightLimit (r:1 w:0) + /// Proof Skipped: XcmTransactor TransactInfoWithWeightLimit (max_values: None, max_size: None, mode: Measured) + /// Storage: XcmTransactor DestinationAssetFeePerSecond (r:1 w:0) + /// Proof Skipped: XcmTransactor DestinationAssetFeePerSecond (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn transact_through_signed() -> Weight { + // Proof Size summary in bytes: + // Measured: `433` + // Estimated: `3898` + // Minimum execution time: 28_236_000 picoseconds. + Weight::from_parts(28_728_000, 0) + .saturating_add(Weight::from_parts(0, 3898)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: AssetManager AssetIdType (r:1 w:0) + /// Proof Skipped: AssetManager AssetIdType (max_values: None, max_size: None, mode: Measured) + /// Storage: XcmTransactor TransactInfoWithWeightLimit (r:1 w:0) + /// Proof Skipped: XcmTransactor TransactInfoWithWeightLimit (max_values: None, max_size: None, mode: Measured) + /// Storage: XcmTransactor DestinationAssetFeePerSecond (r:1 w:0) + /// Proof Skipped: XcmTransactor DestinationAssetFeePerSecond (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem HostConfiguration (r:1 w:0) + /// Proof Skipped: ParachainSystem HostConfiguration (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + /// Proof Skipped: ParachainSystem PendingUpwardMessages (max_values: Some(1), max_size: None, mode: Measured) + fn hrmp_manage() -> Weight { + // Proof Size summary in bytes: + // Measured: `433` + // Estimated: `3898` + // Minimum execution time: 28_653_000 picoseconds. + Weight::from_parts(29_169_000, 0) + .saturating_add(Weight::from_parts(0, 3898)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/tracing/2601/runtime/moonbase/Cargo.toml b/tracing/2601/runtime/moonbase/Cargo.toml new file mode 100644 index 00000000..419a0df5 --- /dev/null +++ b/tracing/2601/runtime/moonbase/Cargo.toml @@ -0,0 +1,364 @@ +[package] +name = "moonbase-runtime" +authors = { workspace = true } +build = "build.rs" +description = "Moonbase Runtime" +edition = "2021" +homepage = "https://moonbeam.network" +license = "GPL-3.0-only" +version = "0.8.4" + +[dependencies] +hex-literal = { workspace = true, optional = true } +log = { workspace = true } +num_enum = { workspace = true } +rlp = { workspace = true, optional = true } +serde = { workspace = true, features = [ "derive" ] } +sha3 = { workspace = true, optional = true } +smallvec = { workspace = true } +strum = { workspace = true } +strum_macros = { workspace = true } + +# Moonbeam +account = { workspace = true } +moonbeam-core-primitives = { workspace = true } +moonbeam-relay-encoder = { workspace = true } +moonbeam-runtime-common = { workspace = true } +precompile-utils = { workspace = true } +session-keys-primitives = { workspace = true } +xcm-primitives = { workspace = true } + +# Moonbeam pallets +moonbeam-xcm-benchmarks = { workspace = true } +pallet-asset-manager = { workspace = true } +pallet-author-mapping = { workspace = true } +pallet-crowdloan-rewards = { workspace = true } +pallet-erc20-xcm-bridge = { workspace = true } +pallet-evm-chain-id = { workspace = true } +pallet-ethereum-xcm = { workspace = true } +pallet-maintenance-mode = { workspace = true, features = [ "xcm-support" ] } +pallet-migrations = { workspace = true } +pallet-moonbeam-orbiters = { workspace = true } +pallet-parachain-staking = { workspace = true } +pallet-proxy-genesis-companion = { workspace = true } +pallet-randomness = { workspace = true } +pallet-xcm-transactor = { workspace = true } + +# Moonbeam precompiles +pallet-evm-precompile-author-mapping = { workspace = true } +pallet-evm-precompile-balances-erc20 = { workspace = true } +pallet-evm-precompile-batch = { workspace = true } +pallet-evm-precompile-call-permit = { workspace = true } +pallet-evm-precompile-collective = { workspace = true } +pallet-evm-precompile-conviction-voting = { workspace = true } +pallet-evm-precompile-crowdloan-rewards = { workspace = true } +pallet-evm-precompile-democracy = { workspace = true } +pallet-evm-precompile-gmp = { workspace = true } +pallet-evm-precompile-identity = { workspace = true } +pallet-evm-precompile-parachain-staking = { workspace = true } +pallet-evm-precompile-preimage = { workspace = true } +pallet-evm-precompile-proxy = { workspace = true } +pallet-evm-precompile-randomness = { workspace = true } +pallet-evm-precompile-referenda = { workspace = true } +pallet-evm-precompile-registry = { workspace = true } +pallet-evm-precompile-relay-encoder = { workspace = true } +pallet-evm-precompile-xcm-transactor = { workspace = true } +pallet-evm-precompile-xcm-utils = { workspace = true } +pallet-evm-precompile-xtokens = { workspace = true } +pallet-evm-precompileset-assets-erc20 = { workspace = true } + +# Moonbeam tracing +evm-tracing-events = { workspace = true, optional = true } +moonbeam-evm-tracer = { workspace = true, optional = true } +moonbeam-rpc-primitives-debug = { workspace = true } +moonbeam-rpc-primitives-txpool = { workspace = true } + +# Substrate +frame-executive = { workspace = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +frame-system-rpc-runtime-api = { workspace = true } +pallet-assets = { workspace = true } +pallet-balances = { workspace = true, features = [ "insecure_zero_ed" ] } +pallet-collective = { workspace = true } +pallet-conviction-voting = { workspace = true } +pallet-democracy = { workspace = true } +pallet-identity = { workspace = true } +pallet-multisig = { workspace = true } +pallet-preimage = { workspace = true } +pallet-proxy = { workspace = true } +pallet-referenda = { workspace = true } +pallet-root-testing = { workspace = true } +pallet-scheduler = { workspace = true } +pallet-society = { workspace = true } +pallet-sudo = { workspace = true } +pallet-timestamp = { workspace = true } +pallet-transaction-payment = { workspace = true } +pallet-transaction-payment-rpc-runtime-api = { workspace = true } +pallet-treasury = { workspace = true } +pallet-utility = { workspace = true } +pallet-whitelist = { workspace = true } +parity-scale-codec = { workspace = true, features = [ + "derive", + "max-encoded-len", + "chain-error", +] } +scale-info = { workspace = true, features = [ "derive" ] } +sp-api = { workspace = true } +sp-block-builder = { workspace = true } +sp-core = { workspace = true } +sp-debug-derive = { workspace = true } +sp-inherents = { workspace = true } +sp-io = { workspace = true, features = [ "improved_panic_error_reporting" ] } +sp-offchain = { workspace = true } +sp-runtime = { workspace = true } +sp-session = { workspace = true } +sp-std = { workspace = true } +sp-transaction-pool = { workspace = true } +sp-version = { workspace = true } +sp-weights = { workspace = true } + +# Frontier +fp-evm = { workspace = true } +fp-rpc = { workspace = true } +fp-self-contained = { workspace = true, features = [ "serde" ] } +pallet-base-fee = { workspace = true } +pallet-ethereum = { workspace = true, features = [ "forbid-evm-reentrancy" ] } +pallet-evm = { workspace = true, features = [ "forbid-evm-reentrancy" ] } +pallet-evm-precompile-blake2 = { workspace = true } +pallet-evm-precompile-bn128 = { workspace = true } +pallet-evm-precompile-dispatch = { workspace = true } +pallet-evm-precompile-modexp = { workspace = true } +pallet-evm-precompile-sha3fips = { workspace = true } +pallet-evm-precompile-simple = { workspace = true } + +# Polkadot / XCM +orml-traits = { workspace = true } +orml-xcm-support = { workspace = true } +orml-xtokens = { workspace = true } +pallet-xcm = { workspace = true } +pallet-xcm-benchmarks = { workspace = true, optional = true } +polkadot-core-primitives = { workspace = true } +polkadot-parachain = { workspace = true } +xcm = { workspace = true } +xcm-builder = { workspace = true } +xcm-executor = { workspace = true } + +# Cumulus +cumulus-pallet-dmp-queue = { workspace = true } +cumulus-pallet-parachain-system = { workspace = true } +cumulus-pallet-xcm = { workspace = true } +cumulus-pallet-xcmp-queue = { workspace = true } +cumulus-primitives-core = { workspace = true } +cumulus-primitives-timestamp = { workspace = true } +cumulus-primitives-utility = { workspace = true } +parachain-info = { workspace = true } + +# Moonkit +moonkit-xcm-primitives = { workspace = true } +nimbus-primitives = { workspace = true } +pallet-author-inherent = { workspace = true } +pallet-author-slot-filter = { workspace = true } + +# Benchmarking +frame-benchmarking = { workspace = true, optional = true } +frame-system-benchmarking = { workspace = true, optional = true } +frame-try-runtime = { workspace = true, optional = true } + +[build-dependencies] +substrate-wasm-builder = { workspace = true } + +[features] +default = [ "std" , "evm-tracing"] +std = [ + "account/std", + "cumulus-pallet-dmp-queue/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-xcm/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-primitives-core/std", + "cumulus-primitives-timestamp/std", + "evm-tracing-events/std", + "fp-evm/std", + "fp-rpc/std", + "fp-self-contained/std", + "frame-benchmarking/std", + "frame-executive/std", + "frame-support/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "moonbeam-core-primitives/std", + "moonbeam-evm-tracer/std", + "moonbeam-relay-encoder/std", + "moonbeam-rpc-primitives-debug/std", + "moonbeam-rpc-primitives-txpool/std", + "moonbeam-runtime-common/std", + "moonkit-xcm-primitives/std", + "nimbus-primitives/std", + "orml-xtokens/std", + "pallet-asset-manager/std", + "pallet-assets/std", + "pallet-author-inherent/std", + "pallet-author-mapping/std", + "pallet-author-slot-filter/std", + "pallet-balances/std", + "pallet-base-fee/std", + "pallet-collective/std", + "pallet-conviction-voting/std", + "pallet-crowdloan-rewards/std", + "pallet-democracy/std", + "pallet-erc20-xcm-bridge/std", + "pallet-evm-chain-id/std", + "pallet-ethereum-xcm/std", + "pallet-ethereum/std", + "pallet-evm-precompile-author-mapping/std", + "pallet-evm-precompile-balances-erc20/std", + "pallet-evm-precompile-batch/std", + "pallet-evm-precompile-call-permit/std", + "pallet-evm-precompile-collective/std", + "pallet-evm-precompile-conviction-voting/std", + "pallet-evm-precompile-democracy/std", + "pallet-evm-precompile-parachain-staking/std", + "pallet-evm-precompile-preimage/std", + "pallet-evm-precompile-randomness/std", + "pallet-evm-precompile-referenda/std", + "pallet-evm-precompile-registry/std", + "pallet-evm-precompile-xcm-transactor/std", + "pallet-evm-precompile-xcm-utils/std", + "pallet-evm-precompile-xtokens/std", + "pallet-evm-precompileset-assets-erc20/std", + "pallet-evm/std", + "pallet-identity/std", + "pallet-maintenance-mode/std", + "pallet-migrations/std", + "pallet-moonbeam-orbiters/std", + "pallet-multisig/std", + "pallet-parachain-staking/std", + "pallet-preimage/std", + "pallet-proxy-genesis-companion/std", + "pallet-proxy/std", + "pallet-randomness/std", + "pallet-referenda/std", + "pallet-root-testing/std", + "pallet-scheduler/std", + "pallet-society/std", + "pallet-sudo/std", + "pallet-timestamp/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", + "pallet-treasury/std", + "pallet-utility/std", + "pallet-whitelist/std", + "pallet-xcm-transactor/std", + "pallet-xcm/std", + "parachain-info/std", + "parity-scale-codec/std", + "precompile-utils/std", + "scale-info/std", + "session-keys-primitives/std", + "sp-api/std", + "sp-block-builder/std", + "sp-core/std", + "sp-inherents/std", + "sp-io/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-transaction-pool/std", + "sp-version/std", + "strum/std", + "xcm-builder/std", + "xcm-executor/std", + "xcm-primitives/std", + "xcm/std", +] + +# Must be enabled for tracing runtimes only +evm-tracing = [ "evm-tracing-events", "moonbeam-evm-tracer", "rlp", "sha3" ] + +# Allow to print logs details (no wasm:stripped) +force-debug = [ "sp-debug-derive/force-debug" ] + +# Will be enabled by the `wasm-builder` when building the runtime for WASM. +runtime-wasm = [ ] + +# A feature that should be enabled when the runtime should be build for on-chain +# deployment. This will disable stuff that shouldn't be part of the on-chain wasm +# to make it smaller like logging for example. +on-chain-release-build = [ "sp-api/disable-logging" ] + +runtime-benchmarks = [ + "cumulus-pallet-parachain-system/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "hex-literal", + "moonbeam-relay-encoder/runtime-benchmarks", + "moonbeam-runtime-common/runtime-benchmarks", + "moonbeam-xcm-benchmarks/runtime-benchmarks", + "pallet-asset-manager/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pallet-author-inherent/runtime-benchmarks", + "pallet-author-mapping/runtime-benchmarks", + "pallet-author-slot-filter/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-collective/runtime-benchmarks", + "pallet-conviction-voting/runtime-benchmarks", + "pallet-crowdloan-rewards/runtime-benchmarks", + "pallet-democracy/runtime-benchmarks", + "pallet-ethereum-xcm/runtime-benchmarks", + "pallet-ethereum/runtime-benchmarks", + "pallet-evm/runtime-benchmarks", + "pallet-identity/runtime-benchmarks", + "pallet-migrations/runtime-benchmarks", + "pallet-moonbeam-orbiters/runtime-benchmarks", + "pallet-multisig/runtime-benchmarks", + "pallet-parachain-staking/runtime-benchmarks", + "pallet-preimage/runtime-benchmarks", + "pallet-proxy/runtime-benchmarks", + "pallet-randomness/runtime-benchmarks", + "pallet-referenda/runtime-benchmarks", + "pallet-scheduler/runtime-benchmarks", + "pallet-society/runtime-benchmarks", + "pallet-sudo/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "pallet-treasury/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "pallet-whitelist/runtime-benchmarks", + "pallet-xcm-benchmarks", + "pallet-xcm-transactor/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "session-keys-primitives/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", +] + +try-runtime = [ + "fp-self-contained/try-runtime", + "frame-executive/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime", + "moonbeam-runtime-common/try-runtime", + "pallet-asset-manager/try-runtime", + "pallet-author-mapping/try-runtime", + "pallet-author-slot-filter/try-runtime", + "pallet-balances/try-runtime", + "pallet-collective/try-runtime", + "pallet-conviction-voting/try-runtime", + "pallet-democracy/try-runtime", + "pallet-maintenance-mode/try-runtime", + "pallet-maintenance-mode/try-runtime", + "pallet-migrations/try-runtime", + "pallet-parachain-staking/try-runtime", + "pallet-preimage/try-runtime", + "pallet-referenda/try-runtime", + "pallet-root-testing/try-runtime", + "pallet-scheduler/try-runtime", + "pallet-society/try-runtime", + "pallet-timestamp/try-runtime", + "pallet-xcm-transactor/try-runtime", +] + +moonbase-runtime-benchmarks = [ ] diff --git a/tracing/2601/runtime/moonbase/build.rs b/tracing/2601/runtime/moonbase/build.rs new file mode 100644 index 00000000..3934b9c5 --- /dev/null +++ b/tracing/2601/runtime/moonbase/build.rs @@ -0,0 +1,25 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +use substrate_wasm_builder::WasmBuilder; + +fn main() { + WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build() +} diff --git a/tracing/2601/runtime/moonbase/src/asset_config.rs b/tracing/2601/runtime/moonbase/src/asset_config.rs new file mode 100644 index 00000000..5e060c5b --- /dev/null +++ b/tracing/2601/runtime/moonbase/src/asset_config.rs @@ -0,0 +1,343 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Asset configuration for Moonbase. +//! + +use super::{ + currency, governance, xcm_config, AccountId, AssetId, AssetManager, Assets, Balance, Balances, + CouncilInstance, LocalAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX, +}; + +use moonbeam_runtime_common::weights as moonbeam_weights; +use pallet_evm_precompileset_assets_erc20::AccountIdAssetIdConversion; +use sp_runtime::traits::Hash as THash; + +use frame_support::{ + dispatch::GetDispatchInfo, + parameter_types, + traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, EitherOfDiverse}, + weights::Weight, +}; + +use frame_system::{EnsureNever, EnsureRoot}; +use parity_scale_codec::{Compact, Decode, Encode}; +use scale_info::TypeInfo; +use sp_core::{H160, H256}; + +use sp_std::{ + convert::{From, Into}, + prelude::*, +}; + +// Number of items that can be destroyed with our configured max extrinsic proof size. +// x = (a - b) / c where: +// a: maxExtrinsic proof size +// b: base proof size for destroy_accounts in pallet_assets weights +// c: proof size for each item +// 656.87 = (3_407_872 - 8232) / 5180 +const REMOVE_ITEMS_LIMIT: u32 = 656; + +// Not to disrupt the previous asset instance, we assign () to Foreign +pub type ForeignAssetInstance = (); +pub type LocalAssetInstance = pallet_assets::Instance1; + +// For foreign assets, these parameters dont matter much +// as this will only be called by root with the forced arguments +// No deposit is substracted with those methods +// For local assets, they do matter. We use similar parameters +// to those in statemine (except for approval) +parameter_types! { + pub const AssetDeposit: Balance = 100 * currency::UNIT * currency::SUPPLY_FACTOR; + pub const ApprovalDeposit: Balance = 0; + pub const AssetsStringLimit: u32 = 50; + pub const MetadataDepositBase: Balance = currency::deposit(1,68); + pub const MetadataDepositPerByte: Balance = currency::deposit(0, 1); +} + +/// We allow root and Chain council to execute privileged asset operations. +pub type AssetsForceOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; + +// Required for runtime benchmarks +pallet_assets::runtime_benchmarks_enabled! { + pub struct BenchmarkHelper; + impl pallet_assets::BenchmarkHelper for BenchmarkHelper + where + AssetIdParameter: From, + { + fn create_asset_id_parameter(id: u32) -> AssetIdParameter { + (id as u128).into() + } + } +} + +// Foreign assets +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = AssetsForceOrigin; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = ConstU128<{ currency::deposit(1, 18) }>; + type WeightInfo = moonbeam_weights::pallet_assets::WeightInfo; + type RemoveItemsLimit = ConstU32<{ REMOVE_ITEMS_LIMIT }>; + type AssetIdParameter = Compact; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +// Local assets +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = EnsureNever; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = ConstU128<{ currency::deposit(1, 18) }>; + type WeightInfo = moonbeam_weights::pallet_assets::WeightInfo; + type RemoveItemsLimit = ConstU32<{ REMOVE_ITEMS_LIMIT }>; + type AssetIdParameter = Compact; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +// We instruct how to register the Assets +// In this case, we tell it to Create an Asset in pallet-assets +pub struct AssetRegistrar; +use frame_support::{pallet_prelude::DispatchResult, transactional}; + +impl pallet_asset_manager::AssetRegistrar for AssetRegistrar { + #[transactional] + fn create_foreign_asset( + asset: AssetId, + min_balance: Balance, + metadata: AssetRegistrarMetadata, + is_sufficient: bool, + ) -> DispatchResult { + Assets::force_create( + RuntimeOrigin::root(), + asset.into(), + AssetManager::account_id(), + is_sufficient, + min_balance, + )?; + + // TODO uncomment when we feel comfortable + /* + // The asset has been created. Let's put the revert code in the precompile address + let precompile_address = Runtime::asset_id_to_account(ASSET_PRECOMPILE_ADDRESS_PREFIX, asset); + pallet_evm::AccountCodes::::insert( + precompile_address, + vec![0x60, 0x00, 0x60, 0x00, 0xfd], + );*/ + + // Lastly, the metadata + Assets::force_set_metadata( + RuntimeOrigin::root(), + asset.into(), + metadata.name, + metadata.symbol, + metadata.decimals, + metadata.is_frozen, + ) + } + + #[transactional] + fn create_local_asset( + asset: AssetId, + _creator: AccountId, + min_balance: Balance, + is_sufficient: bool, + owner: AccountId, + ) -> DispatchResult { + // We create with root, because we need to decide whether we want to create the asset + // as sufficient. Take into account this does not hold any reserved amount + // in pallet-assets + LocalAssets::force_create( + RuntimeOrigin::root(), + asset.into(), + owner, + is_sufficient, + min_balance, + )?; + + // No metadata needs to be set, as this can be set through regular calls + + // TODO: should we put the revert code? + // The asset has been created. Let's put the revert code in the precompile address + let precompile_address: H160 = + Runtime::asset_id_to_account(LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX, asset).into(); + pallet_evm::AccountCodes::::insert( + precompile_address, + vec![0x60, 0x00, 0x60, 0x00, 0xfd], + ); + Ok(()) + } + + #[transactional] + fn destroy_foreign_asset(asset: AssetId) -> DispatchResult { + // First destroy the asset + Assets::start_destroy(RuntimeOrigin::root(), asset.into())?; + + // We remove the EVM revert code + // This does not panick even if there is no code in the address + let precompile_address: H160 = + Runtime::asset_id_to_account(FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, asset).into(); + pallet_evm::AccountCodes::::remove(precompile_address); + Ok(()) + } + + #[transactional] + fn destroy_local_asset(asset: AssetId) -> DispatchResult { + // First destroy the asset + LocalAssets::start_destroy(RuntimeOrigin::root(), asset.into())?; + + // We remove the EVM revert code + // This does not panick even if there is no code in the address + let precompile_address: H160 = + Runtime::asset_id_to_account(LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX, asset).into(); + pallet_evm::AccountCodes::::remove(precompile_address); + Ok(()) + } + + fn destroy_asset_dispatch_info_weight(asset: AssetId) -> Weight { + // For us both of them (Foreign and Local) have the same annotated weight for a given + // witness + // We need to take the dispatch info from the destroy call, which is already annotated in + // the assets pallet + // Additionally, we need to add a DB write for removing the precompile revert code in the + // EVM + + // This is the dispatch info of destroy + let call_weight = RuntimeCall::Assets( + pallet_assets::Call::::start_destroy { + id: asset.into(), + }, + ) + .get_dispatch_info() + .weight; + + // This is the db write + call_weight.saturating_add(::DbWeight::get().writes(1)) + } +} + +pub struct LocalAssetIdCreator; +impl pallet_asset_manager::LocalAssetIdCreator for LocalAssetIdCreator { + fn create_asset_id_from_metadata(local_asset_counter: u128) -> AssetId { + // Our means of converting a local asset counter to an assetId + // We basically hash (local asset counter) + let mut result: [u8; 16] = [0u8; 16]; + let hash: H256 = + local_asset_counter.using_encoded(::Hashing::hash); + result.copy_from_slice(&hash.as_fixed_bytes()[0..16]); + u128::from_le_bytes(result) + } +} + +#[derive(Clone, Default, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub struct AssetRegistrarMetadata { + pub name: Vec, + pub symbol: Vec, + pub decimals: u8, + pub is_frozen: bool, +} + +pub type ForeignAssetModifierOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; +pub type LocalAssetModifierOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; + +impl pallet_asset_manager::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type AssetRegistrarMetadata = AssetRegistrarMetadata; + type ForeignAssetType = xcm_config::AssetType; + type AssetRegistrar = AssetRegistrar; + type ForeignAssetModifierOrigin = ForeignAssetModifierOrigin; + type LocalAssetModifierOrigin = LocalAssetModifierOrigin; + type LocalAssetIdCreator = LocalAssetIdCreator; + type Currency = Balances; + type LocalAssetDeposit = AssetDeposit; + type WeightInfo = moonbeam_weights::pallet_asset_manager::WeightInfo; +} + +// Instruct how to go from an H160 to an AssetID +// We just take the lowest 128 bits +impl AccountIdAssetIdConversion for Runtime { + /// The way to convert an account to assetId is by ensuring that the prefix is 0XFFFFFFFF + /// and by taking the lowest 128 bits as the assetId + fn account_to_asset_id(account: AccountId) -> Option<(Vec, AssetId)> { + let h160_account: H160 = account.into(); + let mut data = [0u8; 16]; + let (prefix_part, id_part) = h160_account.as_fixed_bytes().split_at(4); + if prefix_part == FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX + || prefix_part == LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX + { + data.copy_from_slice(id_part); + let asset_id: AssetId = u128::from_be_bytes(data).into(); + Some((prefix_part.to_vec(), asset_id)) + } else { + None + } + } + + // The opposite conversion + fn asset_id_to_account(prefix: &[u8], asset_id: AssetId) -> AccountId { + let mut data = [0u8; 20]; + data[0..4].copy_from_slice(prefix); + data[4..20].copy_from_slice(&asset_id.to_be_bytes()); + AccountId::from(data) + } +} diff --git a/tracing/2601/runtime/moonbase/src/governance/councils.rs b/tracing/2601/runtime/moonbase/src/governance/councils.rs new file mode 100644 index 00000000..59a74c6f --- /dev/null +++ b/tracing/2601/runtime/moonbase/src/governance/councils.rs @@ -0,0 +1,98 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Councils for Gov1 and Gov2 + +use super::*; +use moonbeam_runtime_common::weights as moonbeam_weights; + +pub type CouncilInstance = pallet_collective::Instance1; +pub type TechCommitteeInstance = pallet_collective::Instance2; +pub type TreasuryCouncilInstance = pallet_collective::Instance3; +pub type OpenTechCommitteeInstance = pallet_collective::Instance4; + +parameter_types! { + // TODO: Check value of this parameter + pub MaxProposalWeight: Weight = Perbill::from_percent(50) * BlockWeights::get().max_block; +} + +impl pallet_collective::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Proposal = RuntimeCall; + /// The maximum amount of time (in blocks) for council members to vote on motions. + /// Motions may end in fewer blocks if enough votes are cast to determine the result. + type MotionDuration = ConstU32<{ 3 * DAYS }>; + /// The maximum number of proposals that can be open in the council at once. + type MaxProposals = ConstU32<100>; + /// The maximum number of council members. + type MaxMembers = ConstU32<100>; + type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote; + type WeightInfo = moonbeam_weights::pallet_collective::WeightInfo; + type SetMembersOrigin = referenda::GeneralAdminOrRoot; + type MaxProposalWeight = MaxProposalWeight; +} + +impl pallet_collective::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Proposal = RuntimeCall; + /// The maximum amount of time (in blocks) for technical committee members to vote on motions. + /// Motions may end in fewer blocks if enough votes are cast to determine the result. + type MotionDuration = ConstU32<{ 3 * DAYS }>; + /// The maximum number of proposals that can be open in the technical committee at once. + type MaxProposals = ConstU32<100>; + /// The maximum number of technical committee members. + type MaxMembers = ConstU32<100>; + type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote; + type WeightInfo = moonbeam_weights::pallet_collective::WeightInfo; + type SetMembersOrigin = referenda::GeneralAdminOrRoot; + type MaxProposalWeight = MaxProposalWeight; +} + +impl pallet_collective::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Proposal = RuntimeCall; + /// The maximum amount of time (in blocks) for treasury council members to vote on motions. + /// Motions may end in fewer blocks if enough votes are cast to determine the result. + type MotionDuration = ConstU32<{ 3 * DAYS }>; + /// The maximum number of proposals that can be open in the treasury council at once. + type MaxProposals = ConstU32<20>; + /// The maximum number of treasury council members. + type MaxMembers = ConstU32<9>; + type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote; + type WeightInfo = moonbeam_weights::pallet_collective::WeightInfo; + type SetMembersOrigin = referenda::GeneralAdminOrRoot; + type MaxProposalWeight = MaxProposalWeight; +} + +impl pallet_collective::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Proposal = RuntimeCall; + /// The maximum amount of time (in blocks) for technical committee members to vote on motions. + /// Motions may end in fewer blocks if enough votes are cast to determine the result. + type MotionDuration = ConstU32<{ 14 * DAYS }>; + /// The maximum number of proposals that can be open in the technical committee at once. + type MaxProposals = ConstU32<100>; + /// The maximum number of technical committee members. + type MaxMembers = ConstU32<100>; + type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote; + type WeightInfo = moonbeam_weights::pallet_collective::WeightInfo; + type SetMembersOrigin = referenda::GeneralAdminOrRoot; + type MaxProposalWeight = MaxProposalWeight; +} diff --git a/tracing/2601/runtime/moonbase/src/governance/democracy.rs b/tracing/2601/runtime/moonbase/src/governance/democracy.rs new file mode 100644 index 00000000..ff8d6c33 --- /dev/null +++ b/tracing/2601/runtime/moonbase/src/governance/democracy.rs @@ -0,0 +1,76 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Democracy config for Gov1 + +use super::councils::*; +use crate::*; + +// The purpose of this offset is to ensure that a democratic proposal will not apply in the same +// block as a round change. +const ENACTMENT_OFFSET: u32 = 300; + +impl pallet_democracy::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type EnactmentPeriod = ConstU32<{ 1 * DAYS + ENACTMENT_OFFSET }>; + type LaunchPeriod = ConstU32<{ 1 * DAYS }>; + type VotingPeriod = ConstU32<{ 5 * DAYS }>; + type VoteLockingPeriod = ConstU32<{ 1 * DAYS }>; + type FastTrackVotingPeriod = ConstU32<{ 4 * HOURS }>; + type MinimumDeposit = ConstU128<{ 4 * currency::UNIT * currency::SUPPLY_FACTOR }>; + /// To decide what their next motion is. + type ExternalOrigin = + pallet_collective::EnsureProportionAtLeast; + /// To have the next scheduled referendum be a straight majority-carries vote. + type ExternalMajorityOrigin = + pallet_collective::EnsureProportionAtLeast; + /// To have the next scheduled referendum be a straight default-carries (NTB) vote. + type ExternalDefaultOrigin = + pallet_collective::EnsureProportionAtLeast; + /// To allow a shorter voting/enactment period for external proposals. + type FastTrackOrigin = + pallet_collective::EnsureProportionAtLeast; + /// To instant fast track. + type InstantOrigin = + pallet_collective::EnsureProportionAtLeast; + // To cancel a proposal which has been passed. + type CancellationOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, + >; + // To cancel a proposal before it has been passed. + type CancelProposalOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, + >; + type BlacklistOrigin = EnsureRoot; + // Any single technical committee member may veto a coming council proposal, however they can + // only do it once and it lasts only for the cooloff period. + type VetoOrigin = pallet_collective::EnsureMember; + type CooloffPeriod = ConstU32<{ 7 * DAYS }>; + type Slash = (); + type InstantAllowed = ConstBool; + type Scheduler = Scheduler; + type MaxVotes = ConstU32<100>; + type PalletsOrigin = OriginCaller; + type WeightInfo = moonbeam_weights::pallet_democracy::WeightInfo; + type MaxProposals = ConstU32<100>; + type Preimages = Preimage; + type MaxDeposits = ConstU32<100>; + type MaxBlacklisted = ConstU32<100>; + type SubmitOrigin = EnsureSigned; +} diff --git a/tracing/2601/runtime/moonbase/src/governance/mod.rs b/tracing/2601/runtime/moonbase/src/governance/mod.rs new file mode 100644 index 00000000..0367cdf0 --- /dev/null +++ b/tracing/2601/runtime/moonbase/src/governance/mod.rs @@ -0,0 +1,30 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Governance configurations + +pub mod councils; +mod democracy; +pub mod referenda; + +use super::*; + +mod origins; +pub use origins::{ + custom_origins, GeneralAdmin, ReferendumCanceller, ReferendumKiller, WhitelistedCaller, +}; +mod tracks; +pub use tracks::TracksInfo; diff --git a/tracing/2601/runtime/moonbase/src/governance/origins.rs b/tracing/2601/runtime/moonbase/src/governance/origins.rs new file mode 100644 index 00000000..20d0829f --- /dev/null +++ b/tracing/2601/runtime/moonbase/src/governance/origins.rs @@ -0,0 +1,80 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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. + +//! Custom origins for governance interventions. +pub use custom_origins::*; + +#[frame_support::pallet] +pub mod custom_origins { + use frame_support::pallet_prelude::*; + use strum_macros::EnumString; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[derive( + PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug, EnumString, + )] + #[strum(serialize_all = "snake_case")] + #[pallet::origin] + pub enum Origin { + /// Origin able to dispatch a whitelisted call. + WhitelistedCaller, + /// General admin + GeneralAdmin, + /// Origin able to cancel referenda. + ReferendumCanceller, + /// Origin able to kill referenda. + ReferendumKiller, + } + + macro_rules! decl_unit_ensures { + ( $name:ident: $success_type:ty = $success:expr ) => { + pub struct $name; + impl> + From> + EnsureOrigin for $name + { + type Success = $success_type; + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + Origin::$name => Ok($success), + r => Err(O::from(r)), + }) + } + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin() -> Result { + Ok(O::from(Origin::$name)) + } + } + }; + ( $name:ident ) => { decl_unit_ensures! { $name : () = () } }; + ( $name:ident: $success_type:ty = $success:expr, $( $rest:tt )* ) => { + decl_unit_ensures! { $name: $success_type = $success } + decl_unit_ensures! { $( $rest )* } + }; + ( $name:ident, $( $rest:tt )* ) => { + decl_unit_ensures! { $name } + decl_unit_ensures! { $( $rest )* } + }; + () => {} + } + decl_unit_ensures!( + ReferendumCanceller, + ReferendumKiller, + WhitelistedCaller, + GeneralAdmin + ); +} diff --git a/tracing/2601/runtime/moonbase/src/governance/referenda.rs b/tracing/2601/runtime/moonbase/src/governance/referenda.rs new file mode 100644 index 00000000..ced47563 --- /dev/null +++ b/tracing/2601/runtime/moonbase/src/governance/referenda.rs @@ -0,0 +1,98 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! # Gov2 config +//! Includes runtime configs for these substrate pallets: +//! 1. pallet-conviction-voting +//! 2. pallet-whitelist +//! 3. pallet-referenda + +use super::*; +use crate::currency::*; +use frame_support::traits::{EitherOf, MapSuccess}; +use frame_system::EnsureRootWithSuccess; +use moonbeam_runtime_common::weights as moonbeam_weights; +use sp_runtime::traits::Replace; + +parameter_types! { + pub const VoteLockingPeriod: BlockNumber = 1 * DAYS; +} + +impl pallet_conviction_voting::Config for Runtime { + type WeightInfo = moonbeam_weights::pallet_conviction_voting::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type Polls = Referenda; + type MaxTurnout = frame_support::traits::TotalIssuanceOf; + // Maximum number of concurrent votes an account may have + type MaxVotes = ConstU32<20>; + // Minimum period of vote locking + type VoteLockingPeriod = VoteLockingPeriod; +} + +parameter_types! { + pub const AlarmInterval: BlockNumber = 1; + pub const SubmissionDeposit: Balance = 10 * UNIT * SUPPLY_FACTOR; + pub const UndecidingTimeout: BlockNumber = 21 * DAYS; +} + +pub type GeneralAdminOrRoot = EitherOf, origins::GeneralAdmin>; + +impl custom_origins::Config for Runtime {} + +// The purpose of this pallet is to queue calls to be dispatched as by root later => the Dispatch +// origin corresponds to the Gov2 Whitelist track. +impl pallet_whitelist::Config for Runtime { + type WeightInfo = moonbeam_weights::pallet_whitelist::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type WhitelistOrigin = EitherOf< + EnsureRootWithSuccess>, + MapSuccess< + pallet_collective::EnsureProportionAtLeast< + Self::AccountId, + OpenTechCommitteeInstance, + 5, + 9, + >, + Replace>, + >, + >; + type DispatchWhitelistedOrigin = EitherOf, WhitelistedCaller>; + type Preimages = Preimage; +} + +pallet_referenda::impl_tracksinfo_get!(TracksInfo, Balance, BlockNumber); + +impl pallet_referenda::Config for Runtime { + type WeightInfo = moonbeam_weights::pallet_referenda::WeightInfo; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type Scheduler = Scheduler; + type Currency = Balances; + type SubmitOrigin = frame_system::EnsureSigned; + type CancelOrigin = EitherOf, ReferendumCanceller>; + type KillOrigin = EitherOf, ReferendumKiller>; + type Slash = Treasury; + type Votes = pallet_conviction_voting::VotesOf; + type Tally = pallet_conviction_voting::TallyOf; + type SubmissionDeposit = SubmissionDeposit; + type MaxQueued = ConstU32<100>; + type UndecidingTimeout = UndecidingTimeout; + type AlarmInterval = AlarmInterval; + type Tracks = TracksInfo; + type Preimages = Preimage; +} diff --git a/tracing/2601/runtime/moonbase/src/governance/tracks.rs b/tracing/2601/runtime/moonbase/src/governance/tracks.rs new file mode 100644 index 00000000..1b0bd312 --- /dev/null +++ b/tracing/2601/runtime/moonbase/src/governance/tracks.rs @@ -0,0 +1,179 @@ +// Copyright 2022 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 . + +//! Track configurations for governance. + +use super::*; +use crate::currency::{KILOUNIT, SUPPLY_FACTOR, UNIT}; +use sp_std::str::FromStr; + +const fn percent(x: i32) -> sp_runtime::FixedI64 { + sp_runtime::FixedI64::from_rational(x as u128, 100) +} +const fn permill(x: i32) -> sp_runtime::FixedI64 { + sp_runtime::FixedI64::from_rational(x as u128, 1000) +} + +use pallet_referenda::Curve; +const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 5] = [ + ( + 0, + pallet_referenda::TrackInfo { + // Name of this track. + name: "root", + // A limit for the number of referenda on this track that can be being decided at once. + // For Root origin this should generally be just one. + max_deciding: 5, + // Amount that must be placed on deposit before a decision can be made. + decision_deposit: 100 * KILOUNIT * SUPPLY_FACTOR, + // Amount of time this must be submitted for before a decision can be made. + prepare_period: 1 * DAYS, + // Amount of time that a decision may take to be approved prior to cancellation. + decision_period: 14 * DAYS, + // Amount of time that the approval criteria must hold before it can be approved. + confirm_period: 1 * DAYS, + // Minimum amount of time that an approved proposal must be in the dispatch queue. + min_enactment_period: 1 * DAYS, + // Minimum aye votes as percentage of overall conviction-weighted votes needed for + // approval as a function of time into decision period. + min_approval: Curve::make_reciprocal(4, 14, percent(80), percent(50), percent(100)), + // Minimum pre-conviction aye-votes ("support") as percentage of overall population that + // is needed for approval as a function of time into decision period. + min_support: Curve::make_linear(14, 14, permill(5), percent(25)), + }, + ), + ( + 1, + pallet_referenda::TrackInfo { + name: "whitelisted_caller", + max_deciding: 100, + decision_deposit: 10 * KILOUNIT * SUPPLY_FACTOR, + prepare_period: 10 * MINUTES, + decision_period: 14 * DAYS, + confirm_period: 10 * MINUTES, + min_enactment_period: 30 * MINUTES, + min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)), + min_support: Curve::make_reciprocal(1, 14 * 24, percent(1), percent(0), percent(2)), + }, + ), + ( + 2, + pallet_referenda::TrackInfo { + name: "general_admin", + max_deciding: 10, + decision_deposit: 500 * UNIT * SUPPLY_FACTOR, + prepare_period: 1 * HOURS, + decision_period: 14 * DAYS, + confirm_period: 1 * DAYS, + min_enactment_period: 1 * DAYS, + min_approval: Curve::make_reciprocal(4, 14, percent(80), percent(50), percent(100)), + min_support: Curve::make_reciprocal(7, 14, percent(10), percent(0), percent(50)), + }, + ), + ( + 3, + pallet_referenda::TrackInfo { + name: "referendum_canceller", + max_deciding: 20, + decision_deposit: 10 * KILOUNIT * SUPPLY_FACTOR, + prepare_period: 1 * HOURS, + decision_period: 14 * DAYS, + confirm_period: 3 * HOURS, + min_enactment_period: 10 * MINUTES, + min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)), + min_support: Curve::make_reciprocal(1, 14, percent(1), percent(0), percent(50)), + }, + ), + ( + 4, + pallet_referenda::TrackInfo { + name: "referendum_killer", + max_deciding: 100, + decision_deposit: 20 * KILOUNIT * SUPPLY_FACTOR, + prepare_period: 1 * HOURS, + decision_period: 14 * DAYS, + confirm_period: 3 * HOURS, + min_enactment_period: 10 * MINUTES, + min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)), + min_support: Curve::make_reciprocal(1, 14, percent(1), percent(0), percent(10)), + }, + ), +]; + +pub struct TracksInfo; +impl pallet_referenda::TracksInfo for TracksInfo { + type Id = u16; + type RuntimeOrigin = ::PalletsOrigin; + fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { + &TRACKS_DATA[..] + } + fn track_for(id: &Self::RuntimeOrigin) -> Result { + if let Ok(system_origin) = frame_system::RawOrigin::try_from(id.clone()) { + match system_origin { + frame_system::RawOrigin::Root => { + if let Some((track_id, _)) = Self::tracks() + .into_iter() + .find(|(_, track)| track.name == "root") + { + Ok(*track_id) + } else { + Err(()) + } + } + _ => Err(()), + } + } else if let Ok(custom_origin) = custom_origins::Origin::try_from(id.clone()) { + if let Some((track_id, _)) = Self::tracks().into_iter().find(|(_, track)| { + if let Ok(track_custom_origin) = custom_origins::Origin::from_str(track.name) { + track_custom_origin == custom_origin + } else { + false + } + }) { + Ok(*track_id) + } else { + Err(()) + } + } else { + Err(()) + } + } +} + +#[test] +/// To ensure voters are always locked into their vote +fn vote_locking_always_longer_than_enactment_period() { + for (_, track) in TRACKS_DATA { + assert!( + ::VoteLockingPeriod::get() + >= track.min_enactment_period, + "Track {} has enactment period {} < vote locking period {}", + track.name, + track.min_enactment_period, + ::VoteLockingPeriod::get(), + ); + } +} + +#[test] +fn all_tracks_have_origins() { + for (_, track) in TRACKS_DATA { + // check name.into() is successful either converts into "root" or custom origin + let track_is_root = track.name == "root"; + let track_has_custom_origin = custom_origins::Origin::from_str(track.name).is_ok(); + assert!(track_is_root || track_has_custom_origin); + } +} diff --git a/tracing/2601/runtime/moonbase/src/lib.rs b/tracing/2601/runtime/moonbase/src/lib.rs new file mode 100644 index 00000000..a8fc394b --- /dev/null +++ b/tracing/2601/runtime/moonbase/src/lib.rs @@ -0,0 +1,1807 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! The Moonbase Runtime. +//! +//! Primary features of this runtime include: +//! * Ethereum compatibility +//! * Moonbase tokenomics + +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +use cumulus_pallet_parachain_system::{RelayChainStateProof, RelaychainDataProvider}; +use cumulus_primitives_core::relay_chain; +use fp_rpc::TransactionStatus; + +use account::AccountId20; + +// Re-export required by get! macro. +pub use frame_support::traits::Get; +use frame_support::{ + construct_runtime, + dispatch::{DispatchClass, GetDispatchInfo, PostDispatchInfo}, + ensure, + pallet_prelude::DispatchResult, + parameter_types, + traits::{ + ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, Contains, + Currency as CurrencyT, EitherOfDiverse, EqualPrivilegeOnly, FindAuthor, Imbalance, + InstanceFilter, OffchainWorker, OnFinalize, OnIdle, OnInitialize, OnRuntimeUpgrade, + OnUnbalanced, + }, + weights::{ + constants::{RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND}, + ConstantMultiplier, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, + WeightToFeePolynomial, + }, + PalletId, +}; + +#[cfg(feature = "std")] +pub use fp_evm::GenesisAccount; +use frame_system::{EnsureRoot, EnsureSigned}; +pub use moonbeam_core_primitives::{ + AccountId, AccountIndex, Address, AssetId, Balance, BlockNumber, DigestItem, Hash, Header, + Index, Signature, +}; +use moonbeam_rpc_primitives_txpool::TxPoolResponse; +use moonbeam_runtime_common::weights as moonbeam_weights; +pub use pallet_author_slot_filter::EligibilityValue; +use pallet_balances::NegativeImbalance; +use pallet_ethereum::Call::transact; +use pallet_ethereum::{PostLogContent, Transaction as EthereumTransaction}; +use pallet_evm::{ + Account as EVMAccount, EVMCurrencyAdapter, EnsureAddressNever, EnsureAddressRoot, + FeeCalculator, GasWeightMapping, IdentityAddressMapping, + OnChargeEVMTransaction as OnChargeEVMTransactionT, Runner, +}; +pub use pallet_parachain_staking::{weights::WeightInfo, InflationInfo, Range}; +use pallet_transaction_payment::{CurrencyAdapter, Multiplier, TargetedFeeAdjustment}; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_api::impl_runtime_apis; +use sp_core::{OpaqueMetadata, H160, H256, U256}; +#[cfg(feature = "try-runtime")] +use sp_runtime::TryRuntimeError; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + traits::{ + BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, IdentityLookup, + PostDispatchInfoOf, UniqueSaturatedInto, Zero, + }, + transaction_validity::{ + InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError, + }, + ApplyExtrinsicResult, DispatchErrorWithPostInfo, FixedPointNumber, Perbill, Permill, + Perquintill, +}; +use sp_std::{ + convert::{From, Into}, + prelude::*, +}; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; + +use nimbus_primitives::CanAuthor; + +mod precompiles; +pub use precompiles::{ + MoonbasePrecompiles, PrecompileName, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX, +}; +use smallvec::smallvec; +use sp_runtime::serde::{Deserialize, Serialize}; + +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; + +pub type Precompiles = MoonbasePrecompiles; + +pub mod asset_config; +pub mod governance; +pub mod xcm_config; +use governance::councils::*; + +/// UNIT, the native token, uses 18 decimals of precision. +pub mod currency { + use super::Balance; + + // Provide a common factor between runtimes based on a supply of 10_000_000 tokens. + pub const SUPPLY_FACTOR: Balance = 1; + + pub const WEI: Balance = 1; + pub const KILOWEI: Balance = 1_000; + pub const MEGAWEI: Balance = 1_000_000; + pub const GIGAWEI: Balance = 1_000_000_000; + pub const MICROUNIT: Balance = 1_000_000_000_000; + pub const MILLIUNIT: Balance = 1_000_000_000_000_000; + pub const UNIT: Balance = 1_000_000_000_000_000_000; + pub const KILOUNIT: Balance = 1_000_000_000_000_000_000_000; + + pub const TRANSACTION_BYTE_FEE: Balance = 1 * GIGAWEI * SUPPLY_FACTOR; + pub const STORAGE_BYTE_FEE: Balance = 100 * MICROUNIT * SUPPLY_FACTOR; + pub const WEIGHT_FEE: Balance = 50 * KILOWEI * SUPPLY_FACTOR; + + pub const fn deposit(items: u32, bytes: u32) -> Balance { + items as Balance * 1 * UNIT * SUPPLY_FACTOR + (bytes as Balance) * STORAGE_BYTE_FEE + } +} + +/// Maximum weight per block +pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND, u64::MAX) + .saturating_div(2) + .set_proof_size(cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64); + +pub const MILLISECS_PER_BLOCK: u64 = 12000; +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; +pub const WEEKS: BlockNumber = DAYS * 7; +/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know +/// the specifics of the runtime. They can then be made to be agnostic over specific formats +/// of data like extrinsics, allowing for them to continue syncing the network through upgrades +/// to even the core data structures. +pub mod opaque { + use super::*; + + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + pub type Block = generic::Block; + + impl_opaque_keys! { + pub struct SessionKeys { + pub nimbus: AuthorInherent, + pub vrf: session_keys_primitives::VrfSessionKey, + } + } +} + +/// This runtime version. +/// The spec_version is composed of 2x2 digits. The first 2 digits represent major changes +/// that can't be skipped, such as data migration upgrades. The last 2 digits represent minor +/// changes which can be skipped. +#[sp_version::runtime_version] +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("moonbase"), + impl_name: create_runtime_str!("moonbase"), + authoring_version: 4, + spec_version: 2601, + impl_version: 0, + apis: RUNTIME_API_VERSIONS, + transaction_version: 2, + state_version: 0, +}; + +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); +pub const NORMAL_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_mul(3).saturating_div(4); +// Here we assume Ethereum's base fee of 21000 gas and convert to weight, but we +// subtract roughly the cost of a balance transfer from it (about 1/3 the cost) +// and some cost to account for per-byte-fee. +// TODO: we should use benchmarking's overhead feature to measure this +pub const EXTRINSIC_BASE_WEIGHT: Weight = Weight::from_parts(10000 * WEIGHT_PER_GAS, 0); + +pub struct RuntimeBlockWeights; +impl Get for RuntimeBlockWeights { + fn get() -> frame_system::limits::BlockWeights { + frame_system::limits::BlockWeights::builder() + .for_class(DispatchClass::Normal, |weights| { + weights.base_extrinsic = EXTRINSIC_BASE_WEIGHT; + weights.max_total = NORMAL_WEIGHT.into(); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = MAXIMUM_BLOCK_WEIGHT.into(); + weights.reserved = (MAXIMUM_BLOCK_WEIGHT - NORMAL_WEIGHT).into(); + }) + .avg_block_initialization(Perbill::from_percent(10)) + .build() + .expect("Provided BlockWeight definitions are valid, qed") + } +} + +parameter_types! { + pub const Version: RuntimeVersion = VERSION; + /// TODO: this is left here so that `impl_runtime_apis_plus_common` will find the same type for + /// `BlockWeights` in all runtimes. It can probably be removed once the custom + /// `RuntimeBlockWeights` has been pushed to each runtime. + pub BlockWeights: frame_system::limits::BlockWeights = RuntimeBlockWeights::get(); + /// We allow for 5 MB blocks. + pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength + ::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); +} + +impl frame_system::Config for Runtime { + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = IdentityLookup; + /// The index type for storing how many extrinsics an account has signed. + type Nonce = Index; + /// The index type for blocks. + type Block = Block; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + /// The ubiquitous origin type. + type RuntimeOrigin = RuntimeOrigin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = ConstU32<256>; + /// Maximum weight of each block. With a default weight system of 1byte == 1weight, 4mb is ok. + type BlockWeights = RuntimeBlockWeights; + /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. + type BlockLength = BlockLength; + /// Runtime version. + type Version = Version; + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type DbWeight = RocksDbWeight; + type BaseCallFilter = MaintenanceMode; + type SystemWeightInfo = (); + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = ConstU16<1287>; + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl pallet_utility::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; + type WeightInfo = moonbeam_weights::pallet_utility::WeightInfo; +} + +impl pallet_timestamp::Config for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = ConstU64<6000>; + type WeightInfo = moonbeam_weights::pallet_timestamp::WeightInfo; +} + +impl pallet_balances::Config for Runtime { + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 4]; + type MaxLocks = ConstU32<50>; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ConstU128<0>; + type AccountStore = System; + type FreezeIdentifier = (); + type MaxFreezes = ConstU32<0>; + type RuntimeHoldReason = RuntimeHoldReason; + type MaxHolds = ConstU32<0>; + type WeightInfo = moonbeam_weights::pallet_balances::WeightInfo; +} + +pub struct DealWithFees(sp_std::marker::PhantomData); +impl OnUnbalanced> for DealWithFees +where + R: pallet_balances::Config + pallet_treasury::Config, + pallet_treasury::Pallet: OnUnbalanced>, +{ + // this seems to be called for substrate-based transactions + fn on_unbalanceds(mut fees_then_tips: impl Iterator>) { + if let Some(fees) = fees_then_tips.next() { + // for fees, 80% are burned, 20% to the treasury + let (_, to_treasury) = fees.ration(80, 20); + // Balances pallet automatically burns dropped Negative Imbalances by decreasing + // total_supply accordingly + as OnUnbalanced<_>>::on_unbalanced(to_treasury); + + // handle tip if there is one + if let Some(tip) = fees_then_tips.next() { + // for now we use the same burn/treasury strategy used for regular fees + let (_, to_treasury) = tip.ration(80, 20); + as OnUnbalanced<_>>::on_unbalanced(to_treasury); + } + } + } + + // this is called from pallet_evm for Ethereum-based transactions + // (technically, it calls on_unbalanced, which calls this when non-zero) + fn on_nonzero_unbalanced(amount: NegativeImbalance) { + // Balances pallet automatically burns dropped Negative Imbalances by decreasing + // total_supply accordingly + let (_, to_treasury) = amount.ration(80, 20); + as OnUnbalanced<_>>::on_unbalanced(to_treasury); + } +} + +pub struct LengthToFee; +impl WeightToFeePolynomial for LengthToFee { + type Balance = Balance; + + fn polynomial() -> WeightToFeeCoefficients { + smallvec![ + WeightToFeeCoefficient { + degree: 1, + coeff_frac: Perbill::zero(), + coeff_integer: currency::TRANSACTION_BYTE_FEE, + negative: false, + }, + WeightToFeeCoefficient { + degree: 3, + coeff_frac: Perbill::zero(), + coeff_integer: 1 * currency::SUPPLY_FACTOR, + negative: false, + }, + ] + } +} + +impl pallet_transaction_payment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = CurrencyAdapter>; + type OperationalFeeMultiplier = ConstU8<5>; + type WeightToFee = ConstantMultiplier>; + type LengthToFee = LengthToFee; + type FeeMultiplierUpdate = FastAdjustingFeeUpdate; +} + +impl pallet_sudo::Config for Runtime { + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = moonbeam_weights::pallet_sudo::WeightInfo; +} + +impl pallet_evm_chain_id::Config for Runtime {} + +/// Current approximation of the gas/s consumption considering +/// EVM execution over compiled WASM (on 4.4Ghz CPU). +/// Given the 500ms Weight, from which 75% only are used for transactions, +/// the total EVM execution gas limit is: GAS_PER_SECOND * 0.500 * 0.75 ~= 15_000_000. +pub const GAS_PER_SECOND: u64 = 40_000_000; + +/// Approximate ratio of the amount of Weight per Gas. +/// u64 works for approximations because Weight is a very small unit compared to gas. +pub const WEIGHT_PER_GAS: u64 = WEIGHT_REF_TIME_PER_SECOND / GAS_PER_SECOND; +/// The highest amount of new storage that can be created in a block (40KB). +pub const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024; +parameter_types! { + pub BlockGasLimit: U256 + = U256::from(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT.ref_time() / WEIGHT_PER_GAS); + /// The portion of the `NORMAL_DISPATCH_RATIO` that we adjust the fees with. Blocks filled less + /// than this will decrease the weight and more will increase. + pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); + /// The adjustment variable of the runtime. Higher values will cause `TargetBlockFullness` to + /// change the fees more rapidly. This fast multiplier responds by doubling/halving in + /// approximately one hour at extreme block congestion levels. + pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(4, 1_000); + /// Minimum amount of the multiplier. This value cannot be too low. A test case should ensure + /// that combined with `AdjustmentVariable`, we can recover from the minimum. + /// See `multiplier_can_grow_from_zero` in integration_tests.rs. + pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 10); + /// Maximum multiplier. We pick a value that is expensive but not impossibly so; it should act + /// as a safety net. + pub MaximumMultiplier: Multiplier = Multiplier::from(100_000u128); + pub PrecompilesValue: MoonbasePrecompiles = MoonbasePrecompiles::<_>::new(); + pub WeightPerGas: Weight = Weight::from_parts(WEIGHT_PER_GAS, 0); + /// The amount of gas per pov. A ratio of 4 if we convert ref_time to gas and we compare + /// it with the pov_size for a block. E.g. + /// ceil( + /// (max_extrinsic.ref_time() / max_extrinsic.proof_size()) / WEIGHT_PER_GAS + /// ) + pub const GasLimitPovSizeRatio: u64 = 4; + /// The amount of gas per storage (in bytes): BLOCK_GAS_LIMIT / BLOCK_STORAGE_LIMIT + /// (15_000_000 / 40kb) + pub GasLimitStorageGrowthRatio: u64 = 366; +} + +pub struct TransactionPaymentAsGasPrice; +impl FeeCalculator for TransactionPaymentAsGasPrice { + fn min_gas_price() -> (U256, Weight) { + // TODO: transaction-payment differs from EIP-1559 in that its tip and length fees are not + // scaled by the multiplier, which means its multiplier will be overstated when + // applied to an ethereum transaction + // note: transaction-payment uses both a congestion modifier (next_fee_multiplier, which is + // updated once per block in on_finalize) and a 'WeightToFee' implementation. Our + // runtime implements this as a 'ConstantModifier', so we can get away with a simple + // multiplication here. + // It is imperative that `saturating_mul_int` be performed as late as possible in the + // expression since it involves fixed point multiplication with a division by a fixed + // divisor. This leads to truncation and subsequent precision loss if performed too early. + // This can lead to min_gas_price being same across blocks even if the multiplier changes. + // There's still some precision loss when the final `gas_price` (used_gas * min_gas_price) + // is computed in frontier, but that's currently unavoidable. + let min_gas_price = TransactionPayment::next_fee_multiplier() + .saturating_mul_int(currency::WEIGHT_FEE.saturating_mul(WEIGHT_PER_GAS as u128)); + ( + min_gas_price.into(), + ::DbWeight::get().reads(1), + ) + } +} + +/// A "Fast" TargetedFeeAdjustment. Parameters chosen based on model described here: +/// https://research.web3.foundation/en/latest/polkadot/overview/2-token-economics.html#-1.-fast-adjusting-mechanism // editorconfig-checker-disable-line +/// +/// The adjustment algorithm boils down to: +/// +/// diff = (previous_block_weight - target) / maximum_block_weight +/// next_multiplier = prev_multiplier * (1 + (v * diff) + ((v * diff)^2 / 2)) +/// assert(next_multiplier > min) +/// where: v is AdjustmentVariable +/// target is TargetBlockFullness +/// min is MinimumMultiplier +pub type FastAdjustingFeeUpdate = TargetedFeeAdjustment< + R, + TargetBlockFullness, + AdjustmentVariable, + MinimumMultiplier, + MaximumMultiplier, +>; + +/// The author inherent provides an AccountId, but pallet evm needs an H160. +/// This simple adapter makes the conversion for any types T, U such that T: Into +pub struct FindAuthorAdapter(sp_std::marker::PhantomData<(T, U, Inner)>); + +impl FindAuthor for FindAuthorAdapter +where + T: Into, + Inner: FindAuthor, +{ + fn find_author<'a, I>(digests: I) -> Option + where + I: 'a + IntoIterator, + { + Inner::find_author(digests).map(Into::into) + } +} + +moonbeam_runtime_common::impl_on_charge_evm_transaction!(); + +impl pallet_evm::Config for Runtime { + type FeeCalculator = TransactionPaymentAsGasPrice; + type GasWeightMapping = pallet_evm::FixedGasWeightMapping; + type WeightPerGas = WeightPerGas; + type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping; + type CallOrigin = EnsureAddressRoot; + type WithdrawOrigin = EnsureAddressNever; + type AddressMapping = IdentityAddressMapping; + type Currency = Balances; + type RuntimeEvent = RuntimeEvent; + type Runner = pallet_evm::runner::stack::Runner; + type PrecompilesType = MoonbasePrecompiles; + type PrecompilesValue = PrecompilesValue; + type ChainId = EthereumChainId; + type OnChargeTransaction = OnChargeEVMTransaction>; + type BlockGasLimit = BlockGasLimit; + type FindAuthor = FindAuthorAdapter; + type OnCreate = (); + type GasLimitPovSizeRatio = GasLimitPovSizeRatio; + type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio; + type Timestamp = Timestamp; + type WeightInfo = moonbeam_weights::pallet_evm::WeightInfo; +} + +parameter_types! { + pub MaximumSchedulerWeight: Weight = NORMAL_DISPATCH_RATIO * RuntimeBlockWeights::get().max_block; + pub const NoPreimagePostponement: Option = Some(10); +} + +impl pallet_scheduler::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type MaximumWeight = MaximumSchedulerWeight; + type ScheduleOrigin = EnsureRoot; + type MaxScheduledPerBlock = ConstU32<50>; + type WeightInfo = moonbeam_weights::pallet_scheduler::WeightInfo; + type OriginPrivilegeCmp = EqualPrivilegeOnly; + type Preimages = Preimage; +} + +impl pallet_preimage::Config for Runtime { + type WeightInfo = moonbeam_weights::pallet_preimage::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type BaseDeposit = ConstU128<{ 5 * currency::UNIT * currency::SUPPLY_FACTOR }>; + type ByteDeposit = ConstU128<{ currency::STORAGE_BYTE_FEE }>; +} + +parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const TreasuryId: PalletId = PalletId(*b"pc/trsry"); +} + +type TreasuryApproveOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, +>; + +type TreasuryRejectOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionMoreThan, +>; + +impl pallet_treasury::Config for Runtime { + type PalletId = TreasuryId; + type Currency = Balances; + // At least three-fifths majority of the council is required (or root) to approve a proposal + type ApproveOrigin = TreasuryApproveOrigin; + // More than half of the council is required (or root) to reject a proposal + type RejectOrigin = TreasuryRejectOrigin; + type RuntimeEvent = RuntimeEvent; + // If spending proposal rejected, transfer proposer bond to treasury + type OnSlash = Treasury; + type ProposalBond = ProposalBond; + type ProposalBondMinimum = ConstU128<{ 1 * currency::UNIT * currency::SUPPLY_FACTOR }>; + type SpendPeriod = ConstU32<{ 6 * DAYS }>; + type Burn = (); + type BurnDestination = (); + type MaxApprovals = ConstU32<100>; + type WeightInfo = moonbeam_weights::pallet_treasury::WeightInfo; + type SpendFunds = (); + type ProposalBondMaximum = (); + type SpendOrigin = frame_support::traits::NeverEnsureOrigin; // Same as Polkadot +} + +type IdentityForceOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; +type IdentityRegistrarOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; + +impl pallet_identity::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + // Add one item in storage and take 258 bytes + type BasicDeposit = ConstU128<{ currency::deposit(1, 258) }>; + // Not add any item to the storage but takes 66 bytes + type FieldDeposit = ConstU128<{ currency::deposit(0, 66) }>; + // Add one item in storage and take 53 bytes + type SubAccountDeposit = ConstU128<{ currency::deposit(1, 53) }>; + type MaxSubAccounts = ConstU32<100>; + type MaxAdditionalFields = ConstU32<100>; + type MaxRegistrars = ConstU32<20>; + type Slashed = Treasury; + type ForceOrigin = IdentityForceOrigin; + type RegistrarOrigin = IdentityRegistrarOrigin; + type WeightInfo = moonbeam_weights::pallet_identity::WeightInfo; +} + +pub struct TransactionConverter; + +impl fp_rpc::ConvertTransaction for TransactionConverter { + fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic { + UncheckedExtrinsic::new_unsigned( + pallet_ethereum::Call::::transact { transaction }.into(), + ) + } +} + +impl fp_rpc::ConvertTransaction for TransactionConverter { + fn convert_transaction( + &self, + transaction: pallet_ethereum::Transaction, + ) -> opaque::UncheckedExtrinsic { + let extrinsic = UncheckedExtrinsic::new_unsigned( + pallet_ethereum::Call::::transact { transaction }.into(), + ); + let encoded = extrinsic.encode(); + opaque::UncheckedExtrinsic::decode(&mut &encoded[..]) + .expect("Encoded extrinsic is always valid") + } +} + +parameter_types! { + pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes; +} + +impl pallet_ethereum::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type StateRoot = pallet_ethereum::IntermediateStateRoot; + type PostLogContent = PostBlockAndTxnHashes; + type ExtraDataLength = ConstU32<30>; +} + +pub struct EthereumXcmEnsureProxy; +impl xcm_primitives::EnsureProxy for EthereumXcmEnsureProxy { + fn ensure_ok(delegator: AccountId, delegatee: AccountId) -> Result<(), &'static str> { + // The EVM implicitely contains an Any proxy, so we only allow for "Any" proxies + let def: pallet_proxy::ProxyDefinition = + pallet_proxy::Pallet::::find_proxy( + &delegator, + &delegatee, + Some(ProxyType::Any), + ) + .map_err(|_| "proxy error: expected `ProxyType::Any`")?; + // We only allow to use it for delay zero proxies, as the call will immediatly be executed + ensure!(def.delay.is_zero(), "proxy delay is Non-zero`"); + Ok(()) + } +} + +impl pallet_ethereum_xcm::Config for Runtime { + type InvalidEvmTransactionError = pallet_ethereum::InvalidTransactionWrapper; + type ValidatedTransaction = pallet_ethereum::ValidatedTransaction; + type XcmEthereumOrigin = pallet_ethereum_xcm::EnsureXcmEthereumTransaction; + type ReservedXcmpWeight = ReservedXcmpWeight; + type EnsureProxy = EthereumXcmEnsureProxy; + type ControllerOrigin = EnsureRoot; +} + +parameter_types! { + pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); +} + +impl cumulus_pallet_parachain_system::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnSystemEvent = (); + type SelfParaId = ParachainInfo; + type DmpMessageHandler = MaintenanceMode; + type ReservedDmpWeight = ReservedDmpWeight; + type OutboundXcmpMessageSource = XcmpQueue; + type XcmpMessageHandler = XcmpQueue; + type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; +} + +impl parachain_info::Config for Runtime {} + +pub struct OnNewRound; +impl pallet_parachain_staking::OnNewRound for OnNewRound { + fn on_new_round(round_index: pallet_parachain_staking::RoundIndex) -> Weight { + MoonbeamOrbiters::on_new_round(round_index) + } +} +pub struct PayoutCollatorOrOrbiterReward; +impl pallet_parachain_staking::PayoutCollatorReward for PayoutCollatorOrOrbiterReward { + fn payout_collator_reward( + for_round: pallet_parachain_staking::RoundIndex, + collator_id: AccountId, + amount: Balance, + ) -> Weight { + let extra_weight = if MoonbeamOrbiters::is_orbiter(for_round, collator_id) { + MoonbeamOrbiters::distribute_rewards(for_round, collator_id, amount) + } else { + ParachainStaking::mint_collator_reward(for_round, collator_id, amount) + }; + + ::DbWeight::get() + .reads(1) + .saturating_add(extra_weight) + } +} + +pub struct OnInactiveCollator; +impl pallet_parachain_staking::OnInactiveCollator for OnInactiveCollator { + fn on_inactive_collator( + collator_id: AccountId, + round: pallet_parachain_staking::RoundIndex, + ) -> Result> { + let extra_weight = if !MoonbeamOrbiters::is_orbiter(round, collator_id.clone()) { + ParachainStaking::go_offline_inner(collator_id)?; + ::WeightInfo::go_offline( + pallet_parachain_staking::MAX_CANDIDATES, + ) + } else { + Weight::zero() + }; + + Ok(::DbWeight::get() + .reads(1) + .saturating_add(extra_weight)) + } +} + +type MonetaryGovernanceOrigin = + EitherOfDiverse, governance::custom_origins::GeneralAdmin>; + +impl pallet_parachain_staking::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type MonetaryGovernanceOrigin = MonetaryGovernanceOrigin; + /// Minimum round length is 2 minutes (10 * 12 second block times) + type MinBlocksPerRound = ConstU32<10>; + /// If a collator doesn't produce any block on this number of rounds, it is notified as inactive + type MaxOfflineRounds = ConstU32<2>; + /// Rounds before the collator leaving the candidates request can be executed + type LeaveCandidatesDelay = ConstU32<2>; + /// Rounds before the candidate bond increase/decrease can be executed + type CandidateBondLessDelay = ConstU32<2>; + /// Rounds before the delegator exit can be executed + type LeaveDelegatorsDelay = ConstU32<2>; + /// Rounds before the delegator revocation can be executed + type RevokeDelegationDelay = ConstU32<2>; + /// Rounds before the delegator bond increase/decrease can be executed + type DelegationBondLessDelay = ConstU32<2>; + /// Rounds before the reward is paid + type RewardPaymentDelay = ConstU32<2>; + /// Minimum collators selected per round, default at genesis and minimum forever after + type MinSelectedCandidates = ConstU32<8>; + /// Maximum top delegations per candidate + type MaxTopDelegationsPerCandidate = ConstU32<300>; + /// Maximum bottom delegations per candidate + type MaxBottomDelegationsPerCandidate = ConstU32<50>; + /// Maximum delegations per delegator + type MaxDelegationsPerDelegator = ConstU32<100>; + /// Minimum stake required to be reserved to be a candidate + type MinCandidateStk = ConstU128<{ 500 * currency::UNIT * currency::SUPPLY_FACTOR }>; + /// Minimum stake required to be reserved to be a delegator + type MinDelegation = ConstU128<{ 1 * currency::UNIT * currency::SUPPLY_FACTOR }>; + type BlockAuthor = AuthorInherent; + type OnCollatorPayout = (); + type PayoutCollatorReward = PayoutCollatorOrOrbiterReward; + type OnInactiveCollator = OnInactiveCollator; + type OnNewRound = OnNewRound; + type WeightInfo = moonbeam_weights::pallet_parachain_staking::WeightInfo; + type MaxCandidates = ConstU32<200>; +} + +impl pallet_author_inherent::Config for Runtime { + type SlotBeacon = RelaychainDataProvider; + type AccountLookup = MoonbeamOrbiters; + type CanAuthor = AuthorFilter; + type AuthorId = AccountId; + type WeightInfo = moonbeam_weights::pallet_author_inherent::WeightInfo; +} + +impl pallet_author_slot_filter::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RandomnessSource = Randomness; + type PotentialAuthors = ParachainStaking; + type WeightInfo = moonbeam_weights::pallet_author_slot_filter::WeightInfo; +} + +parameter_types! { + pub const InitializationPayment: Perbill = Perbill::from_percent(30); + pub const RelaySignaturesThreshold: Perbill = Perbill::from_percent(100); + pub const SignatureNetworkIdentifier: &'static [u8] = b"moonbase-"; + +} + +impl pallet_crowdloan_rewards::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Initialized = ConstBool; + type InitializationPayment = InitializationPayment; + type MaxInitContributors = ConstU32<500>; + // TODO to be revisited + type MinimumReward = ConstU128<0>; + type RewardCurrency = Balances; + type RelayChainAccountId = [u8; 32]; + type RewardAddressAssociateOrigin = EnsureSigned; + type RewardAddressChangeOrigin = EnsureSigned; + type RewardAddressRelayVoteThreshold = RelaySignaturesThreshold; + type SignatureNetworkIdentifier = SignatureNetworkIdentifier; + type VestingBlockNumber = cumulus_primitives_core::relay_chain::BlockNumber; + type VestingBlockProvider = RelaychainDataProvider; + type WeightInfo = moonbeam_weights::pallet_crowdloan_rewards::WeightInfo; +} + +// This is a simple session key manager. It should probably either work with, or be replaced +// entirely by pallet sessions +impl pallet_author_mapping::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type DepositCurrency = Balances; + type DepositAmount = ConstU128<{ 100 * currency::UNIT * currency::SUPPLY_FACTOR }>; + type Keys = session_keys_primitives::VrfId; + type WeightInfo = moonbeam_weights::pallet_author_mapping::WeightInfo; +} + +/// The type used to represent the kinds of proxying allowed. +#[derive( + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + Debug, + MaxEncodedLen, + TypeInfo, + Serialize, + Deserialize, +)] +pub enum ProxyType { + /// All calls can be proxied. This is the trivial/most permissive filter. + Any = 0, + /// Only extrinsics that do not transfer funds. + NonTransfer = 1, + /// Only extrinsics related to governance (democracy and collectives). + Governance = 2, + /// Only extrinsics related to staking. + Staking = 3, + /// Allow to veto an announced proxy call. + CancelProxy = 4, + /// Allow extrinsic related to Balances. + Balances = 5, + /// Allow extrinsic related to AuthorMapping. + AuthorMapping = 6, + /// Allow extrinsic related to IdentityJudgement. + IdentityJudgement = 7, +} + +impl Default for ProxyType { + fn default() -> Self { + Self::Any + } +} + +fn is_governance_precompile(precompile_name: &precompiles::PrecompileName) -> bool { + matches!( + precompile_name, + PrecompileName::DemocracyPrecompile + | PrecompileName::CouncilInstance + | PrecompileName::TechCommitteeInstance + | PrecompileName::TreasuryCouncilInstance + | PrecompileName::ReferendaPrecompile + | PrecompileName::ConvictionVotingPrecompile + | PrecompileName::PreimagePrecompile + | PrecompileName::OpenTechCommitteeInstance, + ) +} + +// Be careful: Each time this filter is modified, the substrate filter must also be modified +// consistently. +impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType { + fn is_evm_proxy_call_allowed( + &self, + call: &pallet_evm_precompile_proxy::EvmSubCall, + recipient_has_code: bool, + gas: u64, + ) -> precompile_utils::EvmResult { + Ok(match self { + ProxyType::Any => true, + ProxyType::NonTransfer => { + call.value == U256::zero() + && match PrecompileName::from_address(call.to.0) { + Some( + PrecompileName::AuthorMappingPrecompile + | PrecompileName::IdentityPrecompile + | PrecompileName::ParachainStakingPrecompile, + ) => true, + Some(ref precompile) if is_governance_precompile(precompile) => true, + _ => false, + } + } + ProxyType::Governance => { + call.value == U256::zero() + && matches!( + PrecompileName::from_address(call.to.0), + Some(ref precompile) if is_governance_precompile(precompile) + ) + } + ProxyType::Staking => { + call.value == U256::zero() + && matches!( + PrecompileName::from_address(call.to.0), + Some( + PrecompileName::AuthorMappingPrecompile + | PrecompileName::ParachainStakingPrecompile + ) + ) + } + // The proxy precompile does not contain method cancel_proxy + ProxyType::CancelProxy => false, + ProxyType::Balances => { + // Allow only "simple" accounts as recipient (no code nor precompile). + // Note: Checking the presence of the code is not enough because some precompiles + // have no code. + !recipient_has_code + && !precompile_utils::precompile_set::is_precompile_or_fail::( + call.to.0, gas, + )? + } + ProxyType::AuthorMapping => { + call.value == U256::zero() + && matches!( + PrecompileName::from_address(call.to.0), + Some(PrecompileName::AuthorMappingPrecompile) + ) + } + // There is no identity precompile + ProxyType::IdentityJudgement => false, + }) + } +} + +// Be careful: Each time this filter is modified, the EVM filter must also be modified consistently. +impl InstanceFilter for ProxyType { + fn filter(&self, c: &RuntimeCall) -> bool { + match self { + ProxyType::Any => true, + ProxyType::NonTransfer => { + matches!( + c, + RuntimeCall::System(..) + | RuntimeCall::ParachainSystem(..) + | RuntimeCall::Timestamp(..) + | RuntimeCall::ParachainStaking(..) + | RuntimeCall::Democracy(..) + | RuntimeCall::Referenda(..) + | RuntimeCall::Preimage(..) + | RuntimeCall::ConvictionVoting(..) + | RuntimeCall::CouncilCollective(..) + | RuntimeCall::TreasuryCouncilCollective(..) + | RuntimeCall::TechCommitteeCollective(..) + | RuntimeCall::OpenTechCommitteeCollective(..) + | RuntimeCall::Identity(..) + | RuntimeCall::Utility(..) + | RuntimeCall::Proxy(..) | RuntimeCall::AuthorMapping(..) + | RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::claim { .. } + ) + ) + } + ProxyType::Governance => matches!( + c, + RuntimeCall::Democracy(..) + | RuntimeCall::Referenda(..) + | RuntimeCall::Preimage(..) + | RuntimeCall::ConvictionVoting(..) + | RuntimeCall::CouncilCollective(..) + | RuntimeCall::TreasuryCouncilCollective(..) + | RuntimeCall::TechCommitteeCollective(..) + | RuntimeCall::OpenTechCommitteeCollective(..) + | RuntimeCall::Utility(..) + ), + ProxyType::Staking => matches!( + c, + RuntimeCall::ParachainStaking(..) + | RuntimeCall::Utility(..) + | RuntimeCall::AuthorMapping(..) + | RuntimeCall::MoonbeamOrbiters(..) + ), + ProxyType::CancelProxy => matches!( + c, + RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) + ), + ProxyType::Balances => { + matches!(c, RuntimeCall::Balances(..) | RuntimeCall::Utility(..)) + } + ProxyType::AuthorMapping => matches!(c, RuntimeCall::AuthorMapping(..)), + ProxyType::IdentityJudgement => matches!( + c, + RuntimeCall::Identity(pallet_identity::Call::provide_judgement { .. }) + | RuntimeCall::Utility(..) + ), + } + } + + fn is_superset(&self, o: &Self) -> bool { + match (self, o) { + (x, y) if x == y => true, + (ProxyType::Any, _) => true, + (_, ProxyType::Any) => false, + _ => false, + } + } +} + +impl pallet_proxy::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type ProxyType = ProxyType; + // One storage item; key size 32, value size 8 + type ProxyDepositBase = ConstU128<{ currency::deposit(1, 8) }>; + // Additional storage item size of 21 bytes (20 bytes AccountId + 1 byte sizeof(ProxyType)). + type ProxyDepositFactor = ConstU128<{ currency::deposit(0, 21) }>; + type MaxProxies = ConstU32<32>; + type WeightInfo = moonbeam_weights::pallet_proxy::WeightInfo; + type MaxPending = ConstU32<32>; + type CallHasher = BlakeTwo256; + type AnnouncementDepositBase = ConstU128<{ currency::deposit(1, 8) }>; + // Additional storage item size of 56 bytes: + // - 20 bytes AccountId + // - 32 bytes Hasher (Blake2256) + // - 4 bytes BlockNumber (u32) + type AnnouncementDepositFactor = ConstU128<{ currency::deposit(0, 56) }>; +} + +use pallet_migrations::{GetMigrations, Migration}; +pub struct TransactorRelayIndexMigration(sp_std::marker::PhantomData); + +impl GetMigrations for TransactorRelayIndexMigration +where + Runtime: pallet_xcm_transactor::Config, +{ + fn get_migrations() -> Vec> { + vec![Box::new( + moonbeam_runtime_common::migrations::PopulateRelayIndices::( + moonbeam_relay_encoder::westend::WESTEND_RELAY_INDICES, + Default::default(), + ), + )] + } +} + +impl pallet_migrations::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + // TODO wire up our correct list of migrations here. Maybe this shouldn't be in + // `moonbeam_runtime_common`. + type MigrationsList = ( + moonbeam_runtime_common::migrations::CommonMigrations< + Runtime, + CouncilCollective, + TechCommitteeCollective, + >, + moonbeam_runtime_common::migrations::ReferendaMigrations< + Runtime, + CouncilCollective, + TechCommitteeCollective, + >, + TransactorRelayIndexMigration, + ); + type XcmExecutionManager = XcmExecutionManager; +} + +/// Maintenance mode Call filter +pub struct MaintenanceFilter; +impl Contains for MaintenanceFilter { + fn contains(c: &RuntimeCall) -> bool { + match c { + RuntimeCall::Assets(_) => false, + RuntimeCall::LocalAssets(_) => false, + RuntimeCall::Balances(_) => false, + RuntimeCall::CrowdloanRewards(_) => false, + RuntimeCall::Ethereum(_) => false, + RuntimeCall::EVM(_) => false, + RuntimeCall::Identity(_) => false, + RuntimeCall::XTokens(_) => false, + RuntimeCall::ParachainStaking(_) => false, + RuntimeCall::MoonbeamOrbiters(_) => false, + RuntimeCall::PolkadotXcm(_) => false, + RuntimeCall::Treasury(_) => false, + RuntimeCall::XcmTransactor(_) => false, + RuntimeCall::EthereumXcm(_) => false, + _ => true, + } + } +} + +/// Normal Call Filter +/// We dont allow to create nor mint assets, this for now is disabled +/// We only allow transfers. For now creation of assets will go through +/// asset-manager, while minting/burning only happens through xcm messages +/// This can change in the future +pub struct NormalFilter; +impl Contains for NormalFilter { + fn contains(c: &RuntimeCall) -> bool { + match c { + RuntimeCall::Assets(method) => match method { + pallet_assets::Call::transfer { .. } => true, + pallet_assets::Call::transfer_keep_alive { .. } => true, + pallet_assets::Call::approve_transfer { .. } => true, + pallet_assets::Call::transfer_approved { .. } => true, + pallet_assets::Call::cancel_approval { .. } => true, + pallet_assets::Call::destroy_accounts { .. } => true, + pallet_assets::Call::destroy_approvals { .. } => true, + pallet_assets::Call::finish_destroy { .. } => true, + _ => false, + }, + // We want to disable create, as we dont want users to be choosing the + // assetId of their choice + // We also disable destroy, as we want to route destroy through the + // asset-manager, which guarantees the removal both at the EVM and + // substrate side of things + RuntimeCall::LocalAssets(method) => match method { + pallet_assets::Call::create { .. } => false, + pallet_assets::Call::start_destroy { .. } => false, + _ => true, + }, + // We filter anonymous proxy as they make "reserve" inconsistent + // See: https://github.com/paritytech/substrate/blob/37cca710eed3dadd4ed5364c7686608f5175cce1/frame/proxy/src/lib.rs#L270 // editorconfig-checker-disable-line + RuntimeCall::Proxy(method) => match method { + pallet_proxy::Call::create_pure { .. } => false, + pallet_proxy::Call::kill_pure { .. } => false, + pallet_proxy::Call::proxy { real, .. } => { + !pallet_evm::AccountCodes::::contains_key(H160::from(*real)) + } + _ => true, + }, + // Filtering the EVM prevents possible re-entrancy from the precompiles which could + // lead to unexpected scenarios. + // See https://github.com/PureStake/sr-moonbeam/issues/30 + // Note: It is also assumed that EVM calls are only allowed through `Origin::Root` so + // this can be seen as an additional security + RuntimeCall::EVM(_) => false, + _ => true, + } + } +} + +use cumulus_primitives_core::{relay_chain::BlockNumber as RelayBlockNumber, DmpMessageHandler}; + +pub struct XcmExecutionManager; +impl moonkit_xcm_primitives::PauseXcmExecution for XcmExecutionManager { + fn suspend_xcm_execution() -> DispatchResult { + XcmpQueue::suspend_xcm_execution(RuntimeOrigin::root()) + } + fn resume_xcm_execution() -> DispatchResult { + XcmpQueue::resume_xcm_execution(RuntimeOrigin::root()) + } +} + +pub struct NormalDmpHandler; +impl DmpMessageHandler for NormalDmpHandler { + // This implementation makes messages be queued + // Since the limit is 0, messages are queued for next iteration + fn handle_dmp_messages( + iter: impl Iterator)>, + limit: Weight, + ) -> Weight { + (if Migrations::should_pause_xcm() { + DmpQueue::handle_dmp_messages(iter, Weight::zero()) + } else { + DmpQueue::handle_dmp_messages(iter, limit) + }) + ::DbWeight::get().reads(1) + } +} + +pub struct MaintenanceDmpHandler; +impl DmpMessageHandler for MaintenanceDmpHandler { + // This implementation makes messages be queued + // Since the limit is 0, messages are queued for next iteration + fn handle_dmp_messages( + iter: impl Iterator)>, + _limit: Weight, + ) -> Weight { + DmpQueue::handle_dmp_messages(iter, Weight::zero()) + } +} + +/// The hooks we wnat to run in Maintenance Mode +pub struct MaintenanceHooks; + +impl OnInitialize for MaintenanceHooks { + fn on_initialize(n: BlockNumber) -> Weight { + AllPalletsWithSystem::on_initialize(n) + } +} + +// return 0 +// For some reason using empty tuple () isnt working +// There exist only two pallets that use onIdle and these are xcmp and dmp queues +// For some reason putting an empty tumple does not work (transaction never finishes) +// We use an empty onIdle, if on the future we want one of the pallets to execute it +// we need to provide it here +impl OnIdle for MaintenanceHooks { + fn on_idle(_n: BlockNumber, _max_weight: Weight) -> Weight { + Weight::zero() + } +} + +impl OnRuntimeUpgrade for MaintenanceHooks { + fn on_runtime_upgrade() -> Weight { + AllPalletsWithSystem::on_runtime_upgrade() + } + + #[cfg(feature = "try-runtime")] + fn try_on_runtime_upgrade(checks: bool) -> Result { + AllPalletsWithSystem::try_on_runtime_upgrade(checks) + } +} + +impl OnFinalize for MaintenanceHooks { + fn on_finalize(n: BlockNumber) { + AllPalletsWithSystem::on_finalize(n) + } +} + +impl OffchainWorker for MaintenanceHooks { + fn offchain_worker(n: BlockNumber) { + AllPalletsWithSystem::offchain_worker(n) + } +} + +impl pallet_maintenance_mode::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type NormalCallFilter = NormalFilter; + type MaintenanceCallFilter = MaintenanceFilter; + type MaintenanceOrigin = + pallet_collective::EnsureProportionAtLeast; + type XcmExecutionManager = XcmExecutionManager; + type NormalDmpHandler = NormalDmpHandler; + type MaintenanceDmpHandler = MaintenanceDmpHandler; + // We use AllPalletsWithSystem because we dont want to change the hooks in normal + // operation + type NormalExecutiveHooks = AllPalletsWithSystem; + type MaintenanceExecutiveHooks = MaintenanceHooks; +} + +impl pallet_proxy_genesis_companion::Config for Runtime { + type ProxyType = ProxyType; +} + +parameter_types! { + pub OrbiterReserveIdentifier: [u8; 4] = [b'o', b'r', b'b', b'i']; +} + +type AddCollatorOrigin = + EitherOfDiverse, governance::custom_origins::GeneralAdmin>; +type DelCollatorOrigin = + EitherOfDiverse, governance::custom_origins::GeneralAdmin>; + +impl pallet_moonbeam_orbiters::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type AccountLookup = AuthorMapping; + type AddCollatorOrigin = AddCollatorOrigin; + type Currency = Balances; + type DelCollatorOrigin = DelCollatorOrigin; + /// Maximum number of orbiters per collator + type MaxPoolSize = ConstU32<8>; + /// Maximum number of round to keep on storage + type MaxRoundArchive = ConstU32<4>; + type OrbiterReserveIdentifier = OrbiterReserveIdentifier; + type RotatePeriod = ConstU32<3>; + /// Round index type. + type RoundIndex = pallet_parachain_staking::RoundIndex; + type WeightInfo = moonbeam_weights::pallet_moonbeam_orbiters::WeightInfo; +} + +/// Only callable after `set_validation_data` is called which forms this proof the same way +fn relay_chain_state_proof() -> RelayChainStateProof { + let relay_storage_root = ParachainSystem::validation_data() + .expect("set in `set_validation_data`") + .relay_parent_storage_root; + let relay_chain_state = + ParachainSystem::relay_state_proof().expect("set in `set_validation_data`"); + RelayChainStateProof::new(ParachainInfo::get(), relay_storage_root, relay_chain_state) + .expect("Invalid relay chain state proof, already constructed in `set_validation_data`") +} + +pub struct BabeDataGetter; +impl pallet_randomness::GetBabeData> for BabeDataGetter { + // Tolerate panic here because only ever called in inherent (so can be omitted) + fn get_epoch_index() -> u64 { + if cfg!(feature = "runtime-benchmarks") { + // storage reads as per actual reads + let _relay_storage_root = ParachainSystem::validation_data(); + let _relay_chain_state = ParachainSystem::relay_state_proof(); + const BENCHMARKING_NEW_EPOCH: u64 = 10u64; + return BENCHMARKING_NEW_EPOCH; + } + relay_chain_state_proof() + .read_optional_entry(relay_chain::well_known_keys::EPOCH_INDEX) + .ok() + .flatten() + .expect("expected to be able to read epoch index from relay chain state proof") + } + fn get_epoch_randomness() -> Option { + if cfg!(feature = "runtime-benchmarks") { + // storage reads as per actual reads + let _relay_storage_root = ParachainSystem::validation_data(); + let _relay_chain_state = ParachainSystem::relay_state_proof(); + let benchmarking_babe_output = Hash::default(); + return Some(benchmarking_babe_output); + } + relay_chain_state_proof() + .read_optional_entry(relay_chain::well_known_keys::ONE_EPOCH_AGO_RANDOMNESS) + .ok() + .flatten() + } +} + +impl pallet_randomness::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type AddressMapping = sp_runtime::traits::ConvertInto; + type Currency = Balances; + type BabeDataGetter = BabeDataGetter; + type VrfKeyLookup = AuthorMapping; + type Deposit = ConstU128<{ 1 * currency::UNIT * currency::SUPPLY_FACTOR }>; + type MaxRandomWords = ConstU8<100>; + type MinBlockDelay = ConstU32<2>; + type MaxBlockDelay = ConstU32<2_000>; + type BlockExpirationDelay = ConstU32<10_000>; + type EpochExpirationDelay = ConstU64<10_000>; + type WeightInfo = moonbeam_weights::pallet_randomness::WeightInfo; +} + +impl pallet_root_testing::Config for Runtime {} + +parameter_types! { + // One storage item; key size is 32 + 20; value is size 4+4+16+20 bytes = 44 bytes. + pub const DepositBase: Balance = currency::deposit(1, 96); + // Additional storage item size of 20 bytes. + pub const DepositFactor: Balance = currency::deposit(0, 20); + pub const MaxSignatories: u32 = 100; +} + +impl pallet_multisig::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type DepositBase = DepositBase; + type DepositFactor = DepositFactor; + type MaxSignatories = MaxSignatories; + type WeightInfo = moonbeam_weights::pallet_multisig::WeightInfo; +} + +construct_runtime! { + pub enum Runtime + { + System: frame_system::{Pallet, Call, Storage, Config, Event} = 0, + Utility: pallet_utility::{Pallet, Call, Event} = 1, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 2, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event} = 3, + Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event} = 4, + // Previously 5: pallet_randomness_collective_flip + ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event} = 6, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Config, Event} = 7, + ParachainInfo: parachain_info::{Pallet, Storage, Config} = 8, + EthereumChainId: pallet_evm_chain_id::{Pallet, Storage, Config} = 9, + EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 10, + Ethereum: pallet_ethereum::{Pallet, Call, Storage, Event, Origin, Config} = 11, + ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Event, Config} = 12, + Scheduler: pallet_scheduler::{Pallet, Storage, Event, Call} = 13, + Democracy: pallet_democracy::{Pallet, Storage, Config, Event, Call} = 14, + CouncilCollective: + pallet_collective::::{Pallet, Call, Storage, Event, Origin, Config} = 15, + TechCommitteeCollective: + pallet_collective::::{Pallet, Call, Storage, Event, Origin, Config} = 16, + Treasury: pallet_treasury::{Pallet, Storage, Config, Event, Call} = 17, + AuthorInherent: pallet_author_inherent::{Pallet, Call, Storage, Inherent} = 18, + AuthorFilter: pallet_author_slot_filter::{Pallet, Call, Storage, Event, Config} = 19, + CrowdloanRewards: pallet_crowdloan_rewards::{Pallet, Call, Config, Storage, Event} = 20, + AuthorMapping: pallet_author_mapping::{Pallet, Call, Config, Storage, Event} = 21, + Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 22, + MaintenanceMode: pallet_maintenance_mode::{Pallet, Call, Config, Storage, Event} = 23, + Identity: pallet_identity::{Pallet, Call, Storage, Event} = 24, + XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 25, + CumulusXcm: cumulus_pallet_xcm::{Pallet, Event, Origin} = 26, + DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 27, + PolkadotXcm: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 28, + Assets: pallet_assets::{Pallet, Call, Storage, Event} = 29, + XTokens: orml_xtokens::{Pallet, Call, Storage, Event} = 30, + AssetManager: pallet_asset_manager::{Pallet, Call, Storage, Event} = 31, + Migrations: pallet_migrations::{Pallet, Storage, Config, Event} = 32, + XcmTransactor: pallet_xcm_transactor::{Pallet, Call, Config, Storage, Event} = 33, + ProxyGenesisCompanion: pallet_proxy_genesis_companion::{Pallet, Config} = 34, + LocalAssets: pallet_assets::::{Pallet, Call, Storage, Event} = 36, + MoonbeamOrbiters: pallet_moonbeam_orbiters::{Pallet, Call, Storage, Event} = 37, + EthereumXcm: pallet_ethereum_xcm::{Pallet, Call, Storage, Origin} = 38, + Randomness: pallet_randomness::{Pallet, Call, Storage, Event, Inherent} = 39, + TreasuryCouncilCollective: + pallet_collective::::{Pallet, Call, Storage, Event, Origin, Config} = 40, + ConvictionVoting: pallet_conviction_voting::{Pallet, Call, Storage, Event} = 41, + Referenda: pallet_referenda::{Pallet, Call, Storage, Event} = 42, + Origins: governance::custom_origins::{Origin} = 43, + Preimage: pallet_preimage::{Pallet, Call, Storage, Event} = 44, + Whitelist: pallet_whitelist::{Pallet, Call, Storage, Event} = 45, + OpenTechCommitteeCollective: + pallet_collective::::{Pallet, Call, Storage, Event, Origin, Config} = 46, + RootTesting: pallet_root_testing::{Pallet, Call, Storage} = 47, + Erc20XcmBridge: pallet_erc20_xcm_bridge::{Pallet} = 48, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 49, + } +} + +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; + +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckNonZeroSender, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, +); +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = + fp_self_contained::UncheckedExtrinsic; +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = + fp_self_contained::CheckedExtrinsic; +/// Executive: handles dispatch to the various pallets. +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + pallet_maintenance_mode::ExecutiveHooks, +>; + +#[cfg(feature = "runtime-benchmarks")] +use { + moonbeam_xcm_benchmarks::generic::benchmarking as MoonbeamXcmBenchmarks, + MoonbeamXcmBenchmarks::XcmGenericBenchmarks as MoonbeamXcmGenericBench, +}; +#[cfg(feature = "runtime-benchmarks")] +mod benches { + frame_benchmarking::define_benchmarks!( + [pallet_utility, Utility] + [pallet_timestamp, Timestamp] + [pallet_balances, Balances] + [pallet_sudo, Sudo] + [pallet_evm, EVM] + [pallet_assets, Assets] + [pallet_collective, CouncilCollective] + [pallet_parachain_staking, ParachainStaking] + [pallet_scheduler, Scheduler] + [pallet_democracy, Democracy] + [pallet_treasury, Treasury] + [pallet_author_inherent, AuthorInherent] + [pallet_author_slot_filter, AuthorFilter] + [pallet_crowdloan_rewards, CrowdloanRewards] + [pallet_author_mapping, AuthorMapping] + [pallet_proxy, Proxy] + [pallet_identity, Identity] + [cumulus_pallet_xcmp_queue, XcmpQueue] + [pallet_xcm, PolkadotXcm] + [pallet_asset_manager, AssetManager] + [pallet_xcm_transactor, XcmTransactor] + [pallet_moonbeam_orbiters, MoonbeamOrbiters] + [pallet_randomness, Randomness] + [pallet_conviction_voting, ConvictionVoting] + [pallet_referenda, Referenda] + [pallet_preimage, Preimage] + [pallet_whitelist, Whitelist] + [pallet_multisig, Multisig] + [moonbeam_xcm_benchmarks::weights::generic, MoonbeamXcmGenericBench::] + ); +} + +// All of our runtimes share most of their Runtime API implementations. +// We use a macro to implement this common part and add runtime-specific additional implementations. +// This macro expands to : +// ``` +// impl_runtime_apis! { +// // All impl blocks shared between all runtimes. +// +// // Specific impls provided to the `impl_runtime_apis_plus_common!` macro. +// } +// ``` +moonbeam_runtime_common::impl_runtime_apis_plus_common! { + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction( + source: TransactionSource, + xt: ::Extrinsic, + block_hash: ::Hash, + ) -> TransactionValidity { + // Filtered calls should not enter the tx pool as they'll fail if inserted. + // If this call is not allowed, we return early. + if !::BaseCallFilter::contains(&xt.0.function) { + return InvalidTransaction::Call.into(); + } + + // This runtime uses Substrate's pallet transaction payment. This + // makes the chain feel like a standard Substrate chain when submitting + // frame transactions and using Substrate ecosystem tools. It has the downside that + // transaction are not prioritized by gas_price. The following code reprioritizes + // transactions to overcome this. + // + // A more elegant, ethereum-first solution is + // a pallet that replaces pallet transaction payment, and allows users + // to directly specify a gas price rather than computing an effective one. + // #HopefullySomeday + + // First we pass the transactions to the standard FRAME executive. This calculates all the + // necessary tags, longevity and other properties that we will leave unchanged. + // This also assigns some priority that we don't care about and will overwrite next. + let mut intermediate_valid = Executive::validate_transaction(source, xt.clone(), block_hash)?; + + let dispatch_info = xt.get_dispatch_info(); + + // If this is a pallet ethereum transaction, then its priority is already set + // according to effective priority fee from pallet ethereum. If it is any other kind of + // transaction, we modify its priority. The goal is to arrive at a similar metric used + // by pallet ethereum, which means we derive a fee-per-gas from the txn's tip and + // weight. + Ok(match &xt.0.function { + RuntimeCall::Ethereum(transact { .. }) => intermediate_valid, + _ if dispatch_info.class != DispatchClass::Normal => intermediate_valid, + _ => { + let tip = match xt.0.signature { + None => 0, + Some((_, _, ref signed_extra)) => { + // Yuck, this depends on the index of charge transaction in Signed Extra + let charge_transaction = &signed_extra.7; + charge_transaction.tip() + } + }; + + let effective_gas = + ::GasWeightMapping::weight_to_gas( + dispatch_info.weight + ); + let tip_per_gas = if effective_gas > 0 { + tip.saturating_div(effective_gas as u128) + } else { + 0 + }; + + // Overwrite the original prioritization with this ethereum one + intermediate_valid.priority = tip_per_gas as u64; + intermediate_valid + } + }) + } + } +} + +// Check the timestamp and parachain inherents +struct CheckInherents; + +impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { + fn check_inherents( + block: &Block, + relay_state_proof: &RelayChainStateProof, + ) -> sp_inherents::CheckInherentsResult { + let relay_chain_slot = relay_state_proof + .read_slot() + .expect("Could not read the relay chain slot from the proof"); + + let inherent_data = + cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); + + inherent_data.check_extrinsics(&block) + } +} + +// Nimbus's Executive wrapper allows relay validators to verify the seal digest +cumulus_pallet_parachain_system::register_validate_block!( + Runtime = Runtime, + BlockExecutor = pallet_author_inherent::BlockExecutor::, + CheckInherents = CheckInherents, +); + +moonbeam_runtime_common::impl_self_contained_call!(); + +// Shorthand for a Get field of a pallet Config. +#[macro_export] +macro_rules! get { + ($pallet:ident, $name:ident, $type:ty) => { + <<$crate::Runtime as $pallet::Config>::$name as $crate::Get<$type>>::get() + }; +} + +#[cfg(test)] +mod tests { + use super::{currency::*, *}; + + #[test] + // Helps us to identify a Pallet Call in case it exceeds the 1kb limit. + // Hint: this should be a rare case. If that happens, one or more of the dispatchable arguments + // need to be Boxed. + fn call_max_size() { + const CALL_ALIGN: u32 = 1024; + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!( + std::mem::size_of::>() + <= CALL_ALIGN as usize + ); + } + + #[test] + fn currency_constants_are_correct() { + assert_eq!(SUPPLY_FACTOR, 1); + + // txn fees + assert_eq!(TRANSACTION_BYTE_FEE, Balance::from(1 * GIGAWEI)); + assert_eq!( + get!(pallet_transaction_payment, OperationalFeeMultiplier, u8), + 5_u8 + ); + assert_eq!(STORAGE_BYTE_FEE, Balance::from(100 * MICROUNIT)); + + // democracy minimums + assert_eq!( + get!(pallet_democracy, MinimumDeposit, u128), + Balance::from(4 * UNIT) + ); + assert_eq!( + get!(pallet_preimage, ByteDeposit, u128), + Balance::from(100 * MICROUNIT) + ); + assert_eq!( + get!(pallet_treasury, ProposalBondMinimum, u128), + Balance::from(1 * UNIT) + ); + + // pallet_identity deposits + assert_eq!( + get!(pallet_identity, BasicDeposit, u128), + Balance::from(1 * UNIT + 25800 * MICROUNIT) + ); + assert_eq!( + get!(pallet_identity, FieldDeposit, u128), + Balance::from(6600 * MICROUNIT) + ); + assert_eq!( + get!(pallet_identity, SubAccountDeposit, u128), + Balance::from(1 * UNIT + 5300 * MICROUNIT) + ); + + // staking minimums + assert_eq!( + get!(pallet_parachain_staking, MinCandidateStk, u128), + Balance::from(500 * UNIT) + ); + assert_eq!( + get!(pallet_parachain_staking, MinDelegation, u128), + Balance::from(1 * UNIT) + ); + + // crowdloan min reward + assert_eq!( + get!(pallet_crowdloan_rewards, MinimumReward, u128), + Balance::from(0u128) + ); + + // deposit for AuthorMapping + assert_eq!( + get!(pallet_author_mapping, DepositAmount, u128), + Balance::from(100 * UNIT) + ); + + // proxy deposits + assert_eq!( + get!(pallet_proxy, ProxyDepositBase, u128), + Balance::from(1 * UNIT + 800 * MICROUNIT) + ); + assert_eq!( + get!(pallet_proxy, ProxyDepositFactor, u128), + Balance::from(2100 * MICROUNIT) + ); + assert_eq!( + get!(pallet_proxy, AnnouncementDepositBase, u128), + Balance::from(1 * UNIT + 800 * MICROUNIT) + ); + assert_eq!( + get!(pallet_proxy, AnnouncementDepositFactor, u128), + Balance::from(5600 * MICROUNIT) + ); + } + + #[test] + fn max_offline_rounds_lower_or_eq_than_reward_payment_delay() { + assert!( + get!(pallet_parachain_staking, MaxOfflineRounds, u32) + <= get!(pallet_parachain_staking, RewardPaymentDelay, u32) + ); + } + + #[test] + // Required migration is + // pallet_parachain_staking::migrations::IncreaseMaxTopDelegationsPerCandidate + // Purpose of this test is to remind of required migration if constant is ever changed + fn updating_maximum_delegators_per_candidate_requires_configuring_required_migration() { + assert_eq!( + get!(pallet_parachain_staking, MaxTopDelegationsPerCandidate, u32), + 300 + ); + assert_eq!( + get!( + pallet_parachain_staking, + MaxBottomDelegationsPerCandidate, + u32 + ), + 50 + ); + } + + #[test] + fn test_proxy_type_can_be_decoded_from_valid_values() { + let test_cases = vec![ + // (input, expected) + (0u8, ProxyType::Any), + (1, ProxyType::NonTransfer), + (2, ProxyType::Governance), + (3, ProxyType::Staking), + (4, ProxyType::CancelProxy), + (5, ProxyType::Balances), + (6, ProxyType::AuthorMapping), + (7, ProxyType::IdentityJudgement), + ]; + + for (input, expected) in test_cases { + let actual = ProxyType::decode(&mut input.to_le_bytes().as_slice()); + assert_eq!( + Ok(expected), + actual, + "failed decoding ProxyType for value '{}'", + input + ); + } + } + + #[test] + fn configured_base_extrinsic_weight_is_evm_compatible() { + let min_ethereum_transaction_weight = WeightPerGas::get() * 21_000; + let base_extrinsic = ::BlockWeights::get() + .get(frame_support::dispatch::DispatchClass::Normal) + .base_extrinsic; + assert!(base_extrinsic.ref_time() <= min_ethereum_transaction_weight.ref_time()); + } + + #[test] + fn test_storage_growth_ratio_is_correct() { + let expected_storage_growth_ratio = BlockGasLimit::get() + .low_u64() + .saturating_div(BLOCK_STORAGE_LIMIT); + let actual_storage_growth_ratio = + ::GasLimitStorageGrowthRatio::get(); + assert_eq!( + expected_storage_growth_ratio, actual_storage_growth_ratio, + "Storage growth ratio is not correct" + ); + } +} diff --git a/tracing/2601/runtime/moonbase/src/precompiles.rs b/tracing/2601/runtime/moonbase/src/precompiles.rs new file mode 100644 index 00000000..48ffdb8f --- /dev/null +++ b/tracing/2601/runtime/moonbase/src/precompiles.rs @@ -0,0 +1,271 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +use crate::{ + asset_config::{ForeignAssetInstance, LocalAssetInstance}, + xcm_config::XcmExecutorConfig, + CouncilInstance, OpenTechCommitteeInstance, TechCommitteeInstance, TreasuryCouncilInstance, +}; +use frame_support::parameter_types; +use pallet_evm_precompile_author_mapping::AuthorMappingPrecompile; +use pallet_evm_precompile_balances_erc20::{Erc20BalancesPrecompile, Erc20Metadata}; +use pallet_evm_precompile_batch::BatchPrecompile; +use pallet_evm_precompile_blake2::Blake2F; +use pallet_evm_precompile_bn128::{Bn128Add, Bn128Mul, Bn128Pairing}; +use pallet_evm_precompile_call_permit::CallPermitPrecompile; +use pallet_evm_precompile_collective::CollectivePrecompile; +use pallet_evm_precompile_conviction_voting::ConvictionVotingPrecompile; +use pallet_evm_precompile_crowdloan_rewards::CrowdloanRewardsPrecompile; +use pallet_evm_precompile_democracy::DemocracyPrecompile; +use pallet_evm_precompile_gmp::GmpPrecompile; +use pallet_evm_precompile_identity::IdentityPrecompile; +use pallet_evm_precompile_modexp::Modexp; +use pallet_evm_precompile_parachain_staking::ParachainStakingPrecompile; +use pallet_evm_precompile_preimage::PreimagePrecompile; +use pallet_evm_precompile_proxy::{OnlyIsProxyAndProxy, ProxyPrecompile}; +use pallet_evm_precompile_randomness::RandomnessPrecompile; +use pallet_evm_precompile_referenda::ReferendaPrecompile; +use pallet_evm_precompile_registry::PrecompileRegistry; +use pallet_evm_precompile_relay_encoder::RelayEncoderPrecompile; +use pallet_evm_precompile_sha3fips::Sha3FIPS256; +use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; +use pallet_evm_precompile_xcm_transactor::{ + v1::XcmTransactorPrecompileV1, v2::XcmTransactorPrecompileV2, v3::XcmTransactorPrecompileV3, +}; +use pallet_evm_precompile_xcm_utils::{AllExceptXcmExecute, XcmUtilsPrecompile}; +use pallet_evm_precompile_xtokens::XtokensPrecompile; +use pallet_evm_precompileset_assets_erc20::{Erc20AssetsPrecompileSet, IsForeign, IsLocal}; +use precompile_utils::precompile_set::*; + +/// ERC20 metadata for the native token. +pub struct NativeErc20Metadata; + +impl Erc20Metadata for NativeErc20Metadata { + /// Returns the name of the token. + fn name() -> &'static str { + "DEV token" + } + + /// Returns the symbol of the token. + fn symbol() -> &'static str { + "DEV" + } + + /// Returns the decimals places of the token. + fn decimals() -> u8 { + 18 + } + + /// Must return `true` only if it represents the main native currency of + /// the network. It must be the currency used in `pallet_evm`. + fn is_native_currency() -> bool { + true + } +} + +/// The asset precompile address prefix. Addresses that match against this prefix will be routed +/// to Erc20AssetsPrecompileSet being marked as foreign +pub const FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 4]; +/// The asset precompile address prefix. Addresses that match against this prefix will be routed +/// to Erc20AssetsPrecompileSet being marked as local +pub const LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8, 255u8, 255u8, 254u8]; + +parameter_types! { + pub ForeignAssetPrefix: &'static [u8] = FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX; + pub LocalAssetPrefix: &'static [u8] = LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX; +} + +type EthereumPrecompilesChecks = (AcceptDelegateCall, CallableByContract, CallableByPrecompile); + +#[precompile_utils::precompile_name_from_address] +type MoonbasePrecompilesAt = ( + // Ethereum precompiles: + // We allow DELEGATECALL to stay compliant with Ethereum behavior. + PrecompileAt, ECRecover, EthereumPrecompilesChecks>, + PrecompileAt, Sha256, EthereumPrecompilesChecks>, + PrecompileAt, Ripemd160, EthereumPrecompilesChecks>, + PrecompileAt, Identity, EthereumPrecompilesChecks>, + PrecompileAt, Modexp, EthereumPrecompilesChecks>, + PrecompileAt, Bn128Add, EthereumPrecompilesChecks>, + PrecompileAt, Bn128Mul, EthereumPrecompilesChecks>, + PrecompileAt, Bn128Pairing, EthereumPrecompilesChecks>, + PrecompileAt, Blake2F, EthereumPrecompilesChecks>, + // Non-Moonbeam specific nor Ethereum precompiles : + PrecompileAt, Sha3FIPS256, (CallableByContract, CallableByPrecompile)>, + RemovedPrecompileAt>, // Dispatch + PrecompileAt, ECRecoverPublicKey, (CallableByContract, CallableByPrecompile)>, + // Moonbeam specific precompiles: + PrecompileAt< + AddressU64<2048>, + ParachainStakingPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2049>, + CrowdloanRewardsPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2050>, + Erc20BalancesPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2051>, + DemocracyPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2052>, + XtokensPrecompile, + ( + SubcallWithMaxNesting<1>, + CallableByContract, + CallableByPrecompile, + ), + >, + PrecompileAt< + AddressU64<2053>, + RelayEncoderPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2054>, + XcmTransactorPrecompileV1, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2055>, + AuthorMappingPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2056>, + BatchPrecompile, + ( + SubcallWithMaxNesting<2>, + // Batch is the only precompile allowed to call Batch. + CallableByPrecompile>>, + ), + >, + PrecompileAt< + AddressU64<2057>, + RandomnessPrecompile, + (SubcallWithMaxNesting<0>, CallableByContract), + >, + PrecompileAt< + AddressU64<2058>, + CallPermitPrecompile, + (SubcallWithMaxNesting<0>, CallableByContract), + >, + PrecompileAt< + AddressU64<2059>, + ProxyPrecompile, + ( + CallableByContract>, + SubcallWithMaxNesting<0>, + // Batch is the only precompile allowed to call Proxy. + CallableByPrecompile>>, + ), + >, + PrecompileAt< + AddressU64<2060>, + XcmUtilsPrecompile, + CallableByContract>, + >, + PrecompileAt< + AddressU64<2061>, + XcmTransactorPrecompileV2, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2062>, + CollectivePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2063>, + CollectivePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2064>, + CollectivePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2065>, + ReferendaPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2066>, + ConvictionVotingPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2067>, + PreimagePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2068>, + CollectivePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2069>, + PrecompileRegistry, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt, GmpPrecompile, SubcallWithMaxNesting<0>>, + PrecompileAt< + AddressU64<2071>, + XcmTransactorPrecompileV3, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2072>, + IdentityPrecompile, + (CallableByContract, CallableByPrecompile), + >, +); + +/// The PrecompileSet installed in the Moonbase runtime. +/// We include the nine Istanbul precompiles +/// (https://github.com/ethereum/go-ethereum/blob/3c46f557/core/vm/contracts.go#L69) +/// The following distribution has been decided for the precompiles +/// 0-1023: Ethereum Mainnet Precompiles +/// 1024-2047 Precompiles that are not in Ethereum Mainnet but are neither Moonbeam specific +/// 2048-4095 Moonbeam specific precompiles +pub type MoonbasePrecompiles = PrecompileSetBuilder< + R, + ( + // Skip precompiles if out of range. + PrecompilesInRangeInclusive<(AddressU64<1>, AddressU64<4095>), MoonbasePrecompilesAt>, + // Prefixed precompile sets (XC20) + PrecompileSetStartingWith< + ForeignAssetPrefix, + Erc20AssetsPrecompileSet, + (CallableByContract, CallableByPrecompile), + >, + PrecompileSetStartingWith< + LocalAssetPrefix, + Erc20AssetsPrecompileSet, + (CallableByContract, CallableByPrecompile), + >, + ), +>; diff --git a/tracing/2601/runtime/moonbase/src/xcm_config.rs b/tracing/2601/runtime/moonbase/src/xcm_config.rs new file mode 100644 index 00000000..5c0acba6 --- /dev/null +++ b/tracing/2601/runtime/moonbase/src/xcm_config.rs @@ -0,0 +1,702 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! XCM configuration for Moonbase. +//! + +use super::{ + governance, AccountId, AssetId, AssetManager, Assets, Balance, Balances, DealWithFees, + Erc20XcmBridge, LocalAssets, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, + RuntimeEvent, RuntimeOrigin, Treasury, XcmpQueue, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, +}; +use moonbeam_runtime_common::weights as moonbeam_weights; +use pallet_evm_precompileset_assets_erc20::AccountIdAssetIdConversion; +use sp_runtime::{ + traits::{Hash as THash, MaybeEquivalence, PostDispatchInfoOf}, + DispatchErrorWithPostInfo, +}; + +use frame_support::{ + parameter_types, + traits::{EitherOfDiverse, Everything, Nothing, PalletInfoAccess}, +}; + +use frame_system::{EnsureRoot, RawOrigin}; +use sp_core::{ConstU32, H160, H256}; +use sp_weights::Weight; +use xcm_builder::{ + AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, + CurrencyAdapter as XcmCurrencyAdapter, EnsureXcmOrigin, FungiblesAdapter, NoChecking, + ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountKey20AsNative, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, + WeightInfoBounds, WithComputedOrigin, +}; + +use xcm::latest::prelude::*; +use xcm_executor::traits::{CallDispatcher, ConvertLocation, JustTry}; + +use orml_xcm_support::MultiNativeAsset; +use xcm_primitives::{ + AbsoluteAndRelativeReserve, AccountIdToCurrencyId, AccountIdToMultiLocation, AsAssetType, + FirstAssetTrader, SignedToAccountId20, UtilityAvailableCalls, UtilityEncodeCall, XcmTransact, +}; + +use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; + +use sp_std::{ + convert::{From, Into, TryFrom}, + prelude::*, +}; + +use orml_traits::parameter_type_with_key; + +use crate::governance::referenda::GeneralAdminOrRoot; + +parameter_types! { + // The network Id of the relay + pub const RelayNetwork: NetworkId = NetworkId::Westend; + // The relay chain Origin type + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + // The universal location within the global consensus system + pub UniversalLocation: InteriorMultiLocation = + X2(GlobalConsensus(RelayNetwork::get()), Parachain(ParachainInfo::parachain_id().into())); + + + // Self Reserve location, defines the multilocation identifiying the self-reserve currency + // This is used to match it also against our Balances pallet when we receive such + // a MultiLocation: (Self Balances pallet index) + // We use the RELATIVE multilocation + pub SelfReserve: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; + + // This is the relative view of our local assets. + // Indentified by thix prefix + generalIndex(assetId) + // We use the RELATIVE multilocation + pub LocalAssetsPalletLocation: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; +} + +/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used +/// when determining ownership of accounts for asset transacting and when attempting to use XCM +/// `Transact` in order to determine the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the default `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // If we receive a MultiLocation of type AccountKey20, just generate a native account + AccountKey20Aliases, + // Generate remote accounts according to polkadot standards + xcm_builder::HashedDescriptionDescribeFamilyAllTerminal, +); + +/// Wrapper type around `LocationToAccountId` to convert an `AccountId` to type `H160`. +pub struct LocationToH160; +impl ConvertLocation for LocationToH160 { + fn convert_location(location: &MultiLocation) -> Option { + >::convert_location(location) + .map(Into::into) + } +} + +// The non-reserve fungible transactor type +// It will use pallet-assets, and the Id will be matched against AsAssetType +// This is intended to match FOREIGN ASSETS +pub type ForeignFungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + Assets, + // Use this currency when it is a fungible asset matching the given location or name: + ( + ConvertedConcreteId< + AssetId, + Balance, + AsAssetType, + JustTry, + >, + ), + // Do a simple punn to convert an AccountId20 MultiLocation into a native chain account ID: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont allow teleports. + NoChecking, + // We dont track any teleports + (), +>; + +/// The transactor for our own chain currency. +pub type LocalAssetTransactor = XcmCurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching any of the locations in + // SelfReserveRepresentations + xcm_builder::IsConcrete, + // We can convert the MultiLocations with our converter above: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont allow teleport + (), +>; + +/// Means for transacting local assets that are not the native currency +/// This transactor uses the new reanchor logic +pub type LocalFungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + LocalAssets, + // Use this currency when it is a fungible asset matching the given location or name: + ( + ConvertedConcreteId< + AssetId, + Balance, + // This just tells to convert an assetId into a GeneralIndex junction prepended + // by LocalAssetsPalletLocation + AsPrefixedGeneralIndex, + JustTry, + >, + ), + // Convert an XCM MultiLocation into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont want to allow teleporting assets + NoChecking, + // The account to use for tracking teleports. + (), +>; + +// We use all transactors +// These correspond to +// SelfReserve asset, both pre and post 0.9.16 +// Foreign assets +// Local assets, both pre and post 0.9.16 +// We can remove the Old reanchor once +// we import https://github.com/open-web3-stack/open-runtime-module-library/pull/708 +pub type AssetTransactors = ( + LocalAssetTransactor, + ForeignFungiblesTransactor, + LocalFungiblesTransactor, + Erc20XcmBridge, +); + +/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, +/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can +/// biases the kind of local `Origin` it will become. +pub type XcmOriginToTransactDispatchOrigin = ( + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // recognised. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognised. + SiblingParachainAsNative, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + pallet_xcm::XcmPassthrough, + // Xcm Origins defined by a Multilocation of type AccountKey20 can be converted to a 20 byte- + // account local origin + SignedAccountKey20AsNative, +); + +parameter_types! { + /// Maximum number of instructions in a single XCM fragment. A sanity check against + /// weight caculations getting too crazy. + pub MaxInstructions: u32 = 100; +} + +/// Xcm Weigher shared between multiple Xcm-related configs. +pub type XcmWeigher = WeightInfoBounds< + moonbeam_xcm_benchmarks::weights::XcmWeight, + RuntimeCall, + MaxInstructions, +>; + +pub type XcmBarrier = ( + // Weight that is paid for may be consumed. + TakeWeightCredit, + // Expected responses are OK. + AllowKnownQueryResponses, + WithComputedOrigin< + ( + // If the message is one that immediately attemps to pay for execution, then allow it. + AllowTopLevelPaidExecutionFrom, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, + ), + UniversalLocation, + ConstU32<8>, + >, +); + +parameter_types! { + /// Xcm fees will go to the treasury account + pub XcmFeesAccount: AccountId = Treasury::account_id(); +} + +/// This is the struct that will handle the revenue from xcm fees +/// We do not burn anything because we want to mimic exactly what +/// the sovereign account has +pub type XcmFeesToAccount = xcm_primitives::XcmFeesToAccount< + Assets, + ( + ConvertedConcreteId< + AssetId, + Balance, + AsAssetType, + JustTry, + >, + ), + AccountId, + XcmFeesAccount, +>; + +// Our implementation of the Moonbeam Call +// Attachs the right origin in case the call is made to pallet-ethereum-xcm +#[cfg(not(feature = "evm-tracing"))] +moonbeam_runtime_common::impl_moonbeam_xcm_call!(); +#[cfg(feature = "evm-tracing")] +moonbeam_runtime_common::impl_moonbeam_xcm_call_tracing!(); + +moonbeam_runtime_common::impl_evm_runner_precompile_or_eth_xcm!(); + +pub struct SafeCallFilter; +impl frame_support::traits::Contains for SafeCallFilter { + fn contains(_call: &RuntimeCall) -> bool { + // TODO review + // This needs to be addressed at EVM level + true + } +} + +parameter_types! { + pub const MaxAssetsIntoHolding: u32 = xcm_primitives::MAX_ASSETS; +} + +pub struct XcmExecutorConfig; +impl xcm_executor::Config for XcmExecutorConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + // How to withdraw and deposit an asset. + type AssetTransactor = AssetTransactors; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + // Filter to the reserve withdraw operations + // Whenever the reserve matches the relative or absolute value + // of our chain, we always return the relative reserve + type IsReserve = MultiNativeAsset>; + type IsTeleporter = (); // No teleport + type UniversalLocation = UniversalLocation; + type Barrier = XcmBarrier; + type Weigher = XcmWeigher; + // We use two traders + // When we receive the relative representation of the self-reserve asset, + // we use UsingComponents and the local way of handling fees + // When we receive a non-reserve asset, we use AssetManager to fetch how many + // units per second we should charge + type Trader = ( + UsingComponents< + ::WeightToFee, + SelfReserve, + AccountId, + Balances, + DealWithFees, + >, + FirstAssetTrader, + ); + type ResponseHandler = PolkadotXcm; + type SubscriptionService = PolkadotXcm; + type AssetTrap = pallet_erc20_xcm_bridge::AssetTrapWrapper; + type AssetClaims = PolkadotXcm; + type CallDispatcher = MoonbeamCall; + type PalletInstancesInfo = crate::AllPalletsWithSystem; + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type AssetLocker = (); + type AssetExchanger = (); + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; + type SafeCallFilter = SafeCallFilter; + type Aliasers = Nothing; +} + +// Converts a Signed Local Origin into a MultiLocation +pub type LocalOriginToLocation = SignedToAccountId20; + +/// The means for routing XCM messages which are not for local execution into the right message +/// queues. +pub type XcmRouter = ( + // Two routers - use UMP to communicate with the relay chain: + cumulus_primitives_utility::ParentAsUmp, + // ..and XCMP to communicate with the sibling chains. + XcmpQueue, +); + +type XcmExecutor = pallet_erc20_xcm_bridge::XcmExecutorWrapper< + RuntimeCall, + xcm_executor::XcmExecutor, +>; + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parent.into()); +} + +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 = XcmWeigher; + 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 = (); + type SovereignAccountOf = LocationToAccountId; + type MaxLockers = ConstU32<8>; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + // TODO pallet-xcm weights + type WeightInfo = moonbeam_weights::pallet_xcm::WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + type AdminOrigin = EnsureRoot; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +impl cumulus_pallet_xcmp_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; + type ChannelInfo = ParachainSystem; + type VersionWrapper = PolkadotXcm; + type ExecuteOverweightOrigin = EnsureRoot; + type ControllerOrigin = EnsureRoot; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; + type WeightInfo = moonbeam_weights::cumulus_pallet_xcmp_queue::WeightInfo; + type PriceForSiblingDelivery = (); +} + +impl cumulus_pallet_dmp_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; + type ExecuteOverweightOrigin = EnsureRoot; +} + +// Our AssetType. For now we only handle Xcm Assets +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum AssetType { + Xcm(MultiLocation), +} +impl Default for AssetType { + fn default() -> Self { + Self::Xcm(MultiLocation::here()) + } +} + +impl From for AssetType { + fn from(location: MultiLocation) -> Self { + Self::Xcm(location) + } +} + +impl Into> for AssetType { + fn into(self) -> Option { + match self { + Self::Xcm(location) => Some(location), + } + } +} + +// Implementation on how to retrieve the AssetId from an AssetType +// We take it +impl From for AssetId { + fn from(asset: AssetType) -> AssetId { + match asset { + AssetType::Xcm(id) => { + let mut result: [u8; 16] = [0u8; 16]; + let hash: H256 = id.using_encoded(::Hashing::hash); + result.copy_from_slice(&hash.as_fixed_bytes()[0..16]); + u128::from_le_bytes(result) + } + } + } +} + +// Our currencyId. We distinguish for now between SelfReserve, and Others, defined by their Id. +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum CurrencyId { + // Our native token + SelfReserve, + // Assets representing other chains native tokens + ForeignAsset(AssetId), + // Our local assets + LocalAssetReserve(AssetId), + // Erc20 token + Erc20 { contract_address: H160 }, +} + +impl AccountIdToCurrencyId for Runtime { + fn account_to_currency_id(account: AccountId) -> Option { + Some(match account { + // the self-reserve currency is identified by the pallet-balances address + a if a == H160::from_low_u64_be(2050).into() => CurrencyId::SelfReserve, + // the rest of the currencies, by their corresponding erc20 address + _ => match Runtime::account_to_asset_id(account) { + // We distinguish by prefix, and depending on it we create either + // Foreign or Local + Some((prefix, asset_id)) => { + if prefix == FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX.to_vec() { + CurrencyId::ForeignAsset(asset_id) + } else { + CurrencyId::LocalAssetReserve(asset_id) + } + } + // If no known prefix is identified, we consider that it's a "real" erc20 token + // (i.e. managed by a real smart contract) + None => CurrencyId::Erc20 { + contract_address: account.into(), + }, + }, + }) + } +} + +// How to convert from CurrencyId to MultiLocation +pub struct CurrencyIdtoMultiLocation(sp_std::marker::PhantomData); +impl sp_runtime::traits::Convert> + for CurrencyIdtoMultiLocation +where + AssetXConverter: MaybeEquivalence, +{ + fn convert(currency: CurrencyId) -> Option { + match currency { + CurrencyId::SelfReserve => { + let multi: MultiLocation = SelfReserve::get(); + Some(multi) + } + CurrencyId::ForeignAsset(asset) => AssetXConverter::convert_back(&asset), + CurrencyId::LocalAssetReserve(asset) => { + let mut location = LocalAssetsPalletLocation::get(); + location.push_interior(Junction::GeneralIndex(asset)).ok(); + Some(location) + } + CurrencyId::Erc20 { contract_address } => { + let mut location = Erc20XcmBridgePalletLocation::get(); + location + .push_interior(Junction::AccountKey20 { + key: contract_address.0, + network: None, + }) + .ok(); + Some(location) + } + } + } +} + +parameter_types! { + pub const BaseXcmWeight: Weight + = Weight::from_parts(200_000_000u64, 0); + pub const MaxAssetsForTransfer: usize = 2; + // This is how we are going to detect whether the asset is a Reserve asset + // This however is the chain part only + pub SelfLocation: MultiLocation = MultiLocation::here(); + // We need this to be able to catch when someone is trying to execute a non- + // cross-chain transfer in xtokens through the absolute path way + pub SelfLocationAbsolute: MultiLocation = MultiLocation { + parents:1, + interior: Junctions::X1( + Parachain(ParachainInfo::parachain_id().into()) + ) + }; + +} + +parameter_type_with_key! { + pub ParachainMinFee: |location: MultiLocation| -> Option { + match (location.parents, location.first_interior()) { + // AssetHub fee + (1, Some(Parachain(1001u32))) => Some(50_000_000u128), + _ => None, + } + }; +} + +impl orml_xtokens::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type CurrencyId = CurrencyId; + type AccountIdToMultiLocation = AccountIdToMultiLocation; + type CurrencyIdConvert = + CurrencyIdtoMultiLocation>; + type XcmExecutor = XcmExecutor; + type SelfLocation = SelfLocation; + type Weigher = XcmWeigher; + type BaseXcmWeight = BaseXcmWeight; + type UniversalLocation = UniversalLocation; + type MaxAssetsForTransfer = MaxAssetsForTransfer; + type MinXcmFee = ParachainMinFee; + type MultiLocationsFilter = Everything; + type ReserveProvider = AbsoluteAndRelativeReserve; +} + +// 1 WND/ROC should be enough +parameter_types! { + pub MaxHrmpRelayFee: MultiAsset = (MultiLocation::parent(), 1_000_000_000_000u128).into(); +} + +// For now we only allow to transact in the relay, although this might change in the future +// Transactors just defines the chains in which we allow transactions to be issued through +// xcm +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum Transactors { + Relay, +} + +// Default for benchmarking +#[cfg(feature = "runtime-benchmarks")] +impl Default for Transactors { + fn default() -> Self { + Transactors::Relay + } +} + +impl TryFrom for Transactors { + type Error = (); + fn try_from(value: u8) -> Result { + match value { + 0u8 => Ok(Transactors::Relay), + _ => Err(()), + } + } +} + +impl UtilityEncodeCall for Transactors { + fn encode_call(self, call: UtilityAvailableCalls) -> Vec { + match self { + Transactors::Relay => pallet_xcm_transactor::Pallet::::encode_call( + pallet_xcm_transactor::Pallet(sp_std::marker::PhantomData::), + call, + ), + } + } +} + +impl XcmTransact for Transactors { + fn destination(self) -> MultiLocation { + match self { + Transactors::Relay => MultiLocation::parent(), + } + } +} + +pub type DerivativeAddressRegistrationOrigin = + EitherOfDiverse, governance::custom_origins::GeneralAdmin>; + +impl pallet_xcm_transactor::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type Transactor = Transactors; + type DerivativeAddressRegistrationOrigin = DerivativeAddressRegistrationOrigin; + type SovereignAccountDispatcherOrigin = EnsureRoot; + type CurrencyId = CurrencyId; + type AccountIdToMultiLocation = AccountIdToMultiLocation; + type CurrencyIdToMultiLocation = + CurrencyIdtoMultiLocation>; + type XcmSender = XcmRouter; + type SelfLocation = SelfLocation; + type Weigher = XcmWeigher; + type UniversalLocation = UniversalLocation; + type BaseXcmWeight = BaseXcmWeight; + type AssetTransactor = AssetTransactors; + type ReserveProvider = AbsoluteAndRelativeReserve; + type WeightInfo = moonbeam_weights::pallet_xcm_transactor::WeightInfo; + type HrmpManipulatorOrigin = GeneralAdminOrRoot; + type MaxHrmpFee = xcm_builder::Case; +} + +parameter_types! { + // This is the relative view of erc20 assets. + // Identified by this prefix + AccountKey20(contractAddress) + // We use the RELATIVE multilocation + pub Erc20XcmBridgePalletLocation: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; + + // To be able to support almost all erc20 implementations, + // we provide a sufficiently hight gas limit. + pub Erc20XcmBridgeTransferGasLimit: u64 = 200_000; +} + +impl pallet_erc20_xcm_bridge::Config for Runtime { + type AccountIdConverter = LocationToH160; + type Erc20MultilocationPrefix = Erc20XcmBridgePalletLocation; + type Erc20TransferGasLimit = Erc20XcmBridgeTransferGasLimit; + type EvmRunner = EvmRunnerPrecompileOrEthXcm; +} + +#[cfg(feature = "runtime-benchmarks")] +mod testing { + use super::*; + use xcm_executor::traits::ConvertLocation; + + /// This From exists for benchmarking purposes. It has the potential side-effect of calling + /// AssetManager::set_asset_type_asset_id() and should NOT be used in any production code. + impl From for CurrencyId { + fn from(location: MultiLocation) -> CurrencyId { + use xcm_primitives::AssetTypeGetter; + + // If it does not exist, for benchmarking purposes, we create the association + let asset_id = if let Some(asset_id) = + AsAssetType::::convert_location(&location) + { + asset_id + } else { + let asset_type = AssetType::Xcm(location); + let asset_id: AssetId = asset_type.clone().into(); + AssetManager::set_asset_type_asset_id(asset_type, asset_id); + asset_id + }; + + CurrencyId::ForeignAsset(asset_id) + } + } +} diff --git a/tracing/2601/runtime/moonbase/tests/common/mod.rs b/tracing/2601/runtime/moonbase/tests/common/mod.rs new file mode 100644 index 00000000..3168dcc5 --- /dev/null +++ b/tracing/2601/runtime/moonbase/tests/common/mod.rs @@ -0,0 +1,384 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +#![allow(dead_code)] + +use cumulus_primitives_parachain_inherent::ParachainInherentData; +use fp_evm::GenesisAccount; +use frame_support::{ + assert_ok, + traits::{OnFinalize, OnInitialize}, +}; +use moonbase_runtime::{asset_config::AssetRegistrarMetadata, xcm_config::AssetType}; +pub use moonbase_runtime::{ + currency::{GIGAWEI, SUPPLY_FACTOR, UNIT, WEI}, + AccountId, AssetId, AssetManager, Assets, AuthorInherent, Balance, Balances, CrowdloanRewards, + Ethereum, Executive, Header, InflationInfo, LocalAssets, ParachainStaking, Range, Runtime, + RuntimeCall, RuntimeEvent, System, TransactionConverter, TransactionPaymentAsGasPrice, + UncheckedExtrinsic, HOURS, WEEKS, +}; +use nimbus_primitives::{NimbusId, NIMBUS_ENGINE_ID}; +use sp_core::{Encode, H160}; +use sp_runtime::{traits::Dispatchable, BuildStorage, Digest, DigestItem, Perbill, Percent}; + +use std::collections::BTreeMap; + +use fp_rpc::ConvertTransaction; +use pallet_transaction_payment::Multiplier; + +// A valid signed Alice transfer. +pub const VALID_ETH_TX: &str = + "02f86d8205018085174876e80085e8d4a5100082520894f24ff3a9cf04c71dbc94d0b566f7a27b9456\ + 6cac8080c001a0e1094e1a52520a75c0255db96132076dd0f1263089f838bea548cbdbfc64a4d19f031c\ + 92a8cb04e2d68d20a6158d542a07ac440cc8d07b6e36af02db046d92df"; + +// An invalid signed Alice transfer with a gas limit artifically set to 0. +pub const INVALID_ETH_TX: &str = + "f86180843b9aca00809412cb274aad8251c875c0bf6872b67d9983e53fdd01801ca00e28ba2dd3c5a\ + 3fd467d4afd7aefb4a34b373314fff470bb9db743a84d674a0aa06e5994f2d07eafe1c37b4ce5471ca\ + ecec29011f6f5bf0b1a552c55ea348df35f"; + +pub fn rpc_run_to_block(n: u32) { + while System::block_number() < n { + Ethereum::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + Ethereum::on_initialize(System::block_number()); + } +} + +/// Utility function that advances the chain to the desired block number. +/// If an author is provided, that author information is injected to all the blocks in the meantime. +pub fn run_to_block(n: u32, author: Option) { + // Finalize the first block + Ethereum::on_finalize(System::block_number()); + AuthorInherent::on_finalize(System::block_number()); + while System::block_number() < n { + // Set the new block number and author + match author { + Some(ref author) => { + let pre_digest = Digest { + logs: vec![DigestItem::PreRuntime(NIMBUS_ENGINE_ID, author.encode())], + }; + System::reset_events(); + System::initialize( + &(System::block_number() + 1), + &System::parent_hash(), + &pre_digest, + ); + } + None => { + System::set_block_number(System::block_number() + 1); + } + } + + // Initialize the new block + AuthorInherent::on_initialize(System::block_number()); + ParachainStaking::on_initialize(System::block_number()); + Ethereum::on_initialize(System::block_number()); + + // Finalize the block + Ethereum::on_finalize(System::block_number()); + AuthorInherent::on_finalize(System::block_number()); + ParachainStaking::on_finalize(System::block_number()); + } +} + +pub fn last_event() -> RuntimeEvent { + System::events().pop().expect("Event expected").event +} + +// Test struct with the purpose of initializing xcm assets +#[derive(Clone)] +pub struct XcmAssetInitialization { + pub asset_type: AssetType, + pub metadata: AssetRegistrarMetadata, + pub balances: Vec<(AccountId, Balance)>, + pub is_sufficient: bool, +} + +pub struct ExtBuilder { + // endowed accounts with balances + balances: Vec<(AccountId, Balance)>, + // [asset, Vec, owner] + local_assets: Vec<(AssetId, Vec<(AccountId, Balance)>, AccountId)>, + // [collator, amount] + collators: Vec<(AccountId, Balance)>, + // [delegator, collator, nomination_amount] + delegations: Vec<(AccountId, AccountId, Balance, Percent)>, + // per-round inflation config + inflation: InflationInfo, + // AuthorId -> AccoutId mappings + mappings: Vec<(NimbusId, AccountId)>, + // Crowdloan fund + crowdloan_fund: Balance, + // Chain id + chain_id: u64, + // EVM genesis accounts + evm_accounts: BTreeMap, + // [assettype, metadata, Vec] + xcm_assets: Vec, + safe_xcm_version: Option, +} + +impl Default for ExtBuilder { + fn default() -> ExtBuilder { + ExtBuilder { + balances: vec![], + delegations: vec![], + local_assets: vec![], + collators: vec![], + inflation: InflationInfo { + expect: Range { + min: 100_000 * UNIT, + ideal: 200_000 * UNIT, + max: 500_000 * UNIT, + }, + // not used + annual: Range { + min: Perbill::from_percent(50), + ideal: Perbill::from_percent(50), + max: Perbill::from_percent(50), + }, + // unrealistically high parameterization, only for testing + round: Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }, + }, + mappings: vec![], + crowdloan_fund: 0, + chain_id: CHAIN_ID, + evm_accounts: BTreeMap::new(), + xcm_assets: vec![], + safe_xcm_version: None, + } + } +} + +impl ExtBuilder { + pub fn with_evm_accounts(mut self, accounts: BTreeMap) -> Self { + self.evm_accounts = accounts; + self + } + + pub fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { + self.balances = balances; + self + } + + pub fn with_collators(mut self, collators: Vec<(AccountId, Balance)>) -> Self { + self.collators = collators; + self + } + + pub fn with_delegations(mut self, delegations: Vec<(AccountId, AccountId, Balance)>) -> Self { + self.delegations = delegations + .into_iter() + .map(|d| (d.0, d.1, d.2, Percent::zero())) + .collect(); + self + } + + pub fn with_xcm_assets(mut self, xcm_assets: Vec) -> Self { + self.xcm_assets = xcm_assets; + self + } + + pub fn with_crowdloan_fund(mut self, crowdloan_fund: Balance) -> Self { + self.crowdloan_fund = crowdloan_fund; + self + } + + pub fn with_mappings(mut self, mappings: Vec<(NimbusId, AccountId)>) -> Self { + self.mappings = mappings; + self + } + + pub fn with_safe_xcm_version(mut self, safe_xcm_version: u32) -> Self { + self.safe_xcm_version = Some(safe_xcm_version); + self + } + + #[allow(dead_code)] + pub fn with_inflation(mut self, inflation: InflationInfo) -> Self { + self.inflation = inflation; + self + } + + pub fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap(); + + pallet_balances::GenesisConfig:: { + balances: self.balances, + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_parachain_staking::GenesisConfig:: { + candidates: self.collators, + delegations: self.delegations, + inflation_config: self.inflation, + collator_commission: Perbill::from_percent(20), + parachain_bond_reserve_percent: Percent::from_percent(30), + blocks_per_round: 2 * HOURS, + num_selected_candidates: 8, + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_crowdloan_rewards::GenesisConfig:: { + funded_amount: self.crowdloan_fund, + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_author_mapping::GenesisConfig:: { + mappings: self.mappings, + } + .assimilate_storage(&mut t) + .unwrap(); + + let genesis_config = pallet_evm_chain_id::GenesisConfig:: { + chain_id: self.chain_id, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let genesis_config = pallet_evm::GenesisConfig:: { + accounts: self.evm_accounts, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let genesis_config = pallet_ethereum::GenesisConfig:: { + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let genesis_config = pallet_xcm::GenesisConfig:: { + safe_xcm_version: self.safe_xcm_version, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let genesis_config = pallet_transaction_payment::GenesisConfig:: { + multiplier: Multiplier::from(8u128), + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + + let local_assets = self.local_assets.clone(); + let xcm_assets = self.xcm_assets.clone(); + + ext.execute_with(|| { + // If any local assets specified, we create them here + for (asset_id, balances, owner) in local_assets.clone() { + LocalAssets::force_create(root_origin(), asset_id.into(), owner, true, 1).unwrap(); + for (account, balance) in balances { + LocalAssets::mint(origin_of(owner.into()), asset_id.into(), account, balance) + .unwrap(); + } + } + // If any xcm assets specified, we register them here + for xcm_asset_initialization in xcm_assets { + let asset_id: AssetId = xcm_asset_initialization.asset_type.clone().into(); + AssetManager::register_foreign_asset( + root_origin(), + xcm_asset_initialization.asset_type, + xcm_asset_initialization.metadata, + 1, + xcm_asset_initialization.is_sufficient, + ) + .unwrap(); + for (account, balance) in xcm_asset_initialization.balances { + Assets::mint( + origin_of(AssetManager::account_id()), + asset_id.into(), + account, + balance, + ) + .unwrap(); + } + } + System::set_block_number(1); + }); + ext + } +} + +pub const CHAIN_ID: u64 = 1281; +pub const ALICE: [u8; 20] = [4u8; 20]; +pub const ALICE_NIMBUS: [u8; 32] = [4u8; 32]; +pub const BOB: [u8; 20] = [5u8; 20]; +pub const CHARLIE: [u8; 20] = [6u8; 20]; +pub const DAVE: [u8; 20] = [7u8; 20]; +pub const EVM_CONTRACT: [u8; 20] = [8u8; 20]; + +pub fn origin_of(account_id: AccountId) -> ::RuntimeOrigin { + ::RuntimeOrigin::signed(account_id) +} + +pub fn inherent_origin() -> ::RuntimeOrigin { + ::RuntimeOrigin::none() +} + +pub fn root_origin() -> ::RuntimeOrigin { + ::RuntimeOrigin::root() +} + +/// Mock the inherent that sets validation data in ParachainSystem, which +/// contains the `relay_chain_block_number`, which is used in `author-filter` as a +/// source of randomness to filter valid authors at each block. +pub fn set_parachain_inherent_data() { + use cumulus_primitives_core::PersistedValidationData; + use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; + let (relay_parent_storage_root, relay_chain_state) = + RelayStateSproofBuilder::default().into_state_root_and_proof(); + let vfp = PersistedValidationData { + relay_parent_number: 1u32, + relay_parent_storage_root, + ..Default::default() + }; + let parachain_inherent_data = ParachainInherentData { + validation_data: vfp, + relay_chain_state: relay_chain_state, + downward_messages: Default::default(), + horizontal_messages: Default::default(), + }; + assert_ok!(RuntimeCall::ParachainSystem( + cumulus_pallet_parachain_system::Call::::set_validation_data { + data: parachain_inherent_data + } + ) + .dispatch(inherent_origin())); +} + +pub fn unchecked_eth_tx(raw_hex_tx: &str) -> UncheckedExtrinsic { + let converter = TransactionConverter; + converter.convert_transaction(ethereum_transaction(raw_hex_tx)) +} + +pub fn ethereum_transaction(raw_hex_tx: &str) -> pallet_ethereum::Transaction { + let bytes = hex::decode(raw_hex_tx).expect("Transaction bytes."); + let transaction = ethereum::EnvelopedDecodable::decode(&bytes[..]); + assert!(transaction.is_ok()); + transaction.unwrap() +} diff --git a/tracing/2601/runtime/moonbase/tests/evm_tracing.rs b/tracing/2601/runtime/moonbase/tests/evm_tracing.rs new file mode 100644 index 00000000..b0f967d5 --- /dev/null +++ b/tracing/2601/runtime/moonbase/tests/evm_tracing.rs @@ -0,0 +1,94 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Moonbase EVM tracing Integration Tests + +mod common; + +#[cfg(test)] +#[cfg(feature = "evm-tracing")] +mod tests { + use super::common::*; + + use pallet_evm::AddressMapping; + use sp_core::H160; + + use moonbeam_rpc_primitives_debug::runtime_decl_for_debug_runtime_api::DebugRuntimeApi; + use std::str::FromStr; + + #[test] + fn debug_runtime_api_trace_transaction() { + let alith = ::AddressMapping::into_account_id( + H160::from_str("6be02d1d3665660d22ff9624b7be0551ee1ac91b") + .expect("internal H160 is valid; qed"), + ); + ExtBuilder::default() + .with_balances(vec![ + (alith, 2_000 * UNIT), + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .build() + .execute_with(|| { + let non_eth_uxt = UncheckedExtrinsic::new_unsigned( + pallet_balances::Call::::transfer { + dest: AccountId::from(BOB), + value: 1 * UNIT, + } + .into(), + ); + let transaction = ethereum_transaction(VALID_ETH_TX); + let eth_uxt = unchecked_eth_tx(VALID_ETH_TX); + assert!(Runtime::trace_transaction( + vec![non_eth_uxt.clone(), eth_uxt, non_eth_uxt.clone()], + &transaction + ) + .is_ok()); + }); + } + + #[test] + fn debug_runtime_api_trace_block() { + let alith = ::AddressMapping::into_account_id( + H160::from_str("6be02d1d3665660d22ff9624b7be0551ee1ac91b") + .expect("internal H160 is valid; qed"), + ); + ExtBuilder::default() + .with_balances(vec![ + (alith, 2_000 * UNIT), + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .build() + .execute_with(|| { + let non_eth_uxt = UncheckedExtrinsic::new_unsigned( + pallet_balances::Call::::transfer { + dest: AccountId::from(BOB), + value: 1 * UNIT, + } + .into(), + ); + let eth_uxt = unchecked_eth_tx(VALID_ETH_TX); + let eth_tx = ethereum_transaction(VALID_ETH_TX); + let eth_extrinsic_hash = eth_tx.hash(); + assert!(Runtime::trace_block( + vec![non_eth_uxt.clone(), eth_uxt.clone(), non_eth_uxt, eth_uxt], + vec![eth_extrinsic_hash, eth_extrinsic_hash] + ) + .is_ok()); + }); + } +} diff --git a/tracing/2601/runtime/moonbase/tests/integration_test.rs b/tracing/2601/runtime/moonbase/tests/integration_test.rs new file mode 100644 index 00000000..84d4c035 --- /dev/null +++ b/tracing/2601/runtime/moonbase/tests/integration_test.rs @@ -0,0 +1,3086 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Moonbase Runtime Integration Tests + +mod common; +use common::*; + +use pallet_balances::NegativeImbalance; +use precompile_utils::{ + precompile_set::{is_precompile_or_fail, IsActivePrecompile}, + prelude::*, + testing::*, +}; + +use fp_evm::{Context, IsPrecompileResult}; +use frame_support::{ + assert_noop, assert_ok, + dispatch::DispatchClass, + traits::{ + fungible::Inspect, Currency as CurrencyT, EnsureOrigin, PalletInfo, StorageInfo, + StorageInfoTrait, + }, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, + StorageHasher, Twox128, +}; +use moonbase_runtime::{ + asset_config::AssetRegistrarMetadata, + asset_config::LocalAssetInstance, + get, + xcm_config::{AssetType, SelfReserve}, + AccountId, AssetId, AssetManager, Assets, Balances, CouncilCollective, CrowdloanRewards, + OpenTechCommitteeCollective, ParachainStaking, PolkadotXcm, Precompiles, Runtime, + RuntimeBlockWeights, RuntimeCall, RuntimeEvent, System, TechCommitteeCollective, + TransactionPayment, TreasuryCouncilCollective, XTokens, XcmTransactor, + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, +}; +use polkadot_parachain::primitives::Sibling; +use precompile_utils::testing::MockHandle; +use sp_runtime::{ + traits::{Convert as XcmConvert, Dispatchable}, + BuildStorage, +}; +use std::str::from_utf8; +use xcm_builder::{ParentIsPreset, SiblingParachainConvertsVia}; +use xcm_executor::traits::ConvertLocation; + +use moonbeam_xcm_benchmarks::weights::XcmWeight; +use nimbus_primitives::NimbusId; +use pallet_evm::PrecompileSet; +use pallet_evm_precompileset_assets_erc20::{ + AccountIdAssetIdConversion, IsLocal, SELECTOR_LOG_APPROVAL, SELECTOR_LOG_TRANSFER, +}; +use pallet_transaction_payment::Multiplier; +use pallet_xcm_transactor::{Currency, CurrencyPayment, HrmpOperation, TransactWeights}; +use parity_scale_codec::Encode; +use sha3::{Digest, Keccak256}; +use sp_core::{crypto::UncheckedFrom, ByteArray, Pair, H160, H256, U256}; +use sp_runtime::{DispatchError, ModuleError}; +use xcm::latest::prelude::*; + +type AuthorMappingPCall = + pallet_evm_precompile_author_mapping::AuthorMappingPrecompileCall; +type BatchPCall = pallet_evm_precompile_batch::BatchPrecompileCall; +type CrowdloanRewardsPCall = + pallet_evm_precompile_crowdloan_rewards::CrowdloanRewardsPrecompileCall; +type XcmUtilsPCall = pallet_evm_precompile_xcm_utils::XcmUtilsPrecompileCall< + Runtime, + moonbase_runtime::xcm_config::XcmExecutorConfig, +>; +type XtokensPCall = pallet_evm_precompile_xtokens::XtokensPrecompileCall; +type LocalAssetsPCall = pallet_evm_precompileset_assets_erc20::Erc20AssetsPrecompileSetCall< + Runtime, + IsLocal, + LocalAssetInstance, +>; +type XcmTransactorV1PCall = + pallet_evm_precompile_xcm_transactor::v1::XcmTransactorPrecompileV1Call; +type XcmTransactorV2PCall = + pallet_evm_precompile_xcm_transactor::v2::XcmTransactorPrecompileV2Call; + +// TODO: can we construct a const U256...? +const BASE_FEE_GENISIS: u128 = 10 * GIGAWEI; + +#[test] +fn xcmp_queue_controller_origin_is_root() { + // important for the XcmExecutionManager impl of PauseExecution which uses root origin + // to suspend/resume XCM execution in xcmp_queue::on_idle + assert_ok!( + ::ControllerOrigin::ensure_origin(root_origin()) + ); +} + +#[test] +fn fast_track_available() { + assert!(get!(pallet_democracy, InstantAllowed, bool)); +} + +#[test] +fn verify_pallet_prefixes() { + fn is_pallet_prefix(name: &str) { + // Compares the unhashed pallet prefix in the `StorageInstance` implementation by every + // storage item in the pallet P. This pallet prefix is used in conjunction with the + // item name to get the unique storage key: hash(PalletPrefix) + hash(StorageName) + // https://github.com/paritytech/substrate/blob/master/frame/support/procedural/src/pallet/ + // expand/storage.rs#L389-L401 + assert_eq!( + ::PalletInfo::name::

(), + Some(name) + ); + } + // TODO: use StorageInfoTrait from https://github.com/paritytech/substrate/pull/9246 + // This is now available with polkadot-v0.9.9 dependencies + is_pallet_prefix::("System"); + is_pallet_prefix::("Utility"); + is_pallet_prefix::("ParachainSystem"); + is_pallet_prefix::("TransactionPayment"); + is_pallet_prefix::("ParachainInfo"); + is_pallet_prefix::("EthereumChainId"); + is_pallet_prefix::("EVM"); + is_pallet_prefix::("Ethereum"); + is_pallet_prefix::("ParachainStaking"); + is_pallet_prefix::("Scheduler"); + is_pallet_prefix::("Democracy"); + is_pallet_prefix::("CouncilCollective"); + is_pallet_prefix::("TechCommitteeCollective"); + is_pallet_prefix::("Treasury"); + is_pallet_prefix::( + "OpenTechCommitteeCollective", + ); + is_pallet_prefix::("AuthorInherent"); + is_pallet_prefix::("AuthorFilter"); + is_pallet_prefix::("CrowdloanRewards"); + is_pallet_prefix::("AuthorMapping"); + is_pallet_prefix::("MaintenanceMode"); + is_pallet_prefix::("Identity"); + is_pallet_prefix::("XcmpQueue"); + is_pallet_prefix::("CumulusXcm"); + is_pallet_prefix::("DmpQueue"); + is_pallet_prefix::("PolkadotXcm"); + is_pallet_prefix::("Assets"); + is_pallet_prefix::("XTokens"); + is_pallet_prefix::("AssetManager"); + is_pallet_prefix::("Migrations"); + is_pallet_prefix::("XcmTransactor"); + is_pallet_prefix::("ProxyGenesisCompanion"); + is_pallet_prefix::("LocalAssets"); + is_pallet_prefix::("MoonbeamOrbiters"); + is_pallet_prefix::("EthereumXcm"); + is_pallet_prefix::("Randomness"); + is_pallet_prefix::("TreasuryCouncilCollective"); + + let prefix = |pallet_name, storage_name| { + let mut res = [0u8; 32]; + res[0..16].copy_from_slice(&Twox128::hash(pallet_name)); + res[16..32].copy_from_slice(&Twox128::hash(storage_name)); + res.to_vec() + }; + assert_eq!( + ::storage_info(), + vec![ + StorageInfo { + pallet_name: b"Timestamp".to_vec(), + storage_name: b"Now".to_vec(), + prefix: prefix(b"Timestamp", b"Now"), + max_values: Some(1), + max_size: Some(8), + }, + StorageInfo { + pallet_name: b"Timestamp".to_vec(), + storage_name: b"DidUpdate".to_vec(), + prefix: prefix(b"Timestamp", b"DidUpdate"), + max_values: Some(1), + max_size: Some(1), + } + ] + ); + assert_eq!( + ::storage_info(), + vec![ + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"TotalIssuance".to_vec(), + prefix: prefix(b"Balances", b"TotalIssuance"), + max_values: Some(1), + max_size: Some(16), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"InactiveIssuance".to_vec(), + prefix: prefix(b"Balances", b"InactiveIssuance"), + max_values: Some(1), + max_size: Some(16), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Account".to_vec(), + prefix: prefix(b"Balances", b"Account"), + max_values: None, + max_size: Some(100), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Locks".to_vec(), + prefix: prefix(b"Balances", b"Locks"), + max_values: None, + max_size: Some(1287), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Reserves".to_vec(), + prefix: prefix(b"Balances", b"Reserves"), + max_values: None, + max_size: Some(1037), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Holds".to_vec(), + prefix: prefix(b"Balances", b"Holds"), + max_values: None, + max_size: Some(37), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Freezes".to_vec(), + prefix: prefix(b"Balances", b"Freezes"), + max_values: None, + max_size: Some(37), + }, + ] + ); + assert_eq!( + ::storage_info(), + vec![StorageInfo { + pallet_name: b"Sudo".to_vec(), + storage_name: b"Key".to_vec(), + prefix: prefix(b"Sudo", b"Key"), + max_values: Some(1), + max_size: Some(20), + }] + ); + assert_eq!( + ::storage_info(), + vec![ + StorageInfo { + pallet_name: b"Proxy".to_vec(), + storage_name: b"Proxies".to_vec(), + prefix: prefix(b"Proxy", b"Proxies"), + max_values: None, + max_size: Some(845), + }, + StorageInfo { + pallet_name: b"Proxy".to_vec(), + storage_name: b"Announcements".to_vec(), + prefix: prefix(b"Proxy", b"Announcements"), + max_values: None, + max_size: Some(1837), + } + ] + ); + assert_eq!( + ::storage_info(), + vec![StorageInfo { + pallet_name: b"MaintenanceMode".to_vec(), + storage_name: b"MaintenanceMode".to_vec(), + prefix: prefix(b"MaintenanceMode", b"MaintenanceMode"), + max_values: Some(1), + max_size: None, + },] + ); +} + +#[test] +fn test_collectives_storage_item_prefixes() { + for StorageInfo { pallet_name, .. } in + ::storage_info() + { + assert_eq!(pallet_name, b"CouncilCollective".to_vec()); + } + + for StorageInfo { pallet_name, .. } in + ::storage_info() + { + assert_eq!(pallet_name, b"TechCommitteeCollective".to_vec()); + } + + for StorageInfo { pallet_name, .. } in + ::storage_info() + { + assert_eq!(pallet_name, b"TreasuryCouncilCollective".to_vec()); + } + + for StorageInfo { pallet_name, .. } in + ::storage_info() + { + assert_eq!(pallet_name, b"OpenTechCommitteeCollective".to_vec()); + } +} + +#[test] +fn collective_set_members_root_origin_works() { + ExtBuilder::default().build().execute_with(|| { + // CouncilCollective + assert_ok!(CouncilCollective::set_members( + ::RuntimeOrigin::root(), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + )); + // TechCommitteeCollective + assert_ok!(TechCommitteeCollective::set_members( + ::RuntimeOrigin::root(), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + )); + // TreasuryCouncilCollective + assert_ok!(TreasuryCouncilCollective::set_members( + ::RuntimeOrigin::root(), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + )); + // OpenTechCommitteeCollective + assert_ok!(OpenTechCommitteeCollective::set_members( + ::RuntimeOrigin::root(), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + )); + }); +} + +#[test] +fn collective_set_members_general_admin_origin_works() { + use moonbase_runtime::{ + governance::custom_origins::Origin as CustomOrigin, OriginCaller, Utility, + }; + + ExtBuilder::default().build().execute_with(|| { + let root_caller = ::RuntimeOrigin::root(); + let alice = AccountId::from(ALICE); + + // CouncilCollective + let _ = Utility::dispatch_as( + root_caller.clone(), + Box::new(OriginCaller::Origins(CustomOrigin::GeneralAdmin)), + Box::new( + pallet_collective::Call::::set_members { + new_members: vec![alice, AccountId::from(BOB)], + prime: Some(alice), + old_count: 2, + } + .into(), + ), + ); + // TechCommitteeCollective + let _ = Utility::dispatch_as( + root_caller.clone(), + Box::new(OriginCaller::Origins(CustomOrigin::GeneralAdmin)), + Box::new( + pallet_collective::Call::::set_members { + new_members: vec![alice, AccountId::from(BOB)], + prime: Some(alice), + old_count: 2, + } + .into(), + ), + ); + // TreasuryCouncilCollective + let _ = Utility::dispatch_as( + root_caller.clone(), + Box::new(OriginCaller::Origins(CustomOrigin::GeneralAdmin)), + Box::new( + pallet_collective::Call::::set_members { + new_members: vec![alice, AccountId::from(BOB)], + prime: Some(alice), + old_count: 2, + } + .into(), + ), + ); + // OpenTechCommitteeCollective + let _ = Utility::dispatch_as( + root_caller, + Box::new(OriginCaller::Origins(CustomOrigin::GeneralAdmin)), + Box::new( + pallet_collective::Call::::set_members { + new_members: vec![alice, AccountId::from(BOB)], + prime: Some(alice), + old_count: 2, + } + .into(), + ), + ); + + assert_eq!( + System::events() + .into_iter() + .filter_map(|r| { + match r.event { + RuntimeEvent::Utility(pallet_utility::Event::DispatchedAs { result }) + if result.is_ok() => + { + Some(true) + } + _ => None, + } + }) + .collect::>() + .len(), + 4 + ) + }); +} + +#[test] +fn collective_set_members_signed_origin_does_not_work() { + let alice = AccountId::from(ALICE); + ExtBuilder::default().build().execute_with(|| { + // CouncilCollective + assert!(CouncilCollective::set_members( + ::RuntimeOrigin::signed(alice), + vec![alice, AccountId::from(BOB)], + Some(alice), + 2 + ) + .is_err()); + // TechCommitteeCollective + assert!(TechCommitteeCollective::set_members( + ::RuntimeOrigin::signed(alice), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + ) + .is_err()); + // TreasuryCouncilCollective + assert!(TreasuryCouncilCollective::set_members( + ::RuntimeOrigin::signed(alice), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + ) + .is_err()); + // OpenTechCommitteeCollective + assert!(OpenTechCommitteeCollective::set_members( + ::RuntimeOrigin::signed(alice), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + ) + .is_err()); + }); +} + +#[test] +fn verify_pallet_indices() { + fn is_pallet_index(index: usize) { + assert_eq!( + ::PalletInfo::index::

(), + Some(index) + ); + } + is_pallet_index::(0); + is_pallet_index::(1); + is_pallet_index::(2); + is_pallet_index::(3); + is_pallet_index::(4); + is_pallet_index::(6); + is_pallet_index::(7); + is_pallet_index::(8); + is_pallet_index::(9); + is_pallet_index::(10); + is_pallet_index::(11); + is_pallet_index::(12); + is_pallet_index::(13); + is_pallet_index::(14); + is_pallet_index::(15); + is_pallet_index::(16); + is_pallet_index::(17); + is_pallet_index::(18); + is_pallet_index::(19); + is_pallet_index::(20); + is_pallet_index::(21); + is_pallet_index::(22); + is_pallet_index::(23); + is_pallet_index::(24); + is_pallet_index::(25); + is_pallet_index::(26); + is_pallet_index::(27); + is_pallet_index::(28); + is_pallet_index::(29); + is_pallet_index::(30); + is_pallet_index::(31); + is_pallet_index::(32); + is_pallet_index::(33); + is_pallet_index::(34); + is_pallet_index::(36); + is_pallet_index::(37); + is_pallet_index::(38); + is_pallet_index::(39); + is_pallet_index::(40); + is_pallet_index::(46); +} + +#[test] +fn verify_reserved_indices() { + use frame_metadata::*; + let metadata = moonbase_runtime::Runtime::metadata(); + let metadata = match metadata.1 { + RuntimeMetadata::V14(metadata) => metadata, + _ => panic!("metadata has been bumped, test needs to be updated"), + }; + // 35: BaseFee + let reserved = vec![35]; + let existing = metadata + .pallets + .iter() + .map(|p| p.index) + .collect::>(); + assert!(reserved.iter().all(|index| !existing.contains(index))); +} + +#[test] +fn verify_proxy_type_indices() { + assert_eq!(moonbase_runtime::ProxyType::Any as u8, 0); + assert_eq!(moonbase_runtime::ProxyType::NonTransfer as u8, 1); + assert_eq!(moonbase_runtime::ProxyType::Governance as u8, 2); + assert_eq!(moonbase_runtime::ProxyType::Staking as u8, 3); + assert_eq!(moonbase_runtime::ProxyType::CancelProxy as u8, 4); + assert_eq!(moonbase_runtime::ProxyType::Balances as u8, 5); + assert_eq!(moonbase_runtime::ProxyType::AuthorMapping as u8, 6); + assert_eq!(moonbase_runtime::ProxyType::IdentityJudgement as u8, 7); +} + +#[test] +fn join_collator_candidates() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 2_000 * UNIT), + (AccountId::from(CHARLIE), 1_100 * UNIT), + (AccountId::from(DAVE), 1_000 * UNIT), + ]) + .with_collators(vec![ + (AccountId::from(ALICE), 1_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_delegations(vec![ + (AccountId::from(CHARLIE), AccountId::from(ALICE), 50 * UNIT), + (AccountId::from(CHARLIE), AccountId::from(BOB), 50 * UNIT), + ]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates( + origin_of(AccountId::from(ALICE)), + 1_000 * UNIT, + 2u32 + ), + pallet_parachain_staking::Error::::CandidateExists + ); + assert_noop!( + ParachainStaking::join_candidates( + origin_of(AccountId::from(CHARLIE)), + 1_000 * UNIT, + 2u32 + ), + pallet_parachain_staking::Error::::DelegatorExists + ); + assert!(System::events().is_empty()); + assert_ok!(ParachainStaking::join_candidates( + origin_of(AccountId::from(DAVE)), + 1_000 * UNIT, + 2u32 + )); + assert_eq!( + last_event(), + RuntimeEvent::ParachainStaking( + pallet_parachain_staking::Event::JoinedCollatorCandidates { + account: AccountId::from(DAVE), + amount_locked: 1_000 * UNIT, + new_total_amt_locked: 3_100 * UNIT + } + ) + ); + let candidates = ParachainStaking::candidate_pool(); + assert_eq!(candidates.0[0].owner, AccountId::from(ALICE)); + assert_eq!(candidates.0[0].amount, 1_050 * UNIT); + assert_eq!(candidates.0[1].owner, AccountId::from(BOB)); + assert_eq!(candidates.0[1].amount, 1_050 * UNIT); + assert_eq!(candidates.0[2].owner, AccountId::from(DAVE)); + assert_eq!(candidates.0[2].amount, 1_000 * UNIT); + }); +} + +#[test] +fn transfer_through_evm_to_stake() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 2_000 * UNIT)]) + .build() + .execute_with(|| { + // Charlie has no balance => fails to stake + assert_noop!( + ParachainStaking::join_candidates( + origin_of(AccountId::from(CHARLIE)), + 1_000 * UNIT, + 0u32 + ), + DispatchError::Module(ModuleError { + index: 12, + error: [8, 0, 0, 0], + message: Some("InsufficientBalance") + }) + ); + + // Alice transfer from free balance 2000 UNIT to Bob + assert_ok!(Balances::transfer( + origin_of(AccountId::from(ALICE)), + AccountId::from(BOB), + 2_000 * UNIT, + )); + assert_eq!(Balances::free_balance(AccountId::from(BOB)), 2_000 * UNIT); + + let gas_limit = 100000u64; + // Bob transfers 1000 UNIT to Charlie via EVM + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(CHARLIE), + input: Vec::new(), + value: (1_000 * UNIT).into(), + gas_limit, + max_fee_per_gas: U256::from(BASE_FEE_GENISIS), + max_priority_fee_per_gas: None, + nonce: None, + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + assert_eq!( + Balances::free_balance(AccountId::from(CHARLIE)), + 1_000 * UNIT, + ); + + // Charlie can stake now + assert_ok!(ParachainStaking::join_candidates( + origin_of(AccountId::from(CHARLIE)), + 1_000 * UNIT, + 0u32, + ),); + let candidates = ParachainStaking::candidate_pool(); + assert_eq!(candidates.0[0].owner, AccountId::from(CHARLIE)); + assert_eq!(candidates.0[0].amount, 1_000 * UNIT); + }); +} + +#[test] +fn reward_block_authors() { + ExtBuilder::default() + .with_balances(vec![ + // Alice gets 100 extra tokens for her mapping deposit + (AccountId::from(ALICE), 2_100 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 500 * UNIT, + )]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + for x in 2..1199 { + run_to_block(x, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + } + // no rewards doled out yet + assert_eq!( + Balances::usable_balance(AccountId::from(ALICE)), + 1_100 * UNIT, + ); + assert_eq!(Balances::usable_balance(AccountId::from(BOB)), 500 * UNIT,); + run_to_block(1201, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + // rewards minted and distributed + assert_eq!( + Balances::usable_balance(AccountId::from(ALICE)), + 1213666666584000000000, + ); + assert_eq!( + Balances::usable_balance(AccountId::from(BOB)), + 541333333292000000000, + ); + }); +} + +#[test] +fn reward_block_authors_with_parachain_bond_reserved() { + ExtBuilder::default() + .with_balances(vec![ + // Alice gets 100 extra tokens for her mapping deposit + (AccountId::from(ALICE), 2_100 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + (AccountId::from(CHARLIE), UNIT), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 500 * UNIT, + )]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + assert_ok!(ParachainStaking::set_parachain_bond_account( + root_origin(), + AccountId::from(CHARLIE), + ),); + for x in 2..1199 { + run_to_block(x, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + } + // no rewards doled out yet + assert_eq!( + Balances::usable_balance(AccountId::from(ALICE)), + 1_100 * UNIT, + ); + assert_eq!(Balances::usable_balance(AccountId::from(BOB)), 500 * UNIT,); + assert_eq!(Balances::usable_balance(AccountId::from(CHARLIE)), UNIT,); + run_to_block(1201, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + // rewards minted and distributed + assert_eq!( + Balances::usable_balance(AccountId::from(ALICE)), + 1182693333281650000000, + ); + assert_eq!( + Balances::usable_balance(AccountId::from(BOB)), + 525841666640825000000, + ); + // 30% reserved for parachain bond + assert_eq!( + Balances::usable_balance(AccountId::from(CHARLIE)), + 47515000000000000000, + ); + }); +} + +#[test] +fn initialize_crowdloan_addresses_with_batch_and_pay() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * UNIT) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * UNIT + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 1_500_000 * UNIT + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + // 30 percent initial payout + assert_eq!(Balances::balance(&AccountId::from(CHARLIE)), 450_000 * UNIT); + // 30 percent initial payout + assert_eq!(Balances::balance(&AccountId::from(DAVE)), 450_000 * UNIT); + let expected = RuntimeEvent::Utility(pallet_utility::Event::BatchCompleted); + assert_eq!(last_event(), expected); + // This one should fail, as we already filled our data + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch { + calls: vec![RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![([4u8; 32].into(), Some(AccountId::from(ALICE)), 432000)] + } + )] + }) + .dispatch(root_origin()) + ); + let expected_fail = RuntimeEvent::Utility(pallet_utility::Event::BatchInterrupted { + index: 0, + error: DispatchError::Module(ModuleError { + index: 20, + error: [8, 0, 0, 0], + message: None, + }), + }); + assert_eq!(last_event(), expected_fail); + // Claim 1 block. + assert_ok!(CrowdloanRewards::claim(origin_of(AccountId::from(CHARLIE)))); + assert_ok!(CrowdloanRewards::claim(origin_of(AccountId::from(DAVE)))); + + let vesting_period = 4 * WEEKS as u128; + let per_block = (1_050_000 * UNIT) / vesting_period; + + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(CHARLIE)) + .unwrap() + .claimed_reward, + (450_000 * UNIT) + per_block + ); + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(DAVE)) + .unwrap() + .claimed_reward, + (450_000 * UNIT) + per_block + ); + // The total claimed reward should be equal to the account balance at this point. + assert_eq!( + Balances::balance(&AccountId::from(CHARLIE)), + (450_000 * UNIT) + per_block + ); + assert_eq!( + Balances::balance(&AccountId::from(DAVE)), + (450_000 * UNIT) + per_block + ); + assert_noop!( + CrowdloanRewards::claim(origin_of(AccountId::from(ALICE))), + pallet_crowdloan_rewards::Error::::NoAssociatedClaim + ); + }); +} + +#[test] +fn initialize_crowdloan_address_and_change_with_relay_key_sig() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * UNIT) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + + let (pair1, _) = sp_core::sr25519::Pair::generate(); + let (pair2, _) = sp_core::sr25519::Pair::generate(); + + let public1 = pair1.public(); + let public2 = pair2.public(); + + // signature: + // WRAP_BYTES|| NetworkIdentifier|| new_account || previous_account || WRAP_BYTES + let mut message = pallet_crowdloan_rewards::WRAPPED_BYTES_PREFIX.to_vec(); + message.append(&mut b"moonbase-".to_vec()); + message.append(&mut AccountId::from(DAVE).encode()); + message.append(&mut AccountId::from(CHARLIE).encode()); + message.append(&mut pallet_crowdloan_rewards::WRAPPED_BYTES_POSTFIX.to_vec()); + + let signature1 = pair1.sign(&message); + let signature2 = pair2.sign(&message); + + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + // two relay accounts pointing at the same reward account + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + public1.into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * UNIT + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + public2.into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * UNIT + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + // 30 percent initial payout + assert_eq!(Balances::balance(&AccountId::from(CHARLIE)), 900_000 * UNIT); + + // this should fail, as we are only providing one signature + assert_noop!( + CrowdloanRewards::change_association_with_relay_keys( + origin_of(AccountId::from(CHARLIE)), + AccountId::from(DAVE), + AccountId::from(CHARLIE), + vec![(public1.into(), signature1.clone().into())] + ), + pallet_crowdloan_rewards::Error::::InsufficientNumberOfValidProofs + ); + + // this should be valid + assert_ok!(CrowdloanRewards::change_association_with_relay_keys( + origin_of(AccountId::from(CHARLIE)), + AccountId::from(DAVE), + AccountId::from(CHARLIE), + vec![ + (public1.into(), signature1.into()), + (public2.into(), signature2.into()) + ] + )); + + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(DAVE)) + .unwrap() + .claimed_reward, + (900_000 * UNIT) + ); + }); +} + +#[test] +fn claim_via_precompile() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * UNIT) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * UNIT + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 1_500_000 * UNIT + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + + // 30 percent initial payout + assert_eq!(Balances::balance(&AccountId::from(CHARLIE)), 450_000 * UNIT); + // 30 percent initial payout + assert_eq!(Balances::balance(&AccountId::from(DAVE)), 450_000 * UNIT); + + let crowdloan_precompile_address = H160::from_low_u64_be(2049); + + // Alice uses the crowdloan precompile to claim through the EVM + let gas_limit = 100000u64; + let gas_price: U256 = BASE_FEE_GENISIS.into(); + + // Construct the call data (selector, amount) + let mut call_data = Vec::::from([0u8; 4]); + call_data[0..4].copy_from_slice(&Keccak256::digest(b"claim()")[0..4]); + + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(CHARLIE), + target: crowdloan_precompile_address, + input: call_data, + value: U256::zero(), // No value sent in EVM + gas_limit, + max_fee_per_gas: gas_price, + max_priority_fee_per_gas: None, + nonce: None, // Use the next nonce + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let vesting_period = 4 * WEEKS as u128; + let per_block = (1_050_000 * UNIT) / vesting_period; + + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(CHARLIE)) + .unwrap() + .claimed_reward, + (450_000 * UNIT) + per_block + ); + }) +} + +#[test] +fn is_contributor_via_precompile() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * UNIT) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * UNIT + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 1_500_000 * UNIT + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + + let crowdloan_precompile_address = H160::from_low_u64_be(2049); + + // Assert precompile reports Bob is not a contributor + Precompiles::new() + .prepare_test( + ALICE, + crowdloan_precompile_address, + CrowdloanRewardsPCall::is_contributor { + contributor: Address(BOB.into()), + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(false); + + // Assert precompile reports Charlie is a nominator + Precompiles::new() + .prepare_test( + ALICE, + crowdloan_precompile_address, + CrowdloanRewardsPCall::is_contributor { + contributor: Address(CHARLIE.into()), + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(true); + }) +} + +#[test] +fn reward_info_via_precompile() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * UNIT) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * UNIT + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 1_500_000 * UNIT + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + + let crowdloan_precompile_address = H160::from_low_u64_be(2049); + + let expected_total: U256 = (1_500_000 * UNIT).into(); + let expected_claimed: U256 = (450_000 * UNIT).into(); + + // Assert precompile reports correct Charlie reward info. + Precompiles::new() + .prepare_test( + ALICE, + crowdloan_precompile_address, + CrowdloanRewardsPCall::reward_info { + contributor: Address(AccountId::from(CHARLIE).into()), + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns((expected_total, expected_claimed)); + }) +} + +#[test] +fn update_reward_address_via_precompile() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * UNIT) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * UNIT + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 1_500_000 * UNIT + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + + let crowdloan_precompile_address = H160::from_low_u64_be(2049); + + // Charlie uses the crowdloan precompile to update address through the EVM + let gas_limit = 100000u64; + let gas_price: U256 = BASE_FEE_GENISIS.into(); + + // Construct the input data to check if Bob is a contributor + let mut call_data = Vec::::from([0u8; 36]); + call_data[0..4] + .copy_from_slice(&Keccak256::digest(b"update_reward_address(address)")[0..4]); + call_data[16..36].copy_from_slice(&ALICE); + + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(CHARLIE), + target: crowdloan_precompile_address, + input: call_data, + value: U256::zero(), // No value sent in EVM + gas_limit, + max_fee_per_gas: gas_price, + max_priority_fee_per_gas: None, + nonce: None, // Use the next nonce + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + assert!(CrowdloanRewards::accounts_payable(&AccountId::from(CHARLIE)).is_none()); + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(ALICE)) + .unwrap() + .claimed_reward, + (450_000 * UNIT) + ); + }) +} + +#[test] +fn asset_can_be_registered() { + ExtBuilder::default().build().execute_with(|| { + let source_location = AssetType::Xcm(MultiLocation::parent()); + let source_id: moonbase_runtime::AssetId = source_location.clone().into(); + let asset_metadata = AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }; + assert_ok!(AssetManager::register_foreign_asset( + moonbase_runtime::RuntimeOrigin::root(), + source_location, + asset_metadata, + 1u128, + true, + )); + assert!(AssetManager::asset_id_type(source_id).is_some()); + }); +} + +#[test] +fn local_assets_cannot_be_create_by_signed_origins() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT * SUPPLY_FACTOR), + (AccountId::from(BOB), 1_000 * UNIT * SUPPLY_FACTOR), + ]) + .build() + .execute_with(|| { + assert_noop!( + RuntimeCall::LocalAssets( + pallet_assets::Call::::create { + id: 11u128.into(), + admin: AccountId::from(ALICE), + min_balance: 1u128 + } + ) + .dispatch(::RuntimeOrigin::signed( + AccountId::from(ALICE) + )), + frame_system::Error::::CallFiltered + ); + }); +} + +#[test] +fn xcm_asset_erc20_precompiles_supply_and_balance() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000 * UNIT)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .build() + .execute_with(|| { + // We have the assetId that corresponds to the relay chain registered + let relay_asset_id: AssetId = AssetType::Xcm(MultiLocation::parent()).into(); + + // Its address is + let asset_precompile_address = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + relay_asset_id, + ); + + // Assert the asset has been created with the correct supply + assert_eq!(Assets::total_supply(relay_asset_id), 1_000 * UNIT); + + // Access totalSupply through precompile. Important that the context is correct + Precompiles::new() + .prepare_test( + ALICE, + asset_precompile_address, + LocalAssetsPCall::total_supply {}, + ) + .expect_cost(2000) + .expect_no_logs() + .execute_returns(U256::from(1000 * UNIT)); + + // Access balanceOf through precompile + Precompiles::new() + .prepare_test( + ALICE, + asset_precompile_address, + LocalAssetsPCall::balance_of { + who: Address(ALICE.into()), + }, + ) + .expect_cost(2000) + .expect_no_logs() + .execute_returns(U256::from(1000 * UNIT)); + }); +} + +#[test] +fn xcm_asset_erc20_precompiles_transfer() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000 * UNIT)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .build() + .execute_with(|| { + // We have the assetId that corresponds to the relay chain registered + let relay_asset_id: AssetId = AssetType::Xcm(MultiLocation::parent()).into(); + + // Its address is + let asset_precompile_address = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + relay_asset_id, + ); + + // Transfer tokens from Alice to Bob, 400 UNIT. + Precompiles::new() + .prepare_test( + ALICE, + asset_precompile_address, + LocalAssetsPCall::transfer { + to: Address(BOB.into()), + value: { 400 * UNIT }.into(), + }, + ) + .expect_cost(23763) + .expect_log(log3( + asset_precompile_address, + SELECTOR_LOG_TRANSFER, + H160::from(ALICE), + H160::from(BOB), + solidity::encode_event_data(U256::from(400 * UNIT)), + )) + .execute_returns(true); + + // Make sure BOB has 400 UNIT + Precompiles::new() + .prepare_test( + BOB, + asset_precompile_address, + LocalAssetsPCall::balance_of { + who: Address(BOB.into()), + }, + ) + .expect_cost(2000) + .expect_no_logs() + .execute_returns(U256::from(400 * UNIT)); + }); +} + +#[test] +fn xcm_asset_erc20_precompiles_approve() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000 * UNIT)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .build() + .execute_with(|| { + // We have the assetId that corresponds to the relay chain registered + let relay_asset_id: AssetId = AssetType::Xcm(MultiLocation::parent()).into(); + + // Its address is + let asset_precompile_address = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + relay_asset_id, + ); + + // Aprove Bob for spending 400 UNIT from Alice + Precompiles::new() + .prepare_test( + ALICE, + asset_precompile_address, + LocalAssetsPCall::approve { + spender: Address(BOB.into()), + value: { 400 * UNIT }.into(), + }, + ) + .expect_cost(14210) + .expect_log(log3( + asset_precompile_address, + SELECTOR_LOG_APPROVAL, + H160::from(ALICE), + H160::from(BOB), + solidity::encode_event_data(U256::from(400 * UNIT)), + )) + .execute_returns(true); + + // Transfer tokens from Alice to Charlie by using BOB as origin + Precompiles::new() + .prepare_test( + BOB, + asset_precompile_address, + LocalAssetsPCall::transfer_from { + from: Address(ALICE.into()), + to: Address(CHARLIE.into()), + value: { 400 * UNIT }.into(), + }, + ) + .expect_cost(28991) + .expect_log(log3( + asset_precompile_address, + SELECTOR_LOG_TRANSFER, + H160::from(ALICE), + H160::from(CHARLIE), + solidity::encode_event_data(U256::from(400 * UNIT)), + )) + .execute_returns(true); + + // Make sure CHARLIE has 400 UNIT + Precompiles::new() + .prepare_test( + CHARLIE, + asset_precompile_address, + LocalAssetsPCall::balance_of { + who: Address(CHARLIE.into()), + }, + ) + .expect_cost(2000) + .expect_no_logs() + .execute_returns(U256::from(400 * UNIT)); + }); +} + +#[test] +fn xtokens_precompiles_transfer() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + let xtokens_precompile_address = H160::from_low_u64_be(2052); + + // We have the assetId that corresponds to the relay chain registered + let relay_asset_id: AssetId = AssetType::Xcm(MultiLocation::parent()).into(); + + // Its address is + let asset_precompile_address = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + relay_asset_id, + ); + + // Alice has 1000 tokens. She should be able to send through precompile + let destination = MultiLocation::new( + 1, + Junctions::X1(Junction::AccountId32 { + network: None, + id: [1u8; 32], + }), + ); + + // We use the address of the asset as an identifier of the asset we want to transfer + Precompiles::new() + .prepare_test( + ALICE, + xtokens_precompile_address, + XtokensPCall::transfer { + currency_address: Address(asset_precompile_address.into()), + amount: 500_000_000_000_000u128.into(), + destination, + weight: 4_000_000, + }, + ) + .expect_cost(57639) + .expect_no_logs() + .execute_returns(()) + }) +} + +#[test] +fn xtokens_precompiles_transfer_multiasset() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + let xtokens_precompile_address = H160::from_low_u64_be(2052); + + // Alice has 1000 tokens. She should be able to send through precompile + let destination = MultiLocation::new( + 1, + Junctions::X1(Junction::AccountId32 { + network: None, + id: [1u8; 32], + }), + ); + + // This time we transfer it through TransferMultiAsset + // Instead of the address, we encode directly the multilocation referencing the asset + Precompiles::new() + .prepare_test( + ALICE, + xtokens_precompile_address, + XtokensPCall::transfer_multiasset { + // We want to transfer the relay token + asset: MultiLocation::parent(), + amount: 500_000_000_000_000u128.into(), + destination, + weight: 4_000_000, + }, + ) + .expect_cost(57639) + .expect_no_logs() + .execute_returns(()); + }) +} + +#[test] +fn xtokens_precompiles_transfer_native() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + let xtokens_precompile_address = H160::from_low_u64_be(2052); + + // Its address is + let asset_precompile_address = H160::from_low_u64_be(2050); + + // Alice has 1000 tokens. She should be able to send through precompile + let destination = MultiLocation::new( + 1, + Junctions::X1(Junction::AccountId32 { + network: None, + id: [1u8; 32], + }), + ); + + // We use the address of the asset as an identifier of the asset we want to transfer + Precompiles::new() + .prepare_test( + ALICE, + xtokens_precompile_address, + XtokensPCall::transfer { + currency_address: Address(asset_precompile_address), + amount: { 500 * UNIT }.into(), + destination: destination.clone(), + weight: 4_000_000, + }, + ) + .expect_cost(16000) + .expect_no_logs() + .execute_returns(()); + }) +} + +fn run_with_system_weight(w: Weight, mut assertions: F) +where + F: FnMut() -> (), +{ + let mut t: sp_io::TestExternalities = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap() + .into(); + t.execute_with(|| { + System::set_block_consumed_resources(w, 0); + assertions() + }); +} + +#[test] +#[rustfmt::skip] +fn length_fee_is_sensible() { + use sp_runtime::testing::TestXt; + + // tests that length fee is sensible for a few hypothetical transactions + ExtBuilder::default().build().execute_with(|| { + let call = frame_system::Call::remark:: { remark: vec![] }; + let uxt: TestXt<_, ()> = TestXt::new(call, Some((1u64, ()))); + + let calc_fee = |len: u32| -> Balance { + moonbase_runtime::TransactionPayment::query_fee_details(uxt.clone(), len) + .inclusion_fee + .expect("fee should be calculated") + .len_fee + }; + + // editorconfig-checker-disable + // left: cost of length fee, right: size in bytes + // /------------- proportional component: O(N * 1B) + // | /- exponential component: O(N ** 3) + // | | + assert_eq!( 1_000_000_001, calc_fee(1)); + assert_eq!( 10_000_001_000, calc_fee(10)); + assert_eq!( 100_001_000_000, calc_fee(100)); + assert_eq!( 1_001_000_000_000, calc_fee(1_000)); + assert_eq!( 11_000_000_000_000, calc_fee(10_000)); // inflection point + assert_eq!( 1_100_000_000_000_000, calc_fee(100_000)); + assert_eq!( 1_001_000_000_000_000_000, calc_fee(1_000_000)); // one UNIT, ~ 1MB + assert_eq!( 1_000_010_000_000_000_000_000, calc_fee(10_000_000)); + assert_eq!(1_000_000_100_000_000_000_000_000, calc_fee(100_000_000)); + // editorconfig-checker-enable + }); +} + +#[test] +fn multiplier_can_grow_from_zero() { + use frame_support::traits::Get; + + let minimum_multiplier = moonbase_runtime::MinimumMultiplier::get(); + let target = moonbase_runtime::TargetBlockFullness::get() + * RuntimeBlockWeights::get() + .get(DispatchClass::Normal) + .max_total + .unwrap(); + // if the min is too small, then this will not change, and we are doomed forever. + // the weight is 1/100th bigger than target. + run_with_system_weight(target * 101 / 100, || { + let next = moonbase_runtime::FastAdjustingFeeUpdate::::convert(minimum_multiplier); + assert!( + next > minimum_multiplier, + "{:?} !>= {:?}", + next, + minimum_multiplier + ); + }) +} + +#[test] +fn ethereum_invalid_transaction() { + ExtBuilder::default().build().execute_with(|| { + // Ensure an extrinsic not containing enough gas limit to store the transaction + // on chain is rejected. + assert_eq!( + Executive::apply_extrinsic(unchecked_eth_tx(INVALID_ETH_TX)), + Err( + sp_runtime::transaction_validity::TransactionValidityError::Invalid( + sp_runtime::transaction_validity::InvalidTransaction::Custom(3u8) + ) + ) + ); + }); +} + +#[test] +fn transfer_ed_0_substrate() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), (1 * UNIT) + (1 * WEI)), + (AccountId::from(BOB), 0), + ]) + .build() + .execute_with(|| { + // Substrate transfer + assert_ok!(Balances::transfer( + origin_of(AccountId::from(ALICE)), + AccountId::from(BOB), + 1 * UNIT, + )); + // 1 WEI is left in the account + assert_eq!(Balances::free_balance(AccountId::from(ALICE)), 1 * WEI); + }); +} + +#[test] +fn initial_gas_fee_is_correct() { + use fp_evm::FeeCalculator; + + ExtBuilder::default().build().execute_with(|| { + let multiplier = TransactionPayment::next_fee_multiplier(); + assert_eq!(multiplier, Multiplier::from(8u128)); + + assert_eq!( + TransactionPaymentAsGasPrice::min_gas_price(), + ( + 10_000_000_000u128.into(), + Weight::from_parts(25_000_000u64, 0) + ) + ); + }); +} + +#[test] +fn transfer_ed_0_evm() { + ExtBuilder::default() + .with_balances(vec![ + ( + AccountId::from(ALICE), + ((1 * UNIT) + (21_000 * BASE_FEE_GENISIS)) + (1 * WEI), + ), + (AccountId::from(BOB), 0), + ]) + .build() + .execute_with(|| { + // EVM transfer + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(ALICE), + target: H160::from(BOB), + input: Vec::new(), + value: (1 * UNIT).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(BASE_FEE_GENISIS), + max_priority_fee_per_gas: None, + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + // 1 WEI is left in the account + assert_eq!(Balances::free_balance(AccountId::from(ALICE)), 1 * WEI,); + }); +} + +#[test] +fn refund_ed_0_evm() { + ExtBuilder::default() + .with_balances(vec![ + ( + AccountId::from(ALICE), + ((1 * UNIT) + (21_777 * BASE_FEE_GENISIS)), + ), + (AccountId::from(BOB), 0), + ]) + .build() + .execute_with(|| { + // EVM transfer that zeroes ALICE + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(ALICE), + target: H160::from(BOB), + input: Vec::new(), + value: (1 * UNIT).into(), + gas_limit: 21_777u64, + max_fee_per_gas: U256::from(BASE_FEE_GENISIS), + max_priority_fee_per_gas: None, + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + // ALICE is refunded + assert_eq!( + Balances::free_balance(AccountId::from(ALICE)), + 777 * BASE_FEE_GENISIS, + ); + }); +} + +#[test] +fn author_does_not_receive_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * UNIT) + (21_000 * (500 * GIGAWEI)), + )]) + .build() + .execute_with(|| { + // Some block author as seen by pallet-evm. + let author = AccountId::from(>::find_author()); + // Currently the default impl of the evm uses `deposit_into_existing`. + // If we were to use this implementation, and for an author to receive eventual tips, + // the account needs to be somehow initialized, otherwise the deposit would fail. + Balances::make_free_balance_be(&author, 100 * UNIT); + + // EVM transfer. + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * UNIT).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(300 * GIGAWEI), + max_priority_fee_per_gas: Some(U256::from(200 * GIGAWEI)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + // Author free balance didn't change. + assert_eq!(Balances::free_balance(author), 100 * UNIT,); + }); +} + +#[test] +fn total_issuance_after_evm_transaction_with_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * UNIT) + (21_000 * (2 * BASE_FEE_GENISIS)), + )]) + .build() + .execute_with(|| { + let issuance_before = ::Currency::total_issuance(); + // EVM transfer. + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * UNIT).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(2 * BASE_FEE_GENISIS), + max_priority_fee_per_gas: Some(U256::from(BASE_FEE_GENISIS)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let issuance_after = ::Currency::total_issuance(); + // Fee is 1 * base_fee + tip. + let fee = ((2 * BASE_FEE_GENISIS) * 21_000) as f64; + // 80% was burned. + let expected_burn = (fee * 0.8) as u128; + assert_eq!(issuance_after, issuance_before - expected_burn,); + // 20% was sent to treasury. + let expected_treasury = (fee * 0.2) as u128; + assert_eq!(moonbase_runtime::Treasury::pot(), expected_treasury); + }); +} + +#[test] +fn total_issuance_after_evm_transaction_without_priority_fee() { + use fp_evm::FeeCalculator; + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * UNIT) + (21_000 * (2 * BASE_FEE_GENISIS)), + )]) + .build() + .execute_with(|| { + let issuance_before = ::Currency::total_issuance(); + // EVM transfer. + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * UNIT).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(BASE_FEE_GENISIS), + max_priority_fee_per_gas: None, + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let issuance_after = ::Currency::total_issuance(); + // Fee is 1 GWEI base fee. + let base_fee = TransactionPaymentAsGasPrice::min_gas_price().0; + assert_eq!(base_fee.as_u128(), BASE_FEE_GENISIS); // hint in case following asserts fail + let fee = (base_fee.as_u128() * 21_000u128) as f64; + // 80% was burned. + let expected_burn = (fee * 0.8) as u128; + assert_eq!(issuance_after, issuance_before - expected_burn,); + // 20% was sent to treasury. + let expected_treasury = (fee * 0.2) as u128; + assert_eq!(moonbase_runtime::Treasury::pot(), expected_treasury); + }); +} + +#[test] +fn root_can_change_default_xcm_vers() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .build() + .execute_with(|| { + let source_location = AssetType::Xcm(MultiLocation::parent()); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: [1u8; 32], + }), + }; + let source_id: moonbase_runtime::AssetId = source_location.clone().into(); + // Default XCM version is not set yet, so xtokens should fail because it does not + // know with which version to send + assert_noop!( + XTokens::transfer( + origin_of(AccountId::from(ALICE)), + moonbase_runtime::xcm_config::CurrencyId::ForeignAsset(source_id), + 100_000_000_000_000, + Box::new(xcm::VersionedMultiLocation::V3(dest.clone())), + WeightLimit::Limited(4000000000.into()) + ), + orml_xtokens::Error::::XcmExecutionFailed + ); + + // Root sets the defaultXcm + assert_ok!(PolkadotXcm::force_default_xcm_version( + root_origin(), + Some(2) + )); + + // Now transferring does not fail + assert_ok!(XTokens::transfer( + origin_of(AccountId::from(ALICE)), + moonbase_runtime::xcm_config::CurrencyId::ForeignAsset(source_id), + 100_000_000_000_000, + Box::new(xcm::VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(4000000000.into()) + )); + }) +} + +#[test] +fn transactor_cannot_use_more_than_max_weight() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .build() + .execute_with(|| { + let source_location = AssetType::Xcm(MultiLocation::parent()); + let source_id: moonbase_runtime::AssetId = source_location.clone().into(); + assert_ok!(XcmTransactor::register( + root_origin(), + AccountId::from(ALICE), + 0, + )); + + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + root_origin(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + // Relay charges 1000 for every instruction, and we have 3, so 3000 + 3000.into(), + 20000.into(), + None + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + root_origin(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + 1, + )); + + assert_noop!( + XcmTransactor::transact_through_derivative( + origin_of(AccountId::from(ALICE)), + moonbase_runtime::xcm_config::Transactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new( + xcm::VersionedMultiLocation::V3(MultiLocation::parent()) + )), + fee_amount: None + }, + vec![], + // 20000 is the max + TransactWeights { + transact_required_weight_at_most: 17001.into(), + overall_weight: None + }, + false + ), + pallet_xcm_transactor::Error::::MaxWeightTransactReached + ); + assert_noop!( + XcmTransactor::transact_through_derivative( + origin_of(AccountId::from(ALICE)), + moonbase_runtime::xcm_config::Transactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsCurrencyId( + moonbase_runtime::xcm_config::CurrencyId::ForeignAsset(source_id) + ), + fee_amount: None + }, + vec![], + // 20000 is the max + TransactWeights { + transact_required_weight_at_most: 17001.into(), + overall_weight: None + }, + false + ), + pallet_xcm_transactor::Error::::MaxWeightTransactReached + ); + }) +} + +#[test] +fn root_can_use_hrmp_manage() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .build() + .execute_with(|| { + // It fails sending, because the router does not work in test mode + // But all rest checks pass + assert_noop!( + XcmTransactor::hrmp_manage( + root_origin(), + HrmpOperation::Accept { + para_id: 2000u32.into() + }, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new( + xcm::VersionedMultiLocation::V3(MultiLocation::parent()) + )), + fee_amount: Some(10000) + }, + // 20000 is the max + TransactWeights { + transact_required_weight_at_most: 17001.into(), + overall_weight: Some(20000.into()) + } + ), + pallet_xcm_transactor::Error::::ErrorValidating + ); + }) +} + +#[test] +fn transact_through_signed_precompile_works_v1() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + // Destination + let dest = MultiLocation::parent(); + + let fee_payer_asset = MultiLocation::parent(); + + let bytes = vec![1u8, 2u8, 3u8]; + + let xcm_transactor_v1_precompile_address = H160::from_low_u64_be(2054); + + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + root_origin(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + // Relay charges 1000 for every instruction, and we have 3, so 3000 + 3000.into(), + Weight::from_parts(200_000, (xcm_primitives::DEFAULT_PROOF_SIZE) + 4000), + Some(4000.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + root_origin(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + 1, + )); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_transactor_v1_precompile_address, + XcmTransactorV1PCall::transact_through_signed_multilocation { + dest, + fee_asset: fee_payer_asset, + weight: 15000, + call: bytes.into(), + }, + ) + .expect_cost(17149) + .expect_no_logs() + .execute_returns(()); + }); +} + +#[test] +fn transact_through_signed_precompile_works_v2() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + // Destination + let dest = MultiLocation::parent(); + + let fee_payer_asset = MultiLocation::parent(); + + let bytes = vec![1u8, 2u8, 3u8]; + + let total_weight = 1_000_000_000u64; + + let xcm_transactor_v2_precompile_address = H160::from_low_u64_be(2061); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_transactor_v2_precompile_address, + XcmTransactorV2PCall::transact_through_signed_multilocation { + dest, + fee_asset: fee_payer_asset, + weight: 4_000_000, + call: bytes.into(), + fee_amount: u128::from(total_weight).into(), + overall_weight: total_weight, + }, + ) + .expect_cost(17149) + .expect_no_logs() + .execute_returns(()); + }); +} + +#[test] +fn transact_through_signed_cannot_send_to_local_chain() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + // Destination + let dest = MultiLocation::here(); + + let fee_payer_asset = MultiLocation::parent(); + + let bytes = vec![1u8, 2u8, 3u8]; + + let total_weight = 1_000_000_000u64; + + let xcm_transactor_v2_precompile_address = H160::from_low_u64_be(2061); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_transactor_v2_precompile_address, + XcmTransactorV2PCall::transact_through_signed_multilocation { + dest, + fee_asset: fee_payer_asset, + weight: 4_000_000, + call: bytes.into(), + fee_amount: u128::from(total_weight).into(), + overall_weight: total_weight, + }, + ) + .execute_reverts(|output| { + from_utf8(&output) + .unwrap() + .contains("Dispatched call failed with error:") + && from_utf8(&output).unwrap().contains("ErrorValidating") + }); + }); +} + +// Test to ensure we can use either in crowdloan rewards without worrying for migrations +#[test] +fn account_id_32_encodes_like_32_byte_u8_slice() { + let account_as_account_id_32: sp_runtime::AccountId32 = [1u8; 32].into(); + let account_as_slice = [1u8; 32]; + assert_eq!(account_as_account_id_32.encode(), account_as_slice.encode()); +} + +#[test] +fn author_mapping_precompile_associate_update_and_clear() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .build() + .execute_with(|| { + let author_mapping_precompile_address = H160::from_low_u64_be(2055); + let first_nimbus_id: NimbusId = + sp_core::sr25519::Public::unchecked_from([1u8; 32]).into(); + let first_vrf_id: session_keys_primitives::VrfId = + sp_core::sr25519::Public::unchecked_from([1u8; 32]).into(); + let second_nimbus_id: NimbusId = + sp_core::sr25519::Public::unchecked_from([2u8; 32]).into(); + let second_vrf_id: session_keys_primitives::VrfId = + sp_core::sr25519::Public::unchecked_from([2u8; 32]).into(); + + // Associate it + Precompiles::new() + .prepare_test( + ALICE, + author_mapping_precompile_address, + AuthorMappingPCall::add_association { + nimbus_id: [1u8; 32].into(), + }, + ) + .expect_cost(14737) + .expect_no_logs() + .execute_returns(()); + + let expected_associate_event = + RuntimeEvent::AuthorMapping(pallet_author_mapping::Event::KeysRegistered { + nimbus_id: first_nimbus_id.clone(), + account_id: AccountId::from(ALICE), + keys: first_vrf_id.clone(), + }); + assert_eq!(last_event(), expected_associate_event); + + // Update it + Precompiles::new() + .prepare_test( + ALICE, + author_mapping_precompile_address, + AuthorMappingPCall::update_association { + old_nimbus_id: [1u8; 32].into(), + new_nimbus_id: [2u8; 32].into(), + }, + ) + .expect_cost(14515) + .expect_no_logs() + .execute_returns(()); + + let expected_update_event = + RuntimeEvent::AuthorMapping(pallet_author_mapping::Event::KeysRotated { + new_nimbus_id: second_nimbus_id.clone(), + account_id: AccountId::from(ALICE), + new_keys: second_vrf_id.clone(), + }); + assert_eq!(last_event(), expected_update_event); + + // Clear it + Precompiles::new() + .prepare_test( + ALICE, + author_mapping_precompile_address, + AuthorMappingPCall::clear_association { + nimbus_id: [2u8; 32].into(), + }, + ) + .expect_cost(14795) + .expect_no_logs() + .execute_returns(()); + + let expected_clear_event = + RuntimeEvent::AuthorMapping(pallet_author_mapping::Event::KeysRemoved { + nimbus_id: second_nimbus_id, + account_id: AccountId::from(ALICE), + keys: second_vrf_id, + }); + assert_eq!(last_event(), expected_clear_event); + }); +} + +#[test] +fn author_mapping_register_and_set_keys() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .build() + .execute_with(|| { + let author_mapping_precompile_address = H160::from_low_u64_be(2055); + let first_nimbus_id: NimbusId = + sp_core::sr25519::Public::unchecked_from([1u8; 32]).into(); + let first_vrf_key: session_keys_primitives::VrfId = + sp_core::sr25519::Public::unchecked_from([3u8; 32]).into(); + let second_nimbus_id: NimbusId = + sp_core::sr25519::Public::unchecked_from([2u8; 32]).into(); + let second_vrf_key: session_keys_primitives::VrfId = + sp_core::sr25519::Public::unchecked_from([4u8; 32]).into(); + + // Associate it + Precompiles::new() + .prepare_test( + ALICE, + author_mapping_precompile_address, + AuthorMappingPCall::set_keys { + keys: solidity::encode_arguments(( + H256::from([1u8; 32]), + H256::from([3u8; 32]), + )) + .into(), + }, + ) + .expect_cost(15816) + .expect_no_logs() + .execute_returns(()); + + let expected_associate_event = + RuntimeEvent::AuthorMapping(pallet_author_mapping::Event::KeysRegistered { + nimbus_id: first_nimbus_id.clone(), + account_id: AccountId::from(ALICE), + keys: first_vrf_key.clone(), + }); + assert_eq!(last_event(), expected_associate_event); + + // Update it + Precompiles::new() + .prepare_test( + ALICE, + author_mapping_precompile_address, + AuthorMappingPCall::set_keys { + keys: solidity::encode_arguments(( + H256::from([2u8; 32]), + H256::from([4u8; 32]), + )) + .into(), + }, + ) + .expect_cost(15816) + .expect_no_logs() + .execute_returns(()); + + let expected_update_event = + RuntimeEvent::AuthorMapping(pallet_author_mapping::Event::KeysRotated { + new_nimbus_id: second_nimbus_id.clone(), + account_id: AccountId::from(ALICE), + new_keys: second_vrf_key.clone(), + }); + assert_eq!(last_event(), expected_update_event); + }); +} + +#[test] +fn test_xcm_utils_ml_tp_account() { + ExtBuilder::default().build().execute_with(|| { + let xcm_utils_precompile_address = H160::from_low_u64_be(2060); + let expected_address_parent: H160 = + ParentIsPreset::::convert_location(&MultiLocation::parent()) + .unwrap() + .into(); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_utils_precompile_address, + XcmUtilsPCall::multilocation_to_address { + multilocation: MultiLocation::parent(), + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(Address(expected_address_parent)); + + let parachain_2000_multilocation = MultiLocation::new(1, X1(Parachain(2000))); + let expected_address_parachain: H160 = + SiblingParachainConvertsVia::::convert_location( + ¶chain_2000_multilocation, + ) + .unwrap() + .into(); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_utils_precompile_address, + XcmUtilsPCall::multilocation_to_address { + multilocation: parachain_2000_multilocation, + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(Address(expected_address_parachain)); + + let alice_in_parachain_2000_multilocation = MultiLocation::new( + 1, + X2( + Parachain(2000), + AccountKey20 { + network: None, + key: ALICE, + }, + ), + ); + let expected_address_alice_in_parachain_2000: H160 = + xcm_builder::HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &alice_in_parachain_2000_multilocation, + ) + .unwrap() + .into(); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_utils_precompile_address, + XcmUtilsPCall::multilocation_to_address { + multilocation: alice_in_parachain_2000_multilocation, + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(Address(expected_address_alice_in_parachain_2000)); + }); +} + +#[test] +fn test_xcm_utils_weight_message() { + ExtBuilder::default().build().execute_with(|| { + let xcm_utils_precompile_address = H160::from_low_u64_be(2060); + let expected_weight = + XcmWeight::::clear_origin().ref_time(); + + let message: Vec = xcm::VersionedXcm::<()>::V3(Xcm(vec![ClearOrigin])).encode(); + + let input = XcmUtilsPCall::weight_message { + message: message.into(), + }; + + Precompiles::new() + .prepare_test(ALICE, xcm_utils_precompile_address, input) + .expect_cost(0) + .expect_no_logs() + .execute_returns(expected_weight); + }); +} + +#[test] +fn test_xcm_utils_get_units_per_second() { + ExtBuilder::default().build().execute_with(|| { + let xcm_utils_precompile_address = H160::from_low_u64_be(2060); + let multilocation = SelfReserve::get(); + + let input = XcmUtilsPCall::get_units_per_second { multilocation }; + + let expected_units = + WEIGHT_REF_TIME_PER_SECOND as u128 * moonbase_runtime::currency::WEIGHT_FEE; + + Precompiles::new() + .prepare_test(ALICE, xcm_utils_precompile_address, input) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(expected_units); + }); +} + +#[test] +fn precompile_existence() { + ExtBuilder::default().build().execute_with(|| { + let precompiles = Precompiles::new(); + let precompile_addresses: std::collections::BTreeSet<_> = vec![ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 1024, 1025, 1026, 2048, 2049, 2050, 2051, 2052, 2053, 2054, + 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, + 2069, 2070, 2071, 2072, + ] + .into_iter() + .map(H160::from_low_u64_be) + .collect(); + + for i in 0..3000 { + let address = H160::from_low_u64_be(i); + + if precompile_addresses.contains(&address) { + assert!( + is_precompile_or_fail::(address, 100_000u64).expect("to be ok"), + "is_precompile({}) should return true", + i + ); + + assert!( + precompiles + .execute(&mut MockHandle::new( + address, + Context { + address, + caller: H160::zero(), + apparent_value: U256::zero() + } + ),) + .is_some(), + "execute({},..) should return Some(_)", + i + ); + } else { + assert!( + !is_precompile_or_fail::(address, 100_000u64).expect("to be ok"), + "is_precompile({}) should return false", + i + ); + + assert!( + precompiles + .execute(&mut MockHandle::new( + address, + Context { + address, + caller: H160::zero(), + apparent_value: U256::zero() + } + ),) + .is_none(), + "execute({},..) should return None", + i + ); + } + } + }); +} + +#[test] +fn removed_precompiles() { + ExtBuilder::default().build().execute_with(|| { + let precompiles = Precompiles::new(); + let removed_precompiles = [1025]; + + for i in 1..3000 { + let address = H160::from_low_u64_be(i); + + if !is_precompile_or_fail::(address, 100_000u64).expect("to be ok") { + continue; + } + + if !removed_precompiles.contains(&i) { + assert!( + match precompiles.is_active_precompile(address, 100_000u64) { + IsPrecompileResult::Answer { is_precompile, .. } => is_precompile, + _ => false, + }, + "{i} should be an active precompile" + ); + continue; + } + + assert!( + !match precompiles.is_active_precompile(address, 100_000u64) { + IsPrecompileResult::Answer { is_precompile, .. } => is_precompile, + _ => false, + }, + "{i} shouldn't be an active precompile" + ); + + precompiles + .prepare_test(Alice, address, []) + .execute_reverts(|out| out == b"Removed precompile"); + } + }) +} + +#[test] +fn substrate_based_fees_zero_txn_costs_only_base_extrinsic() { + use frame_support::dispatch::{DispatchInfo, Pays}; + use moonbase_runtime::{currency, EXTRINSIC_BASE_WEIGHT}; + + ExtBuilder::default().build().execute_with(|| { + let size_bytes = 0; + let tip = 0; + let dispatch_info = DispatchInfo { + weight: Weight::zero(), + class: DispatchClass::Normal, + pays_fee: Pays::Yes, + }; + + assert_eq!( + TransactionPayment::compute_fee(size_bytes, &dispatch_info, tip), + EXTRINSIC_BASE_WEIGHT.ref_time() as u128 * currency::WEIGHT_FEE, + ); + }); +} + +#[test] +fn deal_with_fees_handles_tip() { + use frame_support::traits::OnUnbalanced; + use moonbase_runtime::{DealWithFees, Treasury}; + + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 10_000)]) + .build() + .execute_with(|| { + // Alice has 10_000, which makes inital supply 10_000. + // drop()ing the NegativeImbalance below will cause the total_supply to be decreased + // incorrectly (since there was never a withdraw to begin with), which in this case has + // the desired effect of showing that currency was burned. + let total_supply_before = Balances::total_issuance(); + assert_eq!(total_supply_before, 10_000); + + let fees_then_tips = vec![ + NegativeImbalance::::new(100), + NegativeImbalance::::new(1_000), + ]; + DealWithFees::on_unbalanceds(fees_then_tips.into_iter()); + + // treasury should have received 20% + assert_eq!(Balances::free_balance(&Treasury::account_id()), 220); + + // verify 80% burned + let total_supply_after = Balances::total_issuance(); + assert_eq!(total_supply_before - total_supply_after, 880); + }); +} + +#[test] +fn evm_revert_substrate_events() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .build() + .execute_with(|| { + let batch_precompile_address = H160::from_low_u64_be(2056); + + // Batch a transfer followed by an invalid call to batch. + // Thus BatchAll will revert the transfer. + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::call { + source: ALICE.into(), + target: batch_precompile_address, + input: BatchPCall::batch_all { + to: vec![Address(BOB.into()), Address(batch_precompile_address)].into(), + value: vec![U256::from(1 * UNIT), U256::zero()].into(), + call_data: vec![].into(), + gas_limit: vec![].into() + } + .into(), + value: U256::zero(), // No value sent in EVM + gas_limit: 500_000, + max_fee_per_gas: U256::from(BASE_FEE_GENISIS), + max_priority_fee_per_gas: None, + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let transfer_count = System::events() + .iter() + .filter(|r| match r.event { + RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => true, + _ => false, + }) + .count(); + + assert_eq!(transfer_count, 0, "there should be no transfer event"); + }); +} + +#[test] +fn evm_success_keeps_substrate_events() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .build() + .execute_with(|| { + let batch_precompile_address = H160::from_low_u64_be(2056); + + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::call { + source: ALICE.into(), + target: batch_precompile_address, + input: BatchPCall::batch_all { + to: vec![Address(BOB.into())].into(), + value: vec![U256::from(1 * UNIT)].into(), + call_data: vec![].into(), + gas_limit: vec![].into() + } + .into(), + value: U256::zero(), // No value sent in EVM + gas_limit: 500_000, + max_fee_per_gas: U256::from(BASE_FEE_GENISIS), + max_priority_fee_per_gas: None, + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let transfer_count = System::events() + .iter() + .filter(|r| match r.event { + RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => true, + _ => false, + }) + .count(); + + assert_eq!(transfer_count, 1, "there should be 1 transfer event"); + }); +} + +#[test] +fn validate_transaction_fails_on_filtered_call() { + use sp_runtime::transaction_validity::{ + InvalidTransaction, TransactionSource, TransactionValidityError, + }; + use sp_transaction_pool::runtime_api::runtime_decl_for_tagged_transaction_queue::TaggedTransactionQueueV3; // editorconfig-checker-disable-line + + ExtBuilder::default().build().execute_with(|| { + let xt = UncheckedExtrinsic::new_unsigned( + pallet_evm::Call::::call { + source: Default::default(), + target: H160::default(), + input: Vec::new(), + value: Default::default(), + gas_limit: Default::default(), + max_fee_per_gas: Default::default(), + max_priority_fee_per_gas: Default::default(), + nonce: Default::default(), + access_list: Default::default(), + } + .into(), + ); + + assert_eq!( + Runtime::validate_transaction(TransactionSource::External, xt, Default::default(),), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); + }); +} + +#[cfg(test)] +mod fee_tests { + use super::*; + use fp_evm::FeeCalculator; + use frame_support::{ + traits::{ConstU128, OnFinalize}, + weights::{ConstantMultiplier, WeightToFee}, + }; + use moonbase_runtime::{ + currency, BlockWeights, FastAdjustingFeeUpdate, LengthToFee, MinimumMultiplier, + TargetBlockFullness, NORMAL_WEIGHT, WEIGHT_PER_GAS, + }; + use sp_runtime::{BuildStorage, FixedPointNumber, Perbill}; + + fn run_with_system_weight(w: Weight, mut assertions: F) + where + F: FnMut() -> (), + { + let mut t: sp_io::TestExternalities = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap() + .into(); + t.execute_with(|| { + System::set_block_consumed_resources(w, 0); + assertions() + }); + } + + #[test] + fn test_multiplier_can_grow_from_zero() { + let minimum_multiplier = MinimumMultiplier::get(); + let target = TargetBlockFullness::get() + * BlockWeights::get() + .get(DispatchClass::Normal) + .max_total + .unwrap(); + // if the min is too small, then this will not change, and we are doomed forever. + // the weight is 1/100th bigger than target. + run_with_system_weight(target * 101 / 100, || { + let next = FastAdjustingFeeUpdate::::convert(minimum_multiplier); + assert!( + next > minimum_multiplier, + "{:?} !>= {:?}", + next, + minimum_multiplier + ); + }) + } + + #[test] + fn test_fee_calculation() { + let base_extrinsic = BlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic; + let multiplier = sp_runtime::FixedU128::from_float(0.999000000000000000); + let extrinsic_len = 100u32; + let extrinsic_weight = 5_000u64; + let tip = 42u128; + type WeightToFeeImpl = + ConstantMultiplier>; + type LengthToFeeImpl = LengthToFee; + + // base_fee + (multiplier * extrinsic_weight_fee) + extrinsic_length_fee + tip + let expected_fee = + WeightToFeeImpl::weight_to_fee(&base_extrinsic) + + multiplier.saturating_mul_int(WeightToFeeImpl::weight_to_fee( + &Weight::from_parts(extrinsic_weight, 1), + )) + LengthToFeeImpl::weight_to_fee(&Weight::from_parts(extrinsic_len as u64, 1)) + + tip; + + let mut t: sp_io::TestExternalities = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap() + .into(); + t.execute_with(|| { + pallet_transaction_payment::NextFeeMultiplier::::set(multiplier); + let actual_fee = TransactionPayment::compute_fee( + extrinsic_len, + &frame_support::dispatch::DispatchInfo { + class: DispatchClass::Normal, + pays_fee: frame_support::dispatch::Pays::Yes, + weight: Weight::from_parts(extrinsic_weight, 1), + }, + tip, + ); + + assert_eq!( + expected_fee, + actual_fee, + "The actual fee did not match the expected fee, diff {}", + actual_fee - expected_fee + ); + }); + } + + #[test] + fn test_min_gas_price_is_deterministic() { + let mut t: sp_io::TestExternalities = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap() + .into(); + t.execute_with(|| { + let multiplier = sp_runtime::FixedU128::from_u32(1); + pallet_transaction_payment::NextFeeMultiplier::::set(multiplier); + let actual = TransactionPaymentAsGasPrice::min_gas_price().0; + let expected: U256 = multiplier + .saturating_mul_int(currency::WEIGHT_FEE.saturating_mul(WEIGHT_PER_GAS as u128)) + .into(); + + assert_eq!(expected, actual); + }); + } + + #[test] + fn test_min_gas_price_has_no_precision_loss_from_saturating_mul_int() { + let mut t: sp_io::TestExternalities = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap() + .into(); + t.execute_with(|| { + let multiplier_1 = sp_runtime::FixedU128::from_float(0.999593900000000000); + let multiplier_2 = sp_runtime::FixedU128::from_float(0.999593200000000000); + + pallet_transaction_payment::NextFeeMultiplier::::set(multiplier_1); + let a = TransactionPaymentAsGasPrice::min_gas_price(); + pallet_transaction_payment::NextFeeMultiplier::::set(multiplier_2); + let b = TransactionPaymentAsGasPrice::min_gas_price(); + + assert_ne!( + a, b, + "both gas prices were equal, unexpected precision loss incurred" + ); + }); + } + + #[test] + fn test_fee_scenarios() { + use sp_runtime::FixedU128; + let mut t: sp_io::TestExternalities = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap() + .into(); + t.execute_with(|| { + let weight_fee_per_gas = currency::WEIGHT_FEE.saturating_mul(WEIGHT_PER_GAS as u128); + let sim = |start_gas_price: u128, fullness: Perbill, num_blocks: u64| -> U256 { + let start_multiplier = + FixedU128::from_rational(start_gas_price, weight_fee_per_gas); + pallet_transaction_payment::NextFeeMultiplier::::set(start_multiplier); + + let block_weight = NORMAL_WEIGHT * fullness; + + for i in 0..num_blocks { + System::set_block_number(i as u32); + System::set_block_consumed_resources(block_weight, 0); + TransactionPayment::on_finalize(i as u32); + } + + TransactionPaymentAsGasPrice::min_gas_price().0 + }; + + assert_eq!( + sim(1_000_000_000, Perbill::from_percent(0), 1), + U256::from(999_000_500), + ); + assert_eq!( + sim(1_000_000_000, Perbill::from_percent(25), 1), + U256::from(1_000_000_000), + ); + assert_eq!( + sim(1_000_000_000, Perbill::from_percent(50), 1), + U256::from(1_001_000_500), + ); + assert_eq!( + sim(1_000_000_000, Perbill::from_percent(100), 1), + U256::from(1_003_004_500), + ); + + // 1 "real" hour (at 12-second blocks) + assert_eq!( + sim(1_000_000_000, Perbill::from_percent(0), 300), + U256::from(740_818_257), + ); + assert_eq!( + sim(1_000_000_000, Perbill::from_percent(25), 300), + U256::from(1_000_000_000), + ); + assert_eq!( + sim(1_000_000_000, Perbill::from_percent(50), 300), + U256::from(1_349_858_740), + ); + assert_eq!( + sim(1_000_000_000, Perbill::from_percent(100), 300), + U256::from(2_459_599_798u128), + ); + + // 1 "real" day (at 12-second blocks) + assert_eq!( + sim(1_000_000_000, Perbill::from_percent(0), 7200), + U256::from(125_000_000), // lower bound enforced + ); + assert_eq!( + sim(1_000_000_000, Perbill::from_percent(25), 7200), + U256::from(1_000_000_000), + ); + assert_eq!( + sim(1_000_000_000, Perbill::from_percent(50), 7200), + U256::from(1_339_429_158_283u128), + ); + assert_eq!( + sim(1_000_000_000, Perbill::from_percent(100), 7200), + U256::from(125_000_000_000_000u128), // upper bound enforced + ); + }); + } +} diff --git a/tracing/2601/runtime/moonbase/tests/runtime_apis.rs b/tracing/2601/runtime/moonbase/tests/runtime_apis.rs new file mode 100644 index 00000000..86c21d00 --- /dev/null +++ b/tracing/2601/runtime/moonbase/tests/runtime_apis.rs @@ -0,0 +1,397 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Moonbase Runtime Api Integration Tests + +mod common; +use common::*; + +use fp_evm::GenesisAccount; +use frame_support::assert_ok; +use nimbus_primitives::NimbusId; +use pallet_evm::{Account as EVMAccount, AddressMapping, FeeCalculator}; +use sp_core::{ByteArray, H160, H256, U256}; + +use fp_rpc::runtime_decl_for_ethereum_runtime_rpc_api::EthereumRuntimeRPCApi; +use moonbeam_rpc_primitives_txpool::runtime_decl_for_tx_pool_runtime_api::TxPoolRuntimeApi; +use nimbus_primitives::runtime_decl_for_nimbus_api::NimbusApi; +use std::{collections::BTreeMap, str::FromStr}; + +#[test] +fn ethereum_runtime_rpc_api_chain_id() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Runtime::chain_id(), CHAIN_ID); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_account_basic() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 2_000 * UNIT)]) + .build() + .execute_with(|| { + assert_eq!( + Runtime::account_basic(H160::from(ALICE)), + EVMAccount { + balance: U256::from(2_000 * UNIT), + nonce: U256::zero() + } + ); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_gas_price() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!( + Runtime::gas_price(), + TransactionPaymentAsGasPrice::min_gas_price().0 + ); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_account_code_at() { + let address = H160::from(EVM_CONTRACT); + let code: Vec = vec![1, 2, 3, 4, 5]; + ExtBuilder::default() + .with_evm_accounts({ + let mut map = BTreeMap::new(); + map.insert( + address, + GenesisAccount { + balance: U256::zero(), + code: code.clone(), + nonce: Default::default(), + storage: Default::default(), + }, + ); + map + }) + .build() + .execute_with(|| { + assert_eq!(Runtime::account_code_at(address), code); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_author() { + ExtBuilder::default() + .with_collators(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 500 * UNIT, + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + run_to_block(2, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + assert_eq!(Runtime::author(), H160::from(ALICE)); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_storage_at() { + let address = H160::from(EVM_CONTRACT); + let mut key = [0u8; 32]; + key[31..32].copy_from_slice(&[6u8][..]); + let mut value = [0u8; 32]; + value[31..32].copy_from_slice(&[7u8][..]); + let item = H256::from_slice(&key[..]); + let mut storage: BTreeMap = BTreeMap::new(); + storage.insert(H256::from_slice(&key[..]), item); + ExtBuilder::default() + .with_evm_accounts({ + let mut map = BTreeMap::new(); + map.insert( + address, + GenesisAccount { + balance: U256::zero(), + code: Vec::new(), + nonce: Default::default(), + storage: storage.clone(), + }, + ); + map + }) + .build() + .execute_with(|| { + assert_eq!(Runtime::storage_at(address, U256::from(6)), item); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_call() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 2_000 * UNIT), + ]) + .build() + .execute_with(|| { + let execution_result = Runtime::call( + H160::from(ALICE), // from + H160::from(BOB), // to + Vec::new(), // data + U256::from(1000u64), // value + U256::from(100000u64), // gas_limit + None, // max_fee_per_gas + None, // max_priority_fee_per_gas + None, // nonce + false, // estimate + None, // access_list + ); + assert!(execution_result.is_ok()); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_create() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 2_000 * UNIT)]) + .build() + .execute_with(|| { + let execution_result = Runtime::create( + H160::from(ALICE), // from + vec![0, 1, 1, 0], // data + U256::zero(), // value + U256::from(100000u64), // gas_limit + None, // max_fee_per_gas + None, // max_priority_fee_per_gas + None, // nonce + false, // estimate + None, // access_list + ); + assert!(execution_result.is_ok()); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_current_transaction_statuses() { + let alith = ::AddressMapping::into_account_id( + H160::from_str("f24ff3a9cf04c71dbc94d0b566f7a27b94566cac") + .expect("internal H160 is valid; qed"), + ); + ExtBuilder::default() + .with_collators(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_balances(vec![ + (alith, 2_000 * UNIT), + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 500 * UNIT, + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + let _result = Executive::apply_extrinsic(unchecked_eth_tx(VALID_ETH_TX)); + rpc_run_to_block(2); + let statuses = + Runtime::current_transaction_statuses().expect("Transaction statuses result."); + assert_eq!(statuses.len(), 1); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_current_block() { + ExtBuilder::default() + .with_collators(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 500 * UNIT, + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + rpc_run_to_block(2); + let block = Runtime::current_block().expect("Block result."); + assert_eq!(block.header.number, U256::from(1u8)); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_current_receipts() { + let alith = ::AddressMapping::into_account_id( + H160::from_str("f24ff3a9cf04c71dbc94d0b566f7a27b94566cac") + .expect("internal H160 is valid; qed"), + ); + ExtBuilder::default() + .with_collators(vec![(AccountId::from(ALICE), 1_000 * UNIT)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_balances(vec![ + (alith, 2_000 * UNIT), + (AccountId::from(ALICE), 2_000 * UNIT), + (AccountId::from(BOB), 1_000 * UNIT), + ]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 500 * UNIT, + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + let _result = Executive::apply_extrinsic(unchecked_eth_tx(VALID_ETH_TX)); + rpc_run_to_block(2); + let receipts = Runtime::current_receipts().expect("Receipts result."); + assert_eq!(receipts.len(), 1); + }); +} + +#[test] +fn txpool_runtime_api_extrinsic_filter() { + ExtBuilder::default().build().execute_with(|| { + let non_eth_uxt = UncheckedExtrinsic::new_unsigned( + pallet_balances::Call::::transfer { + dest: AccountId::from(BOB), + value: 1 * UNIT, + } + .into(), + ); + + let eth_uxt = unchecked_eth_tx(VALID_ETH_TX); + let txpool = >::extrinsic_filter( + vec![eth_uxt.clone(), non_eth_uxt.clone()], + vec![unchecked_eth_tx(VALID_ETH_TX), non_eth_uxt], + ); + assert_eq!(txpool.ready.len(), 1); + assert_eq!(txpool.future.len(), 1); + }); +} + +#[test] +fn can_author_when_selected_is_empty() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 20_000_000 * UNIT), + (AccountId::from(BOB), 10_000_000 * UNIT), + ]) + .with_collators(vec![(AccountId::from(ALICE), 2_000_000 * UNIT)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + run_to_block(2, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + + assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); + + let slot_number = 0; + let parent = Header { + digest: Default::default(), + extrinsics_root: Default::default(), + number: Default::default(), + parent_hash: Default::default(), + state_root: Default::default(), + }; + + // Base case: ALICE can author blocks when she is the only candidate + let can_author_block = Runtime::can_author( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + slot_number, + &parent, + ); + + assert!(can_author_block); + + // Remove ALICE from candidate pool, leaving the candidate_pool empty + assert_ok!(ParachainStaking::go_offline(origin_of(AccountId::from( + ALICE + )))); + + // Need to fast forward to right before the next session, which is when selected candidates + // will be updated. We want to test the creation of the first block of the next session. + run_to_block(1799, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + + assert_eq!(ParachainStaking::candidate_pool().0.len(), 0); + + let slot_number = 0; + let parent = Header { + digest: Default::default(), + extrinsics_root: Default::default(), + number: 1799, + parent_hash: Default::default(), + state_root: Default::default(), + }; + + let can_author_block = Runtime::can_author( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + slot_number, + &parent, + ); + + assert!(can_author_block); + + // Check that it works as expected after session update + run_to_block(1800, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + + assert_eq!(ParachainStaking::candidate_pool().0.len(), 0); + + let slot_number = 0; + let parent = Header { + digest: Default::default(), + extrinsics_root: Default::default(), + number: 1800, + parent_hash: Default::default(), + state_root: Default::default(), + }; + + let can_author_block = Runtime::can_author( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + slot_number, + &parent, + ); + + assert!(can_author_block); + }); +} + +// Some Priority-related test ideas +// 1. Eth balance transfer with various gas prices. Priority == gas price +// 2. Eth contract call with various gas prices. Priority == gas price +// 3. System remark with no tip -> calculate expected priority from gas weight mapping +// 4. System remark with tip. +// 5. Operational dispatch has higher priority than normal for otherwise same transactions diff --git a/tracing/2601/runtime/moonbase/tests/xcm_mock/mod.rs b/tracing/2601/runtime/moonbase/tests/xcm_mock/mod.rs new file mode 100644 index 00000000..56d396e9 --- /dev/null +++ b/tracing/2601/runtime/moonbase/tests/xcm_mock/mod.rs @@ -0,0 +1,274 @@ +// Copyright 2021 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 . + +pub mod parachain; +pub mod relay_chain; +pub mod statemint_like; +use cumulus_primitives_core::ParaId; +use pallet_xcm_transactor::relay_indices::*; +use sp_runtime::traits::AccountIdConversion; +use sp_runtime::{AccountId32, BuildStorage}; +use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt}; + +use polkadot_runtime_parachains::configuration::{ + GenesisConfig as ConfigurationGenesisConfig, HostConfiguration, +}; +use polkadot_runtime_parachains::paras::{ + GenesisConfig as ParasGenesisConfig, ParaGenesisArgs, ParaKind, +}; + +use sp_core::{H160, U256}; +use std::{collections::BTreeMap, str::FromStr}; + +pub const PARAALICE: [u8; 20] = [1u8; 20]; +pub const RELAYALICE: AccountId32 = AccountId32::new([0u8; 32]); +pub const RELAYBOB: AccountId32 = AccountId32::new([2u8; 32]); + +pub fn para_a_account() -> AccountId32 { + ParaId::from(1).into_account_truncating() +} + +pub fn para_b_account() -> AccountId32 { + ParaId::from(2).into_account_truncating() +} + +pub fn para_a_account_20() -> parachain::AccountId { + ParaId::from(1).into_account_truncating() +} + +pub fn evm_account() -> H160 { + H160::from_str("1000000000000000000000000000000000000001").unwrap() +} + +pub fn mock_para_genesis_info() -> ParaGenesisArgs { + ParaGenesisArgs { + genesis_head: vec![1u8].into(), + validation_code: vec![1u8].into(), + para_kind: ParaKind::Parachain, + } +} + +pub fn mock_relay_config() -> HostConfiguration { + HostConfiguration:: { + hrmp_channel_max_capacity: u32::MAX, + hrmp_channel_max_total_size: u32::MAX, + hrmp_max_parachain_inbound_channels: 10, + hrmp_max_parachain_outbound_channels: 10, + hrmp_channel_max_message_size: u32::MAX, + // Changed to avoid aritmetic errors within hrmp_close + max_downward_message_size: 100_000u32, + ..Default::default() + } +} + +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_parachain! { + pub struct ParaC { + Runtime = parachain::Runtime, + XcmpMessageHandler = parachain::MsgQueue, + DmpMessageHandler = parachain::MsgQueue, + new_ext = para_ext(3), + } +} + +decl_test_parachain! { + pub struct Statemint { + Runtime = statemint_like::Runtime, + XcmpMessageHandler = statemint_like::MsgQueue, + DmpMessageHandler = statemint_like::MsgQueue, + new_ext = statemint_ext(4), + } +} + +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(vec![1, 2, 3, 4]), + } +} + +decl_test_network! { + pub struct MockNet { + relay_chain = Relay, + parachains = vec![ + (1, ParaA), + (2, ParaB), + (3, ParaC), + (4, Statemint), + ], + } +} + +pub const INITIAL_BALANCE: u128 = 10_000_000_000_000_000; + +pub const INITIAL_EVM_BALANCE: u128 = 0; +pub const INITIAL_EVM_NONCE: u32 = 1; + +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![(PARAALICE.into(), INITIAL_BALANCE)], + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_xcm_transactor::GenesisConfig:: { + // match relay runtime construct_runtime order in xcm_mock::relay_chain + relay_indices: RelayChainIndices { + hrmp: 6u8, + init_open_channel: 0u8, + accept_open_channel: 1u8, + close_channel: 2u8, + cancel_open_request: 6u8, + ..Default::default() + }, + ..Default::default() + } + .assimilate_storage(&mut t) + .unwrap(); + + // EVM accounts are self-sufficient. + let mut evm_accounts = BTreeMap::new(); + evm_accounts.insert( + evm_account(), + fp_evm::GenesisAccount { + nonce: U256::from(INITIAL_EVM_NONCE), + balance: U256::from(INITIAL_EVM_BALANCE), + storage: Default::default(), + code: vec![ + 0x00, // STOP + ], + }, + ); + + let genesis_config = pallet_evm::GenesisConfig:: { + accounts: evm_accounts, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + MsgQueue::set_para_id(para_id.into()); + }); + ext +} + +pub fn statemint_ext(para_id: u32) -> sp_io::TestExternalities { + use statemint_like::{MsgQueue, Runtime, System}; + + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap(); + + pallet_balances::GenesisConfig:: { + balances: vec![ + (RELAYALICE.into(), INITIAL_BALANCE), + (RELAYBOB.into(), INITIAL_BALANCE), + ], + } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + MsgQueue::set_para_id(para_id.into()); + }); + ext +} + +pub fn relay_ext(paras: Vec) -> sp_io::TestExternalities { + use relay_chain::{Runtime, System}; + + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap(); + + pallet_balances::GenesisConfig:: { + balances: vec![(RELAYALICE, INITIAL_BALANCE)], + } + .assimilate_storage(&mut t) + .unwrap(); + + let para_genesis: Vec<(ParaId, ParaGenesisArgs)> = paras + .iter() + .map(|¶_id| (para_id.into(), mock_para_genesis_info())) + .collect(); + + let genesis_config = ConfigurationGenesisConfig:: { + config: mock_relay_config(), + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let genesis_config = ParasGenesisConfig:: { + paras: para_genesis, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + }); + ext +} +pub type RelayChainPalletXcm = pallet_xcm::Pallet; +pub type Hrmp = polkadot_runtime_parachains::hrmp::Pallet; + +pub type StatemintBalances = pallet_balances::Pallet; +pub type StatemintChainPalletXcm = pallet_xcm::Pallet; +pub type StatemintAssets = pallet_assets::Pallet; + +pub type ParachainPalletXcm = pallet_xcm::Pallet; +pub type Assets = pallet_assets::Pallet; +pub type LocalAssets = pallet_assets::Pallet; + +pub type Balances = pallet_balances::Pallet; +pub type Treasury = pallet_treasury::Pallet; +pub type AssetManager = pallet_asset_manager::Pallet; +pub type XTokens = orml_xtokens::Pallet; +pub type RelayBalances = pallet_balances::Pallet; +pub type ParaBalances = pallet_balances::Pallet; +pub type XcmTransactor = pallet_xcm_transactor::Pallet; diff --git a/tracing/2601/runtime/moonbase/tests/xcm_mock/parachain.rs b/tracing/2601/runtime/moonbase/tests/xcm_mock/parachain.rs new file mode 100644 index 00000000..090f355d --- /dev/null +++ b/tracing/2601/runtime/moonbase/tests/xcm_mock/parachain.rs @@ -0,0 +1,1229 @@ +// Copyright 2021 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 frame_support::{ + construct_runtime, + dispatch::GetDispatchInfo, + ensure, parameter_types, + traits::{ + AsEnsureOriginWithArg, ConstU32, Everything, Get, InstanceFilter, Nothing, PalletInfoAccess, + }, + weights::Weight, + PalletId, +}; + +use frame_system::{pallet_prelude::BlockNumberFor, EnsureNever, EnsureRoot}; +use pallet_xcm::migration::v1::VersionUncheckedMigrateToV1; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use sp_core::H256; +use sp_runtime::{ + traits::{BlakeTwo256, Hash, IdentityLookup, MaybeEquivalence, Zero}, + Permill, +}; +use sp_std::{convert::TryFrom, prelude::*}; +use xcm::{latest::prelude::*, Version as XcmVersion, VersionedXcm}; + +use cumulus_primitives_core::relay_chain::HrmpChannelId; +use orml_traits::parameter_type_with_key; +use pallet_ethereum::PostLogContent; +use polkadot_core_primitives::BlockNumber as RelayBlockNumber; +use polkadot_parachain::primitives::{Id as ParaId, Sibling}; +use xcm::latest::{ + AssetId as XcmAssetId, Error as XcmError, ExecuteXcm, + Junction::{PalletInstance, Parachain}, + Junctions, MultiLocation, NetworkId, Outcome, Xcm, +}; +use xcm_builder::{ + AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, + CurrencyAdapter as XcmCurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, + FungiblesAdapter, IsConcrete, NoChecking, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountKey20AsNative, SovereignSignedViaLocation, TakeWeightCredit, WithComputedOrigin, +}; +use xcm_executor::{traits::JustTry, Config, XcmExecutor}; + +use scale_info::TypeInfo; +use xcm_simulator::{ + DmpMessageHandlerT as DmpMessageHandler, XcmpMessageFormat, + XcmpMessageHandlerT as XcmpMessageHandler, +}; + +pub type AccountId = moonbeam_core_primitives::AccountId; +pub type Balance = u128; +pub type AssetId = u128; +pub type BlockNumber = BlockNumberFor; + +parameter_types! { + pub const BlockHashCount: u32 = 250; +} + +impl frame_system::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Block = Block; + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + 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 = frame_support::traits::ConstU32<16>; +} + +parameter_types! { + pub ExistentialDeposit: Balance = 0; + 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 = (); + type FreezeIdentifier = (); + type MaxHolds = (); + type MaxFreezes = (); +} + +pub type ForeignAssetInstance = (); +pub type LocalAssetInstance = pallet_assets::Instance1; + +// Required for runtime benchmarks +pallet_assets::runtime_benchmarks_enabled! { + pub struct BenchmarkHelper; + impl pallet_assets::BenchmarkHelper for BenchmarkHelper + where + AssetIdParameter: From, + { + fn create_asset_id_parameter(id: u32) -> AssetIdParameter { + (id as u128).into() + } + } +} + +parameter_types! { + pub const AssetDeposit: Balance = 10; // Does not really matter as this will be only called by root + pub const ApprovalDeposit: Balance = 0; + pub const AssetsStringLimit: u32 = 50; + pub const MetadataDepositBase: Balance = 0; + pub const MetadataDepositPerByte: Balance = 0; + pub const AssetAccountDeposit: Balance = 0; +} + +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = AssetAccountDeposit; + type WeightInfo = pallet_assets::weights::SubstrateWeight; + type RemoveItemsLimit = ConstU32<656>; + type AssetIdParameter = AssetId; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = AssetAccountDeposit; + type WeightInfo = pallet_assets::weights::SubstrateWeight; + type RemoveItemsLimit = ConstU32<656>; + type AssetIdParameter = AssetId; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used +/// when determining ownership of accounts for asset transacting and when attempting to use XCM +/// `Transact` in order to determine the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the default `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + AccountKey20Aliases, + // The rest of multilocations convert via hashing it + xcm_builder::HashedDescriptionDescribeFamilyAllTerminal, +); + +/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, +/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can +/// biases the kind of local `Origin` it will become. +pub type XcmOriginToTransactDispatchOrigin = ( + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // recognised. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognised. + SiblingParachainAsNative, + // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a + // transaction from the Root origin. + ParentAsSuperuser, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + pallet_xcm::XcmPassthrough, + SignedAccountKey20AsNative, +); + +parameter_types! { + pub const UnitWeightCost: Weight = Weight::from_parts(1u64, 1u64); + pub MaxInstructions: u32 = 100; +} + +// Instructing how incoming xcm assets will be handled +pub type ForeignFungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + Assets, + // Use this currency when it is a fungible asset matching any of the locations in + // SelfReserveRepresentations + ( + ConvertedConcreteId< + AssetId, + Balance, + xcm_primitives::AsAssetType, + JustTry, + >, + ), + // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont allow teleports. + NoChecking, + // We dont track any teleports + (), +>; + +/// The transactor for our own chain currency. +pub type LocalAssetTransactor = XcmCurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching any of the locations in + // SelfReserveRepresentations + IsConcrete, + // We can convert the MultiLocations with our converter above: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont allow teleport + (), +>; + +/// Means for transacting local assets besides the native currency on this chain. +pub type LocalFungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + LocalAssets, + // Use this currency when it is a fungible asset matching the given location or name: + ( + ConvertedConcreteId< + AssetId, + Balance, + AsPrefixedGeneralIndex, + JustTry, + >, + ), + // Convert an XCM MultiLocation into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont want to allow teleporting assets + NoChecking, + // The account to use for tracking teleports. + (), +>; + +// These will be our transactors +// We use both transactors +pub type AssetTransactors = ( + LocalAssetTransactor, + ForeignFungiblesTransactor, + LocalFungiblesTransactor, +); + +pub type XcmRouter = super::ParachainXcmRouter; + +pub type XcmBarrier = ( + // Weight that is paid for may be consumed. + TakeWeightCredit, + // Expected responses are OK. + AllowKnownQueryResponses, + WithComputedOrigin< + ( + // If the message is one that immediately attemps to pay for execution, then allow it. + AllowTopLevelPaidExecutionFrom, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, + ), + UniversalLocation, + ConstU32<8>, + >, +); + +parameter_types! { + /// Xcm fees will go to the treasury account + pub XcmFeesAccount: AccountId = Treasury::account_id(); +} + +/// This is the struct that will handle the revenue from xcm fees +pub type XcmFeesToAccount_ = xcm_primitives::XcmFeesToAccount< + Assets, + ( + ConvertedConcreteId< + AssetId, + Balance, + xcm_primitives::AsAssetType, + JustTry, + >, + ), + AccountId, + XcmFeesAccount, +>; + +parameter_types! { + // We cannot skip the native trader for some specific tests, so we will have to work with + // a native trader that charges same number of units as weight + // We use both the old and new anchoring logics + pub ParaTokensPerSecond: (XcmAssetId, u128, u128) = ( + Concrete(SelfReserve::get()), + 1000000000000, + 0, + ); +} + +parameter_types! { + pub const RelayNetwork: NetworkId = NetworkId::Polkadot; + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + pub UniversalLocation: InteriorMultiLocation = + X2(GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())); + + // New Self Reserve location, defines the multilocation identifiying the self-reserve currency + // This is used to match it also against our Balances pallet when we receive such + // a MultiLocation: (Self Balances pallet index) + pub SelfReserve: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; + + pub LocalAssetsPalletLocation: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; + pub const MaxAssetsIntoHolding: u32 = 64; +} + +use frame_system::RawOrigin; +use sp_runtime::traits::PostDispatchInfoOf; +use sp_runtime::DispatchErrorWithPostInfo; +use xcm_executor::traits::CallDispatcher; +moonbeam_runtime_common::impl_moonbeam_xcm_call!(); + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = AssetTransactors; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type IsReserve = orml_xcm_support::MultiNativeAsset< + xcm_primitives::AbsoluteAndRelativeReserve, + >; + type IsTeleporter = (); + type UniversalLocation = UniversalLocation; + type Barrier = XcmBarrier; + type Weigher = FixedWeightBounds; + // We use three traders + // When we receive either representation of the self-reserve asset, + // When we receive a non-reserve asset, we use AssetManager to fetch how many + // units per second we should charge + type Trader = ( + FixedRateOfFungible, + xcm_primitives::FirstAssetTrader, + ); + + type ResponseHandler = PolkadotXcm; + type SubscriptionService = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type CallDispatcher = MoonbeamCall; + type AssetLocker = (); + type AssetExchanger = (); + type PalletInstancesInfo = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; + type SafeCallFilter = Everything; + type Aliasers = Nothing; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +// Our currencyId. We distinguish for now between SelfReserve, and Others, defined by their Id. +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum CurrencyId { + SelfReserve, + ForeignAsset(AssetId), + LocalAssetReserve(AssetId), +} + +// How to convert from CurrencyId to MultiLocation +pub struct CurrencyIdtoMultiLocation(sp_std::marker::PhantomData); +impl sp_runtime::traits::Convert> + for CurrencyIdtoMultiLocation +where + AssetXConverter: MaybeEquivalence, +{ + fn convert(currency: CurrencyId) -> Option { + match currency { + CurrencyId::SelfReserve => { + // For now and until Xtokens is adapted to handle 0.9.16 version we use + // the old anchoring here + // This is not a problem in either cases, since the view of the destination + // chain does not change + // TODO! change this to NewAnchoringSelfReserve once xtokens is adapted for it + let multi: MultiLocation = SelfReserve::get(); + Some(multi) + } + CurrencyId::ForeignAsset(asset) => AssetXConverter::convert_back(&asset), + CurrencyId::LocalAssetReserve(asset) => { + let mut location = LocalAssetsPalletLocation::get(); + location.push_interior(Junction::GeneralIndex(asset)).ok(); + Some(location) + } + } + } +} + +parameter_types! { + pub const BaseXcmWeight: Weight = Weight::from_parts(100u64, 100u64); + pub const MaxAssetsForTransfer: usize = 2; + pub SelfLocation: MultiLocation = MultiLocation::here(); + pub SelfLocationAbsolute: MultiLocation = MultiLocation { + parents:1, + interior: Junctions::X1( + Parachain(MsgQueue::parachain_id().into()) + ) + }; +} + +parameter_type_with_key! { + pub ParachainMinFee: |location: MultiLocation| -> Option { + match (location.parents, location.first_interior()) { + (1, Some(Parachain(4u32))) => Some(50u128), + _ => None, + } + }; +} + +// The XCM message wrapper wrapper +impl orml_xtokens::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type CurrencyId = CurrencyId; + type AccountIdToMultiLocation = xcm_primitives::AccountIdToMultiLocation; + type CurrencyIdConvert = + CurrencyIdtoMultiLocation>; + type XcmExecutor = XcmExecutor; + type SelfLocation = SelfLocation; + type Weigher = xcm_builder::FixedWeightBounds; + type BaseXcmWeight = BaseXcmWeight; + type UniversalLocation = UniversalLocation; + type MaxAssetsForTransfer = MaxAssetsForTransfer; + type MinXcmFee = ParachainMinFee; + type MultiLocationsFilter = Everything; + type ReserveProvider = xcm_primitives::AbsoluteAndRelativeReserve; +} + +parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const ProposalBondMinimum: Balance = 0; + pub const SpendPeriod: u32 = 0; + pub const TreasuryId: PalletId = PalletId(*b"pc/trsry"); + pub const MaxApprovals: u32 = 100; +} + +impl pallet_treasury::Config for Runtime { + type PalletId = TreasuryId; + type Currency = Balances; + type ApproveOrigin = EnsureRoot; + type RejectOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type OnSlash = Treasury; + type ProposalBond = ProposalBond; + type ProposalBondMinimum = ProposalBondMinimum; + type SpendPeriod = SpendPeriod; + type Burn = (); + type BurnDestination = (); + type MaxApprovals = MaxApprovals; + type WeightInfo = (); + type SpendFunds = (); + type ProposalBondMaximum = (); + type SpendOrigin = frame_support::traits::NeverEnsureOrigin; // Same as Polkadot +} + +#[frame_support::pallet] +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] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn parachain_id)] + pub(super) type ParachainId = StorageValue<_, ParaId, 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 (result, event) = match Xcm::::try_from(xcm) { + Ok(xcm) => { + let location = MultiLocation::new(1, Junctions::X1(Parachain(sender.into()))); + let mut id = [0u8; 32]; + id.copy_from_slice(hash.as_ref()); + match T::XcmExecutor::execute_xcm(location, xcm, id, max_weight) { + Outcome::Error(e) => (Err(e.clone()), 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 (_i, (_sent_at, data)) in iter.enumerate() { + let id = sp_io::hashing::blake2_256(&data[..]); + let maybe_msg = VersionedXcm::::decode(&mut &data[..]) + .map(Xcm::::try_from); + match maybe_msg { + Err(_) => { + Self::deposit_event(Event::InvalidFormat(id)); + } + Ok(Err(())) => { + Self::deposit_event(Event::UnsupportedVersion(id)); + } + Ok(Ok(x)) => { + let outcome = T::XcmExecutor::execute_xcm(Parent, x, id, limit); + + Self::deposit_event(Event::ExecutedDownward(id, outcome)); + } + } + } + limit + } + } +} + +// Pallet to provide the version, used to test runtime upgrade version changes +#[frame_support::pallet] +pub mod mock_version_changer { + use super::*; + use frame_support::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + } + + #[pallet::call] + impl Pallet {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn current_version)] + pub(super) type CurrentVersion = StorageValue<_, XcmVersion, ValueQuery>; + + impl Get for Pallet { + fn get() -> XcmVersion { + Self::current_version() + } + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + // XCMP + /// Some XCM was executed OK. + VersionChanged(XcmVersion), + } + + impl Pallet { + pub fn set_version(version: XcmVersion) { + CurrentVersion::::put(version); + Self::deposit_event(Event::VersionChanged(version)); + } + } +} + +impl mock_msg_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +impl mock_version_changer::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} + +pub type LocalOriginToLocation = + xcm_primitives::SignedToAccountId20; + +parameter_types! { + pub MatcherLocation: MultiLocation = MultiLocation::here(); +} + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parent.into()); +} + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = frame_support::traits::Nothing; + type XcmExecutor = XcmExecutor; + // Do not allow teleports + 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; + // We use a custom one to test runtime ugprades + type AdvertisedXcmVersion = XcmVersioner; + type Currency = Balances; + type CurrencyMatcher = IsConcrete; + type TrustedLockers = (); + type SovereignAccountOf = (); + type MaxLockers = ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type AdminOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; +} + +// Our AssetType. For now we only handle Xcm Assets +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum AssetType { + Xcm(MultiLocation), +} +impl Default for AssetType { + fn default() -> Self { + Self::Xcm(MultiLocation::here()) + } +} + +impl From for AssetType { + fn from(location: MultiLocation) -> Self { + Self::Xcm(location) + } +} + +impl Into> for AssetType { + fn into(self) -> Option { + match self { + Self::Xcm(location) => Some(location), + } + } +} + +// Implementation on how to retrieve the AssetId from an AssetType +// We simply hash the AssetType and take the lowest 128 bits +impl From for AssetId { + fn from(asset: AssetType) -> AssetId { + match asset { + AssetType::Xcm(id) => { + let mut result: [u8; 16] = [0u8; 16]; + let hash: H256 = id.using_encoded(::Hashing::hash); + result.copy_from_slice(&hash.as_fixed_bytes()[0..16]); + u128::from_le_bytes(result) + } + } + } +} + +// We instruct how to register the Assets +// In this case, we tell it to Create an Asset in pallet-assets +pub struct AssetRegistrar; +use frame_support::pallet_prelude::DispatchResult; +impl pallet_asset_manager::AssetRegistrar for AssetRegistrar { + fn create_foreign_asset( + asset: AssetId, + min_balance: Balance, + metadata: AssetMetadata, + is_sufficient: bool, + ) -> DispatchResult { + Assets::force_create( + RuntimeOrigin::root(), + asset, + AssetManager::account_id(), + is_sufficient, + min_balance, + )?; + + Assets::force_set_metadata( + RuntimeOrigin::root(), + asset, + metadata.name, + metadata.symbol, + metadata.decimals, + false, + ) + } + + fn create_local_asset( + asset: AssetId, + _creator: AccountId, + min_balance: Balance, + is_sufficient: bool, + owner: AccountId, + ) -> DispatchResult { + LocalAssets::force_create( + RuntimeOrigin::root(), + asset, + owner, + is_sufficient, + min_balance, + )?; + + // TODO uncomment when we feel comfortable + /* + // The asset has been created. Let's put the revert code in the precompile address + let precompile_address = Runtime::asset_id_to_account(ASSET_PRECOMPILE_ADDRESS_PREFIX, asset); + pallet_evm::AccountCodes::::insert( + precompile_address, + vec![0x60, 0x00, 0x60, 0x00, 0xfd], + );*/ + Ok(()) + } + + fn destroy_foreign_asset(asset: AssetId) -> DispatchResult { + // Mark the asset as destroying + Assets::start_destroy(RuntimeOrigin::root(), asset.into())?; + + Ok(()) + } + + fn destroy_local_asset(asset: AssetId) -> DispatchResult { + // Mark the asset as destroying + LocalAssets::start_destroy(RuntimeOrigin::root(), asset.into())?; + + Ok(()) + } + + fn destroy_asset_dispatch_info_weight(asset: AssetId) -> Weight { + RuntimeCall::Assets( + pallet_assets::Call::::start_destroy { + id: asset.into(), + }, + ) + .get_dispatch_info() + .weight + } +} + +#[derive(Clone, Default, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub struct AssetMetadata { + pub name: Vec, + pub symbol: Vec, + pub decimals: u8, +} + +pub struct LocalAssetIdCreator; +impl pallet_asset_manager::LocalAssetIdCreator for LocalAssetIdCreator { + fn create_asset_id_from_metadata(local_asset_counter: u128) -> AssetId { + // Our means of converting a local asset counter to an assetId + // We basically hash (local asset counter) + let mut result: [u8; 16] = [0u8; 16]; + let hash: H256 = + local_asset_counter.using_encoded(::Hashing::hash); + result.copy_from_slice(&hash.as_fixed_bytes()[0..16]); + u128::from_le_bytes(result) + } +} + +impl pallet_asset_manager::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type AssetRegistrarMetadata = AssetMetadata; + type ForeignAssetType = AssetType; + type AssetRegistrar = AssetRegistrar; + type ForeignAssetModifierOrigin = EnsureRoot; + type LocalAssetModifierOrigin = EnsureRoot; + type LocalAssetIdCreator = LocalAssetIdCreator; + type Currency = Balances; + type LocalAssetDeposit = AssetDeposit; + type WeightInfo = (); +} + +// 1 ROC/WND should be enough +parameter_types! { + pub MaxHrmpRelayFee: MultiAsset = (MultiLocation::parent(), 1_000_000_000_000u128).into(); +} + +impl pallet_xcm_transactor::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type Transactor = MockTransactors; + type DerivativeAddressRegistrationOrigin = EnsureRoot; + type SovereignAccountDispatcherOrigin = frame_system::EnsureRoot; + type CurrencyId = CurrencyId; + type AccountIdToMultiLocation = xcm_primitives::AccountIdToMultiLocation; + type CurrencyIdToMultiLocation = + CurrencyIdtoMultiLocation>; + type SelfLocation = SelfLocation; + type Weigher = xcm_builder::FixedWeightBounds; + type UniversalLocation = UniversalLocation; + type XcmSender = XcmRouter; + type BaseXcmWeight = BaseXcmWeight; + type AssetTransactor = AssetTransactors; + type ReserveProvider = xcm_primitives::AbsoluteAndRelativeReserve; + type WeightInfo = (); + type HrmpManipulatorOrigin = EnsureRoot; + type MaxHrmpFee = xcm_builder::Case; +} + +parameter_types! { + pub const MinimumPeriod: u64 = 1000; +} +impl pallet_timestamp::Config for Runtime { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +use sp_core::U256; + +const MAX_POV_SIZE: u64 = 5 * 1024 * 1024; +/// Block storage limit in bytes. Set to 40 KB. +const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024; + +parameter_types! { + pub BlockGasLimit: U256 = U256::from(u64::MAX); + pub WeightPerGas: Weight = Weight::from_parts(1, 0); + pub GasLimitPovSizeRatio: u64 = { + let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64(); + block_gas_limit.saturating_div(MAX_POV_SIZE) + }; + pub GasLimitStorageGrowthRatio: u64 = + BlockGasLimit::get().min(u64::MAX.into()).low_u64().saturating_div(BLOCK_STORAGE_LIMIT); +} + +impl pallet_evm::Config for Runtime { + type FeeCalculator = (); + type GasWeightMapping = pallet_evm::FixedGasWeightMapping; + type WeightPerGas = WeightPerGas; + + type CallOrigin = pallet_evm::EnsureAddressRoot; + type WithdrawOrigin = pallet_evm::EnsureAddressNever; + + type AddressMapping = pallet_evm::IdentityAddressMapping; + type Currency = Balances; + type Runner = pallet_evm::runner::stack::Runner; + + type RuntimeEvent = RuntimeEvent; + type PrecompilesType = (); + type PrecompilesValue = (); + type ChainId = (); + type BlockGasLimit = BlockGasLimit; + type OnChargeTransaction = (); + type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping; + type FindAuthor = (); + type OnCreate = (); + type GasLimitPovSizeRatio = GasLimitPovSizeRatio; + type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio; + type Timestamp = Timestamp; + type WeightInfo = pallet_evm::weights::SubstrateWeight; +} + +pub struct NormalFilter; +impl frame_support::traits::Contains for NormalFilter { + fn contains(c: &RuntimeCall) -> bool { + match c { + _ => true, + } + } +} + +// We need to use the encoding from the relay mock runtime +#[derive(Encode, Decode)] +pub enum RelayCall { + #[codec(index = 5u8)] + // the index should match the position of the module in `construct_runtime!` + Utility(UtilityCall), + #[codec(index = 6u8)] + // the index should match the position of the module in `construct_runtime!` + Hrmp(HrmpCall), +} + +#[derive(Encode, Decode)] +pub enum UtilityCall { + #[codec(index = 1u8)] + AsDerivative(u16), +} + +// HRMP call encoding, needed for xcm transactor pallet +#[derive(Encode, Decode)] +pub enum HrmpCall { + #[codec(index = 0u8)] + InitOpenChannel(ParaId, u32, u32), + #[codec(index = 1u8)] + AcceptOpenChannel(ParaId), + #[codec(index = 2u8)] + CloseChannel(HrmpChannelId), + #[codec(index = 6u8)] + CancelOpenRequest(HrmpChannelId, u32), +} + +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum MockTransactors { + Relay, +} + +impl xcm_primitives::XcmTransact for MockTransactors { + fn destination(self) -> MultiLocation { + match self { + MockTransactors::Relay => MultiLocation::parent(), + } + } +} + +impl xcm_primitives::UtilityEncodeCall for MockTransactors { + fn encode_call(self, call: xcm_primitives::UtilityAvailableCalls) -> Vec { + match self { + MockTransactors::Relay => match call { + xcm_primitives::UtilityAvailableCalls::AsDerivative(a, b) => { + let mut call = + RelayCall::Utility(UtilityCall::AsDerivative(a.clone())).encode(); + call.append(&mut b.clone()); + call + } + }, + } + } +} + +pub struct MockHrmpEncoder; +impl xcm_primitives::HrmpEncodeCall for MockHrmpEncoder { + fn hrmp_encode_call( + call: xcm_primitives::HrmpAvailableCalls, + ) -> Result, xcm::latest::Error> { + match call { + xcm_primitives::HrmpAvailableCalls::InitOpenChannel(a, b, c) => Ok(RelayCall::Hrmp( + HrmpCall::InitOpenChannel(a.clone(), b.clone(), c.clone()), + ) + .encode()), + xcm_primitives::HrmpAvailableCalls::AcceptOpenChannel(a) => { + Ok(RelayCall::Hrmp(HrmpCall::AcceptOpenChannel(a.clone())).encode()) + } + xcm_primitives::HrmpAvailableCalls::CloseChannel(a) => { + Ok(RelayCall::Hrmp(HrmpCall::CloseChannel(a.clone())).encode()) + } + xcm_primitives::HrmpAvailableCalls::CancelOpenRequest(a, b) => { + Ok(RelayCall::Hrmp(HrmpCall::CancelOpenRequest(a.clone(), b.clone())).encode()) + } + } + } +} + +parameter_types! { + pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes; +} + +impl pallet_ethereum::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type StateRoot = pallet_ethereum::IntermediateStateRoot; + type PostLogContent = PostBlockAndTxnHashes; + type ExtraDataLength = ConstU32<30>; +} +parameter_types! { + pub ReservedXcmpWeight: Weight = Weight::from_parts(u64::max_value(), 0); +} + +#[derive( + Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, MaxEncodedLen, TypeInfo, +)] +pub enum ProxyType { + NotAllowed = 0, + Any = 1, +} + +impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType {} + +impl InstanceFilter for ProxyType { + fn filter(&self, _c: &RuntimeCall) -> bool { + match self { + ProxyType::NotAllowed => false, + ProxyType::Any => true, + } + } + fn is_superset(&self, _o: &Self) -> bool { + false + } +} + +impl Default for ProxyType { + fn default() -> Self { + Self::NotAllowed + } +} + +parameter_types! { + pub const ProxyCost: u64 = 1; +} + +impl pallet_proxy::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type ProxyType = ProxyType; + type ProxyDepositBase = ProxyCost; + type ProxyDepositFactor = ProxyCost; + type MaxProxies = ConstU32<32>; + type WeightInfo = pallet_proxy::weights::SubstrateWeight; + type MaxPending = ConstU32<32>; + type CallHasher = BlakeTwo256; + type AnnouncementDepositBase = ProxyCost; + type AnnouncementDepositFactor = ProxyCost; +} + +pub struct EthereumXcmEnsureProxy; +impl xcm_primitives::EnsureProxy for EthereumXcmEnsureProxy { + fn ensure_ok(delegator: AccountId, delegatee: AccountId) -> Result<(), &'static str> { + // The EVM implicitely contains an Any proxy, so we only allow for "Any" proxies + let def: pallet_proxy::ProxyDefinition = + pallet_proxy::Pallet::::find_proxy( + &delegator, + &delegatee, + Some(ProxyType::Any), + ) + .map_err(|_| "proxy error: expected `ProxyType::Any`")?; + // We only allow to use it for delay zero proxies, as the call will iMmediatly be executed + ensure!(def.delay.is_zero(), "proxy delay is Non-zero`"); + Ok(()) + } +} + +impl pallet_ethereum_xcm::Config for Runtime { + type InvalidEvmTransactionError = pallet_ethereum::InvalidTransactionWrapper; + type ValidatedTransaction = pallet_ethereum::ValidatedTransaction; + type XcmEthereumOrigin = pallet_ethereum_xcm::EnsureXcmEthereumTransaction; + type ReservedXcmpWeight = ReservedXcmpWeight; + type EnsureProxy = EthereumXcmEnsureProxy; + type ControllerOrigin = EnsureRoot; +} + +type Block = frame_system::mocking::MockBlockU32; + +construct_runtime!( + pub enum Runtime { + System: frame_system, + Balances: pallet_balances, + MsgQueue: mock_msg_queue, + XcmVersioner: mock_version_changer, + + PolkadotXcm: pallet_xcm, + Assets: pallet_assets, + CumulusXcm: cumulus_pallet_xcm, + XTokens: orml_xtokens, + AssetManager: pallet_asset_manager, + XcmTransactor: pallet_xcm_transactor, + Treasury: pallet_treasury, + LocalAssets: pallet_assets::, + Proxy: pallet_proxy, + + Timestamp: pallet_timestamp, + EVM: pallet_evm, + Ethereum: pallet_ethereum, + EthereumXcm: pallet_ethereum_xcm, + } +); + +pub(crate) fn para_events() -> Vec { + System::events() + .into_iter() + .map(|r| r.event) + .filter_map(|e| Some(e)) + .collect::>() +} + +use frame_support::traits::{OnFinalize, OnInitialize, OnRuntimeUpgrade}; +pub(crate) fn on_runtime_upgrade() { + VersionUncheckedMigrateToV1::::on_runtime_upgrade(); +} + +pub(crate) fn para_roll_to(n: BlockNumber) { + while System::block_number() < n { + PolkadotXcm::on_finalize(System::block_number()); + Balances::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Balances::on_initialize(System::block_number()); + PolkadotXcm::on_initialize(System::block_number()); + } +} diff --git a/tracing/2601/runtime/moonbase/tests/xcm_mock/relay_chain.rs b/tracing/2601/runtime/moonbase/tests/xcm_mock/relay_chain.rs new file mode 100644 index 00000000..30c5537b --- /dev/null +++ b/tracing/2601/runtime/moonbase/tests/xcm_mock/relay_chain.rs @@ -0,0 +1,406 @@ +// Copyright 2021 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::{Everything, Nothing, ProcessMessage, ProcessMessageError}, +}; +use frame_system::pallet_prelude::BlockNumberFor; +use sp_core::H256; +use sp_runtime::{ + traits::{ConstU32, IdentityLookup}, + AccountId32, +}; + +use frame_support::weights::{Weight, WeightMeter}; +use polkadot_parachain::primitives::Id as ParaId; +use polkadot_runtime_parachains::{ + configuration, dmp, hrmp, + inclusion::{AggregateMessageOrigin, UmpQueueId}, + origin, paras, shared, +}; +use sp_runtime::transaction_validity::TransactionPriority; +use sp_runtime::Permill; +use xcm::latest::prelude::*; +use xcm_builder::{ + Account32Hash, AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, ChildParachainAsNative, ChildParachainConvertsVia, + ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible, + FixedWeightBounds, IsConcrete, ProcessXcmMessage, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, WithComputedOrigin, +}; +use xcm_executor::{Config, XcmExecutor}; +pub type AccountId = AccountId32; +pub type Balance = u128; +pub type BlockNumber = BlockNumberFor; + +parameter_types! { + pub const BlockHashCount: u32 = 250; +} + +impl frame_system::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Block = Block; + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + 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 = (); + type FreezeIdentifier = (); + type MaxHolds = (); + type MaxFreezes = (); +} + +impl pallet_utility::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type WeightInfo = (); + type PalletsOrigin = OriginCaller; +} + +impl shared::Config for Runtime {} + +impl configuration::Config for Runtime { + type WeightInfo = configuration::TestWeightInfo; +} + +parameter_types! { + pub KsmLocation: MultiLocation = Here.into(); + pub const KusamaNetwork: NetworkId = NetworkId::Kusama; + pub const AnyNetwork: Option = None; + pub UniversalLocation: InteriorMultiLocation = Here; +} + +pub type SovereignAccountOf = ( + ChildParachainConvertsVia, + AccountId32Aliases, + // Not enabled in the relay per se, but we enable it to test + // the transact_through_signed extrinsic + Account32Hash, +); + +pub type LocalAssetTransactor = + XcmCurrencyAdapter, SovereignAccountOf, AccountId, ()>; + +type LocalOriginConverter = ( + SovereignSignedViaLocation, + ChildParachainAsNative, + SignedAccountId32AsNative, + ChildSystemParachainAsSuperuser, +); + +parameter_types! { + pub const BaseXcmWeight: Weight = Weight::from_parts(1000u64, 1000u64); + pub KsmPerSecond: (AssetId, u128, u128) = (Concrete(KsmLocation::get()), 1, 1); + pub const MaxInstructions: u32 = 100; + pub const MaxAssetsIntoHolding: u32 = 64; + pub MatcherLocation: MultiLocation = MultiLocation::here(); +} + +pub type XcmRouter = super::RelayChainXcmRouter; + +pub type XcmBarrier = ( + // Weight that is paid for may be consumed. + TakeWeightCredit, + // Expected responses are OK. + AllowKnownQueryResponses, + WithComputedOrigin< + ( + // If the message is one that immediately attemps to pay for execution, then allow it. + AllowTopLevelPaidExecutionFrom, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, + ), + UniversalLocation, + ConstU32<8>, + >, +); + +parameter_types! { + pub Kusama: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(KsmLocation::get()) }); + pub Statemine: MultiLocation = Parachain(4).into(); + pub KusamaForStatemine: (MultiAssetFilter, MultiLocation) = (Kusama::get(), Statemine::get()); +} + +pub type TrustedTeleporters = xcm_builder::Case; + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = LocalAssetTransactor; + type OriginConverter = LocalOriginConverter; + type IsReserve = (); + type IsTeleporter = TrustedTeleporters; + type UniversalLocation = UniversalLocation; + type Barrier = XcmBarrier; + type Weigher = FixedWeightBounds; + type Trader = FixedRateOfFungible; + type ResponseHandler = XcmPallet; + type AssetTrap = XcmPallet; + type AssetClaims = XcmPallet; + type SubscriptionService = XcmPallet; + type CallDispatcher = RuntimeCall; + type AssetLocker = (); + type AssetExchanger = (); + type PalletInstancesInfo = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; + type SafeCallFilter = Everything; + type Aliasers = Nothing; +} + +pub type LocalOriginToLocation = SignedToAccountId32; + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parent.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 = (); + type TrustedLockers = (); + type SovereignAccountOf = (); + type MaxLockers = ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type AdminOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; +} + +parameter_types! { + pub const FirstMessageFactorPercent: u64 = 100; +} + +parameter_types! { + pub const ParasUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); +} + +/// A very dumb implementation of `EstimateNextSessionRotation`. At the moment of writing, this +/// is more to satisfy type requirements rather than to test anything. +pub struct TestNextSessionRotation; + +impl frame_support::traits::EstimateNextSessionRotation for TestNextSessionRotation { + fn average_session_length() -> u32 { + 10 + } + + fn estimate_current_session_progress(_now: u32) -> (Option, Weight) { + (None, Weight::zero()) + } + + fn estimate_next_session_rotation(_now: u32) -> (Option, Weight) { + (None, Weight::zero()) + } +} + +impl paras::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = paras::TestWeightInfo; + type UnsignedPriority = ParasUnsignedPriority; + type NextSessionRotation = TestNextSessionRotation; + type QueueFootprinter = (); + type OnNewHead = (); +} + +impl dmp::Config for Runtime {} + +impl hrmp::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type WeightInfo = TestHrmpWeightInfo; + type ChannelManager = frame_system::EnsureRoot; +} + +impl frame_system::offchain::SendTransactionTypes for Runtime +where + RuntimeCall: From, +{ + type Extrinsic = UncheckedExtrinsic; + type OverarchingCall = RuntimeCall; +} + +impl origin::Config for Runtime {} + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlockU32; + +parameter_types! { + pub MessageQueueServiceWeight: Weight = Weight::from_parts(1_000_000_000, 1_000_000); + pub const MessageQueueHeapSize: u32 = 65_536; + pub const MessageQueueMaxStale: u32 = 16; +} + +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, + }; + ProcessXcmMessage::, 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 WeightInfo = (); + type QueuePausedQuery = (); +} + +construct_runtime!( + pub enum Runtime { + System: frame_system, + Balances: pallet_balances, + ParasOrigin: origin, + MessageQueue: pallet_message_queue, + XcmPallet: pallet_xcm, + Utility: pallet_utility, + Hrmp: hrmp, + Dmp: dmp, + Paras: paras, + Configuration: configuration, + } +); + +pub(crate) fn relay_events() -> Vec { + System::events() + .into_iter() + .map(|r| r.event) + .filter_map(|e| Some(e)) + .collect::>() +} + +use frame_support::traits::{OnFinalize, OnInitialize}; +pub(crate) fn relay_roll_to(n: BlockNumber) { + while System::block_number() < n { + XcmPallet::on_finalize(System::block_number()); + Balances::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Balances::on_initialize(System::block_number()); + XcmPallet::on_initialize(System::block_number()); + } +} + +/// A weight info that is only suitable for testing. +pub struct TestHrmpWeightInfo; + +impl hrmp::WeightInfo for TestHrmpWeightInfo { + fn hrmp_accept_open_channel() -> Weight { + Weight::from_parts(1, 0) + } + fn force_clean_hrmp(_: u32, _: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn force_process_hrmp_close(_: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn force_process_hrmp_open(_: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn hrmp_cancel_open_request(_: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn hrmp_close_channel() -> Weight { + Weight::from_parts(1, 0) + } + fn hrmp_init_open_channel() -> Weight { + Weight::from_parts(1, 0) + } + fn clean_open_channel_requests(_: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn force_open_hrmp_channel(_: u32) -> Weight { + Weight::from_parts(1, 0) + } +} diff --git a/tracing/2601/runtime/moonbase/tests/xcm_mock/statemint_like.rs b/tracing/2601/runtime/moonbase/tests/xcm_mock/statemint_like.rs new file mode 100644 index 00000000..b7270cdf --- /dev/null +++ b/tracing/2601/runtime/moonbase/tests/xcm_mock/statemint_like.rs @@ -0,0 +1,552 @@ +// Copyright 2021 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, match_types, parameter_types, + traits::{AsEnsureOriginWithArg, Everything, Nothing}, + weights::Weight, +}; +use frame_system::{EnsureRoot, EnsureSigned}; + +use sp_core::H256; +use sp_runtime::{ + traits::{ConstU32, Hash, IdentityLookup}, + AccountId32, +}; + +use polkadot_core_primitives::BlockNumber as RelayBlockNumber; + +use polkadot_parachain::primitives::Id as ParaId; +use polkadot_parachain::primitives::Sibling; +use sp_std::convert::TryFrom; +use xcm::latest::prelude::*; +use xcm::VersionedXcm; +use xcm_builder::{ + AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, AsPrefixedGeneralIndex, + ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, + FungiblesAdapter, IsConcrete, NoChecking, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, +}; +use xcm_executor::{traits::JustTry, Config, XcmExecutor}; +use xcm_simulator::{ + DmpMessageHandlerT as DmpMessageHandler, XcmpMessageFormat, + XcmpMessageHandlerT as XcmpMessageHandler, +}; +pub type AccountId = AccountId32; +pub type Balance = u128; +pub type AssetId = u128; + +parameter_types! { + pub const BlockHashCount: u32 = 250; +} + +impl frame_system::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Block = Block; + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + 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 = frame_support::traits::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 = (); + type FreezeIdentifier = (); + type MaxHolds = (); + type MaxFreezes = (); +} + +// Required for runtime benchmarks +pallet_assets::runtime_benchmarks_enabled! { + pub struct BenchmarkHelper; + impl pallet_assets::BenchmarkHelper for BenchmarkHelper + where + AssetIdParameter: From, + { + fn create_asset_id_parameter(id: u32) -> AssetIdParameter { + (id as u128).into() + } + } +} + +parameter_types! { + pub const AssetDeposit: Balance = 0; // 1 UNIT deposit to create asset + pub const ApprovalDeposit: Balance = 0; + pub const AssetsStringLimit: u32 = 50; + /// Key = 32 bytes, Value = 36 bytes (32+1+1+1+1) + // https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271 + pub const MetadataDepositBase: Balance = 0; + pub const MetadataDepositPerByte: Balance = 0; + pub const ExecutiveBody: BodyId = BodyId::Executive; + pub const AssetAccountDeposit: Balance = 0; +} + +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = AssetAccountDeposit; + type WeightInfo = (); + type RemoveItemsLimit = ConstU32<656>; + type AssetIdParameter = AssetId; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +parameter_types! { + pub const KsmLocation: MultiLocation = MultiLocation::parent(); + pub const RelayNetwork: NetworkId = NetworkId::Kusama; + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + pub UniversalLocation: InteriorMultiLocation = + X2(GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())); + pub Local: MultiLocation = Here.into(); + pub CheckingAccount: AccountId = PolkadotXcm::check_account(); + pub KsmPerSecond: (xcm::latest::prelude::AssetId, u128, u128) = + (Concrete(KsmLocation::get()), 1, 1); +} + +/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used +/// when determining ownership of accounts for asset transacting and when attempting to use XCM +/// `Transact` in order to determine the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the default `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // Straight up local `AccountId32` origins just alias directly to `AccountId`. + AccountId32Aliases, +); + +/// Means for transacting the native currency on this chain. +pub type CurrencyTransactor = CurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching the given location or name: + IsConcrete, + // Convert an XCM MultiLocation into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We don't track any teleports of `Balances`. + (), +>; + +/// Means for transacting assets besides the native currency on this chain. +pub type FungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + Assets, + // Use this currency when it is a fungible asset matching the given location or name: + ConvertedConcreteId< + AssetId, + Balance, + AsPrefixedGeneralIndex, + JustTry, + >, + // Convert an XCM MultiLocation into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We only want to allow teleports of known assets. We use non-zero issuance as an indication + // that this asset is known. + NoChecking, + // The account to use for tracking teleports. + CheckingAccount, +>; +/// Means for transacting assets on this chain. +pub type AssetTransactors = (CurrencyTransactor, FungiblesTransactor); + +/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, +/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can +/// biases the kind of local `Origin` it will become. +pub type XcmOriginToTransactDispatchOrigin = ( + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when + // recognised. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognised. + SiblingParachainAsNative, + // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a + // transaction from the Root origin. + ParentAsSuperuser, + // Native signed account converter; this just converts an `AccountId32` origin into a normal + // `Origin::Signed` origin of the same 32-byte value. + SignedAccountId32AsNative, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + pallet_xcm::XcmPassthrough, +); + +parameter_types! { + // One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate. + pub UnitWeightCost: Weight = Weight::from_parts(100u64, 100u64); + pub const MaxInstructions: u32 = 100; +} + +match_types! { + pub type ParentOrParentsExecutivePlurality: impl Contains = { + MultiLocation { parents: 1, interior: Here } | + MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Executive, .. }) } + }; +} +match_types! { + pub type ParentOrSiblings: impl Contains = { + MultiLocation { parents: 1, interior: Here } | + MultiLocation { parents: 1, interior: X1(_) } + }; +} + +pub type Barrier = ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + // Parent and its exec plurality get free execution + AllowUnpaidExecutionFrom, + // Expected responses are OK. + AllowKnownQueryResponses, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, +); + +parameter_types! { + pub MatcherLocation: MultiLocation = MultiLocation::here(); + pub const MaxAssetsIntoHolding: u32 = 64; +} + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = AssetTransactors; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type IsReserve = + orml_xcm_support::MultiNativeAsset; + type IsTeleporter = (); + type UniversalLocation = UniversalLocation; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = FixedRateOfFungible; + type ResponseHandler = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type SubscriptionService = PolkadotXcm; + type CallDispatcher = RuntimeCall; + type AssetLocker = (); + type AssetExchanger = (); + type PalletInstancesInfo = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; + type SafeCallFilter = Everything; + type Aliasers = Nothing; +} + +/// No local origins on this chain are allowed to dispatch XCM sends/executions. +pub type LocalOriginToLocation = SignedToAccountId32; + +pub type XcmRouter = super::ParachainXcmRouter; + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parent.into()); +} + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = 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 = (); + type MaxLockers = ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type AdminOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +#[frame_support::pallet] +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] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn parachain_id)] + pub(super) type ParachainId = StorageValue<_, ParaId, 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 (result, event) = match Xcm::::try_from(xcm) { + Ok(xcm) => { + let location = MultiLocation::new(1, Junctions::X1(Parachain(sender.into()))); + let mut id = [0u8; 32]; + id.copy_from_slice(hash.as_ref()); + match T::XcmExecutor::execute_xcm(location, xcm, id, max_weight) { + Outcome::Error(e) => (Err(e.clone()), 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 (_i, (_sent_at, data)) in iter.enumerate() { + let id = sp_io::hashing::blake2_256(&data[..]); + let maybe_msg = VersionedXcm::::decode(&mut &data[..]) + .map(Xcm::::try_from); + match maybe_msg { + Err(_) => { + Self::deposit_event(Event::InvalidFormat(id)); + } + Ok(Err(())) => { + Self::deposit_event(Event::UnsupportedVersion(id)); + } + Ok(Ok(x)) => { + let outcome = T::XcmExecutor::execute_xcm(Parent, x, id, limit); + + Self::deposit_event(Event::ExecutedDownward(id, outcome)); + } + } + } + limit + } + } +} +impl mock_msg_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +// Pallet to cover test cases for change https://github.com/paritytech/cumulus/pull/831 +#[frame_support::pallet] +pub mod mock_statemint_prefix { + use super::*; + use frame_support::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + } + + #[pallet::call] + impl Pallet {} + + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn current_prefix)] + pub(super) type CurrentPrefix = StorageValue<_, MultiLocation, ValueQuery>; + + impl Get for Pallet { + fn get() -> MultiLocation { + Self::current_prefix() + } + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + // Changed Prefix + PrefixChanged(MultiLocation), + } + + impl Pallet { + pub fn set_prefix(prefix: MultiLocation) { + CurrentPrefix::::put(&prefix); + Self::deposit_event(Event::PrefixChanged(prefix)); + } + } +} + +impl mock_statemint_prefix::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} + +type Block = frame_system::mocking::MockBlockU32; +construct_runtime!( + pub enum Runtime { + System: frame_system, + Balances: pallet_balances, + PolkadotXcm: pallet_xcm, + CumulusXcm: cumulus_pallet_xcm, + MsgQueue: mock_msg_queue, + Assets: pallet_assets, + PrefixChanger: mock_statemint_prefix, + + } +); diff --git a/tracing/2601/runtime/moonbase/tests/xcm_tests.rs b/tracing/2601/runtime/moonbase/tests/xcm_tests.rs new file mode 100644 index 00000000..003b6f00 --- /dev/null +++ b/tracing/2601/runtime/moonbase/tests/xcm_tests.rs @@ -0,0 +1,4054 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Moonbase Runtime Xcm Tests + +mod xcm_mock; +use frame_support::{ + assert_ok, + traits::{ConstU32, PalletInfo, PalletInfoAccess}, + weights::constants::WEIGHT_REF_TIME_PER_SECOND, + weights::Weight, + BoundedVec, +}; +use pallet_asset_manager::LocalAssetIdCreator; +use pallet_xcm_transactor::{ + Currency, CurrencyPayment, HrmpInitParams, HrmpOperation, TransactWeights, +}; +use sp_std::boxed::Box; +use xcm::latest::prelude::*; +use xcm::{VersionedMultiLocation, WrapVersion}; +use xcm_builder::HashedDescriptionDescribeFamilyAllTerminal; +use xcm_executor::traits::ConvertLocation; +use xcm_mock::*; +use xcm_primitives::{UtilityEncodeCall, DEFAULT_PROOF_SIZE}; +use xcm_simulator::TestExt; +mod common; +use common::ExtBuilder; +use cumulus_primitives_core::relay_chain::HrmpChannelId; +// Send a relay asset (like DOT) to a parachain A +#[test] +fn receive_relay_asset_from_relay() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // Verify that parachain received the asset + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 123); + }); +} + +// Send relay asset (like DOT) back from Parachain A to relaychain +#[test] +fn send_relay_asset_to_relay() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + // Register relay asset in paraA + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + // Free execution + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + let dest: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + // First send relay chain asset to Parachain like in previous test + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // Free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 123); + }); + + // Lets gather the balance before sending back money + let mut balance_before_sending = 0; + Relay::execute_with(|| { + balance_before_sending = RelayBalances::free_balance(&RELAYALICE); + }); + + // We now send back some money to the relay + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: RELAYALICE.into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 123, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // The balances in paraAlice should have been substracted + ParaA::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 0); + }); + + // Balances in the relay should have been received + Relay::execute_with(|| { + // Free execution,x full amount received + assert!(RelayBalances::free_balance(&RELAYALICE) > balance_before_sending); + }); +} + +#[test] +fn send_relay_asset_to_para_b() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + // Register asset in paraA. Free execution + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata.clone(), + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location.clone(), + 0u128, + 0 + )); + }); + + // Register asset in paraB. Free execution + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // First send relay chain asset to Parachain A like in previous test + let dest: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // Free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 123); + }); + + // Now send relay asset from para A to para B + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // Para A balances should have been substracted + ParaA::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 23); + }); + + // Para B balances should have been credited + ParaB::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); +} + +#[test] +fn send_para_a_asset_to_para_b() { + MockNet::reset(); + + // this represents the asset in paraA + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + // Register asset in paraB. Free execution + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Send para A asset from para A to para B + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaA::execute_with(|| { + // Free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(800000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // Native token is substracted in paraA + ParaA::execute_with(|| { + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + // Asset is minted in paraB + ParaB::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); +} + +#[test] +fn send_para_a_asset_from_para_b_to_para_c() { + MockNet::reset(); + + // Represents para A asset + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + // Register para A asset in parachain B. Free execution + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata.clone(), + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location.clone(), + 0u128, + 0 + )); + }); + + // Register para A asset in parachain C. Free execution + ParaC::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Send para A asset to para B + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // Para A balances have been substracted + ParaA::execute_with(|| { + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + // Para B balances have been credited + ParaB::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); + + // Send para A asset from para B to para C + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(3), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaB::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // The message passed through parachainA so we needed to pay since its the native token + ParaC::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 96); + }); +} + +#[test] +fn send_para_a_asset_to_para_b_and_back_to_para_a() { + MockNet::reset(); + + // Para A asset + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + // Register para A asset in para B + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Send para A asset to para B + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // Balances have been substracted + ParaA::execute_with(|| { + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + // Para B balances have been credited + ParaB::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); + + // Send back para A asset to para A + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(1), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + ParaB::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // Weight used is 4 + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 4 + ); + }); +} + +#[test] +fn send_para_a_asset_to_para_b_and_back_to_para_a_with_new_reanchoring() { + MockNet::reset(); + + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // Para A asset has been credited + ParaA::execute_with(|| { + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + ParaB::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); + + // This time we will force the new reanchoring by manually sending the + // Message through polkadotXCM pallet + + let dest = MultiLocation { + parents: 1, + interior: X1(Parachain(1)), + }; + + let reanchored_para_a_balances = MultiLocation::new(0, X1(PalletInstance(1u8))); + + let message = xcm::VersionedXcm::<()>::V3(Xcm(vec![ + WithdrawAsset((reanchored_para_a_balances.clone(), 100).into()), + ClearOrigin, + BuyExecution { + fees: (reanchored_para_a_balances, 100).into(), + weight_limit: Limited(80.into()), + }, + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation::new( + 0, + X1(AccountKey20 { + network: None, + key: PARAALICE, + }), + ), + }, + ])); + ParaB::execute_with(|| { + // Send a message to the sovereign account in ParaA to withdraw + // and deposit asset + assert_ok!(ParachainPalletXcm::send( + parachain::RuntimeOrigin::root(), + Box::new(dest.into()), + Box::new(message), + )); + }); + + ParaA::execute_with(|| { + // Weight used is 4 + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 4 + ); + }); +} + +#[test] +fn receive_relay_asset_with_trader() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + // This time we are gonna put a rather high number of units per second + // we know later we will divide by 1e12 + // Lets put 1e6 as units per second + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 2500000000000u128, + 0 + )); + }); + + let dest: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + // We are sending 100 tokens from relay. + // Amount spent in fees is Units per second * weight / 1_000_000_000_000 (weight per second) + // weight is 4 since we are executing 4 instructions with a unitweightcost of 1. + // Units per second should be 2_500_000_000_000_000 + // Therefore with no refund, we should receive 10 tokens less + // Native trader fails for this, and we use the asset trader + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 100).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // non-free execution, not full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 90); + // Fee should have been received by treasury + assert_eq!(Assets::balance(source_id, &Treasury::account_id()), 10); + }); +} + +#[test] +fn send_para_a_asset_to_para_b_with_trader() { + MockNet::reset(); + + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 2500000000000u128, + 0 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + // In destination chain, we only need 4 weight + // We put 10 weight, 6 of which should be refunded and 4 of which should go to treasury + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(10u64, DEFAULT_PROOF_SIZE)) + )); + }); + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + // We are sending 100 tokens from para A. + // Amount spent in fees is Units per second * weight / 1_000_000_000_000 (weight per second) + // weight is 4 since we are executing 4 instructions with a unitweightcost of 1. + // Units per second should be 2_500_000_000_000_000 + // Since we set 10 weight in destination chain, 25 will be charged upfront + // 15 of those will be refunded, while 10 will go to treasury as the true weight used + // will be 4 + ParaB::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 90); + // Fee should have been received by treasury + assert_eq!(Assets::balance(source_id, &Treasury::account_id()), 10); + }); +} + +#[test] +fn send_para_a_asset_to_para_b_with_trader_and_fee() { + MockNet::reset(); + + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + // With these units per second, 80K weight convrets to 1 asset unit + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 12500000u128, + 0 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + // we use transfer_with_fee + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer_with_fee( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + 1, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(800000u64, DEFAULT_PROOF_SIZE)) + )); + }); + ParaA::execute_with(|| { + // 100 tokens transferred plus 1 taken from fees + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 - 1 + ); + }); + + ParaB::execute_with(|| { + // free execution, full amount received because trully the xcm instruction does not cost + // what it is specified + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 101); + }); +} + +#[test] +fn error_when_not_paying_enough() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + let dest: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + // This time we are gonna put a rather high number of units per second + // we know later we will divide by 1e12 + // Lets put 1e6 as units per second + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 2500000000000u128, + 0 + )); + }); + + // We are sending 100 tokens from relay. + // If we set the dest weight to be 1e7, we know the buy_execution will spend 1e7*1e6/1e12 = 10 + // Therefore with no refund, we should receive 10 tokens less + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 5).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // amount not received as it is not paying enough + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 0); + }); +} + +#[test] +fn transact_through_derivative_multilocation() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + // Relay charges 1000 for every instruction, and we have 3, so 3000 + 3000.into(), + 20000000000.into(), + None + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + WEIGHT_REF_TIME_PER_SECOND as u128, + )); + }); + + // Let's construct the call to know how much weight it is going to require + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + // 4000000000 transact + 3000 correspond to 4000003000 tokens. 100 more for the transfer call + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000003100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000003000); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_derivative( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::MockTransactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: None + }, + // 4000000000 + 3000 we should have taken out 4000003000 tokens from the caller + encoded, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + let event_found: Option = parachain::para_events() + .iter() + .find_map(|event| match event.clone() { + parachain::RuntimeEvent::PolkadotXcm(pallet_xcm::Event::AssetsTrapped { + .. + }) => Some(event.clone()), + _ => None, + }); + // Assert that the events do not contain the assets being trapped + assert!(event_found.is_none()); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(®istered_address) == 0); + }); +} + +#[test] +fn transact_through_derivative_with_custom_fee_weight() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + }); + + // Let's construct the call to know how much weight it is going to require + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + // 4000000000 transact + 3000 correspond to 4000003000 tokens. 100 more for the transfer call + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000003100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000003000); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let overall_weight = 4000003000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_derivative( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::MockTransactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + // 1-1 fee weight mapping + fee_amount: Some(overall_weight as u128) + }, + // 4000000000 + 3000 we should have taken out 4000003000 tokens from the caller + encoded, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(overall_weight.into()) + }, + false + )); + let event_found: Option = parachain::para_events() + .iter() + .find_map(|event| match event.clone() { + parachain::RuntimeEvent::PolkadotXcm(pallet_xcm::Event::AssetsTrapped { + .. + }) => Some(event.clone()), + _ => None, + }); + // Assert that the events do not contain the assets being trapped + assert!(event_found.is_none()); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(®istered_address) == 0); + }); +} + +#[test] +fn transact_through_derivative_with_custom_fee_weight_refund() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + }); + + // Let's construct the call to know how much weight it is going to require + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + // 4000000000 transact + 9000 correspond to 4000009000 tokens. 100 more for the transfer call + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000009100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000009100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000009000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000009000); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let overall_weight = 4000009000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_derivative( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::MockTransactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + // 1-1 fee weight mapping + fee_amount: Some(overall_weight as u128) + }, + encoded, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(overall_weight.into()) + }, + true + )); + let event_found: Option = parachain::para_events() + .iter() + .find_map(|event| match event.clone() { + parachain::RuntimeEvent::PolkadotXcm(pallet_xcm::Event::AssetsTrapped { + .. + }) => Some(event.clone()), + _ => None, + }); + // Assert that the events do not contain the assets being trapped + assert!(event_found.is_none()); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + // 4000005186 refunded + 100 transferred = 4000005286 + assert_eq!(RelayBalances::free_balance(¶_a_account()), 4000005286); + assert_eq!(RelayBalances::free_balance(®istered_address), 0); + }); +} + +#[test] +fn transact_through_sovereign() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + // Relay charges 1000 for every instruction, and we have 3, so 3000 + 3000.into(), + 20000000000.into(), + None + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + WEIGHT_REF_TIME_PER_SECOND as u128, + )); + }); + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000003100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000003000); + 0 + }); + + // We send the xcm transact operation to parent + let dest = MultiLocation { + parents: 1, + interior: Here, + }; + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let utility_bytes = parachain::MockTransactors::Relay.encode_call( + xcm_primitives::UtilityAvailableCalls::AsDerivative(0, encoded), + ); + + // Root can directly pass the execution byes to the sovereign + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_sovereign( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(dest)), + PARAALICE.into(), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: None + }, + utility_bytes, + OriginKind::SovereignAccount, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(®istered_address) == 0); + }); +} + +#[test] +fn transact_through_sovereign_with_custom_fee_weight() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + }); + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000003100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000003000); + 0 + }); + + // We send the xcm transact operation to parent + let dest = MultiLocation { + parents: 1, + interior: Here, + }; + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let utility_bytes = parachain::MockTransactors::Relay.encode_call( + xcm_primitives::UtilityAvailableCalls::AsDerivative(0, encoded), + ); + + let total_weight = 4000003000u64; + // Root can directly pass the execution byes to the sovereign + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_sovereign( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(dest)), + PARAALICE.into(), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + // 1-1 fee-weight mapping + fee_amount: Some(total_weight as u128) + }, + utility_bytes, + OriginKind::SovereignAccount, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(total_weight.into()) + }, + false + )); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(®istered_address) == 0); + }); +} + +#[test] +fn transact_through_sovereign_with_custom_fee_weight_refund() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + }); + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000009100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000009100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000009000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000009000); + 0 + }); + + // We send the xcm transact operation to parent + let dest = MultiLocation { + parents: 1, + interior: Here, + }; + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let utility_bytes = parachain::MockTransactors::Relay.encode_call( + xcm_primitives::UtilityAvailableCalls::AsDerivative(0, encoded), + ); + + let total_weight = 4000009000u64; + // Root can directly pass the execution byes to the sovereign + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_sovereign( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(dest)), + PARAALICE.into(), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + // 1-1 fee-weight mapping + fee_amount: Some(total_weight as u128) + }, + utility_bytes, + OriginKind::SovereignAccount, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(total_weight.into()) + }, + true + )); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + // 4000005186 refunded + 100 transferred = 4000005286 + assert_eq!(RelayBalances::free_balance(¶_a_account()), 4000005286); + + assert_eq!(RelayBalances::free_balance(®istered_address), 0); + }); +} + +#[test] +fn test_automatic_versioning_on_runtime_upgrade_with_relay() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A and set XCM version to 1 + ParaA::execute_with(|| { + parachain::XcmVersioner::set_version(1); + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + let response = Response::Version(2); + let querier: MultiLocation = Here.into(); + + // This is irrelevant, nothing will be done with this message, + // but we need to pass a message as an argument to trigger the storage change + let mock_message: Xcm<()> = Xcm(vec![QueryResponse { + query_id: 0, + response, + max_weight: Weight::zero(), + querier: Some(querier), + }]); + // The router is mocked, and we cannot use WrapVersion in ChildParachainRouter. So we will force + // it directly here + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + Relay::execute_with(|| { + // This sets the default version, for not known destinations + assert_ok!(RelayChainPalletXcm::force_default_xcm_version( + relay_chain::RuntimeOrigin::root(), + Some(2) + )); + + // Wrap version, which sets VersionedStorage + // This is necessary because the mock router does not use wrap_version, but + // this is not necessary in prod + assert_ok!(::wrap_version( + &Parachain(1).into(), + mock_message + )); + + // Transfer assets. Since it is an unknown destination, it will query for version + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + + // Let's advance the relay. This should trigger the subscription message + relay_chain::relay_roll_to(2); + + // queries should have been updated + assert!(RelayChainPalletXcm::query(0).is_some()); + }); + + let expected_supported_version: relay_chain::RuntimeEvent = + pallet_xcm::Event::SupportedVersionChanged { + location: MultiLocation { + parents: 0, + interior: X1(Parachain(1)), + }, + version: 1, + } + .into(); + + Relay::execute_with(|| { + // Assert that the events vector contains the version change + assert!(relay_chain::relay_events().contains(&expected_supported_version)); + }); + + // ParaA changes version to 2, and calls on_runtime_upgrade. This should notify the targets + // of the new version change + ParaA::execute_with(|| { + // Set version + parachain::XcmVersioner::set_version(2); + // Do runtime upgrade + parachain::on_runtime_upgrade(); + // Initialize block, to call on_initialize and notify targets + parachain::para_roll_to(2); + // Expect the event in the parachain + assert!(parachain::para_events().iter().any(|e| matches!( + e, + parachain::RuntimeEvent::PolkadotXcm(pallet_xcm::Event::VersionChangeNotified { + result: 2, + .. + }) + ))); + }); + + // This event should have been seen in the relay + let expected_supported_version_2: relay_chain::RuntimeEvent = + pallet_xcm::Event::SupportedVersionChanged { + location: MultiLocation { + parents: 0, + interior: X1(Parachain(1)), + }, + version: 2, + } + .into(); + + Relay::execute_with(|| { + // Assert that the events vector contains the new version change + assert!(relay_chain::relay_events().contains(&expected_supported_version_2)); + }); +} + +#[test] +fn test_automatic_versioning_on_runtime_upgrade_with_para_b() { + MockNet::reset(); + + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + let response = Response::Version(2); + let querier: MultiLocation = Here.into(); + + // This is irrelevant, nothing will be done with this message, + // but we need to pass a message as an argument to trigger the storage change + let mock_message: Xcm<()> = Xcm(vec![QueryResponse { + query_id: 0, + response, + max_weight: Weight::zero(), + querier: Some(querier), + }]); + + ParaA::execute_with(|| { + // advertised version + parachain::XcmVersioner::set_version(2); + }); + + ParaB::execute_with(|| { + // Let's try with v0 + parachain::XcmVersioner::set_version(0); + + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + ParaA::execute_with(|| { + // This sets the default version, for not known destinations + assert_ok!(ParachainPalletXcm::force_default_xcm_version( + parachain::RuntimeOrigin::root(), + Some(2) + )); + // Wrap version, which sets VersionedStorage + assert_ok!(::wrap_version( + &MultiLocation::new(1, X1(Parachain(2))).into(), + mock_message + )); + + parachain::para_roll_to(2); + + // queries should have been updated + assert!(ParachainPalletXcm::query(0).is_some()); + }); + + let expected_supported_version: parachain::RuntimeEvent = + pallet_xcm::Event::SupportedVersionChanged { + location: MultiLocation { + parents: 1, + interior: X1(Parachain(2)), + }, + version: 0, + } + .into(); + + ParaA::execute_with(|| { + // Assert that the events vector contains the version change + assert!(parachain::para_events().contains(&expected_supported_version)); + }); + + // Let's ensure talking in v0 works + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + // free execution, full amount received + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + ParaB::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); + + // ParaB changes version to 2, and calls on_runtime_upgrade. This should notify the targets + // of the new version change + ParaB::execute_with(|| { + // Set version + parachain::XcmVersioner::set_version(2); + // Do runtime upgrade + parachain::on_runtime_upgrade(); + // Initialize block, to call on_initialize and notify targets + parachain::para_roll_to(2); + // Expect the event in the parachain + assert!(parachain::para_events().iter().any(|e| matches!( + e, + parachain::RuntimeEvent::PolkadotXcm(pallet_xcm::Event::VersionChangeNotified { + result: 2, + .. + }) + ))); + }); + + // This event should have been seen in para A + let expected_supported_version_2: parachain::RuntimeEvent = + pallet_xcm::Event::SupportedVersionChanged { + location: MultiLocation { + parents: 1, + interior: X1(Parachain(2)), + }, + version: 2, + } + .into(); + + // Para A should have received the version change + ParaA::execute_with(|| { + // Assert that the events vector contains the new version change + assert!(parachain::para_events().contains(&expected_supported_version_2)); + }); +} + +#[test] +fn receive_asset_with_no_sufficients_not_possible_if_non_existent_account() { + MockNet::reset(); + + let fresh_account = [2u8; 20]; + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + false + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: fresh_account, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest.clone()).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // parachain should not have received assets + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &fresh_account.into()), 0); + }); + + // Send native token to fresh_account + ParaA::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + fresh_account.into(), + 100 + )); + }); + + // Re-send tokens + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // parachain should have received assets + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &fresh_account.into()), 123); + }); +} + +#[test] +fn receive_assets_with_sufficients_true_allows_non_funded_account_to_receive_assets() { + MockNet::reset(); + + let fresh_account = [2u8; 20]; + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: fresh_account, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest.clone()).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // parachain should have received assets + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &fresh_account.into()), 123); + }); +} + +#[test] +fn evm_account_receiving_assets_should_handle_sufficients_ref_count() { + MockNet::reset(); + + let mut sufficient_account = [0u8; 20]; + sufficient_account[0..20].copy_from_slice(&evm_account()[..]); + + let evm_account_id = parachain::AccountId::from(sufficient_account); + + // Evm account is self sufficient + ParaA::execute_with(|| { + assert_eq!(parachain::System::account(evm_account_id).sufficients, 1); + }); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: sufficient_account, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest.clone()).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // Evm account sufficient ref count increased by 1. + ParaA::execute_with(|| { + // TODO: since the suicided logic was introduced the data of the smart contract is not + // removed, it will have to be updated in a future release when there is the ability to + // remove contract data + // assert_eq!(parachain::System::account(evm_account_id).sufficients, 2); + }); + + ParaA::execute_with(|| { + // Remove the account from the evm context. + parachain::EVM::remove_account(&evm_account()); + // Evm account sufficient ref count decreased by 1. + // TODO: since the suicided logic was introduced the data of the smart contract is not + // removed, it will have to be updated in a future release when there is the ability to + // remove contract data + // assert_eq!(parachain::System::account(evm_account_id).sufficients, 1); + }); +} + +#[test] +fn empty_account_should_not_be_reset() { + MockNet::reset(); + + // Test account has nonce 1 on genesis. + let mut sufficient_account = [0u8; 20]; + sufficient_account[0..20].copy_from_slice(&evm_account()[..]); + + let evm_account_id = parachain::AccountId::from(sufficient_account); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + false + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Send native token to evm_account + ParaA::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + evm_account_id, + 100 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: sufficient_account, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest.clone()).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // Empty the assets from the account. + // As this makes the account go below the `min_balance`, the account is considered dead + // at eyes of pallet-assets, and the consumer reference is decreased by 1 and is now Zero. + assert_ok!(parachain::Assets::transfer( + parachain::RuntimeOrigin::signed(evm_account_id), + source_id, + PARAALICE.into(), + 123 + )); + // Verify account asset balance is Zero. + assert_eq!( + parachain::Assets::balance(source_id, &evm_account_id.into()), + 0 + ); + // Because we no longer have consumer references, we can set the balance to Zero. + // This would reset the account if our ED were to be > than Zero. + assert_ok!(ParaBalances::force_set_balance( + parachain::RuntimeOrigin::root(), + evm_account_id, + 0, + )); + // Verify account native balance is Zero. + assert_eq!(ParaBalances::free_balance(&evm_account_id), 0); + // Remove the account from the evm context. + // This decreases the sufficients reference by 1 and now is Zero. + parachain::EVM::remove_account(&evm_account()); + // Verify reference count. + let account = parachain::System::account(evm_account_id); + // TODO: after introducing the suicided fix the value for account.sufficients will remain 1 + // until the storage is not completely removed, it will have to be decreased to 0 once the + // storage can be fully removed + assert_eq!(account.sufficients, 1); + assert_eq!(account.consumers, 0); + assert_eq!(account.providers, 1); + // We expect the account to be alive in a Zero ED context. + // TODO: after introducing the suicided fix the nonce is increased by 1 + // until the storage is not completely removed, it will have to be decreased to 1 once the + // storage can be fully removed + assert_eq!(parachain::System::account_nonce(evm_account_id), 2); + }); +} + +#[test] +fn test_statemint_like() { + MockNet::reset(); + + let dest_para = MultiLocation::new(1, X1(Parachain(1))); + + let sov = xcm_builder::SiblingParachainConvertsVia::< + polkadot_parachain::primitives::Sibling, + statemint_like::AccountId, + >::convert_location(&dest_para) + .unwrap(); + + let statemint_asset_a_balances = MultiLocation::new( + 1, + X3( + Parachain(4), + PalletInstance(5), + xcm::latest::prelude::GeneralIndex(0u128), + ), + ); + let source_location = parachain::AssetType::Xcm(statemint_asset_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"StatemintToken".to_vec(), + symbol: b"StatemintToken".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata.clone(), + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + Statemint::execute_with(|| { + // Set new prefix + statemint_like::PrefixChanger::set_prefix( + PalletInstance(::index() as u8).into(), + ); + assert_ok!(StatemintAssets::create( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + 0, + RELAYALICE, + 1 + )); + + assert_ok!(StatemintAssets::mint( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + 0, + RELAYALICE, + 300000000000000 + )); + + // This is needed, since the asset is created as non-sufficient + assert_ok!(StatemintBalances::transfer( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + sov, + 100000000000000 + )); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + // Send asset with previous prefix + assert_ok!(StatemintChainPalletXcm::reserve_transfer_assets( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + Box::new(MultiLocation::new(1, X1(Parachain(1))).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new( + ( + X2( + xcm::latest::prelude::PalletInstance( + ::index() as u8 + ), + xcm::latest::prelude::GeneralIndex(0), + ), + 123 + ) + .into() + ), + 0, + )); + }); + + ParaA::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 123); + }); +} + +#[test] +fn send_para_a_local_asset_to_para_b() { + ExtBuilder::default().build().execute_with(|| { + MockNet::reset(); + + let asset_id = parachain::LocalAssetIdCreator::create_asset_id_from_metadata(0); + let para_a_local_asset = MultiLocation::new( + 1, + X3(Parachain(1), PalletInstance(11u8), GeneralIndex(asset_id)), + ); + let source_location = parachain::AssetType::Xcm(para_a_local_asset); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaALocalAsset".to_vec(), + symbol: b"ParaALocalAsset".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_local_asset( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + PARAALICE.into(), + true, + 1 + )); + + assert_ok!(LocalAssets::mint( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + asset_id, + PARAALICE.into(), + 300000000000000 + )); + }); + + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::LocalAssetReserve(asset_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(800000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaB::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); + }); +} + +#[test] +fn send_para_a_local_asset_to_para_b_and_send_it_back_together_with_some_dev() { + ExtBuilder::default().build().execute_with(|| { + MockNet::reset(); + + let asset_id = parachain::LocalAssetIdCreator::create_asset_id_from_metadata(0); + let para_a_local_asset = MultiLocation::new( + 1, + X3(Parachain(1), PalletInstance(11u8), GeneralIndex(asset_id)), + ); + let source_location_local_asset = parachain::AssetType::Xcm(para_a_local_asset); + let source_id_local_asset: parachain::AssetId = source_location_local_asset.clone().into(); + + let asset_metadata_local_asset = parachain::AssetMetadata { + name: b"ParaALocalAsset".to_vec(), + symbol: b"ParaALocalAsset".to_vec(), + decimals: 12, + }; + + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location_balances = parachain::AssetType::Xcm(para_a_balances); + let source_id_balances: parachain::AssetId = source_location_balances.clone().into(); + + let asset_metadata_balances = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location_local_asset.clone(), + asset_metadata_local_asset, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location_local_asset, + 0u128, + 0 + )); + + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location_balances.clone(), + asset_metadata_balances, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location_balances, + 0u128, + 1 + )); + }); + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_local_asset( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + PARAALICE.into(), + true, + 1 + )); + + assert_ok!(LocalAssets::mint( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + asset_id, + PARAALICE.into(), + 300000000000000 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer_multicurrencies( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + vec![ + (parachain::CurrencyId::LocalAssetReserve(asset_id), 100), + (parachain::CurrencyId::SelfReserve, 1000000) + ], + 0, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(800000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + let mut alith_balance_asset_before = 0; + let mut alith_balance_native_token_before = 0; + + ParaA::execute_with(|| { + alith_balance_asset_before = LocalAssets::balance(asset_id, &PARAALICE.into()); + alith_balance_native_token_before = Balances::free_balance(&PARAALICE.into()); + }); + + let new_dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(1), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaB::execute_with(|| { + // free execution, full amount received + assert_eq!( + Assets::balance(source_id_local_asset, &PARAALICE.into()), + 100 + ); + assert_eq!( + Assets::balance(source_id_balances, &PARAALICE.into()), + 1000000 + ); + + // free execution, full amount received + assert_ok!(XTokens::transfer_multicurrencies( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + vec![ + (parachain::CurrencyId::ForeignAsset(source_id_balances), 4), + ( + parachain::CurrencyId::ForeignAsset(source_id_local_asset), + 50 + ) + ], + 0, + Box::new(VersionedMultiLocation::V3(new_dest)), + WeightLimit::Limited(Weight::from_parts(4u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + let alith_balance_asset_after = LocalAssets::balance(asset_id, &PARAALICE.into()); + let alith_balance_native_token_after = Balances::free_balance(&PARAALICE.into()); + assert_eq!(alith_balance_asset_after, alith_balance_asset_before + 50); + assert_eq!( + alith_balance_native_token_before, + alith_balance_native_token_after + ); + }); + }); +} + +#[test] +fn send_statemint_asset_from_para_a_to_statemint_with_relay_fee() { + MockNet::reset(); + + // Relay asset + let relay_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_relay_id: parachain::AssetId = relay_location.clone().into(); + + let relay_asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + // Statemint asset + let statemint_asset = MultiLocation::new( + 1, + X3(Parachain(4u32), PalletInstance(5u8), GeneralIndex(10u128)), + ); + let statemint_location_asset = parachain::AssetType::Xcm(statemint_asset); + let source_statemint_asset_id: parachain::AssetId = statemint_location_asset.clone().into(); + + let asset_metadata_statemint_asset = parachain::AssetMetadata { + name: b"USDC".to_vec(), + symbol: b"USDC".to_vec(), + decimals: 12, + }; + + let dest_para = MultiLocation::new(1, X1(Parachain(1))); + + let sov = xcm_builder::SiblingParachainConvertsVia::< + polkadot_parachain::primitives::Sibling, + statemint_like::AccountId, + >::convert_location(&dest_para) + .unwrap(); + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + relay_location.clone(), + relay_asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + relay_location, + 0u128, + 0 + )); + + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + statemint_location_asset.clone(), + asset_metadata_statemint_asset, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + statemint_location_asset, + 0u128, + 1 + )); + }); + + let parachain_beneficiary_from_relay: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + // Send relay chain asset to Alice in Parachain A + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new( + VersionedMultiLocation::V3(parachain_beneficiary_from_relay) + .clone() + .into() + ), + Box::new((Here, 200).into()), + 0, + )); + }); + + Statemint::execute_with(|| { + // Set new prefix + statemint_like::PrefixChanger::set_prefix( + PalletInstance(::index() as u8).into(), + ); + + assert_ok!(StatemintAssets::create( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + 10, + RELAYALICE, + 1 + )); + + assert_ok!(StatemintAssets::mint( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + 10, + RELAYALICE, + 300000000000000 + )); + + // Send some native statemint tokens to sovereign for fees. + // We can't pay fees with USDC as the asset is minted as non-sufficient. + assert_ok!(StatemintBalances::transfer( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + sov, + 100000000000000 + )); + + // Send statemint USDC asset to Alice in Parachain A + let parachain_beneficiary_from_statemint: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + // Send with new prefix + assert_ok!(StatemintChainPalletXcm::reserve_transfer_assets( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + Box::new(MultiLocation::new(1, X1(Parachain(1))).into()), + Box::new( + VersionedMultiLocation::V3(parachain_beneficiary_from_statemint) + .clone() + .into() + ), + Box::new( + ( + X2( + xcm::latest::prelude::PalletInstance( + ::index() as u8 + ), + GeneralIndex(10), + ), + 125 + ) + .into() + ), + 0, + )); + }); + + let statemint_beneficiary = MultiLocation { + parents: 1, + interior: X2( + Parachain(4), + AccountId32 { + network: None, + id: RELAYBOB.into(), + }, + ), + }; + + ParaA::execute_with(|| { + // Alice has received 125 USDC + assert_eq!( + Assets::balance(source_statemint_asset_id, &PARAALICE.into()), + 125 + ); + + // Alice has received 200 Relay assets + assert_eq!(Assets::balance(source_relay_id, &PARAALICE.into()), 200); + }); + + Statemint::execute_with(|| { + // Check that BOB's balance is empty before the transfer + assert_eq!(StatemintAssets::account_balances(RELAYBOB), vec![]); + }); + + // Transfer USDC from Parachain A to Statemint using Relay asset as fee + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer_multicurrencies( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + vec![ + ( + parachain::CurrencyId::ForeignAsset(source_statemint_asset_id), + 100 + ), + (parachain::CurrencyId::ForeignAsset(source_relay_id), 100) + ], + 1, + Box::new(VersionedMultiLocation::V3(statemint_beneficiary)), + WeightLimit::Limited(Weight::from_parts(80_000_000u64, 100_000u64)) + )); + }); + + ParaA::execute_with(|| { + // Alice has 100 USDC less + assert_eq!( + Assets::balance(source_statemint_asset_id, &PARAALICE.into()), + 25 + ); + + // Alice has 100 relay asset less + assert_eq!(Assets::balance(source_relay_id, &PARAALICE.into()), 100); + }); + + Statemint::execute_with(|| { + // Check that BOB received 100 USDC on statemint + assert_eq!(StatemintAssets::account_balances(RELAYBOB), vec![(10, 100)]); + }); +} + +#[test] +fn transact_through_signed_multilocation() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + // Relay charges 1000 for every instruction, and we have 3, so 3000 + 3000.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4000.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + WEIGHT_REF_TIME_PER_SECOND as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the relay will see instead of us + descend_origin_multilocation + .reanchor(&MultiLocation::parent(), ancestry.interior) + .unwrap(); + + let derived = xcm_builder::Account32Hash::< + relay_chain::KusamaNetwork, + relay_chain::AccountId, + >::convert_location(&descend_origin_multilocation) + .unwrap(); + + Relay::execute_with(|| { + // free execution, full amount received + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + derived.clone(), + 4000004100u128, + )); + // derived account has all funds + assert!(RelayBalances::free_balance(&derived) == 4000004100); + // sovereign account has 0 funds + assert!(RelayBalances::free_balance(¶_a_account()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: None + }, + encoded, + // 4000000000 for transfer + 4000 for XCM + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + Relay::execute_with(|| { + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(&derived) == 0); + }); +} + +#[test] +fn transact_through_signed_multilocation_custom_fee_and_weight() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + ParaA::execute_with(|| { + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the relay will see instead of us + descend_origin_multilocation + .reanchor(&MultiLocation::parent(), ancestry.interior) + .unwrap(); + + let derived = xcm_builder::Account32Hash::< + relay_chain::KusamaNetwork, + relay_chain::AccountId, + >::convert_location(&descend_origin_multilocation) + .unwrap(); + + Relay::execute_with(|| { + // free execution, full amount received + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + derived.clone(), + 4000004100u128, + )); + // derived account has all funds + assert!(RelayBalances::free_balance(&derived) == 4000004100); + // sovereign account has 0 funds + assert!(RelayBalances::free_balance(¶_a_account()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let total_weight = 4000004000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_weight as u128) + }, + encoded, + // 4000000000 for transfer + 4000 for XCM + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(total_weight.into()) + }, + false + )); + }); + + Relay::execute_with(|| { + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(&derived) == 0); + }); +} + +#[test] +fn transact_through_signed_multilocation_custom_fee_and_weight_refund() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + ParaA::execute_with(|| { + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the relay will see instead of us + descend_origin_multilocation + .reanchor(&MultiLocation::parent(), ancestry.interior) + .unwrap(); + + let derived = xcm_builder::Account32Hash::< + relay_chain::KusamaNetwork, + relay_chain::AccountId, + >::convert_location(&descend_origin_multilocation) + .unwrap(); + + Relay::execute_with(|| { + // free execution, full amount received + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + derived.clone(), + 4000009100u128, + )); + // derived account has all funds + assert!(RelayBalances::free_balance(&derived) == 4000009100); + // sovereign account has 0 funds + assert!(RelayBalances::free_balance(¶_a_account()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let total_weight = 4000009000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_weight as u128) + }, + encoded, + // 4000000000 for transfer + 9000 for XCM + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(total_weight.into()) + }, + true + )); + }); + + Relay::execute_with(|| { + // 100 transferred + assert_eq!(RelayBalances::free_balance(¶_a_account()), 100); + + // 4000005186 refunded + assert_eq!(RelayBalances::free_balance(&derived), 4000005186); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + // ParaB + Box::new(xcm::VersionedMultiLocation::V3(para_b_location.clone())), + // Para charges 1000 for every instruction, and we have 3, so 3 + 3.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + ParaB::execute_with(|| { + // free execution, full amount received + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000000104u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000000104); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account_20(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: None + }, + encoded, + // 4000000000 for transfer + 4000 for XCM + // 1-1 to fee + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + ParaB::execute_with(|| { + assert!(ParaBalances::free_balance(&derived) == 0); + + assert!(ParaBalances::free_balance(¶_a_account_20()) == 100); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para_refund() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + ParaB::execute_with(|| { + // free execution, full amount received + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000009100u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000009100); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account_20(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let overall_weight = 4000009000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: Some(overall_weight as u128) + }, + encoded, + // 4000000000 for transfer + 9000 for XCM + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(overall_weight.into()) + }, + true + )); + }); + + ParaB::execute_with(|| { + // Check the derived account was refunded + assert_eq!(ParaBalances::free_balance(&derived), 8993); + + // Check the transfer was executed + assert_eq!(ParaBalances::free_balance(¶_a_account_20()), 100); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para_ethereum() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + // ParaB + Box::new(xcm::VersionedMultiLocation::V3(para_b_location.clone())), + // Para charges 1000 for every instruction, and we have 3, so 3 + 3.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + let mut parachain_b_alice_balances_before = 0; + ParaB::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000000104u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000000104); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + + parachain_b_alice_balances_before = ParaBalances::free_balance(&PARAALICE.into()) + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + use sp_core::U256; + // Let's do a EVM transfer + let eth_tx = + xcm_primitives::EthereumXcmTransaction::V1(xcm_primitives::EthereumXcmTransactionV1 { + gas_limit: U256::from(21000), + fee_payment: xcm_primitives::EthereumXcmFee::Auto, + action: pallet_ethereum::TransactionAction::Call(PARAALICE.into()), + value: U256::from(100), + input: BoundedVec::< + u8, + ConstU32<{ xcm_primitives::MAX_ETHEREUM_XCM_INPUT_SIZE }> + >::try_from(vec![]).unwrap(), + access_list: None, + }); + + // Then call bytes + let mut call_bytes = pallet_ethereum_xcm::Call::::transact { + xcm_transaction: eth_tx, + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: None + }, + encoded, + // 4000000000 for transfer + 4000 for XCM + // 1-1 to fee + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + ParaB::execute_with(|| { + // Make sure the EVM transfer went through + assert!( + ParaBalances::free_balance(&PARAALICE.into()) + == parachain_b_alice_balances_before + 100 + ); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para_ethereum_no_proxy_fails() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + // ParaB + Box::new(xcm::VersionedMultiLocation::V3(para_b_location.clone())), + // Para charges 1000 for every instruction, and we have 3, so 3 + 3.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + let mut parachain_b_alice_balances_before = 0; + ParaB::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000000104u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000000104); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + + parachain_b_alice_balances_before = ParaBalances::free_balance(&PARAALICE.into()) + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + use sp_core::U256; + // Let's do a EVM transfer + let eth_tx = + xcm_primitives::EthereumXcmTransaction::V1(xcm_primitives::EthereumXcmTransactionV1 { + gas_limit: U256::from(21000), + fee_payment: xcm_primitives::EthereumXcmFee::Auto, + action: pallet_ethereum::TransactionAction::Call(PARAALICE.into()), + value: U256::from(100), + input: BoundedVec::< + u8, + ConstU32<{ xcm_primitives::MAX_ETHEREUM_XCM_INPUT_SIZE }> + >::try_from(vec![]).unwrap(), + access_list: None, + }); + + // Then call bytes + let mut call_bytes = pallet_ethereum_xcm::Call::::transact_through_proxy { + transact_as: PARAALICE.into(), + xcm_transaction: eth_tx, + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: None + }, + encoded, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + ParaB::execute_with(|| { + // Make sure the EVM transfer wasn't executed + assert!(ParaBalances::free_balance(&PARAALICE.into()) == parachain_b_alice_balances_before); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para_ethereum_proxy_succeeds() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + // ParaB + Box::new(xcm::VersionedMultiLocation::V3(para_b_location.clone())), + // Para charges 1000 for every instruction, and we have 3, so 3 + 3.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + let transfer_recipient = evm_account(); + let mut transfer_recipient_balance_before = 0; + ParaB::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000000104u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000000104); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + + transfer_recipient_balance_before = ParaBalances::free_balance(&transfer_recipient.into()); + + // Add proxy ALICE -> derived + let _ = parachain::Proxy::add_proxy_delegate( + &PARAALICE.into(), + derived, + parachain::ProxyType::Any, + 0, + ); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + use sp_core::U256; + // Let's do a EVM transfer + let eth_tx = + xcm_primitives::EthereumXcmTransaction::V2(xcm_primitives::EthereumXcmTransactionV2 { + gas_limit: U256::from(21000), + action: pallet_ethereum::TransactionAction::Call(transfer_recipient.into()), + value: U256::from(100), + input: BoundedVec::< + u8, + ConstU32<{ xcm_primitives::MAX_ETHEREUM_XCM_INPUT_SIZE }> + >::try_from(vec![]).unwrap(), + access_list: None, + }); + + // Then call bytes + let mut call_bytes = pallet_ethereum_xcm::Call::::transact_through_proxy { + transact_as: PARAALICE.into(), + xcm_transaction: eth_tx, + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: None + }, + encoded, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + ParaB::execute_with(|| { + // Make sure the EVM transfer was executed + assert!( + ParaBalances::free_balance(&transfer_recipient.into()) + == transfer_recipient_balance_before + 100 + ); + }); +} + +#[test] +fn hrmp_init_accept_through_root() { + MockNet::reset(); + + Relay::execute_with(|| { + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + para_a_account(), + 1000u128 + )); + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + para_b_account(), + 1000u128 + )); + }); + + ParaA::execute_with(|| { + let total_fee = 1_000u128; + let total_weight: u64 = 1_000_000_000; + let tx_weight: u64 = 500_000_000; + // Root can send hrmp init channel + assert_ok!(XcmTransactor::hrmp_manage( + parachain::RuntimeOrigin::root(), + HrmpOperation::InitOpen(HrmpInitParams { + para_id: 2u32.into(), + proposed_max_capacity: 1, + proposed_max_message_size: 1 + }), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_fee) + }, + TransactWeights { + transact_required_weight_at_most: tx_weight.into(), + overall_weight: Some(total_weight.into()) + } + )); + }); + Relay::execute_with(|| { + let expected_event: relay_chain::RuntimeEvent = + polkadot_runtime_parachains::hrmp::Event::OpenChannelRequested( + 1u32.into(), + 2u32.into(), + 1u32, + 1u32, + ) + .into(); + assert!(relay_chain::relay_events().contains(&expected_event)); + }); + ParaB::execute_with(|| { + let total_fee = 1_000u128; + let total_weight: u64 = 1_000_000_000; + let tx_weight: u64 = 500_000_000; + // Root can send hrmp accept channel + assert_ok!(XcmTransactor::hrmp_manage( + parachain::RuntimeOrigin::root(), + HrmpOperation::Accept { + para_id: 1u32.into() + }, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_fee) + }, + TransactWeights { + transact_required_weight_at_most: tx_weight.into(), + overall_weight: Some(total_weight.into()) + } + )); + }); + + Relay::execute_with(|| { + let expected_event: relay_chain::RuntimeEvent = + polkadot_runtime_parachains::hrmp::Event::OpenChannelAccepted(1u32.into(), 2u32.into()) + .into(); + assert!(relay_chain::relay_events().contains(&expected_event)); + }); +} + +#[test] +fn hrmp_close_works() { + MockNet::reset(); + + Relay::execute_with(|| { + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + para_a_account(), + 1000u128 + )); + assert_ok!(Hrmp::force_open_hrmp_channel( + relay_chain::RuntimeOrigin::root(), + 1u32.into(), + 2u32.into(), + 1u32, + 1u32 + )); + assert_ok!(Hrmp::force_process_hrmp_open( + relay_chain::RuntimeOrigin::root(), + 0u32 + )); + }); + + ParaA::execute_with(|| { + let total_fee = 1_000u128; + let total_weight: u64 = 1_000_000_000; + let tx_weight: u64 = 500_000_000; + assert_ok!(XcmTransactor::hrmp_manage( + parachain::RuntimeOrigin::root(), + HrmpOperation::Close(HrmpChannelId { + sender: 1u32.into(), + recipient: 2u32.into() + }), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_fee) + }, + TransactWeights { + transact_required_weight_at_most: tx_weight.into(), + overall_weight: Some(total_weight.into()) + } + )); + }); + Relay::execute_with(|| { + let expected_event: relay_chain::RuntimeEvent = + polkadot_runtime_parachains::hrmp::Event::ChannelClosed( + 1u32.into(), + HrmpChannelId { + sender: 1u32.into(), + recipient: 2u32.into(), + }, + ) + .into(); + assert!(relay_chain::relay_events().contains(&expected_event)); + }); +} + +use parity_scale_codec::{Decode, Encode}; +use sp_io::hashing::blake2_256; + +// Helper to derive accountIds +pub fn derivative_account_id(who: sp_runtime::AccountId32, index: u16) -> sp_runtime::AccountId32 { + let entropy = (b"modlpy/utilisuba", who, index).using_encoded(blake2_256); + sp_runtime::AccountId32::decode(&mut &entropy[..]).expect("valid account id") +} diff --git a/tracing/2601/runtime/moonbeam/Cargo.toml b/tracing/2601/runtime/moonbeam/Cargo.toml new file mode 100644 index 00000000..c726ede3 --- /dev/null +++ b/tracing/2601/runtime/moonbeam/Cargo.toml @@ -0,0 +1,351 @@ +[package] +name = "moonbeam-runtime" +authors = { workspace = true } +build = "build.rs" +description = "Moonbeam Runtime" +edition = "2021" +homepage = "https://moonbeam.network" +license = "GPL-3.0-only" +version = "0.8.4" + +[dependencies] +hex-literal = { workspace = true, optional = true } +log = { workspace = true } +num_enum = { workspace = true } +rlp = { workspace = true, optional = true } +serde = { workspace = true, features = [ "derive" ] } +sha3 = { workspace = true, optional = true } +smallvec = { workspace = true } +strum = { workspace = true } +strum_macros = { workspace = true } + +# Moonbeam +account = { workspace = true } +moonbeam-core-primitives = { workspace = true } +moonbeam-relay-encoder = { workspace = true } +moonbeam-runtime-common = { workspace = true } +precompile-utils = { workspace = true } +session-keys-primitives = { workspace = true } +xcm-primitives = { workspace = true } + +# Moonbeam pallets +moonbeam-xcm-benchmarks = { workspace = true } +pallet-asset-manager = { workspace = true } +pallet-author-mapping = { workspace = true } +pallet-crowdloan-rewards = { workspace = true } +pallet-erc20-xcm-bridge = { workspace = true } +pallet-evm-chain-id = { workspace = true } +pallet-ethereum-xcm = { workspace = true } +pallet-maintenance-mode = { workspace = true, features = [ "xcm-support" ] } +pallet-migrations = { workspace = true } +pallet-moonbeam-orbiters = { workspace = true } +pallet-parachain-staking = { workspace = true } +pallet-proxy-genesis-companion = { workspace = true } +pallet-randomness = { workspace = true } +pallet-xcm-transactor = { workspace = true } + +# Moonbeam precompiles +pallet-evm-precompile-author-mapping = { workspace = true } +pallet-evm-precompile-balances-erc20 = { workspace = true } +pallet-evm-precompile-batch = { workspace = true } +pallet-evm-precompile-call-permit = { workspace = true } +pallet-evm-precompile-collective = { workspace = true } +pallet-evm-precompile-conviction-voting = { workspace = true } +pallet-evm-precompile-crowdloan-rewards = { workspace = true } +pallet-evm-precompile-democracy = { workspace = true } +pallet-evm-precompile-gmp = { workspace = true } +pallet-evm-precompile-parachain-staking = { workspace = true } +pallet-evm-precompile-preimage = { workspace = true } +pallet-evm-precompile-proxy = { workspace = true } +pallet-evm-precompile-randomness = { workspace = true } +pallet-evm-precompile-referenda = { workspace = true } +pallet-evm-precompile-registry = { workspace = true } +pallet-evm-precompile-relay-encoder = { workspace = true } +pallet-evm-precompile-xcm-transactor = { workspace = true } +pallet-evm-precompile-xcm-utils = { workspace = true } +pallet-evm-precompile-xtokens = { workspace = true } +pallet-evm-precompileset-assets-erc20 = { workspace = true } + +# Moonbeam tracing +evm-tracing-events = { workspace = true, optional = true } +moonbeam-evm-tracer = { workspace = true, optional = true } +moonbeam-rpc-primitives-debug = { workspace = true } +moonbeam-rpc-primitives-txpool = { workspace = true } + +# Substrate +frame-executive = { workspace = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +frame-system-rpc-runtime-api = { workspace = true } +pallet-assets = { workspace = true } +pallet-balances = { workspace = true, features = [ "insecure_zero_ed" ] } +pallet-collective = { workspace = true } +pallet-conviction-voting = { workspace = true } +pallet-democracy = { workspace = true } +pallet-identity = { workspace = true } +pallet-multisig = { workspace = true } +pallet-preimage = { workspace = true } +pallet-proxy = { workspace = true } +pallet-referenda = { workspace = true } +pallet-root-testing = { workspace = true } +pallet-scheduler = { workspace = true } +pallet-society = { workspace = true } +pallet-timestamp = { workspace = true } +pallet-transaction-payment = { workspace = true } +pallet-transaction-payment-rpc-runtime-api = { workspace = true } +pallet-treasury = { workspace = true } +pallet-utility = { workspace = true } +pallet-whitelist = { workspace = true } +parity-scale-codec = { workspace = true, features = [ + "derive", + "max-encoded-len", + "chain-error", +] } +scale-info = { workspace = true, features = [ "derive" ] } +sp-api = { workspace = true } +sp-block-builder = { workspace = true } +sp-core = { workspace = true } +sp-inherents = { workspace = true } +sp-io = { workspace = true, features = [ "improved_panic_error_reporting" ] } +sp-offchain = { workspace = true } +sp-runtime = { workspace = true } +sp-session = { workspace = true } +sp-std = { workspace = true } +sp-transaction-pool = { workspace = true } +sp-version = { workspace = true } +sp-weights = { workspace = true } + +# Frontier +fp-evm = { workspace = true } +fp-rpc = { workspace = true } +fp-self-contained = { workspace = true, features = [ "serde" ] } +pallet-base-fee = { workspace = true } +pallet-ethereum = { workspace = true, features = [ "forbid-evm-reentrancy" ] } +pallet-evm = { workspace = true, features = [ "forbid-evm-reentrancy" ] } +pallet-evm-precompile-blake2 = { workspace = true } +pallet-evm-precompile-bn128 = { workspace = true } +pallet-evm-precompile-dispatch = { workspace = true } +pallet-evm-precompile-modexp = { workspace = true } +pallet-evm-precompile-sha3fips = { workspace = true } +pallet-evm-precompile-simple = { workspace = true } + +# Polkadot / XCM +orml-traits = { workspace = true } +orml-xcm-support = { workspace = true } +orml-xtokens = { workspace = true } +pallet-xcm = { workspace = true } +pallet-xcm-benchmarks = { workspace = true, optional = true } +polkadot-core-primitives = { workspace = true } +polkadot-parachain = { workspace = true } +xcm = { workspace = true } +xcm-builder = { workspace = true } +xcm-executor = { workspace = true } + +# Cumulus +cumulus-pallet-dmp-queue = { workspace = true } +cumulus-pallet-parachain-system = { workspace = true } +cumulus-pallet-xcm = { workspace = true } +cumulus-pallet-xcmp-queue = { workspace = true } +cumulus-primitives-core = { workspace = true } +cumulus-primitives-timestamp = { workspace = true } +cumulus-primitives-utility = { workspace = true } +parachain-info = { workspace = true } + +# Moonkit +moonkit-xcm-primitives = { workspace = true } +nimbus-primitives = { workspace = true } +pallet-author-inherent = { workspace = true } +pallet-author-slot-filter = { workspace = true } + +# Benchmarking +frame-benchmarking = { workspace = true, optional = true } +frame-system-benchmarking = { workspace = true, optional = true } +frame-try-runtime = { workspace = true, optional = true } + +[build-dependencies] +substrate-wasm-builder = { workspace = true } + +[features] +default = [ "std" , "evm-tracing"] +std = [ + "account/std", + "cumulus-pallet-dmp-queue/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-xcm/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-primitives-core/std", + "cumulus-primitives-timestamp/std", + "evm-tracing-events/std", + "fp-evm/std", + "fp-rpc/std", + "fp-self-contained/std", + "frame-benchmarking/std", + "frame-executive/std", + "frame-support/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "moonbeam-core-primitives/std", + "moonbeam-evm-tracer/std", + "moonbeam-relay-encoder/std", + "moonbeam-rpc-primitives-debug/std", + "moonbeam-rpc-primitives-txpool/std", + "moonbeam-runtime-common/std", + "moonbeam-xcm-benchmarks/std", + "moonkit-xcm-primitives/std", + "nimbus-primitives/std", + "orml-xtokens/std", + "pallet-asset-manager/std", + "pallet-assets/std", + "pallet-author-inherent/std", + "pallet-author-mapping/std", + "pallet-author-slot-filter/std", + "pallet-balances/std", + "pallet-base-fee/std", + "pallet-collective/std", + "pallet-conviction-voting/std", + "pallet-crowdloan-rewards/std", + "pallet-democracy/std", + "pallet-erc20-xcm-bridge/std", + "pallet-evm-chain-id/std", + "pallet-ethereum-xcm/std", + "pallet-ethereum/std", + "pallet-evm-precompile-author-mapping/std", + "pallet-evm-precompile-balances-erc20/std", + "pallet-evm-precompile-batch/std", + "pallet-evm-precompile-call-permit/std", + "pallet-evm-precompile-collective/std", + "pallet-evm-precompile-conviction-voting/std", + "pallet-evm-precompile-parachain-staking/std", + "pallet-evm-precompile-preimage/std", + "pallet-evm-precompile-randomness/std", + "pallet-evm-precompile-referenda/std", + "pallet-evm-precompile-relay-encoder/std", + "pallet-evm-precompile-xcm-transactor/std", + "pallet-evm-precompile-xcm-utils/std", + "pallet-evm-precompile-xtokens/std", + "pallet-evm-precompileset-assets-erc20/std", + "pallet-evm/std", + "pallet-identity/std", + "pallet-maintenance-mode/std", + "pallet-migrations/std", + "pallet-moonbeam-orbiters/std", + "pallet-multisig/std", + "pallet-parachain-staking/std", + "pallet-preimage/std", + "pallet-proxy-genesis-companion/std", + "pallet-proxy/std", + "pallet-randomness/std", + "pallet-referenda/std", + "pallet-root-testing/std", + "pallet-scheduler/std", + "pallet-society/std", + "pallet-timestamp/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", + "pallet-treasury/std", + "pallet-utility/std", + "pallet-whitelist/std", + "pallet-xcm-transactor/std", + "pallet-xcm/std", + "parachain-info/std", + "parity-scale-codec/std", + "precompile-utils/std", + "scale-info/std", + "session-keys-primitives/std", + "sp-api/std", + "sp-block-builder/std", + "sp-core/std", + "sp-inherents/std", + "sp-io/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-transaction-pool/std", + "sp-version/std", + "strum/std", + "xcm-builder/std", + "xcm-executor/std", + "xcm-primitives/std", + "xcm/std", +] +evm-tracing = [ "evm-tracing-events", "moonbeam-evm-tracer", "rlp", "sha3" ] + +# Will be enabled by the `wasm-builder` when building the runtime for WASM. +runtime-wasm = [] + +# A feature that should be enabled when the runtime should be build for on-chain +# deployment. This will disable stuff that shouldn't be part of the on-chain wasm +# to make it smaller like logging for example. +on-chain-release-build = [ "sp-api/disable-logging" ] + +runtime-benchmarks = [ + "cumulus-pallet-parachain-system/runtime-benchmarks", + "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "hex-literal", + "moonbeam-relay-encoder/runtime-benchmarks", + "moonbeam-runtime-common/runtime-benchmarks", + "moonbeam-xcm-benchmarks/runtime-benchmarks", + "pallet-asset-manager/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pallet-author-inherent/runtime-benchmarks", + "pallet-author-mapping/runtime-benchmarks", + "pallet-author-slot-filter/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-collective/runtime-benchmarks", + "pallet-conviction-voting/runtime-benchmarks", + "pallet-crowdloan-rewards/runtime-benchmarks", + "pallet-ethereum-xcm/runtime-benchmarks", + "pallet-ethereum/runtime-benchmarks", + "pallet-evm/runtime-benchmarks", + "pallet-identity/runtime-benchmarks", + "pallet-migrations/runtime-benchmarks", + "pallet-moonbeam-orbiters/runtime-benchmarks", + "pallet-multisig/runtime-benchmarks", + "pallet-parachain-staking/runtime-benchmarks", + "pallet-preimage/runtime-benchmarks", + "pallet-proxy/runtime-benchmarks", + "pallet-randomness/runtime-benchmarks", + "pallet-referenda/runtime-benchmarks", + "pallet-scheduler/runtime-benchmarks", + "pallet-society/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "pallet-treasury/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "pallet-whitelist/runtime-benchmarks", + "pallet-xcm-benchmarks", + "pallet-xcm-transactor/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "session-keys-primitives/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", +] + +try-runtime = [ + "fp-self-contained/try-runtime", + "frame-executive/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime", + "moonbeam-runtime-common/try-runtime", + "pallet-asset-manager/try-runtime", + "pallet-author-mapping/try-runtime", + "pallet-author-slot-filter/try-runtime", + "pallet-balances/try-runtime", + "pallet-collective/try-runtime", + "pallet-conviction-voting/try-runtime", + "pallet-democracy/try-runtime", + "pallet-maintenance-mode/try-runtime", + "pallet-migrations/try-runtime", + "pallet-parachain-staking/try-runtime", + "pallet-preimage/try-runtime", + "pallet-referenda/try-runtime", + "pallet-root-testing/try-runtime", + "pallet-scheduler/try-runtime", + "pallet-society/try-runtime", + "pallet-timestamp/try-runtime", + "pallet-whitelist/try-runtime", +] diff --git a/tracing/2601/runtime/moonbeam/build.rs b/tracing/2601/runtime/moonbeam/build.rs new file mode 100644 index 00000000..3934b9c5 --- /dev/null +++ b/tracing/2601/runtime/moonbeam/build.rs @@ -0,0 +1,25 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +use substrate_wasm_builder::WasmBuilder; + +fn main() { + WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build() +} diff --git a/tracing/2601/runtime/moonbeam/src/asset_config.rs b/tracing/2601/runtime/moonbeam/src/asset_config.rs new file mode 100644 index 00000000..00c1fde4 --- /dev/null +++ b/tracing/2601/runtime/moonbeam/src/asset_config.rs @@ -0,0 +1,342 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Asset configuration for Moonbase. +//! + +use super::{ + currency, governance, xcm_config, AccountId, AssetId, AssetManager, Assets, Balance, Balances, + CouncilInstance, LocalAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX, +}; + +use frame_support::{ + dispatch::GetDispatchInfo, + parameter_types, + traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, EitherOfDiverse}, + weights::Weight, +}; +use moonbeam_runtime_common::weights as moonbeam_weights; +use pallet_evm_precompileset_assets_erc20::AccountIdAssetIdConversion; +use sp_runtime::traits::Hash as THash; + +use frame_system::{EnsureNever, EnsureRoot}; +use sp_core::{H160, H256}; + +use parity_scale_codec::{Compact, Decode, Encode}; +use scale_info::TypeInfo; + +use sp_std::{ + convert::{From, Into}, + prelude::*, +}; + +// Number of items that can be destroyed with our configured max extrinsic proof size. +// x = (a - b) / c where: +// a: maxExtrinsic proof size +// b: base proof size for destroy_accounts in pallet_assets weights +// c: proof size for each item +// 656.87 = (3_407_872 - 8232) / 5180 +const REMOVE_ITEMS_LIMIT: u32 = 656; + +// Not to disrupt the previous asset instance, we assign () to Foreign +pub type ForeignAssetInstance = (); +pub type LocalAssetInstance = pallet_assets::Instance1; + +// For foreign assets, these parameters dont matter much +// as this will only be called by root with the forced arguments +// No deposit is substracted with those methods +// For local assets, they do matter. We use similar parameters +// to those in statemine (except for approval) +parameter_types! { + pub const AssetDeposit: Balance = 100 * currency::GLMR * currency::SUPPLY_FACTOR; + pub const ApprovalDeposit: Balance = 0; + pub const AssetsStringLimit: u32 = 50; + pub const MetadataDepositBase: Balance = currency::deposit(1,68); + pub const MetadataDepositPerByte: Balance = currency::deposit(0, 1); +} + +/// We allow root and Chain council to execute privileged asset operations. +pub type AssetsForceOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; + +// Required for runtime benchmarks +pallet_assets::runtime_benchmarks_enabled! { + pub struct BenchmarkHelper; + impl pallet_assets::BenchmarkHelper for BenchmarkHelper + where + AssetIdParameter: From, + { + fn create_asset_id_parameter(id: u32) -> AssetIdParameter { + (id as u128).into() + } + } +} + +// Foreign assets +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = AssetsForceOrigin; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = ConstU128<{ currency::deposit(1, 18) }>; + type WeightInfo = moonbeam_weights::pallet_assets::WeightInfo; + type RemoveItemsLimit = ConstU32<{ REMOVE_ITEMS_LIMIT }>; + type AssetIdParameter = Compact; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +// Local assets +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = EnsureNever; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = ConstU128<{ currency::deposit(1, 18) }>; + type WeightInfo = moonbeam_weights::pallet_assets::WeightInfo; + type RemoveItemsLimit = ConstU32<{ REMOVE_ITEMS_LIMIT }>; + type AssetIdParameter = Compact; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +// We instruct how to register the Assets +// In this case, we tell it to Create an Asset in pallet-assets +pub struct AssetRegistrar; +use frame_support::{pallet_prelude::DispatchResult, transactional}; + +impl pallet_asset_manager::AssetRegistrar for AssetRegistrar { + #[transactional] + fn create_foreign_asset( + asset: AssetId, + min_balance: Balance, + metadata: AssetRegistrarMetadata, + is_sufficient: bool, + ) -> DispatchResult { + Assets::force_create( + RuntimeOrigin::root(), + asset.into(), + AssetManager::account_id(), + is_sufficient, + min_balance, + )?; + + // TODO uncomment when we feel comfortable + /* + // The asset has been created. Let's put the revert code in the precompile address + let precompile_address = Runtime::asset_id_to_account(ASSET_PRECOMPILE_ADDRESS_PREFIX, asset); + pallet_evm::AccountCodes::::insert( + precompile_address, + vec![0x60, 0x00, 0x60, 0x00, 0xfd], + );*/ + + // Lastly, the metadata + Assets::force_set_metadata( + RuntimeOrigin::root(), + asset.into(), + metadata.name, + metadata.symbol, + metadata.decimals, + metadata.is_frozen, + ) + } + + #[transactional] + fn create_local_asset( + asset: AssetId, + _creator: AccountId, + min_balance: Balance, + is_sufficient: bool, + owner: AccountId, + ) -> DispatchResult { + // We create with root, because we need to decide whether we want to create the asset + // as sufficient. Take into account this does not hold any reserved amount + // in pallet-assets + LocalAssets::force_create( + RuntimeOrigin::root(), + asset.into(), + owner, + is_sufficient, + min_balance, + )?; + + // No metadata needs to be set, as this can be set through regular calls + + // The asset has been created. Let's put the revert code in the precompile address + let precompile_address: H160 = + Runtime::asset_id_to_account(LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX, asset).into(); + pallet_evm::AccountCodes::::insert( + precompile_address, + vec![0x60, 0x00, 0x60, 0x00, 0xfd], + ); + Ok(()) + } + + #[transactional] + fn destroy_foreign_asset(asset: AssetId) -> DispatchResult { + // Mark the asset as destroying + Assets::start_destroy(RuntimeOrigin::root(), asset.into())?; + + // We remove the EVM revert code + // This does not panick even if there is no code in the address + let precompile_address: H160 = + Runtime::asset_id_to_account(FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, asset).into(); + pallet_evm::AccountCodes::::remove(precompile_address); + Ok(()) + } + + #[transactional] + fn destroy_local_asset(asset: AssetId) -> DispatchResult { + // Mark the asset as destroying + LocalAssets::start_destroy(RuntimeOrigin::root(), asset.into())?; + + // We remove the EVM revert code + // This does not panick even if there is no code in the address + let precompile_address: H160 = + Runtime::asset_id_to_account(LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX, asset).into(); + pallet_evm::AccountCodes::::remove(precompile_address); + Ok(()) + } + + fn destroy_asset_dispatch_info_weight(asset: AssetId) -> Weight { + // For us both of them (Foreign and Local) have the same annotated weight for a given + // witness + // We need to take the dispatch info from the destroy call, which is already annotated in + // the assets pallet + // Additionally, we need to add a DB write for removing the precompile revert code in the + // EVM + + // This is the dispatch info of destroy + let call_weight = RuntimeCall::Assets( + pallet_assets::Call::::start_destroy { + id: asset.into(), + }, + ) + .get_dispatch_info() + .weight; + + // This is the db write + call_weight.saturating_add(::DbWeight::get().writes(1)) + } +} + +pub struct LocalAssetIdCreator; +impl pallet_asset_manager::LocalAssetIdCreator for LocalAssetIdCreator { + fn create_asset_id_from_metadata(local_asset_counter: u128) -> AssetId { + // Our means of converting a local asset counter to an assetId + // We basically hash (local asset counter) + let mut result: [u8; 16] = [0u8; 16]; + let hash: H256 = + local_asset_counter.using_encoded(::Hashing::hash); + result.copy_from_slice(&hash.as_fixed_bytes()[0..16]); + u128::from_le_bytes(result) + } +} + +#[derive(Clone, Default, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub struct AssetRegistrarMetadata { + pub name: Vec, + pub symbol: Vec, + pub decimals: u8, + pub is_frozen: bool, +} + +pub type ForeignAssetModifierOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; +pub type LocalAssetModifierOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; + +impl pallet_asset_manager::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type AssetRegistrarMetadata = AssetRegistrarMetadata; + type ForeignAssetType = xcm_config::AssetType; + type AssetRegistrar = AssetRegistrar; + type ForeignAssetModifierOrigin = ForeignAssetModifierOrigin; + type LocalAssetModifierOrigin = LocalAssetModifierOrigin; + type LocalAssetIdCreator = LocalAssetIdCreator; + type Currency = Balances; + type LocalAssetDeposit = AssetDeposit; + type WeightInfo = moonbeam_weights::pallet_asset_manager::WeightInfo; +} + +// Instruct how to go from an H160 to an AssetID +// We just take the lowest 128 bits +impl AccountIdAssetIdConversion for Runtime { + /// The way to convert an account to assetId is by ensuring that the prefix is 0XFFFFFFFF + /// and by taking the lowest 128 bits as the assetId + fn account_to_asset_id(account: AccountId) -> Option<(Vec, AssetId)> { + let h160_account: H160 = account.into(); + let mut data = [0u8; 16]; + let (prefix_part, id_part) = h160_account.as_fixed_bytes().split_at(4); + if prefix_part == FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX + || prefix_part == LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX + { + data.copy_from_slice(id_part); + let asset_id: AssetId = u128::from_be_bytes(data).into(); + Some((prefix_part.to_vec(), asset_id)) + } else { + None + } + } + + // The opposite conversion + fn asset_id_to_account(prefix: &[u8], asset_id: AssetId) -> AccountId { + let mut data = [0u8; 20]; + data[0..4].copy_from_slice(prefix); + data[4..20].copy_from_slice(&asset_id.to_be_bytes()); + AccountId::from(data) + } +} diff --git a/tracing/2601/runtime/moonbeam/src/governance/councils.rs b/tracing/2601/runtime/moonbeam/src/governance/councils.rs new file mode 100644 index 00000000..b444bf0a --- /dev/null +++ b/tracing/2601/runtime/moonbeam/src/governance/councils.rs @@ -0,0 +1,97 @@ +// Copyright 2019-2023 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Councils for Gov1 and Gov2 + +use super::*; + +pub type CouncilInstance = pallet_collective::Instance1; +pub type TechCommitteeInstance = pallet_collective::Instance2; +pub type TreasuryCouncilInstance = pallet_collective::Instance3; +pub type OpenTechCommitteeInstance = pallet_collective::Instance4; + +parameter_types! { + // TODO: Check value of this parameter + pub MaxProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block; +} + +impl pallet_collective::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Proposal = RuntimeCall; + /// The maximum amount of time (in blocks) for council members to vote on motions. + /// Motions may end in fewer blocks if enough votes are cast to determine the result. + type MotionDuration = ConstU32<{ 3 * DAYS }>; + /// The maximum number of proposals that can be open in the council at once. + type MaxProposals = ConstU32<100>; + /// The maximum number of council members. + type MaxMembers = ConstU32<100>; + type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote; + type WeightInfo = moonbeam_weights::pallet_collective::WeightInfo; + type SetMembersOrigin = referenda::GeneralAdminOrRoot; + type MaxProposalWeight = MaxProposalWeight; +} + +impl pallet_collective::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Proposal = RuntimeCall; + /// The maximum amount of time (in blocks) for technical committee members to vote on motions. + /// Motions may end in fewer blocks if enough votes are cast to determine the result. + type MotionDuration = ConstU32<{ 3 * DAYS }>; + /// The maximum number of proposals that can be open in the technical committee at once. + type MaxProposals = ConstU32<100>; + /// The maximum number of technical committee members. + type MaxMembers = ConstU32<100>; + type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote; + type WeightInfo = moonbeam_weights::pallet_collective::WeightInfo; + type SetMembersOrigin = referenda::GeneralAdminOrRoot; + type MaxProposalWeight = MaxProposalWeight; +} + +impl pallet_collective::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Proposal = RuntimeCall; + /// The maximum amount of time (in blocks) for treasury council members to vote on motions. + /// Motions may end in fewer blocks if enough votes are cast to determine the result. + type MotionDuration = ConstU32<{ 3 * DAYS }>; + /// The maximum number of proposals that can be open in the treasury council at once. + type MaxProposals = ConstU32<20>; + /// The maximum number of treasury council members. + type MaxMembers = ConstU32<9>; + type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote; + type WeightInfo = moonbeam_weights::pallet_collective::WeightInfo; + type SetMembersOrigin = referenda::GeneralAdminOrRoot; + type MaxProposalWeight = MaxProposalWeight; +} + +impl pallet_collective::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Proposal = RuntimeCall; + /// The maximum amount of time (in blocks) for technical committee members to vote on motions. + /// Motions may end in fewer blocks if enough votes are cast to determine the result. + type MotionDuration = ConstU32<{ 14 * DAYS }>; + /// The maximum number of proposals that can be open in the technical committee at once. + type MaxProposals = ConstU32<100>; + /// The maximum number of technical committee members. + type MaxMembers = ConstU32<100>; + type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote; + type WeightInfo = moonbeam_weights::pallet_collective::WeightInfo; + type SetMembersOrigin = referenda::GeneralAdminOrRoot; + type MaxProposalWeight = MaxProposalWeight; +} diff --git a/tracing/2601/runtime/moonbeam/src/governance/democracy.rs b/tracing/2601/runtime/moonbeam/src/governance/democracy.rs new file mode 100644 index 00000000..382a53ba --- /dev/null +++ b/tracing/2601/runtime/moonbeam/src/governance/democracy.rs @@ -0,0 +1,77 @@ +// Copyright 2019-2023 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Democracy config for Gov1 + +use super::councils::*; +use crate::*; + +// The purpose of this offset is to ensure that a democratic proposal will not apply in the same +// block as a round change. +const ENACTMENT_OFFSET: u32 = 900; + +impl pallet_democracy::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type EnactmentPeriod = ConstU32<{ 2 * DAYS + ENACTMENT_OFFSET }>; + type LaunchPeriod = ConstU32<{ 7 * DAYS }>; + type VotingPeriod = ConstU32<{ 14 * DAYS }>; + + type VoteLockingPeriod = ConstU32<{ 7 * DAYS }>; + type FastTrackVotingPeriod = ConstU32<{ 1 * DAYS }>; + type MinimumDeposit = ConstU128<{ 4 * currency::GLMR * currency::SUPPLY_FACTOR }>; + /// To decide what their next motion is. + type ExternalOrigin = + pallet_collective::EnsureProportionAtLeast; + /// To have the next scheduled referendum be a straight majority-carries vote. + type ExternalMajorityOrigin = + pallet_collective::EnsureProportionAtLeast; + /// To have the next scheduled referendum be a straight default-carries (NTB) vote. + type ExternalDefaultOrigin = + pallet_collective::EnsureProportionAtLeast; + /// To allow a shorter voting/enactment period for external proposals. + type FastTrackOrigin = + pallet_collective::EnsureProportionAtLeast; + /// To instant fast track. + type InstantOrigin = + pallet_collective::EnsureProportionAtLeast; + // To cancel a proposal which has been passed. + type CancellationOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, + >; + // To cancel a proposal before it has been passed. + type CancelProposalOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, + >; + type BlacklistOrigin = EnsureRoot; + // Any single technical committee member may veto a coming council proposal, however they can + // only do it once and it lasts only for the cooloff period. + type VetoOrigin = pallet_collective::EnsureMember; + type CooloffPeriod = ConstU32<{ 7 * DAYS }>; + type Slash = (); + type InstantAllowed = ConstBool; + type Scheduler = Scheduler; + type MaxVotes = ConstU32<100>; + type PalletsOrigin = OriginCaller; + type WeightInfo = moonbeam_weights::pallet_democracy::WeightInfo; + type MaxProposals = ConstU32<100>; + type Preimages = Preimage; + type MaxDeposits = ConstU32<100>; + type MaxBlacklisted = ConstU32<100>; + type SubmitOrigin = EnsureSigned; +} diff --git a/tracing/2601/runtime/moonbeam/src/governance/mod.rs b/tracing/2601/runtime/moonbeam/src/governance/mod.rs new file mode 100644 index 00000000..bc946aad --- /dev/null +++ b/tracing/2601/runtime/moonbeam/src/governance/mod.rs @@ -0,0 +1,30 @@ +// Copyright 2019-2023 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Governance configurations + +pub mod councils; +mod democracy; +pub mod referenda; + +use super::*; + +mod origins; +pub use origins::{ + custom_origins, GeneralAdmin, ReferendumCanceller, ReferendumKiller, WhitelistedCaller, +}; +mod tracks; +pub use tracks::TracksInfo; diff --git a/tracing/2601/runtime/moonbeam/src/governance/origins.rs b/tracing/2601/runtime/moonbeam/src/governance/origins.rs new file mode 100644 index 00000000..d873cc96 --- /dev/null +++ b/tracing/2601/runtime/moonbeam/src/governance/origins.rs @@ -0,0 +1,82 @@ +// Copyright 2019-2023 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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. + +//! Custom origins for governance interventions. +#![cfg_attr(not(feature = "std"), no_std)] + +pub use custom_origins::*; + +#[frame_support::pallet] +pub mod custom_origins { + use frame_support::pallet_prelude::*; + use strum_macros::EnumString; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[derive( + PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug, EnumString, + )] + #[strum(serialize_all = "snake_case")] + #[pallet::origin] + pub enum Origin { + /// Origin able to dispatch a whitelisted call. + WhitelistedCaller, + /// General admin + GeneralAdmin, + /// Origin able to cancel referenda. + ReferendumCanceller, + /// Origin able to kill referenda. + ReferendumKiller, + } + + macro_rules! decl_unit_ensures { + ( $name:ident: $success_type:ty = $success:expr ) => { + pub struct $name; + impl> + From> + EnsureOrigin for $name + { + type Success = $success_type; + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + Origin::$name => Ok($success), + r => Err(O::from(r)), + }) + } + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin() -> Result { + Ok(O::from(Origin::$name)) + } + } + }; + ( $name:ident ) => { decl_unit_ensures! { $name : () = () } }; + ( $name:ident: $success_type:ty = $success:expr, $( $rest:tt )* ) => { + decl_unit_ensures! { $name: $success_type = $success } + decl_unit_ensures! { $( $rest )* } + }; + ( $name:ident, $( $rest:tt )* ) => { + decl_unit_ensures! { $name } + decl_unit_ensures! { $( $rest )* } + }; + () => {} + } + decl_unit_ensures!( + ReferendumCanceller, + ReferendumKiller, + WhitelistedCaller, + GeneralAdmin + ); +} diff --git a/tracing/2601/runtime/moonbeam/src/governance/referenda.rs b/tracing/2601/runtime/moonbeam/src/governance/referenda.rs new file mode 100644 index 00000000..78d1a18f --- /dev/null +++ b/tracing/2601/runtime/moonbeam/src/governance/referenda.rs @@ -0,0 +1,98 @@ +// Copyright 2019-2023 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! # Gov2 config +//! Includes runtime configs for these substrate pallets: +//! 1. pallet-conviction-voting +//! 2. pallet-whitelist +//! 3. pallet-referenda + +use super::*; +use crate::currency::{GLMR, SUPPLY_FACTOR}; +use frame_support::traits::{EitherOf, MapSuccess}; +use frame_system::EnsureRootWithSuccess; +use sp_runtime::traits::Replace; + +parameter_types! { + pub const VoteLockingPeriod: BlockNumber = 1 * DAYS; +} + +impl pallet_conviction_voting::Config for Runtime { + type WeightInfo = moonbeam_weights::pallet_conviction_voting::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type Polls = Referenda; + type MaxTurnout = frame_support::traits::TotalIssuanceOf; + // Maximum number of concurrent votes an account may have + type MaxVotes = ConstU32<20>; + // Minimum period of vote locking + type VoteLockingPeriod = VoteLockingPeriod; +} + +parameter_types! { + pub const AlarmInterval: BlockNumber = 1; + pub const SubmissionDeposit: Balance = 10 * GLMR * SUPPLY_FACTOR; + pub const UndecidingTimeout: BlockNumber = 21 * DAYS; +} + +// Origin for general admin or root +pub type GeneralAdminOrRoot = EitherOf, origins::GeneralAdmin>; + +impl custom_origins::Config for Runtime {} + +// The purpose of this pallet is to queue calls to be dispatched as by root later => the Dispatch +// origin corresponds to the Gov2 Whitelist track. +impl pallet_whitelist::Config for Runtime { + type WeightInfo = moonbeam_weights::pallet_whitelist::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type WhitelistOrigin = EitherOf< + EnsureRootWithSuccess>, + MapSuccess< + pallet_collective::EnsureProportionAtLeast< + Self::AccountId, + OpenTechCommitteeInstance, + 5, + 9, + >, + Replace>, + >, + >; + type DispatchWhitelistedOrigin = EitherOf, WhitelistedCaller>; + type Preimages = Preimage; +} + +pallet_referenda::impl_tracksinfo_get!(TracksInfo, Balance, BlockNumber); + +impl pallet_referenda::Config for Runtime { + type WeightInfo = moonbeam_weights::pallet_referenda::WeightInfo; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type Scheduler = Scheduler; + type Currency = Balances; + type SubmitOrigin = frame_system::EnsureSigned; + type CancelOrigin = EitherOf, ReferendumCanceller>; + type KillOrigin = EitherOf, ReferendumKiller>; + type Slash = Treasury; + type Votes = pallet_conviction_voting::VotesOf; + type Tally = pallet_conviction_voting::TallyOf; + type SubmissionDeposit = SubmissionDeposit; + type MaxQueued = ConstU32<100>; + type UndecidingTimeout = UndecidingTimeout; + type AlarmInterval = AlarmInterval; + type Tracks = TracksInfo; + type Preimages = Preimage; +} diff --git a/tracing/2601/runtime/moonbeam/src/governance/tracks.rs b/tracing/2601/runtime/moonbeam/src/governance/tracks.rs new file mode 100644 index 00000000..34b527c9 --- /dev/null +++ b/tracing/2601/runtime/moonbeam/src/governance/tracks.rs @@ -0,0 +1,179 @@ +// Copyright 2022 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 . + +//! Track configurations for governance. + +use super::*; +use crate::currency::{GLMR, KILOGLMR, SUPPLY_FACTOR}; +use sp_std::str::FromStr; + +const fn percent(x: i32) -> sp_runtime::FixedI64 { + sp_runtime::FixedI64::from_rational(x as u128, 100) +} +const fn permill(x: i32) -> sp_runtime::FixedI64 { + sp_runtime::FixedI64::from_rational(x as u128, 1000) +} + +use pallet_referenda::Curve; +const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 5] = [ + ( + 0, + pallet_referenda::TrackInfo { + // Name of this track. + name: "root", + // A limit for the number of referenda on this track that can be being decided at once. + // For Root origin this should generally be just one. + max_deciding: 5, + // Amount that must be placed on deposit before a decision can be made. + decision_deposit: 20 * KILOGLMR * SUPPLY_FACTOR, + // Amount of time this must be submitted for before a decision can be made. + prepare_period: 1 * DAYS, + // Amount of time that a decision may take to be approved prior to cancellation. + decision_period: 14 * DAYS, + // Amount of time that the approval criteria must hold before it can be approved. + confirm_period: 1 * DAYS, + // Minimum amount of time that an approved proposal must be in the dispatch queue. + min_enactment_period: 1 * DAYS, + // Minimum aye votes as percentage of overall conviction-weighted votes needed for + // approval as a function of time into decision period. + min_approval: Curve::make_reciprocal(4, 14, percent(80), percent(50), percent(100)), + // Minimum pre-conviction aye-votes ("support") as percentage of overall population that + // is needed for approval as a function of time into decision period. + min_support: Curve::make_linear(14, 14, permill(5), percent(25)), + }, + ), + ( + 1, + pallet_referenda::TrackInfo { + name: "whitelisted_caller", + max_deciding: 100, + decision_deposit: 2 * KILOGLMR * SUPPLY_FACTOR, + prepare_period: 10 * MINUTES, + decision_period: 14 * DAYS, + confirm_period: 10 * MINUTES, + min_enactment_period: 30 * MINUTES, + min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)), + min_support: Curve::make_reciprocal(1, 14 * 24, percent(1), percent(0), percent(2)), + }, + ), + ( + 2, + pallet_referenda::TrackInfo { + name: "general_admin", + max_deciding: 10, + decision_deposit: 100 * GLMR * SUPPLY_FACTOR, + prepare_period: 1 * HOURS, + decision_period: 14 * DAYS, + confirm_period: 1 * DAYS, + min_enactment_period: 1 * DAYS, + min_approval: Curve::make_reciprocal(4, 14, percent(80), percent(50), percent(100)), + min_support: Curve::make_reciprocal(7, 14, percent(10), percent(0), percent(50)), + }, + ), + ( + 3, + pallet_referenda::TrackInfo { + name: "referendum_canceller", + max_deciding: 20, + decision_deposit: 2 * KILOGLMR * SUPPLY_FACTOR, + prepare_period: 1 * HOURS, + decision_period: 14 * DAYS, + confirm_period: 3 * HOURS, + min_enactment_period: 10 * MINUTES, + min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)), + min_support: Curve::make_reciprocal(1, 14, percent(1), percent(0), percent(10)), + }, + ), + ( + 4, + pallet_referenda::TrackInfo { + name: "referendum_killer", + max_deciding: 100, + decision_deposit: 4 * KILOGLMR * SUPPLY_FACTOR, + prepare_period: 1 * HOURS, + decision_period: 14 * DAYS, + confirm_period: 3 * HOURS, + min_enactment_period: 10 * MINUTES, + min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)), + min_support: Curve::make_reciprocal(1, 14, percent(1), percent(0), percent(10)), + }, + ), +]; + +pub struct TracksInfo; +impl pallet_referenda::TracksInfo for TracksInfo { + type Id = u16; + type RuntimeOrigin = ::PalletsOrigin; + fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { + &TRACKS_DATA[..] + } + fn track_for(id: &Self::RuntimeOrigin) -> Result { + if let Ok(system_origin) = frame_system::RawOrigin::try_from(id.clone()) { + match system_origin { + frame_system::RawOrigin::Root => { + if let Some((track_id, _)) = Self::tracks() + .into_iter() + .find(|(_, track)| track.name == "root") + { + Ok(*track_id) + } else { + Err(()) + } + } + _ => Err(()), + } + } else if let Ok(custom_origin) = custom_origins::Origin::try_from(id.clone()) { + if let Some((track_id, _)) = Self::tracks().into_iter().find(|(_, track)| { + if let Ok(track_custom_origin) = custom_origins::Origin::from_str(track.name) { + track_custom_origin == custom_origin + } else { + false + } + }) { + Ok(*track_id) + } else { + Err(()) + } + } else { + Err(()) + } + } +} + +#[test] +/// To ensure voters are always locked into their vote +fn vote_locking_always_longer_than_enactment_period() { + for (_, track) in TRACKS_DATA { + assert!( + ::VoteLockingPeriod::get() + >= track.min_enactment_period, + "Track {} has enactment period {} < vote locking period {}", + track.name, + track.min_enactment_period, + ::VoteLockingPeriod::get(), + ); + } +} + +#[test] +fn all_tracks_have_origins() { + for (_, track) in TRACKS_DATA { + // check name.into() is successful either converts into "root" or custom origin + let track_is_root = track.name == "root"; + let track_has_custom_origin = custom_origins::Origin::from_str(track.name).is_ok(); + assert!(track_is_root || track_has_custom_origin); + } +} diff --git a/tracing/2601/runtime/moonbeam/src/lib.rs b/tracing/2601/runtime/moonbeam/src/lib.rs new file mode 100644 index 00000000..bcdb2214 --- /dev/null +++ b/tracing/2601/runtime/moonbeam/src/lib.rs @@ -0,0 +1,1808 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! The Moonbeam Runtime. +//! +//! Primary features of this runtime include: +//! * Ethereum compatibility +//! * Moonbeam tokenomics + +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +use account::AccountId20; +use cumulus_pallet_parachain_system::{RelayChainStateProof, RelaychainDataProvider}; +use cumulus_primitives_core::relay_chain; +use fp_rpc::TransactionStatus; + +// Re-export required by get! macro. +use cumulus_primitives_core::{relay_chain::BlockNumber as RelayBlockNumber, DmpMessageHandler}; +#[cfg(feature = "std")] +pub use fp_evm::GenesisAccount; +pub use frame_support::traits::Get; +use frame_support::{ + construct_runtime, + dispatch::{DispatchClass, GetDispatchInfo, PostDispatchInfo}, + ensure, + pallet_prelude::DispatchResult, + parameter_types, + traits::{ + ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, Contains, + Currency as CurrencyT, EitherOfDiverse, EqualPrivilegeOnly, Imbalance, InstanceFilter, + OffchainWorker, OnFinalize, OnIdle, OnInitialize, OnRuntimeUpgrade, OnUnbalanced, + }, + weights::{ + constants::{RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND}, + ConstantMultiplier, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, + WeightToFeePolynomial, + }, + PalletId, +}; +use frame_system::{EnsureRoot, EnsureSigned}; +pub use moonbeam_core_primitives::{ + AccountId, AccountIndex, Address, AssetId, Balance, BlockNumber, DigestItem, Hash, Header, + Index, Signature, +}; +use moonbeam_rpc_primitives_txpool::TxPoolResponse; +use moonbeam_runtime_common::weights as moonbeam_weights; +use pallet_balances::NegativeImbalance; +use pallet_ethereum::Call::transact; +use pallet_ethereum::{PostLogContent, Transaction as EthereumTransaction}; +use pallet_evm::{ + Account as EVMAccount, EVMCurrencyAdapter, EnsureAddressNever, EnsureAddressRoot, + FeeCalculator, GasWeightMapping, IdentityAddressMapping, + OnChargeEVMTransaction as OnChargeEVMTransactionT, Runner, +}; +pub use pallet_parachain_staking::{weights::WeightInfo, InflationInfo, Range}; +use pallet_transaction_payment::{CurrencyAdapter, Multiplier, TargetedFeeAdjustment}; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use serde::{Deserialize, Serialize}; +use smallvec::smallvec; +use sp_api::impl_runtime_apis; +use sp_core::{OpaqueMetadata, H160, H256, U256}; +#[cfg(feature = "try-runtime")] +use sp_runtime::TryRuntimeError; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + traits::{ + BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, IdentityLookup, + PostDispatchInfoOf, UniqueSaturatedInto, Zero, + }, + transaction_validity::{ + InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError, + }, + ApplyExtrinsicResult, DispatchErrorWithPostInfo, FixedPointNumber, Perbill, Permill, + Perquintill, SaturatedConversion, +}; +use sp_std::{convert::TryFrom, prelude::*}; + +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; + +use nimbus_primitives::CanAuthor; + +mod precompiles; +pub use precompiles::{ + MoonbeamPrecompiles, PrecompileName, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX, +}; + +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; + +pub type Precompiles = MoonbeamPrecompiles; + +pub mod asset_config; +pub mod governance; +pub mod xcm_config; +use governance::councils::*; + +/// GLMR, the native token, uses 18 decimals of precision. +pub mod currency { + use super::Balance; + + // Provide a common factor between runtimes based on a supply of 10_000_000 tokens. + pub const SUPPLY_FACTOR: Balance = 100; + + pub const WEI: Balance = 1; + pub const KILOWEI: Balance = 1_000; + pub const MEGAWEI: Balance = 1_000_000; + pub const GIGAWEI: Balance = 1_000_000_000; + pub const MICROGLMR: Balance = 1_000_000_000_000; + pub const MILLIGLMR: Balance = 1_000_000_000_000_000; + pub const GLMR: Balance = 1_000_000_000_000_000_000; + pub const KILOGLMR: Balance = 1_000_000_000_000_000_000_000; + + pub const TRANSACTION_BYTE_FEE: Balance = 1 * GIGAWEI * SUPPLY_FACTOR; + pub const STORAGE_BYTE_FEE: Balance = 100 * MICROGLMR * SUPPLY_FACTOR; + pub const WEIGHT_FEE: Balance = 50 * KILOWEI * SUPPLY_FACTOR; + + pub const fn deposit(items: u32, bytes: u32) -> Balance { + items as Balance * 100 * MILLIGLMR * SUPPLY_FACTOR + (bytes as Balance) * STORAGE_BYTE_FEE + } +} + +/// Maximum weight per block +pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND, u64::MAX) + .saturating_div(2) + .set_proof_size(cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64); + +pub const MILLISECS_PER_BLOCK: u64 = 12000; +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; +pub const WEEKS: BlockNumber = DAYS * 7; +pub const MONTHS: BlockNumber = DAYS * 30; +/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know +/// the specifics of the runtime. They can then be made to be agnostic over specific formats +/// of data like extrinsics, allowing for them to continue syncing the network through upgrades +/// to even the core datastructures. +pub mod opaque { + use super::*; + + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + pub type Block = generic::Block; + + impl_opaque_keys! { + pub struct SessionKeys { + pub nimbus: AuthorInherent, + pub vrf: session_keys_primitives::VrfSessionKey, + } + } +} + +/// This runtime version. +/// The spec_version is composed of 2x2 digits. The first 2 digits represent major changes +/// that can't be skipped, such as data migration upgrades. The last 2 digits represent minor +/// changes which can be skipped. +#[sp_version::runtime_version] +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("moonbeam"), + impl_name: create_runtime_str!("moonbeam"), + authoring_version: 3, + spec_version: 2601, + impl_version: 0, + apis: RUNTIME_API_VERSIONS, + transaction_version: 2, + state_version: 0, +}; + +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); +const NORMAL_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_mul(3).saturating_div(4); +// Here we assume Ethereum's base fee of 21000 gas and convert to weight, but we +// subtract roughly the cost of a balance transfer from it (about 1/3 the cost) +// and some cost to account for per-byte-fee. +// TODO: we should use benchmarking's overhead feature to measure this +pub const EXTRINSIC_BASE_WEIGHT: Weight = Weight::from_parts(10000 * WEIGHT_PER_GAS, 0); + +pub struct RuntimeBlockWeights; +impl Get for RuntimeBlockWeights { + fn get() -> frame_system::limits::BlockWeights { + frame_system::limits::BlockWeights::builder() + .for_class(DispatchClass::Normal, |weights| { + weights.base_extrinsic = EXTRINSIC_BASE_WEIGHT; + weights.max_total = NORMAL_WEIGHT.into(); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = MAXIMUM_BLOCK_WEIGHT.into(); + weights.reserved = (MAXIMUM_BLOCK_WEIGHT - NORMAL_WEIGHT).into(); + }) + .avg_block_initialization(Perbill::from_percent(10)) + .build() + .expect("Provided BlockWeight definitions are valid, qed") + } +} + +parameter_types! { + pub const Version: RuntimeVersion = VERSION; + /// We allow for 5 MB blocks. + pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength + ::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); +} + +impl frame_system::Config for Runtime { + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = IdentityLookup; + /// The index type for storing how many extrinsics an account has signed. + type Nonce = Index; + /// The index type for blocks. + type Block = Block; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + /// The ubiquitous origin type. + type RuntimeOrigin = RuntimeOrigin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = ConstU32<256>; + /// Maximum weight of each block. With a default weight system of 1byte == 1weight, 4mb is ok. + type BlockWeights = RuntimeBlockWeights; + /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. + type BlockLength = BlockLength; + /// Runtime version. + type Version = Version; + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type DbWeight = RocksDbWeight; + type BaseCallFilter = MaintenanceMode; + type SystemWeightInfo = (); + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = ConstU16<1284>; + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl pallet_utility::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; + type WeightInfo = moonbeam_weights::pallet_utility::WeightInfo; +} + +impl pallet_timestamp::Config for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = ConstU64<6000>; + type WeightInfo = moonbeam_weights::pallet_timestamp::WeightInfo; +} + +impl pallet_balances::Config for Runtime { + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 4]; + type MaxLocks = ConstU32<50>; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ConstU128<0>; + type AccountStore = System; + type FreezeIdentifier = (); + type MaxFreezes = ConstU32<0>; + type RuntimeHoldReason = RuntimeHoldReason; + type MaxHolds = ConstU32<0>; + type WeightInfo = moonbeam_weights::pallet_balances::WeightInfo; +} + +pub struct DealWithFees(sp_std::marker::PhantomData); +impl OnUnbalanced> for DealWithFees +where + R: pallet_balances::Config + pallet_treasury::Config, + pallet_treasury::Pallet: OnUnbalanced>, +{ + // this seems to be called for substrate-based transactions + fn on_unbalanceds(mut fees_then_tips: impl Iterator>) { + if let Some(fees) = fees_then_tips.next() { + // for fees, 80% are burned, 20% to the treasury + let (_, to_treasury) = fees.ration(80, 20); + // Balances pallet automatically burns dropped Negative Imbalances by decreasing + // total_supply accordingly + as OnUnbalanced<_>>::on_unbalanced(to_treasury); + + // handle tip if there is one + if let Some(tip) = fees_then_tips.next() { + // for now we use the same burn/treasury strategy used for regular fees + let (_, to_treasury) = tip.ration(80, 20); + as OnUnbalanced<_>>::on_unbalanced(to_treasury); + } + } + } + + // this is called from pallet_evm for Ethereum-based transactions + // (technically, it calls on_unbalanced, which calls this when non-zero) + fn on_nonzero_unbalanced(amount: NegativeImbalance) { + // Balances pallet automatically burns dropped Negative Imbalances by decreasing + // total_supply accordingly + let (_, to_treasury) = amount.ration(80, 20); + as OnUnbalanced<_>>::on_unbalanced(to_treasury); + } +} + +pub struct LengthToFee; +impl WeightToFeePolynomial for LengthToFee { + type Balance = Balance; + + fn polynomial() -> WeightToFeeCoefficients { + smallvec![ + WeightToFeeCoefficient { + degree: 1, + coeff_frac: Perbill::zero(), + coeff_integer: currency::TRANSACTION_BYTE_FEE, + negative: false, + }, + WeightToFeeCoefficient { + degree: 3, + coeff_frac: Perbill::zero(), + coeff_integer: 1 * currency::SUPPLY_FACTOR, + negative: false, + }, + ] + } +} + +impl pallet_transaction_payment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = CurrencyAdapter>; + type OperationalFeeMultiplier = ConstU8<5>; + type WeightToFee = ConstantMultiplier>; + type LengthToFee = LengthToFee; + type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; +} + +impl pallet_evm_chain_id::Config for Runtime {} + +/// Current approximation of the gas/s consumption considering +/// EVM execution over compiled WASM (on 4.4Ghz CPU). +/// Given the 500ms Weight, from which 75% only are used for transactions, +/// the total EVM execution gas limit is: GAS_PER_SECOND * 0.500 * 0.75 ~= 15_000_000. +pub const GAS_PER_SECOND: u64 = 40_000_000; + +/// Approximate ratio of the amount of Weight per Gas. +/// u64 works for approximations because Weight is a very small unit compared to gas. +pub const WEIGHT_PER_GAS: u64 = WEIGHT_REF_TIME_PER_SECOND / GAS_PER_SECOND; + +parameter_types! { + pub BlockGasLimit: U256 + = U256::from(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT.ref_time() / WEIGHT_PER_GAS); + /// The portion of the `NORMAL_DISPATCH_RATIO` that we adjust the fees with. Blocks filled less + /// than this will decrease the weight and more will increase. + pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); + /// The adjustment variable of the runtime. Higher values will cause `TargetBlockFullness` to + /// change the fees more rapidly. This low value causes changes to occur slowly over time. + pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(4, 1_000); + /// Minimum amount of the multiplier. This value cannot be too low. A test case should ensure + /// that combined with `AdjustmentVariable`, we can recover from the minimum. + /// See `multiplier_can_grow_from_zero` in integration_tests.rs. + /// This value is currently only used by pallet-transaction-payment as an assertion that the + /// next multiplier is always > min value. + pub MinimumMultiplier: Multiplier = Multiplier::from(1u128); + /// Maximum multiplier. We pick a value that is expensive but not impossibly so; it should act + /// as a safety net. + pub MaximumMultiplier: Multiplier = Multiplier::from(100_000u128); + pub PrecompilesValue: MoonbeamPrecompiles = MoonbeamPrecompiles::<_>::new(); + pub WeightPerGas: Weight = Weight::from_parts(WEIGHT_PER_GAS, 0); + /// The amount of gas per pov. A ratio of 4 if we convert ref_time to gas and we compare + /// it with the pov_size for a block. E.g. + /// ceil( + /// (max_extrinsic.ref_time() / max_extrinsic.proof_size()) / WEIGHT_PER_GAS + /// ) + pub const GasLimitPovSizeRatio: u64 = 4; + /// The amount of gas per storage (in bytes). + pub GasLimitStorageGrowthRatio: u64 = 0; +} + +pub struct TransactionPaymentAsGasPrice; +impl FeeCalculator for TransactionPaymentAsGasPrice { + fn min_gas_price() -> (U256, Weight) { + // note: transaction-payment differs from EIP-1559 in that its tip and length fees are not + // scaled by the multiplier, which means its multiplier will be overstated when + // applied to an ethereum transaction + // note: transaction-payment uses both a congestion modifier (next_fee_multiplier, which is + // updated once per block in on_finalize) and a 'WeightToFee' implementation. Our + // runtime implements this as a 'ConstantModifier', so we can get away with a simple + // multiplication here. + // It is imperative that `saturating_mul_int` be performed as late as possible in the + // expression since it involves fixed point multiplication with a division by a fixed + // divisor. This leads to truncation and subsequent precision loss if performed too early. + // This can lead to min_gas_price being same across blocks even if the multiplier changes. + // There's still some precision loss when the final `gas_price` (used_gas * min_gas_price) + // is computed in frontier, but that's currently unavoidable. + let min_gas_price = TransactionPayment::next_fee_multiplier() + .saturating_mul_int(currency::WEIGHT_FEE.saturating_mul(WEIGHT_PER_GAS as u128)); + ( + min_gas_price.into(), + ::DbWeight::get().reads(1), + ) + } +} + +/// Parameterized slow adjusting fee updated based on +/// https://w3f-research.readthedocs.io/en/latest/polkadot/overview/2-token-economics.html#-2.-slow-adjusting-mechanism // editorconfig-checker-disable-line +/// +/// The adjustment algorithm boils down to: +/// +/// diff = (previous_block_weight - target) / maximum_block_weight +/// next_multiplier = prev_multiplier * (1 + (v * diff) + ((v * diff)^2 / 2)) +/// assert(next_multiplier > min) +/// where: v is AdjustmentVariable +/// target is TargetBlockFullness +/// min is MinimumMultiplier +pub type SlowAdjustingFeeUpdate = TargetedFeeAdjustment< + R, + TargetBlockFullness, + AdjustmentVariable, + MinimumMultiplier, + MaximumMultiplier, +>; + +use frame_support::traits::FindAuthor; +//TODO It feels like this shold be able to work for any T: H160, but I tried for +// embarassingly long and couldn't figure that out. + +/// The author inherent provides a AccountId20, but pallet evm needs an H160. +/// This simple adapter makes the conversion. +pub struct FindAuthorAdapter(sp_std::marker::PhantomData); + +impl FindAuthor for FindAuthorAdapter +where + Inner: FindAuthor, +{ + fn find_author<'a, I>(digests: I) -> Option + where + I: 'a + IntoIterator, + { + Inner::find_author(digests).map(Into::into) + } +} + +moonbeam_runtime_common::impl_on_charge_evm_transaction!(); + +impl pallet_evm::Config for Runtime { + type FeeCalculator = TransactionPaymentAsGasPrice; + type GasWeightMapping = pallet_evm::FixedGasWeightMapping; + type WeightPerGas = WeightPerGas; + type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping; + type CallOrigin = EnsureAddressRoot; + type WithdrawOrigin = EnsureAddressNever; + type AddressMapping = IdentityAddressMapping; + type Currency = Balances; + type RuntimeEvent = RuntimeEvent; + type Runner = pallet_evm::runner::stack::Runner; + type PrecompilesType = MoonbeamPrecompiles; + type PrecompilesValue = PrecompilesValue; + type ChainId = EthereumChainId; + type OnChargeTransaction = OnChargeEVMTransaction>; + type BlockGasLimit = BlockGasLimit; + type FindAuthor = FindAuthorAdapter; + type OnCreate = (); + type GasLimitPovSizeRatio = GasLimitPovSizeRatio; + type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio; + type Timestamp = Timestamp; + type WeightInfo = moonbeam_weights::pallet_evm::WeightInfo; +} + +parameter_types! { + pub MaximumSchedulerWeight: Weight = NORMAL_DISPATCH_RATIO * RuntimeBlockWeights::get().max_block; +} + +impl pallet_scheduler::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type MaximumWeight = MaximumSchedulerWeight; + type ScheduleOrigin = EnsureRoot; + type MaxScheduledPerBlock = ConstU32<50>; + type WeightInfo = moonbeam_weights::pallet_scheduler::WeightInfo; + type OriginPrivilegeCmp = EqualPrivilegeOnly; + type Preimages = Preimage; +} + +impl pallet_preimage::Config for Runtime { + type WeightInfo = moonbeam_weights::pallet_preimage::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type BaseDeposit = ConstU128<{ 5 * currency::GLMR * currency::SUPPLY_FACTOR }>; + type ByteDeposit = ConstU128<{ currency::STORAGE_BYTE_FEE }>; +} + +parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const TreasuryId: PalletId = PalletId(*b"py/trsry"); +} + +type TreasuryApproveOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, +>; + +type TreasuryRejectOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionMoreThan, +>; + +impl pallet_treasury::Config for Runtime { + type PalletId = TreasuryId; + type Currency = Balances; + // At least three-fifths majority of the council is required (or root) to approve a proposal + type ApproveOrigin = TreasuryApproveOrigin; + // More than half of the council is required (or root) to reject a proposal + type RejectOrigin = TreasuryRejectOrigin; + type RuntimeEvent = RuntimeEvent; + // If spending proposal rejected, transfer proposer bond to treasury + type OnSlash = Treasury; + type ProposalBond = ProposalBond; + type ProposalBondMinimum = ConstU128<{ 1 * currency::GLMR * currency::SUPPLY_FACTOR }>; + type SpendPeriod = ConstU32<{ 6 * DAYS }>; + type Burn = (); + type BurnDestination = (); + type MaxApprovals = ConstU32<100>; + type WeightInfo = moonbeam_weights::pallet_treasury::WeightInfo; + type SpendFunds = (); + type ProposalBondMaximum = (); + type SpendOrigin = frame_support::traits::NeverEnsureOrigin; // Same as Polkadot +} + +type IdentityForceOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; +type IdentityRegistrarOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; + +impl pallet_identity::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + // Add one item in storage and take 258 bytes + type BasicDeposit = ConstU128<{ currency::deposit(1, 258) }>; + // Not add any item to the storage but takes 66 bytes + type FieldDeposit = ConstU128<{ currency::deposit(0, 66) }>; + // Add one item in storage and take 53 bytes + type SubAccountDeposit = ConstU128<{ currency::deposit(1, 53) }>; + type MaxSubAccounts = ConstU32<100>; + type MaxAdditionalFields = ConstU32<100>; + type MaxRegistrars = ConstU32<20>; + type Slashed = Treasury; + type ForceOrigin = IdentityForceOrigin; + type RegistrarOrigin = IdentityRegistrarOrigin; + type WeightInfo = moonbeam_weights::pallet_identity::WeightInfo; +} + +pub struct TransactionConverter; + +impl fp_rpc::ConvertTransaction for TransactionConverter { + fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic { + UncheckedExtrinsic::new_unsigned( + pallet_ethereum::Call::::transact { transaction }.into(), + ) + } +} + +impl fp_rpc::ConvertTransaction for TransactionConverter { + fn convert_transaction( + &self, + transaction: pallet_ethereum::Transaction, + ) -> opaque::UncheckedExtrinsic { + let extrinsic = UncheckedExtrinsic::new_unsigned( + pallet_ethereum::Call::::transact { transaction }.into(), + ); + let encoded = extrinsic.encode(); + opaque::UncheckedExtrinsic::decode(&mut &encoded[..]) + .expect("Encoded extrinsic is always valid") + } +} + +parameter_types! { + pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes; +} + +impl pallet_ethereum::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type StateRoot = pallet_ethereum::IntermediateStateRoot; + type PostLogContent = PostBlockAndTxnHashes; + type ExtraDataLength = ConstU32<30>; +} + +impl cumulus_pallet_parachain_system::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnSystemEvent = (); + type SelfParaId = ParachainInfo; + type DmpMessageHandler = MaintenanceMode; + type ReservedDmpWeight = ReservedDmpWeight; + type OutboundXcmpMessageSource = XcmpQueue; + type XcmpMessageHandler = XcmpQueue; + type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; +} + +pub struct EthereumXcmEnsureProxy; +impl xcm_primitives::EnsureProxy for EthereumXcmEnsureProxy { + fn ensure_ok(delegator: AccountId, delegatee: AccountId) -> Result<(), &'static str> { + // The EVM implicitely contains an Any proxy, so we only allow for "Any" proxies + let def: pallet_proxy::ProxyDefinition = + pallet_proxy::Pallet::::find_proxy( + &delegator, + &delegatee, + Some(ProxyType::Any), + ) + .map_err(|_| "proxy error: expected `ProxyType::Any`")?; + // We only allow to use it for delay zero proxies, as the call will immediatly be executed + ensure!(def.delay.is_zero(), "proxy delay is Non-zero`"); + Ok(()) + } +} + +impl pallet_ethereum_xcm::Config for Runtime { + type InvalidEvmTransactionError = pallet_ethereum::InvalidTransactionWrapper; + type ValidatedTransaction = pallet_ethereum::ValidatedTransaction; + type XcmEthereumOrigin = pallet_ethereum_xcm::EnsureXcmEthereumTransaction; + type ReservedXcmpWeight = ReservedXcmpWeight; + type EnsureProxy = EthereumXcmEnsureProxy; + type ControllerOrigin = EnsureRoot; +} + +parameter_types! { + pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); +} + +impl parachain_info::Config for Runtime {} + +pub struct OnNewRound; +impl pallet_parachain_staking::OnNewRound for OnNewRound { + fn on_new_round(round_index: pallet_parachain_staking::RoundIndex) -> Weight { + MoonbeamOrbiters::on_new_round(round_index) + } +} +pub struct PayoutCollatorOrOrbiterReward; +impl pallet_parachain_staking::PayoutCollatorReward for PayoutCollatorOrOrbiterReward { + fn payout_collator_reward( + for_round: pallet_parachain_staking::RoundIndex, + collator_id: AccountId, + amount: Balance, + ) -> Weight { + let extra_weight = if MoonbeamOrbiters::is_orbiter(for_round, collator_id) { + MoonbeamOrbiters::distribute_rewards(for_round, collator_id, amount) + } else { + ParachainStaking::mint_collator_reward(for_round, collator_id, amount) + }; + + ::DbWeight::get() + .reads(1) + .saturating_add(extra_weight) + } +} + +pub struct OnInactiveCollator; +impl pallet_parachain_staking::OnInactiveCollator for OnInactiveCollator { + fn on_inactive_collator( + collator_id: AccountId, + round: pallet_parachain_staking::RoundIndex, + ) -> Result> { + let extra_weight = if !MoonbeamOrbiters::is_orbiter(round, collator_id.clone()) { + ParachainStaking::go_offline_inner(collator_id)?; + ::WeightInfo::go_offline( + pallet_parachain_staking::MAX_CANDIDATES, + ) + } else { + Weight::zero() + }; + + Ok(::DbWeight::get() + .reads(1) + .saturating_add(extra_weight)) + } +} +type MonetaryGovernanceOrigin = + EitherOfDiverse, governance::custom_origins::GeneralAdmin>; + +impl pallet_parachain_staking::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type MonetaryGovernanceOrigin = MonetaryGovernanceOrigin; + /// Minimum round length is 2 minutes (10 * 12 second block times) + type MinBlocksPerRound = ConstU32<10>; + /// If a collator doesn't produce any block on this number of rounds, it is notified as inactive + type MaxOfflineRounds = ConstU32<1>; + /// Rounds before the collator leaving the candidates request can be executed + type LeaveCandidatesDelay = ConstU32<{ 4 * 7 }>; + /// Rounds before the candidate bond increase/decrease can be executed + type CandidateBondLessDelay = ConstU32<{ 4 * 7 }>; + /// Rounds before the delegator exit can be executed + type LeaveDelegatorsDelay = ConstU32<{ 4 * 7 }>; + /// Rounds before the delegator revocation can be executed + type RevokeDelegationDelay = ConstU32<{ 4 * 7 }>; + /// Rounds before the delegator bond increase/decrease can be executed + type DelegationBondLessDelay = ConstU32<{ 4 * 7 }>; + /// Rounds before the reward is paid + type RewardPaymentDelay = ConstU32<2>; + /// Minimum collators selected per round, default at genesis and minimum forever after + type MinSelectedCandidates = ConstU32<8>; + /// Maximum top delegations per candidate + type MaxTopDelegationsPerCandidate = ConstU32<300>; + /// Maximum bottom delegations per candidate + type MaxBottomDelegationsPerCandidate = ConstU32<50>; + /// Maximum delegations per delegator + type MaxDelegationsPerDelegator = ConstU32<100>; + /// Minimum stake required to be reserved to be a candidate + type MinCandidateStk = ConstU128<{ 20_000 * currency::GLMR * currency::SUPPLY_FACTOR }>; + /// Minimum stake required to be reserved to be a delegator + type MinDelegation = ConstU128<{ 500 * currency::MILLIGLMR * currency::SUPPLY_FACTOR }>; + type BlockAuthor = AuthorInherent; + type OnCollatorPayout = (); + type PayoutCollatorReward = PayoutCollatorOrOrbiterReward; + type OnInactiveCollator = OnInactiveCollator; + type OnNewRound = OnNewRound; + type WeightInfo = moonbeam_weights::pallet_parachain_staking::WeightInfo; + type MaxCandidates = ConstU32<200>; +} + +impl pallet_author_inherent::Config for Runtime { + type SlotBeacon = RelaychainDataProvider; + type AccountLookup = MoonbeamOrbiters; + type CanAuthor = AuthorFilter; + type AuthorId = AccountId; + type WeightInfo = moonbeam_weights::pallet_author_inherent::WeightInfo; +} + +impl pallet_author_slot_filter::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RandomnessSource = Randomness; + type PotentialAuthors = ParachainStaking; + type WeightInfo = moonbeam_weights::pallet_author_slot_filter::WeightInfo; +} + +parameter_types! { + pub const InitializationPayment: Perbill = Perbill::from_percent(30); + pub const RelaySignaturesThreshold: Perbill = Perbill::from_percent(100); + pub const SignatureNetworkIdentifier: &'static [u8] = b"moonbeam-"; +} + +impl pallet_crowdloan_rewards::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Initialized = ConstBool; + type InitializationPayment = InitializationPayment; + type MaxInitContributors = ConstU32<500>; + type MinimumReward = ConstU128<0>; + type RewardCurrency = Balances; + type RelayChainAccountId = [u8; 32]; + type RewardAddressAssociateOrigin = EnsureSigned; + type RewardAddressChangeOrigin = EnsureSigned; + type RewardAddressRelayVoteThreshold = RelaySignaturesThreshold; + type SignatureNetworkIdentifier = SignatureNetworkIdentifier; + type VestingBlockNumber = relay_chain::BlockNumber; + type VestingBlockProvider = RelaychainDataProvider; + type WeightInfo = moonbeam_weights::pallet_crowdloan_rewards::WeightInfo; +} + +// This is a simple session key manager. It should probably either work with, or be replaced +// entirely by pallet sessions +impl pallet_author_mapping::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type DepositCurrency = Balances; + type DepositAmount = ConstU128<{ 100 * currency::GLMR * currency::SUPPLY_FACTOR }>; + type Keys = session_keys_primitives::VrfId; + type WeightInfo = moonbeam_weights::pallet_author_mapping::WeightInfo; +} + +/// The type used to represent the kinds of proxying allowed. +#[derive( + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + Debug, + MaxEncodedLen, + TypeInfo, + Serialize, + Deserialize, +)] +pub enum ProxyType { + /// All calls can be proxied. This is the trivial/most permissive filter. + Any = 0, + /// Only extrinsics that do not transfer funds. + NonTransfer = 1, + /// Only extrinsics related to governance (democracy and collectives). + Governance = 2, + /// Only extrinsics related to staking. + Staking = 3, + /// Allow to veto an announced proxy call. + CancelProxy = 4, + /// Allow extrinsic related to Balances. + Balances = 5, + /// Allow extrinsic related to AuthorMapping. + AuthorMapping = 6, + /// Allow extrinsic related to IdentityJudgement. + IdentityJudgement = 7, +} + +impl Default for ProxyType { + fn default() -> Self { + Self::Any + } +} + +fn is_governance_precompile(precompile_name: &precompiles::PrecompileName) -> bool { + matches!( + precompile_name, + PrecompileName::DemocracyPrecompile + | PrecompileName::ConvictionVotingPrecompile + | PrecompileName::CouncilInstance + | PrecompileName::PreimagePrecompile + | PrecompileName::ReferendaPrecompile + | PrecompileName::TechCommitteeInstance + | PrecompileName::OpenTechCommitteeInstance + | PrecompileName::TreasuryCouncilInstance + ) +} + +// Be careful: Each time this filter is modified, the substrate filter must also be modified +// consistently. +impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType { + fn is_evm_proxy_call_allowed( + &self, + call: &pallet_evm_precompile_proxy::EvmSubCall, + recipient_has_code: bool, + gas: u64, + ) -> precompile_utils::EvmResult { + Ok(match self { + ProxyType::Any => { + match PrecompileName::from_address(call.to.0) { + // Any precompile that can execute a subcall should be forbidden here, + // to ensure that unauthorized smart contract can't be called + // indirectly. + // To be safe, we only allow the precompiles we need. + Some( + PrecompileName::AuthorMappingPrecompile + | PrecompileName::ParachainStakingPrecompile, + ) => true, + Some(ref precompile) if is_governance_precompile(precompile) => true, + // All non-whitelisted precompiles are forbidden + Some(_) => false, + // Allow evm transfer to "simple" account (no code nor precompile) + // For the moment, no smart contract other than precompiles is allowed. + // In the future, we may create a dynamic whitelist to authorize some audited + // smart contracts through governance. + None => { + // If the address is not recognized, allow only evm transfert to "simple" + // accounts (no code nor precompile). + // Note: Checking the presence of the code is not enough because some + // precompiles have no code. + !recipient_has_code + && precompile_utils::precompile_set::is_precompile_or_fail::( + call.to.0, gas, + )? + } + } + } + ProxyType::NonTransfer => { + call.value == U256::zero() + && match PrecompileName::from_address(call.to.0) { + Some( + PrecompileName::AuthorMappingPrecompile + | PrecompileName::ParachainStakingPrecompile, + ) => true, + Some(ref precompile) if is_governance_precompile(precompile) => true, + _ => false, + } + } + ProxyType::Governance => { + call.value == U256::zero() + && matches!( + PrecompileName::from_address(call.to.0), + Some(ref precompile) if is_governance_precompile(precompile) + ) + } + ProxyType::Staking => { + call.value == U256::zero() + && matches!( + PrecompileName::from_address(call.to.0), + Some( + PrecompileName::AuthorMappingPrecompile + | PrecompileName::ParachainStakingPrecompile + ) + ) + } + // The proxy precompile does not contain method cancel_proxy + ProxyType::CancelProxy => false, + ProxyType::Balances => { + // Allow only "simple" accounts as recipient (no code nor precompile). + // Note: Checking the presence of the code is not enough because some precompiles + // have no code. + !recipient_has_code + && !precompile_utils::precompile_set::is_precompile_or_fail::( + call.to.0, gas, + )? + } + ProxyType::AuthorMapping => { + call.value == U256::zero() + && matches!( + PrecompileName::from_address(call.to.0), + Some(PrecompileName::AuthorMappingPrecompile) + ) + } + // There is no identity precompile + ProxyType::IdentityJudgement => false, + }) + } +} + +// Be careful: Each time this filter is modified, the EVM filter must also be modified consistently. +impl InstanceFilter for ProxyType { + fn filter(&self, c: &RuntimeCall) -> bool { + match self { + ProxyType::Any => true, + ProxyType::NonTransfer => { + matches!( + c, + RuntimeCall::System(..) + | RuntimeCall::ParachainSystem(..) + | RuntimeCall::Timestamp(..) + | RuntimeCall::ParachainStaking(..) + | RuntimeCall::Democracy(..) + | RuntimeCall::Referenda(..) + | RuntimeCall::Preimage(..) + | RuntimeCall::CouncilCollective(..) + | RuntimeCall::ConvictionVoting(..) + | RuntimeCall::TreasuryCouncilCollective(..) + | RuntimeCall::TechCommitteeCollective(..) + | RuntimeCall::OpenTechCommitteeCollective(..) + | RuntimeCall::Identity(..) + | RuntimeCall::Utility(..) + | RuntimeCall::Proxy(..) | RuntimeCall::AuthorMapping(..) + | RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::claim { .. } + ) + ) + } + ProxyType::Governance => matches!( + c, + RuntimeCall::Democracy(..) + | RuntimeCall::Referenda(..) + | RuntimeCall::Preimage(..) + | RuntimeCall::ConvictionVoting(..) + | RuntimeCall::CouncilCollective(..) + | RuntimeCall::TreasuryCouncilCollective(..) + | RuntimeCall::TechCommitteeCollective(..) + | RuntimeCall::OpenTechCommitteeCollective(..) + | RuntimeCall::Utility(..) + ), + ProxyType::Staking => matches!( + c, + RuntimeCall::ParachainStaking(..) + | RuntimeCall::Utility(..) + | RuntimeCall::AuthorMapping(..) + | RuntimeCall::MoonbeamOrbiters(..) + ), + ProxyType::CancelProxy => matches!( + c, + RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) + ), + ProxyType::Balances => { + matches!(c, RuntimeCall::Balances(..) | RuntimeCall::Utility(..)) + } + ProxyType::AuthorMapping => matches!(c, RuntimeCall::AuthorMapping(..)), + ProxyType::IdentityJudgement => matches!( + c, + RuntimeCall::Identity(pallet_identity::Call::provide_judgement { .. }) + | RuntimeCall::Utility(..) + ), + } + } + + fn is_superset(&self, o: &Self) -> bool { + match (self, o) { + (x, y) if x == y => true, + (ProxyType::Any, _) => true, + (_, ProxyType::Any) => false, + _ => false, + } + } +} + +impl pallet_proxy::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type ProxyType = ProxyType; + // One storage item; key size 32, value size 8 + type ProxyDepositBase = ConstU128<{ currency::deposit(1, 8) }>; + // Additional storage item size of 21 bytes (20 bytes AccountId + 1 byte sizeof(ProxyType)). + type ProxyDepositFactor = ConstU128<{ currency::deposit(0, 21) }>; + type MaxProxies = ConstU32<32>; + type WeightInfo = moonbeam_weights::pallet_proxy::WeightInfo; + type MaxPending = ConstU32<32>; + type CallHasher = BlakeTwo256; + type AnnouncementDepositBase = ConstU128<{ currency::deposit(1, 8) }>; + // Additional storage item size of 56 bytes: + // - 20 bytes AccountId + // - 32 bytes Hasher (Blake2256) + // - 4 bytes BlockNumber (u32) + type AnnouncementDepositFactor = ConstU128<{ currency::deposit(0, 56) }>; +} + +use pallet_migrations::{GetMigrations, Migration}; +pub struct TransactorRelayIndexMigration(sp_std::marker::PhantomData); + +impl GetMigrations for TransactorRelayIndexMigration +where + Runtime: pallet_xcm_transactor::Config, +{ + fn get_migrations() -> Vec> { + vec![Box::new( + moonbeam_runtime_common::migrations::PopulateRelayIndices::( + moonbeam_relay_encoder::polkadot::POLKADOT_RELAY_INDICES, + Default::default(), + ), + )] + } +} + +impl pallet_migrations::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type MigrationsList = ( + moonbeam_runtime_common::migrations::CommonMigrations< + Runtime, + CouncilCollective, + TechCommitteeCollective, + >, + TransactorRelayIndexMigration, + ); + type XcmExecutionManager = XcmExecutionManager; +} + +/// Maintenance mode Call filter +pub struct MaintenanceFilter; +impl Contains for MaintenanceFilter { + fn contains(c: &RuntimeCall) -> bool { + match c { + RuntimeCall::Assets(_) => false, + RuntimeCall::LocalAssets(_) => false, + RuntimeCall::Balances(_) => false, + RuntimeCall::CrowdloanRewards(_) => false, + RuntimeCall::Ethereum(_) => false, + RuntimeCall::EVM(_) => false, + RuntimeCall::Identity(_) => false, + RuntimeCall::XTokens(_) => false, + RuntimeCall::ParachainStaking(_) => false, + RuntimeCall::MoonbeamOrbiters(_) => false, + RuntimeCall::PolkadotXcm(_) => false, + RuntimeCall::Treasury(_) => false, + RuntimeCall::XcmTransactor(_) => false, + RuntimeCall::EthereumXcm(_) => false, + _ => true, + } + } +} + +/// Normal Call Filter +/// We dont allow to create nor mint assets, this for now is disabled +/// We only allow transfers. For now creation of assets will go through +/// asset-manager, while minting/burning only happens through xcm messages +/// This can change in the future +pub struct NormalFilter; +impl Contains for NormalFilter { + fn contains(c: &RuntimeCall) -> bool { + match c { + RuntimeCall::Assets(method) => match method { + pallet_assets::Call::transfer { .. } => true, + pallet_assets::Call::transfer_keep_alive { .. } => true, + pallet_assets::Call::approve_transfer { .. } => true, + pallet_assets::Call::transfer_approved { .. } => true, + pallet_assets::Call::cancel_approval { .. } => true, + pallet_assets::Call::destroy_accounts { .. } => true, + pallet_assets::Call::destroy_approvals { .. } => true, + pallet_assets::Call::finish_destroy { .. } => true, + _ => false, + }, + // We want to disable create, as we dont want users to be choosing the + // assetId of their choice + // We also disable destroy, as we want to route destroy through the + // asset-manager, which guarantees the removal both at the EVM and + // substrate side of things + RuntimeCall::LocalAssets(method) => match method { + pallet_assets::Call::create { .. } => false, + pallet_assets::Call::start_destroy { .. } => false, + _ => true, + }, + // We just want to enable this in case of live chains, since the default version + // is populated at genesis + RuntimeCall::PolkadotXcm(method) => match method { + pallet_xcm::Call::force_default_xcm_version { .. } => true, + _ => false, + }, + // We filter anonymous proxy as they make "reserve" inconsistent + // See: https://github.com/paritytech/substrate/blob/37cca710eed3dadd4ed5364c7686608f5175cce1/frame/proxy/src/lib.rs#L270 // editorconfig-checker-disable-line + RuntimeCall::Proxy(method) => match method { + pallet_proxy::Call::create_pure { .. } => false, + pallet_proxy::Call::kill_pure { .. } => false, + pallet_proxy::Call::proxy { real, .. } => { + !pallet_evm::AccountCodes::::contains_key(H160::from(*real)) + } + _ => true, + }, + // Filtering the EVM prevents possible re-entrancy from the precompiles which could + // lead to unexpected scenarios. + // See https://github.com/PureStake/sr-moonbeam/issues/30 + // Note: It is also assumed that EVM calls are only allowed through `Origin::Root` so + // this can be seen as an additional security + RuntimeCall::EVM(_) => false, + _ => true, + } + } +} + +pub struct XcmExecutionManager; +impl moonkit_xcm_primitives::PauseXcmExecution for XcmExecutionManager { + fn suspend_xcm_execution() -> DispatchResult { + XcmpQueue::suspend_xcm_execution(RuntimeOrigin::root()) + } + fn resume_xcm_execution() -> DispatchResult { + XcmpQueue::resume_xcm_execution(RuntimeOrigin::root()) + } +} + +pub struct NormalDmpHandler; +impl DmpMessageHandler for NormalDmpHandler { + // This implementation makes messages be queued + // Since the limit is 0, messages are queued for next iteration + fn handle_dmp_messages( + iter: impl Iterator)>, + limit: Weight, + ) -> Weight { + (if Migrations::should_pause_xcm() { + DmpQueue::handle_dmp_messages(iter, Weight::zero()) + } else { + DmpQueue::handle_dmp_messages(iter, limit) + }) + ::DbWeight::get().reads(1) + } +} + +pub struct MaintenanceDmpHandler; +impl DmpMessageHandler for MaintenanceDmpHandler { + // This implementation makes messages be queued + // Since the limit is 0, messages are queued for next iteration + fn handle_dmp_messages( + iter: impl Iterator)>, + _limit: Weight, + ) -> Weight { + DmpQueue::handle_dmp_messages(iter, Weight::zero()) + } +} + +/// The hooks we want to run in Maintenance Mode +pub struct MaintenanceHooks; + +impl OnInitialize for MaintenanceHooks { + fn on_initialize(n: BlockNumber) -> Weight { + AllPalletsWithSystem::on_initialize(n) + } +} + +// return 0 +// For some reason using empty tuple () isnt working +// There exist only two pallets that use onIdle and these are xcmp and dmp queues +// For some reason putting an empty tumple does not work (transaction never finishes) +// We use an empty onIdle, if on the future we want one of the pallets to execute it +// we need to provide it here +impl OnIdle for MaintenanceHooks { + fn on_idle(_n: BlockNumber, _max_weight: Weight) -> Weight { + Weight::zero() + } +} + +impl OnRuntimeUpgrade for MaintenanceHooks { + fn on_runtime_upgrade() -> Weight { + AllPalletsWithSystem::on_runtime_upgrade() + } + + #[cfg(feature = "try-runtime")] + fn try_on_runtime_upgrade(checks: bool) -> Result { + AllPalletsWithSystem::try_on_runtime_upgrade(checks) + } +} + +impl OnFinalize for MaintenanceHooks { + fn on_finalize(n: BlockNumber) { + AllPalletsWithSystem::on_finalize(n) + } +} + +impl OffchainWorker for MaintenanceHooks { + fn offchain_worker(n: BlockNumber) { + AllPalletsWithSystem::offchain_worker(n) + } +} + +impl pallet_maintenance_mode::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type NormalCallFilter = NormalFilter; + type MaintenanceCallFilter = MaintenanceFilter; + type MaintenanceOrigin = + pallet_collective::EnsureProportionAtLeast; + type XcmExecutionManager = XcmExecutionManager; + type NormalDmpHandler = NormalDmpHandler; + type MaintenanceDmpHandler = MaintenanceDmpHandler; + // We use AllPalletsWithSystem because we dont want to change the hooks in normal + // operation + type NormalExecutiveHooks = AllPalletsWithSystem; + type MaintenanceExecutiveHooks = MaintenanceHooks; +} + +impl pallet_proxy_genesis_companion::Config for Runtime { + type ProxyType = ProxyType; +} + +parameter_types! { + pub OrbiterReserveIdentifier: [u8; 4] = [b'o', b'r', b'b', b'i']; +} + +type AddCollatorOrigin = + EitherOfDiverse, governance::custom_origins::GeneralAdmin>; +type DelCollatorOrigin = + EitherOfDiverse, governance::custom_origins::GeneralAdmin>; + +impl pallet_moonbeam_orbiters::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type AccountLookup = AuthorMapping; + type AddCollatorOrigin = AddCollatorOrigin; + type Currency = Balances; + type DelCollatorOrigin = DelCollatorOrigin; + /// Maximum number of orbiters per collator + type MaxPoolSize = ConstU32<8>; + /// Maximum number of round to keep on storage + type MaxRoundArchive = ConstU32<4>; + type OrbiterReserveIdentifier = OrbiterReserveIdentifier; + type RotatePeriod = ConstU32<1>; + /// Round index type. + type RoundIndex = pallet_parachain_staking::RoundIndex; + type WeightInfo = moonbeam_weights::pallet_moonbeam_orbiters::WeightInfo; +} + +/// Only callable after `set_validation_data` is called which forms this proof the same way +fn relay_chain_state_proof() -> RelayChainStateProof { + let relay_storage_root = ParachainSystem::validation_data() + .expect("set in `set_validation_data`") + .relay_parent_storage_root; + let relay_chain_state = + ParachainSystem::relay_state_proof().expect("set in `set_validation_data`"); + RelayChainStateProof::new(ParachainInfo::get(), relay_storage_root, relay_chain_state) + .expect("Invalid relay chain state proof, already constructed in `set_validation_data`") +} + +pub struct BabeDataGetter; +impl pallet_randomness::GetBabeData> for BabeDataGetter { + // Tolerate panic here because only ever called in inherent (so can be omitted) + fn get_epoch_index() -> u64 { + if cfg!(feature = "runtime-benchmarks") { + // storage reads as per actual reads + let _relay_storage_root = ParachainSystem::validation_data(); + let _relay_chain_state = ParachainSystem::relay_state_proof(); + const BENCHMARKING_NEW_EPOCH: u64 = 10u64; + return BENCHMARKING_NEW_EPOCH; + } + relay_chain_state_proof() + .read_optional_entry(relay_chain::well_known_keys::EPOCH_INDEX) + .ok() + .flatten() + .expect("expected to be able to read epoch index from relay chain state proof") + } + fn get_epoch_randomness() -> Option { + if cfg!(feature = "runtime-benchmarks") { + // storage reads as per actual reads + let _relay_storage_root = ParachainSystem::validation_data(); + let _relay_chain_state = ParachainSystem::relay_state_proof(); + let benchmarking_babe_output = Hash::default(); + return Some(benchmarking_babe_output); + } + relay_chain_state_proof() + .read_optional_entry(relay_chain::well_known_keys::ONE_EPOCH_AGO_RANDOMNESS) + .ok() + .flatten() + } +} + +impl pallet_randomness::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type AddressMapping = sp_runtime::traits::ConvertInto; + type Currency = Balances; + type BabeDataGetter = BabeDataGetter; + type VrfKeyLookup = AuthorMapping; + type Deposit = ConstU128<{ 1 * currency::GLMR * currency::SUPPLY_FACTOR }>; + type MaxRandomWords = ConstU8<100>; + type MinBlockDelay = ConstU32<2>; + type MaxBlockDelay = ConstU32<2_000>; + type BlockExpirationDelay = ConstU32<10_000>; + type EpochExpirationDelay = ConstU64<10_000>; + type WeightInfo = moonbeam_weights::pallet_randomness::WeightInfo; +} + +impl pallet_root_testing::Config for Runtime {} + +parameter_types! { + // One storage item; key size is 32 + 20; value is size 4+4+16+20 bytes = 44 bytes. + pub const DepositBase: Balance = currency::deposit(1, 96); + // Additional storage item size of 20 bytes. + pub const DepositFactor: Balance = currency::deposit(0, 20); + pub const MaxSignatories: u32 = 100; +} + +impl pallet_multisig::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type DepositBase = DepositBase; + type DepositFactor = DepositFactor; + type MaxSignatories = MaxSignatories; + type WeightInfo = moonbeam_weights::pallet_multisig::WeightInfo; +} + +construct_runtime! { + pub enum Runtime + { + // System support stuff. + System: frame_system::{Pallet, Call, Storage, Config, Event} = 0, + ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event} = 1, + // Previously 2: pallet_randomness_collective_flip + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 3, + ParachainInfo: parachain_info::{Pallet, Storage, Config} = 4, + RootTesting: pallet_root_testing::{Pallet, Call, Storage} = 5, + + // Monetary stuff. + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event} = 10, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Config, Event} = 11, + + // Consensus support. + ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Event, Config} = 20, + AuthorInherent: pallet_author_inherent::{Pallet, Call, Storage, Inherent} = 21, + AuthorFilter: pallet_author_slot_filter::{Pallet, Call, Storage, Event, Config} = 22, + AuthorMapping: pallet_author_mapping::{Pallet, Call, Config, Storage, Event} = 23, + MoonbeamOrbiters: pallet_moonbeam_orbiters::{Pallet, Call, Storage, Event} = 24, + + // Handy utilities. + Utility: pallet_utility::{Pallet, Call, Event} = 30, + Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 31, + MaintenanceMode: pallet_maintenance_mode::{Pallet, Call, Config, Storage, Event} = 32, + Identity: pallet_identity::{Pallet, Call, Storage, Event} = 33, + Migrations: pallet_migrations::{Pallet, Storage, Config, Event} = 34, + ProxyGenesisCompanion: pallet_proxy_genesis_companion::{Pallet, Config} = 35, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 36, + + // Has been permanently removed for safety reasons. + // Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event} = 40, + + // Ethereum compatibility. + EthereumChainId: pallet_evm_chain_id::{Pallet, Storage, Config} = 50, + EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 51, + Ethereum: pallet_ethereum::{Pallet, Call, Storage, Event, Origin, Config} = 52, + + // Governance stuff. + Scheduler: pallet_scheduler::{Pallet, Storage, Event, Call} = 60, + Democracy: pallet_democracy::{Pallet, Storage, Config, Event, Call} = 61, + Preimage: pallet_preimage::{Pallet, Call, Storage, Event} = 62, + ConvictionVoting: pallet_conviction_voting::{Pallet, Call, Storage, Event} = 63, + Referenda: pallet_referenda::{Pallet, Call, Storage, Event} = 64, + Origins: governance::custom_origins::{Origin} = 65, + Whitelist: pallet_whitelist::{Pallet, Call, Storage, Event} = 66, + + // Council stuff. + CouncilCollective: + pallet_collective::::{Pallet, Call, Storage, Event, Origin, Config} = 70, + TechCommitteeCollective: + pallet_collective::::{Pallet, Call, Storage, Event, Origin, Config} = 71, + TreasuryCouncilCollective: + pallet_collective::::{Pallet, Call, Storage, Event, Origin, Config} = 72, + OpenTechCommitteeCollective: + pallet_collective::::{Pallet, Call, Storage, Event, Origin, Config} = 73, + + // Treasury stuff. + Treasury: pallet_treasury::{Pallet, Storage, Config, Event, Call} = 80, + + // Crowdloan stuff. + CrowdloanRewards: pallet_crowdloan_rewards::{Pallet, Call, Config, Storage, Event} = 90, + + // XCM + XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Storage, Event} = 100, + CumulusXcm: cumulus_pallet_xcm::{Pallet, Event, Origin} = 101, + DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 102, + PolkadotXcm: pallet_xcm::{Pallet, Storage, Call, Event, Origin, Config} = 103, + Assets: pallet_assets::{Pallet, Call, Storage, Event} = 104, + AssetManager: pallet_asset_manager::{Pallet, Call, Storage, Event} = 105, + XTokens: orml_xtokens::{Pallet, Call, Storage, Event} = 106, + XcmTransactor: pallet_xcm_transactor::{Pallet, Call, Storage, Event} = 107, + LocalAssets: pallet_assets::::{Pallet, Call, Storage, Event} = 108, + EthereumXcm: pallet_ethereum_xcm::{Pallet, Call, Storage, Origin} = 109, + Erc20XcmBridge: pallet_erc20_xcm_bridge::{Pallet} = 110, + + + // Randomness + Randomness: pallet_randomness::{Pallet, Call, Storage, Event, Inherent} = 120, + } +} + +#[cfg(feature = "runtime-benchmarks")] +use { + moonbeam_xcm_benchmarks::generic::benchmarking as MoonbeamXcmBenchmarks, + MoonbeamXcmBenchmarks::XcmGenericBenchmarks as MoonbeamXcmGenericBench, +}; +#[cfg(feature = "runtime-benchmarks")] +mod benches { + frame_benchmarking::define_benchmarks!( + [pallet_utility, Utility] + [pallet_timestamp, Timestamp] + [pallet_balances, Balances] + [pallet_evm, EVM] + [pallet_assets, Assets] + [pallet_collective, CouncilCollective] + [pallet_parachain_staking, ParachainStaking] + [pallet_scheduler, Scheduler] + [pallet_democracy, Democracy] + [pallet_treasury, Treasury] + [pallet_author_inherent, AuthorInherent] + [pallet_author_slot_filter, AuthorFilter] + [pallet_crowdloan_rewards, CrowdloanRewards] + [pallet_author_mapping, AuthorMapping] + [pallet_proxy, Proxy] + [pallet_identity, Identity] + [cumulus_pallet_xcmp_queue, XcmpQueue] + [pallet_xcm, PolkadotXcm] + [pallet_asset_manager, AssetManager] + [pallet_xcm_transactor, XcmTransactor] + [pallet_moonbeam_orbiters, MoonbeamOrbiters] + [pallet_randomness, Randomness] + [pallet_conviction_voting, ConvictionVoting] + [pallet_referenda, Referenda] + [pallet_preimage, Preimage] + [pallet_whitelist, Whitelist] + [pallet_multisig, Multisig] + [moonbeam_xcm_benchmarks::weights::generic, MoonbeamXcmGenericBench::] + ); +} + +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; + +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckNonZeroSender, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, +); +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = + fp_self_contained::UncheckedExtrinsic; +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = + fp_self_contained::CheckedExtrinsic; +/// Executive: handles dispatch to the various pallets. +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + pallet_maintenance_mode::ExecutiveHooks, +>; + +// All of our runtimes share most of their Runtime API implementations. +// We use a macro to implement this common part and add runtime-specific additional implementations. +// This macro expands to : +// ``` +// impl_runtime_apis! { +// // All impl blocks shared between all runtimes. +// +// // Specific impls provided to the `impl_runtime_apis_plus_common!` macro. +// } +// ``` +moonbeam_runtime_common::impl_runtime_apis_plus_common! { + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction( + source: TransactionSource, + xt: ::Extrinsic, + block_hash: ::Hash, + ) -> TransactionValidity { + // Filtered calls should not enter the tx pool as they'll fail if inserted. + // If this call is not allowed, we return early. + if !::BaseCallFilter::contains(&xt.0.function) { + return InvalidTransaction::Call.into(); + } + + // This runtime uses Substrate's pallet transaction payment. This + // makes the chain feel like a standard Substrate chain when submitting + // frame transactions and using Substrate ecosystem tools. It has the downside that + // transaction are not prioritized by gas_price. The following code reprioritizes + // transactions to overcome this. + // + // A more elegant, ethereum-first solution is + // a pallet that replaces pallet transaction payment, and allows users + // to directly specify a gas price rather than computing an effective one. + // #HopefullySomeday + + // First we pass the transactions to the standard FRAME executive. This calculates all the + // necessary tags, longevity and other properties that we will leave unchanged. + // This also assigns some priority that we don't care about and will overwrite next. + let mut intermediate_valid = Executive::validate_transaction(source, xt.clone(), block_hash)?; + + let dispatch_info = xt.get_dispatch_info(); + + // If this is a pallet ethereum transaction, then its priority is already set + // according to gas price from pallet ethereum. If it is any other kind of transaction, + // we modify its priority. + Ok(match &xt.0.function { + RuntimeCall::Ethereum(transact { .. }) => intermediate_valid, + _ if dispatch_info.class != DispatchClass::Normal => intermediate_valid, + _ => { + let tip = match xt.0.signature { + None => 0, + Some((_, _, ref signed_extra)) => { + // Yuck, this depends on the index of charge transaction in Signed Extra + let charge_transaction = &signed_extra.7; + charge_transaction.tip() + } + }; + + // Calculate the fee that will be taken by pallet transaction payment + let fee: u64 = TransactionPayment::compute_fee( + xt.encode().len() as u32, + &dispatch_info, + tip, + ).saturated_into(); + + // Calculate how much gas this effectively uses according to the existing mapping + let effective_gas = + ::GasWeightMapping::weight_to_gas( + dispatch_info.weight + ); + + // Here we calculate an ethereum-style effective gas price using the + // current fee of the transaction. Because the weight -> gas conversion is + // lossy, we have to handle the case where a very low weight maps to zero gas. + let effective_gas_price = if effective_gas > 0 { + fee / effective_gas + } else { + // If the effective gas was zero, we just act like it was 1. + fee + }; + + // Overwrite the original prioritization with this ethereum one + intermediate_valid.priority = effective_gas_price; + intermediate_valid + } + }) + } + } +} + +// Check the timestamp and parachain inherents +struct CheckInherents; + +impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { + fn check_inherents( + block: &Block, + relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, + ) -> sp_inherents::CheckInherentsResult { + let relay_chain_slot = relay_state_proof + .read_slot() + .expect("Could not read the relay chain slot from the proof"); + + let inherent_data = + cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); + + inherent_data.check_extrinsics(&block) + } +} + +// Nimbus's Executive wrapper allows relay validators to verify the seal digest +cumulus_pallet_parachain_system::register_validate_block!( + Runtime = Runtime, + BlockExecutor = pallet_author_inherent::BlockExecutor::, + CheckInherents = CheckInherents, +); + +moonbeam_runtime_common::impl_self_contained_call!(); + +// Shorthand for a Get field of a pallet Config. +#[macro_export] +macro_rules! get { + ($pallet:ident, $name:ident, $type:ty) => { + <<$crate::Runtime as $pallet::Config>::$name as $crate::Get<$type>>::get() + }; +} + +#[cfg(test)] +mod tests { + use super::{currency::*, *}; + + #[test] + // Helps us to identify a Pallet Call in case it exceeds the 1kb limit. + // Hint: this should be a rare case. If that happens, one or more of the dispatchable arguments + // need to be Boxed. + fn call_max_size() { + const CALL_ALIGN: u32 = 1024; + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!( + std::mem::size_of::>() + <= CALL_ALIGN as usize + ); + } + + #[test] + fn currency_constants_are_correct() { + assert_eq!(SUPPLY_FACTOR, 100); + + // txn fees + assert_eq!(TRANSACTION_BYTE_FEE, Balance::from(100 * GIGAWEI)); + assert_eq!( + get!(pallet_transaction_payment, OperationalFeeMultiplier, u8), + 5_u8 + ); + assert_eq!(STORAGE_BYTE_FEE, Balance::from(10 * MILLIGLMR)); + + // democracy minimums + assert_eq!( + get!(pallet_democracy, MinimumDeposit, u128), + Balance::from(400 * GLMR) + ); + assert_eq!( + get!(pallet_preimage, ByteDeposit, u128), + Balance::from(10 * MILLIGLMR) + ); + assert_eq!( + get!(pallet_treasury, ProposalBondMinimum, u128), + Balance::from(100 * GLMR) + ); + + // pallet_identity deposits + assert_eq!( + get!(pallet_identity, BasicDeposit, u128), + Balance::from(10 * GLMR + 2580 * MILLIGLMR) + ); + assert_eq!( + get!(pallet_identity, FieldDeposit, u128), + Balance::from(660 * MILLIGLMR) + ); + assert_eq!( + get!(pallet_identity, SubAccountDeposit, u128), + Balance::from(10 * GLMR + 530 * MILLIGLMR) + ); + + // staking minimums + assert_eq!( + get!(pallet_parachain_staking, MinCandidateStk, u128), + Balance::from(2_000_000 * GLMR) + ); + assert_eq!( + get!(pallet_parachain_staking, MinDelegation, u128), + Balance::from(50 * GLMR) + ); + + // crowdloan min reward + assert_eq!( + get!(pallet_crowdloan_rewards, MinimumReward, u128), + Balance::from(0u128) + ); + + // deposit for AuthorMapping + assert_eq!( + get!(pallet_author_mapping, DepositAmount, u128), + Balance::from(10 * KILOGLMR) + ); + + // proxy deposits + assert_eq!( + get!(pallet_proxy, ProxyDepositBase, u128), + Balance::from(10 * GLMR + 80 * MILLIGLMR) + ); + assert_eq!( + get!(pallet_proxy, ProxyDepositFactor, u128), + Balance::from(210 * MILLIGLMR) + ); + assert_eq!( + get!(pallet_proxy, AnnouncementDepositBase, u128), + Balance::from(10 * GLMR + 80 * MILLIGLMR) + ); + assert_eq!( + get!(pallet_proxy, AnnouncementDepositFactor, u128), + Balance::from(560 * MILLIGLMR) + ); + } + + #[test] + fn max_offline_rounds_lower_or_eq_than_reward_payment_delay() { + assert!( + get!(pallet_parachain_staking, MaxOfflineRounds, u32) + <= get!(pallet_parachain_staking, RewardPaymentDelay, u32) + ); + } + + #[test] + // Required migration is + // pallet_parachain_staking::migrations::IncreaseMaxTopDelegationsPerCandidate + // Purpose of this test is to remind of required migration if constant is ever changed + fn updating_maximum_delegators_per_candidate_requires_configuring_required_migration() { + assert_eq!( + get!(pallet_parachain_staking, MaxTopDelegationsPerCandidate, u32), + 300 + ); + assert_eq!( + get!( + pallet_parachain_staking, + MaxBottomDelegationsPerCandidate, + u32 + ), + 50 + ); + } + + #[test] + fn configured_base_extrinsic_weight_is_evm_compatible() { + let min_ethereum_transaction_weight = WeightPerGas::get() * 21_000; + let base_extrinsic = ::BlockWeights::get() + .get(frame_support::dispatch::DispatchClass::Normal) + .base_extrinsic; + assert!(base_extrinsic.ref_time() <= min_ethereum_transaction_weight.ref_time()); + } +} diff --git a/tracing/2601/runtime/moonbeam/src/precompiles.rs b/tracing/2601/runtime/moonbeam/src/precompiles.rs new file mode 100644 index 00000000..703456a9 --- /dev/null +++ b/tracing/2601/runtime/moonbeam/src/precompiles.rs @@ -0,0 +1,268 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +use crate::{ + asset_config::{ForeignAssetInstance, LocalAssetInstance}, + xcm_config::XcmExecutorConfig, + CouncilInstance, OpenTechCommitteeInstance, TechCommitteeInstance, TreasuryCouncilInstance, +}; +use frame_support::parameter_types; +use pallet_evm_precompile_author_mapping::AuthorMappingPrecompile; +use pallet_evm_precompile_balances_erc20::{Erc20BalancesPrecompile, Erc20Metadata}; +use pallet_evm_precompile_batch::BatchPrecompile; +use pallet_evm_precompile_blake2::Blake2F; +use pallet_evm_precompile_bn128::{Bn128Add, Bn128Mul, Bn128Pairing}; +use pallet_evm_precompile_call_permit::CallPermitPrecompile; +use pallet_evm_precompile_collective::CollectivePrecompile; +use pallet_evm_precompile_conviction_voting::ConvictionVotingPrecompile; +use pallet_evm_precompile_crowdloan_rewards::CrowdloanRewardsPrecompile; +use pallet_evm_precompile_democracy::DemocracyPrecompile; +use pallet_evm_precompile_gmp::GmpPrecompile; +use pallet_evm_precompile_modexp::Modexp; +use pallet_evm_precompile_parachain_staking::ParachainStakingPrecompile; +use pallet_evm_precompile_preimage::PreimagePrecompile; +use pallet_evm_precompile_proxy::{OnlyIsProxyAndProxy, ProxyPrecompile}; +use pallet_evm_precompile_randomness::RandomnessPrecompile; +use pallet_evm_precompile_referenda::ReferendaPrecompile; +use pallet_evm_precompile_registry::PrecompileRegistry; +use pallet_evm_precompile_relay_encoder::RelayEncoderPrecompile; +use pallet_evm_precompile_sha3fips::Sha3FIPS256; +use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; +use pallet_evm_precompile_xcm_transactor::{ + v1::XcmTransactorPrecompileV1, v2::XcmTransactorPrecompileV2, v3::XcmTransactorPrecompileV3, +}; +use pallet_evm_precompile_xcm_utils::XcmUtilsPrecompile; +use pallet_evm_precompile_xtokens::XtokensPrecompile; +use pallet_evm_precompileset_assets_erc20::{Erc20AssetsPrecompileSet, IsForeign, IsLocal}; +use precompile_utils::precompile_set::*; + +pub struct NativeErc20Metadata; + +/// ERC20 metadata for the native token. +impl Erc20Metadata for NativeErc20Metadata { + /// Returns the name of the token. + fn name() -> &'static str { + "GLMR token" + } + + /// Returns the symbol of the token. + fn symbol() -> &'static str { + "GLMR" + } + + /// Returns the decimals places of the token. + fn decimals() -> u8 { + 18 + } + + /// Must return `true` only if it represents the main native currency of + /// the network. It must be the currency used in `pallet_evm`. + fn is_native_currency() -> bool { + true + } +} + +/// The asset precompile address prefix. Addresses that match against this prefix will be routed +/// to Erc20AssetsPrecompileSet being marked as foreign +pub const FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 4]; +/// The asset precompile address prefix. Addresses that match against this prefix will be routed +/// to Erc20AssetsPrecompileSet being marked as local +pub const LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8, 255u8, 255u8, 254u8]; + +parameter_types! { + pub ForeignAssetPrefix: &'static [u8] = FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX; + pub LocalAssetPrefix: &'static [u8] = LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX; +} + +type EthereumPrecompilesChecks = (AcceptDelegateCall, CallableByContract, CallableByPrecompile); + +#[precompile_utils::precompile_name_from_address] +type MoonbeamPrecompilesAt = ( + // Ethereum precompiles: + // We allow DELEGATECALL to stay compliant with Ethereum behavior. + PrecompileAt, ECRecover, EthereumPrecompilesChecks>, + PrecompileAt, Sha256, EthereumPrecompilesChecks>, + PrecompileAt, Ripemd160, EthereumPrecompilesChecks>, + PrecompileAt, Identity, EthereumPrecompilesChecks>, + PrecompileAt, Modexp, EthereumPrecompilesChecks>, + PrecompileAt, Bn128Add, EthereumPrecompilesChecks>, + PrecompileAt, Bn128Mul, EthereumPrecompilesChecks>, + PrecompileAt, Bn128Pairing, EthereumPrecompilesChecks>, + PrecompileAt, Blake2F, EthereumPrecompilesChecks>, + // Non-Moonbeam specific nor Ethereum precompiles : + PrecompileAt, Sha3FIPS256, (CallableByContract, CallableByPrecompile)>, + RemovedPrecompileAt>, // Dispatch + PrecompileAt, ECRecoverPublicKey, (CallableByContract, CallableByPrecompile)>, + // Moonbeam specific precompiles: + PrecompileAt< + AddressU64<2048>, + ParachainStakingPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2049>, + CrowdloanRewardsPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2050>, + Erc20BalancesPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2051>, + DemocracyPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2052>, + XtokensPrecompile, + ( + SubcallWithMaxNesting<1>, + CallableByContract, + CallableByPrecompile, + ), + >, + PrecompileAt< + AddressU64<2053>, + RelayEncoderPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2054>, + XcmTransactorPrecompileV1, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2055>, + AuthorMappingPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2056>, + BatchPrecompile, + ( + SubcallWithMaxNesting<2>, + // Batch is the only precompile allowed to call Batch. + CallableByPrecompile>>, + ), + >, + PrecompileAt< + AddressU64<2057>, + RandomnessPrecompile, + (SubcallWithMaxNesting<0>, CallableByContract), + >, + PrecompileAt< + AddressU64<2058>, + CallPermitPrecompile, + (SubcallWithMaxNesting<0>, CallableByContract), + >, + PrecompileAt< + AddressU64<2059>, + ProxyPrecompile, + ( + CallableByContract>, + SubcallWithMaxNesting<0>, + // Batch is the only precompile allowed to call Proxy. + CallableByPrecompile>>, + ), + >, + PrecompileAt< + AddressU64<2060>, + XcmUtilsPrecompile, + CallableByContract< + pallet_evm_precompile_xcm_utils::AllExceptXcmExecute, + >, + >, + PrecompileAt< + AddressU64<2061>, + XcmTransactorPrecompileV2, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2062>, + CollectivePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2063>, + CollectivePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2064>, + CollectivePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2065>, + ReferendaPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2066>, + ConvictionVotingPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2067>, + PreimagePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2068>, + CollectivePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2069>, + PrecompileRegistry, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt, GmpPrecompile, SubcallWithMaxNesting<0>>, + PrecompileAt< + AddressU64<2071>, + XcmTransactorPrecompileV3, + (CallableByContract, CallableByPrecompile), + >, +); + +/// The PrecompileSet installed in the Moonbeam runtime. +/// We include the nine Istanbul precompiles +/// (https://github.com/ethereum/go-ethereum/blob/3c46f557/core/vm/contracts.go#L69) +/// as well as a special precompile for dispatching Substrate extrinsics +/// The following distribution has been decided for the precompiles +/// 0-1023: Ethereum Mainnet Precompiles +/// 1024-2047 Precompiles that are not in Ethereum Mainnet but are neither Moonbeam specific +/// 2048-4095 Moonbeam specific precompiles +pub type MoonbeamPrecompiles = PrecompileSetBuilder< + R, + ( + // Skip precompiles if out of range. + PrecompilesInRangeInclusive<(AddressU64<1>, AddressU64<4095>), MoonbeamPrecompilesAt>, + // Prefixed precompile sets (XC20) + PrecompileSetStartingWith< + ForeignAssetPrefix, + Erc20AssetsPrecompileSet, + (CallableByContract, CallableByPrecompile), + >, + PrecompileSetStartingWith< + LocalAssetPrefix, + Erc20AssetsPrecompileSet, + (CallableByContract, CallableByPrecompile), + >, + ), +>; diff --git a/tracing/2601/runtime/moonbeam/src/xcm_config.rs b/tracing/2601/runtime/moonbeam/src/xcm_config.rs new file mode 100644 index 00000000..fb8d5af2 --- /dev/null +++ b/tracing/2601/runtime/moonbeam/src/xcm_config.rs @@ -0,0 +1,691 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! XCM configuration for Moonbase. +//! + +use super::{ + governance, AccountId, AssetId, AssetManager, Assets, Balance, Balances, DealWithFees, + Erc20XcmBridge, LocalAssets, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, + RuntimeEvent, RuntimeOrigin, Treasury, XcmpQueue, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, +}; + +use frame_support::{ + parameter_types, + traits::{EitherOfDiverse, Everything, Nothing, PalletInfoAccess}, +}; +use moonbeam_runtime_common::weights as moonbeam_weights; +use pallet_evm_precompileset_assets_erc20::AccountIdAssetIdConversion; +use sp_runtime::{ + traits::{Hash as THash, PostDispatchInfoOf}, + DispatchErrorWithPostInfo, +}; +use sp_weights::Weight; + +use frame_system::{EnsureRoot, RawOrigin}; +use sp_core::{ConstU32, H160, H256}; + +use xcm_builder::{ + AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, + CurrencyAdapter as XcmCurrencyAdapter, EnsureXcmOrigin, FungiblesAdapter, NoChecking, + ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountKey20AsNative, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, + WeightInfoBounds, WithComputedOrigin, +}; + +use xcm::latest::prelude::*; +use xcm_executor::traits::{CallDispatcher, ConvertLocation, JustTry}; + +use orml_xcm_support::MultiNativeAsset; +use xcm_primitives::{ + AbsoluteAndRelativeReserve, AccountIdToCurrencyId, AccountIdToMultiLocation, AsAssetType, + FirstAssetTrader, SignedToAccountId20, UtilityAvailableCalls, UtilityEncodeCall, XcmTransact, +}; + +use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; + +use sp_std::{ + convert::{From, Into, TryFrom}, + prelude::*, +}; + +use orml_traits::parameter_type_with_key; + +use crate::governance::referenda::GeneralAdminOrRoot; + +parameter_types! { + // The network Id of the relay + pub const RelayNetwork: NetworkId = NetworkId::Polkadot; + // The relay chain Origin type + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + pub UniversalLocation: InteriorMultiLocation = + X2(GlobalConsensus(RelayNetwork::get()), Parachain(ParachainInfo::parachain_id().into())); + // Self Reserve location, defines the multilocation identifiying the self-reserve currency + // This is used to match it also against our Balances pallet when we receive such + // a MultiLocation: (Self Balances pallet index) + // We use the RELATIVE multilocation + pub SelfReserve: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; + + // This is the relative view of our local assets. + // Indentified by thix prefix + generalIndex(assetId) + // We use the RELATIVE multilocation + pub LocalAssetsPalletLocation: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; +} + +/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used +/// when determining ownership of accounts for asset transacting and when attempting to use XCM +/// `Transact` in order to determine the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the default `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // If we receive a MultiLocation of type AccountKey20, just generate a native account + AccountKey20Aliases, + // Generate remote accounts according to polkadot standards + xcm_builder::HashedDescriptionDescribeFamilyAllTerminal, +); + +/// Wrapper type around `LocationToAccountId` to convert an `AccountId` to type `H160`. +pub struct LocationToH160; +impl ConvertLocation for LocationToH160 { + fn convert_location(location: &MultiLocation) -> Option { + >::convert_location(location) + .map(Into::into) + } +} + +// The non-reserve fungible transactor type +// It will use pallet-assets, and the Id will be matched against AsAssetType +pub type ForeignFungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + Assets, + // Use this currency when it is a fungible asset matching the given location or name: + ( + ConvertedConcreteId< + AssetId, + Balance, + AsAssetType, + JustTry, + >, + ), + // Do a simple punn to convert an AccountId20 MultiLocation into a native chain account ID: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont allow teleports. + NoChecking, + // We dont track any teleports + (), +>; + +/// The transactor for our own chain currency. +pub type LocalAssetTransactor = XcmCurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching any of the locations in + // SelfReserveRepresentations + xcm_builder::IsConcrete, + // We can convert the MultiLocations with our converter above: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont allow teleport + (), +>; + +/// Means for transacting local assets besides the native currency on this chain. +pub type LocalFungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + LocalAssets, + // Use this currency when it is a fungible asset matching the given location or name: + ( + ConvertedConcreteId< + AssetId, + Balance, + // This just tells to convert an assetId into a GeneralIndex junction prepended + // by LocalAssetsPalletLocationNewReanchor + AsPrefixedGeneralIndex, + JustTry, + >, + ), + // Convert an XCM MultiLocation into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont want to allow teleporting assets + NoChecking, + // The account to use for tracking teleports. + (), +>; + +// We use all transactors +pub type AssetTransactors = ( + LocalAssetTransactor, + ForeignFungiblesTransactor, + LocalFungiblesTransactor, + Erc20XcmBridge, +); + +/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, +/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can +/// biases the kind of local `Origin` it will become. +pub type XcmOriginToTransactDispatchOrigin = ( + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // recognised. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognised. + SiblingParachainAsNative, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + pallet_xcm::XcmPassthrough, + // Xcm Origins defined by a Multilocation of type AccountKey20 can be converted to a 20 byte- + // account local origin + SignedAccountKey20AsNative, +); + +parameter_types! { + /// The amount of weight an XCM operation takes. This is safe overestimate. + pub UnitWeightCost: Weight = Weight::from_parts(200_000_000u64, 0); + /// Maximum number of instructions in a single XCM fragment. A sanity check against + /// weight caculations getting too crazy. + pub MaxInstructions: u32 = 100; +} + +/// Xcm Weigher shared between multiple Xcm-related configs. +pub type XcmWeigher = WeightInfoBounds< + moonbeam_xcm_benchmarks::weights::XcmWeight, + RuntimeCall, + MaxInstructions, +>; + +pub type XcmBarrier = ( + // Weight that is paid for may be consumed. + TakeWeightCredit, + // Expected responses are OK. + AllowKnownQueryResponses, + WithComputedOrigin< + ( + // If the message is one that immediately attemps to pay for execution, then allow it. + AllowTopLevelPaidExecutionFrom, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, + ), + UniversalLocation, + ConstU32<8>, + >, +); + +parameter_types! { + /// Xcm fees will go to the treasury account + pub XcmFeesAccount: AccountId = Treasury::account_id(); +} + +/// This is the struct that will handle the revenue from xcm fees +/// We do not burn anything because we want to mimic exactly what +/// the sovereign account has +pub type XcmFeesToAccount = xcm_primitives::XcmFeesToAccount< + Assets, + ( + ConvertedConcreteId< + AssetId, + Balance, + AsAssetType, + JustTry, + >, + ), + AccountId, + XcmFeesAccount, +>; + +pub struct SafeCallFilter; +impl frame_support::traits::Contains for SafeCallFilter { + fn contains(_call: &RuntimeCall) -> bool { + // TODO review + // This needs to be addressed at EVM level + true + } +} + +parameter_types! { + pub const MaxAssetsIntoHolding: u32 = xcm_primitives::MAX_ASSETS; +} + +// Our implementation of the Moonbeam Call +// Attachs the right origin in case the call is made to pallet-ethereum-xcm +#[cfg(not(feature = "evm-tracing"))] +moonbeam_runtime_common::impl_moonbeam_xcm_call!(); +#[cfg(feature = "evm-tracing")] +moonbeam_runtime_common::impl_moonbeam_xcm_call_tracing!(); + +moonbeam_runtime_common::impl_evm_runner_precompile_or_eth_xcm!(); + +pub struct XcmExecutorConfig; +impl xcm_executor::Config for XcmExecutorConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + // How to withdraw and deposit an asset. + type AssetTransactor = AssetTransactors; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + // Filter to the reserve withdraw operations + // Whenever the reserve matches the relative or absolute value + // of our chain, we always return the relative reserve + type IsReserve = MultiNativeAsset>; + type IsTeleporter = (); // No teleport + type UniversalLocation = UniversalLocation; + type Barrier = XcmBarrier; + type Weigher = XcmWeigher; + // We use two traders + // When we receive the relative representation of the self-reserve asset, + // we use UsingComponents and the local way of handling fees + // When we receive a non-reserve asset, we use AssetManager to fetch how many + // units per second we should charge + type Trader = ( + UsingComponents< + ::WeightToFee, + SelfReserve, + AccountId, + Balances, + DealWithFees, + >, + FirstAssetTrader, + ); + type ResponseHandler = PolkadotXcm; + type SubscriptionService = PolkadotXcm; + type AssetTrap = pallet_erc20_xcm_bridge::AssetTrapWrapper; + type AssetClaims = PolkadotXcm; + type CallDispatcher = MoonbeamCall; + type PalletInstancesInfo = crate::AllPalletsWithSystem; + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type AssetLocker = (); + type AssetExchanger = (); + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; + type SafeCallFilter = SafeCallFilter; + type Aliasers = Nothing; +} + +type XcmExecutor = pallet_erc20_xcm_bridge::XcmExecutorWrapper< + RuntimeCall, + xcm_executor::XcmExecutor, +>; + +// Converts a Signed Local Origin into a MultiLocation +pub type LocalOriginToLocation = SignedToAccountId20; + +/// The means for routing XCM messages which are not for local execution into the right message +/// queues. +pub type XcmRouter = ( + // Two routers - use UMP to communicate with the relay chain: + cumulus_primitives_utility::ParentAsUmp, + // ..and XCMP to communicate with the sibling chains. + XcmpQueue, +); + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parent.into()); +} + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = Nothing; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = Nothing; + type XcmReserveTransferFilter = Everything; + type Weigher = XcmWeigher; + 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 = (); + type SovereignAccountOf = LocationToAccountId; + type MaxLockers = ConstU32<8>; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + // TODO pallet-xcm weights + type WeightInfo = moonbeam_weights::pallet_xcm::WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + type AdminOrigin = EnsureRoot; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +impl cumulus_pallet_xcmp_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; + type ChannelInfo = ParachainSystem; + type VersionWrapper = PolkadotXcm; + type ExecuteOverweightOrigin = EnsureRoot; + type ControllerOrigin = EnsureRoot; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; + type WeightInfo = moonbeam_weights::cumulus_pallet_xcmp_queue::WeightInfo; + type PriceForSiblingDelivery = (); +} + +impl cumulus_pallet_dmp_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; + type ExecuteOverweightOrigin = EnsureRoot; +} + +// Our AssetType. For now we only handle Xcm Assets +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum AssetType { + Xcm(MultiLocation), +} +impl Default for AssetType { + fn default() -> Self { + Self::Xcm(MultiLocation::here()) + } +} + +impl From for AssetType { + fn from(location: MultiLocation) -> Self { + Self::Xcm(location) + } +} +impl Into> for AssetType { + fn into(self) -> Option { + match self { + Self::Xcm(location) => Some(location), + } + } +} + +// Implementation on how to retrieve the AssetId from an AssetType +// We simply hash the AssetType and take the lowest 128 bits +impl From for AssetId { + fn from(asset: AssetType) -> AssetId { + match asset { + AssetType::Xcm(id) => { + let mut result: [u8; 16] = [0u8; 16]; + let hash: H256 = id.using_encoded(::Hashing::hash); + result.copy_from_slice(&hash.as_fixed_bytes()[0..16]); + u128::from_le_bytes(result) + } + } + } +} + +// Our currencyId. We distinguish for now between SelfReserve, and Others, defined by their Id. +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum CurrencyId { + // Our native token + SelfReserve, + // Assets representing other chains native tokens + ForeignAsset(AssetId), + // Our local assets + LocalAssetReserve(AssetId), + // Erc20 token + Erc20 { contract_address: H160 }, +} + +impl AccountIdToCurrencyId for Runtime { + fn account_to_currency_id(account: AccountId) -> Option { + Some(match account { + // the self-reserve currency is identified by the pallet-balances address + a if a == H160::from_low_u64_be(2050).into() => CurrencyId::SelfReserve, + // the rest of the currencies, by their corresponding erc20 address + _ => match Runtime::account_to_asset_id(account) { + // We distinguish by prefix, and depending on it we create either + // Foreign or Local + Some((prefix, asset_id)) => { + if prefix == FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX.to_vec() { + CurrencyId::ForeignAsset(asset_id) + } else { + CurrencyId::LocalAssetReserve(asset_id) + } + } + // If no known prefix is identified, we consider that it's a "real" erc20 token + // (i.e. managed by a real smart contract) + None => CurrencyId::Erc20 { + contract_address: account.into(), + }, + }, + }) + } +} +// How to convert from CurrencyId to MultiLocation +pub struct CurrencyIdtoMultiLocation(sp_std::marker::PhantomData); +impl sp_runtime::traits::Convert> + for CurrencyIdtoMultiLocation +where + AssetXConverter: sp_runtime::traits::MaybeEquivalence, +{ + fn convert(currency: CurrencyId) -> Option { + match currency { + CurrencyId::SelfReserve => { + let multi: MultiLocation = SelfReserve::get(); + Some(multi) + } + CurrencyId::ForeignAsset(asset) => AssetXConverter::convert_back(&asset), + // No transactor matches this yet, so even if we have this enum variant the transfer will fail + CurrencyId::LocalAssetReserve(asset) => { + let mut location = LocalAssetsPalletLocation::get(); + location.push_interior(Junction::GeneralIndex(asset)).ok(); + Some(location) + } + CurrencyId::Erc20 { contract_address } => { + let mut location = Erc20XcmBridgePalletLocation::get(); + location + .push_interior(Junction::AccountKey20 { + key: contract_address.0, + network: None, + }) + .ok(); + Some(location) + } + } + } +} + +parameter_types! { + pub const BaseXcmWeight: Weight = Weight::from_parts(200_000_000u64, 0); + pub const MaxAssetsForTransfer: usize = 2; + + // This is how we are going to detect whether the asset is a Reserve asset + // This however is the chain part only + pub SelfLocation: MultiLocation = MultiLocation::here(); + // We need this to be able to catch when someone is trying to execute a non- + // cross-chain transfer in xtokens through the absolute path way + pub SelfLocationAbsolute: MultiLocation = MultiLocation { + parents:1, + interior: Junctions::X1( + Parachain(ParachainInfo::parachain_id().into()) + ) + }; +} + +parameter_type_with_key! { + pub ParachainMinFee: |location: MultiLocation| -> Option { + match (location.parents, location.first_interior()) { + // Polkadot AssetHub fee + (1, Some(Parachain(1000u32))) => Some(50_000_000u128), + _ => None, + } + }; +} + +impl orml_xtokens::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type CurrencyId = CurrencyId; + type AccountIdToMultiLocation = AccountIdToMultiLocation; + type CurrencyIdConvert = + CurrencyIdtoMultiLocation>; + type XcmExecutor = XcmExecutor; + type SelfLocation = SelfLocation; + type Weigher = XcmWeigher; + type BaseXcmWeight = BaseXcmWeight; + type UniversalLocation = UniversalLocation; + type MaxAssetsForTransfer = MaxAssetsForTransfer; + type MinXcmFee = ParachainMinFee; + type MultiLocationsFilter = Everything; + type ReserveProvider = AbsoluteAndRelativeReserve; +} + +// 1 DOT should be enough +parameter_types! { + pub MaxHrmpRelayFee: MultiAsset = (MultiLocation::parent(), 1_000_000_000_000u128).into(); +} + +// For now we only allow to transact in the relay, although this might change in the future +// Transactors just defines the chains in which we allow transactions to be issued through +// xcm +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum Transactors { + Relay, +} + +// Default for benchmarking +#[cfg(feature = "runtime-benchmarks")] +impl Default for Transactors { + fn default() -> Self { + Transactors::Relay + } +} + +impl TryFrom for Transactors { + type Error = (); + fn try_from(value: u8) -> Result { + match value { + 0u8 => Ok(Transactors::Relay), + _ => Err(()), + } + } +} + +impl UtilityEncodeCall for Transactors { + fn encode_call(self, call: UtilityAvailableCalls) -> Vec { + match self { + Transactors::Relay => pallet_xcm_transactor::Pallet::::encode_call( + pallet_xcm_transactor::Pallet(sp_std::marker::PhantomData::), + call, + ), + } + } +} + +impl XcmTransact for Transactors { + fn destination(self) -> MultiLocation { + match self { + Transactors::Relay => MultiLocation::parent(), + } + } +} + +pub type DerivativeAddressRegistrationOrigin = + EitherOfDiverse, governance::custom_origins::GeneralAdmin>; + +impl pallet_xcm_transactor::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type Transactor = Transactors; + type DerivativeAddressRegistrationOrigin = DerivativeAddressRegistrationOrigin; + type SovereignAccountDispatcherOrigin = EnsureRoot; + type CurrencyId = CurrencyId; + type AccountIdToMultiLocation = AccountIdToMultiLocation; + type CurrencyIdToMultiLocation = + CurrencyIdtoMultiLocation>; + type XcmSender = XcmRouter; + type SelfLocation = SelfLocation; + type Weigher = XcmWeigher; + type UniversalLocation = UniversalLocation; + type BaseXcmWeight = BaseXcmWeight; + type AssetTransactor = AssetTransactors; + type ReserveProvider = AbsoluteAndRelativeReserve; + type WeightInfo = moonbeam_weights::pallet_xcm_transactor::WeightInfo; + type HrmpManipulatorOrigin = GeneralAdminOrRoot; + type MaxHrmpFee = xcm_builder::Case; +} + +parameter_types! { + // This is the relative view of erc20 assets. + // Identified by this prefix + AccountKey20(contractAddress) + // We use the RELATIVE multilocation + pub Erc20XcmBridgePalletLocation: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; + + // To be able to support almost all erc20 implementations, + // we provide a sufficiently hight gas limit. + pub Erc20XcmBridgeTransferGasLimit: u64 = 200_000; +} + +impl pallet_erc20_xcm_bridge::Config for Runtime { + type AccountIdConverter = LocationToH160; + type Erc20MultilocationPrefix = Erc20XcmBridgePalletLocation; + type Erc20TransferGasLimit = Erc20XcmBridgeTransferGasLimit; + type EvmRunner = EvmRunnerPrecompileOrEthXcm; +} + +#[cfg(feature = "runtime-benchmarks")] +mod testing { + use super::*; + + /// This From exists for benchmarking purposes. It has the potential side-effect of calling + /// AssetManager::set_asset_type_asset_id() and should NOT be used in any production code. + impl From for CurrencyId { + fn from(location: MultiLocation) -> CurrencyId { + use xcm_primitives::AssetTypeGetter; + + // If it does not exist, for benchmarking purposes, we create the association + let asset_id = if let Some(asset_id) = + AsAssetType::::convert_location(&location) + { + asset_id + } else { + let asset_type = AssetType::Xcm(location); + let asset_id: AssetId = asset_type.clone().into(); + AssetManager::set_asset_type_asset_id(asset_type, asset_id); + asset_id + }; + + CurrencyId::ForeignAsset(asset_id) + } + } +} diff --git a/tracing/2601/runtime/moonbeam/tests/common/mod.rs b/tracing/2601/runtime/moonbeam/tests/common/mod.rs new file mode 100644 index 00000000..06869560 --- /dev/null +++ b/tracing/2601/runtime/moonbeam/tests/common/mod.rs @@ -0,0 +1,387 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +#![allow(dead_code)] + +use cumulus_primitives_parachain_inherent::ParachainInherentData; +use fp_evm::GenesisAccount; +use frame_support::{ + assert_ok, + traits::{OnFinalize, OnInitialize}, +}; +pub use moonbeam_runtime::{ + asset_config::AssetRegistrarMetadata, + currency::{GIGAWEI, GLMR, SUPPLY_FACTOR, WEI}, + xcm_config::AssetType, + AccountId, AssetId, AssetManager, Assets, AuthorInherent, Balance, Balances, CrowdloanRewards, + Ethereum, Executive, Header, InflationInfo, LocalAssets, ParachainStaking, Range, Runtime, + RuntimeCall, RuntimeEvent, System, TransactionConverter, TransactionPaymentAsGasPrice, + UncheckedExtrinsic, HOURS, WEEKS, +}; +use nimbus_primitives::{NimbusId, NIMBUS_ENGINE_ID}; +use sp_core::{Encode, H160}; +use sp_runtime::{traits::Dispatchable, BuildStorage, Digest, DigestItem, Perbill, Percent}; + +use std::collections::BTreeMap; + +use fp_rpc::ConvertTransaction; + +// A valid signed Alice transfer. +pub const VALID_ETH_TX: &str = + "02f869820501808085e8d4a51000825208943cd0a705a2dc65e5b1e1205896baa2be8a07c6e00180c\ + 001a061087911e877a5802142a89a40d231d50913db399eb50839bb2d04e612b22ec8a01aa313efdf2\ + 793bea76da6813bda611444af16a6207a8cfef2d9c8aa8f8012f7"; + +// An invalid signed Alice transfer with a gas limit artifically set to 0. +pub const INVALID_ETH_TX: &str = + "f8628085174876e800809412cb274aad8251c875c0bf6872b67d9983e53fdd01801ba011110796057\ + 0e2d49fcc2afbc582e1abd3eeb027242b92abcebcec7cdefab63ea001732f6fac84acdd5b096554230\ + 75003e7f07430652c3d6722e18f50b3d34e29"; + +pub fn rpc_run_to_block(n: u32) { + while System::block_number() < n { + Ethereum::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + Ethereum::on_initialize(System::block_number()); + } +} + +/// Utility function that advances the chain to the desired block number. +/// If an author is provided, that author information is injected to all the blocks in the meantime. +pub fn run_to_block(n: u32, author: Option) { + // Finalize the first block + Ethereum::on_finalize(System::block_number()); + AuthorInherent::on_finalize(System::block_number()); + while System::block_number() < n { + // Set the new block number and author + match author { + Some(ref author) => { + let pre_digest = Digest { + logs: vec![DigestItem::PreRuntime(NIMBUS_ENGINE_ID, author.encode())], + }; + System::reset_events(); + System::initialize( + &(System::block_number() + 1), + &System::parent_hash(), + &pre_digest, + ); + } + None => { + System::set_block_number(System::block_number() + 1); + } + } + + // Initialize the new block + AuthorInherent::on_initialize(System::block_number()); + ParachainStaking::on_initialize(System::block_number()); + Ethereum::on_initialize(System::block_number()); + + // Finalize the block + Ethereum::on_finalize(System::block_number()); + AuthorInherent::on_finalize(System::block_number()); + ParachainStaking::on_finalize(System::block_number()); + } +} + +pub fn last_event() -> RuntimeEvent { + System::events().pop().expect("Event expected").event +} + +// Helper function to give a simple evm context suitable for tests. +// We can remove this once https://github.com/rust-blockchain/evm/pull/35 +// is in our dependency graph. +pub fn evm_test_context() -> fp_evm::Context { + fp_evm::Context { + address: Default::default(), + caller: Default::default(), + apparent_value: From::from(0), + } +} + +// Test struct with the purpose of initializing xcm assets +#[derive(Clone)] +pub struct XcmAssetInitialization { + pub asset_type: AssetType, + pub metadata: AssetRegistrarMetadata, + pub balances: Vec<(AccountId, Balance)>, + pub is_sufficient: bool, +} + +pub struct ExtBuilder { + // [asset, Vec, owner] + local_assets: Vec<(AssetId, Vec<(AccountId, Balance)>, AccountId)>, + // endowed accounts with balances + balances: Vec<(AccountId, Balance)>, + // [collator, amount] + collators: Vec<(AccountId, Balance)>, + // [delegator, collator, nomination_amount] + delegations: Vec<(AccountId, AccountId, Balance, Percent)>, + // per-round inflation config + inflation: InflationInfo, + // AuthorId -> AccountId mappings + mappings: Vec<(NimbusId, AccountId)>, + // Crowdloan fund + crowdloan_fund: Balance, + // Chain id + chain_id: u64, + // EVM genesis accounts + evm_accounts: BTreeMap, + // [assettype, metadata, Vec, is_sufficient] + xcm_assets: Vec, + safe_xcm_version: Option, +} + +impl Default for ExtBuilder { + fn default() -> ExtBuilder { + ExtBuilder { + local_assets: vec![], + balances: vec![], + delegations: vec![], + collators: vec![], + inflation: InflationInfo { + expect: Range { + min: 100_000 * GLMR, + ideal: 200_000 * GLMR, + max: 500_000 * GLMR, + }, + // not used + annual: Range { + min: Perbill::from_percent(50), + ideal: Perbill::from_percent(50), + max: Perbill::from_percent(50), + }, + // unrealistically high parameterization, only for testing + round: Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }, + }, + mappings: vec![], + crowdloan_fund: 0, + chain_id: CHAIN_ID, + evm_accounts: BTreeMap::new(), + xcm_assets: vec![], + safe_xcm_version: None, + } + } +} + +impl ExtBuilder { + pub fn with_evm_accounts(mut self, accounts: BTreeMap) -> Self { + self.evm_accounts = accounts; + self + } + + pub fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { + self.balances = balances; + self + } + + pub fn with_collators(mut self, collators: Vec<(AccountId, Balance)>) -> Self { + self.collators = collators; + self + } + + pub fn with_delegations(mut self, delegations: Vec<(AccountId, AccountId, Balance)>) -> Self { + self.delegations = delegations + .into_iter() + .map(|d| (d.0, d.1, d.2, Percent::zero())) + .collect(); + self + } + + pub fn with_crowdloan_fund(mut self, crowdloan_fund: Balance) -> Self { + self.crowdloan_fund = crowdloan_fund; + self + } + + pub fn with_mappings(mut self, mappings: Vec<(NimbusId, AccountId)>) -> Self { + self.mappings = mappings; + self + } + + pub fn with_xcm_assets(mut self, xcm_assets: Vec) -> Self { + self.xcm_assets = xcm_assets; + self + } + + pub fn with_safe_xcm_version(mut self, safe_xcm_version: u32) -> Self { + self.safe_xcm_version = Some(safe_xcm_version); + self + } + + #[allow(dead_code)] + pub fn with_inflation(mut self, inflation: InflationInfo) -> Self { + self.inflation = inflation; + self + } + + pub fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap(); + + pallet_balances::GenesisConfig:: { + balances: self.balances, + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_parachain_staking::GenesisConfig:: { + candidates: self.collators, + delegations: self.delegations, + inflation_config: self.inflation, + collator_commission: Perbill::from_percent(20), + parachain_bond_reserve_percent: Percent::from_percent(30), + blocks_per_round: 6 * HOURS, + num_selected_candidates: 8, + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_crowdloan_rewards::GenesisConfig:: { + funded_amount: self.crowdloan_fund, + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_author_mapping::GenesisConfig:: { + mappings: self.mappings, + } + .assimilate_storage(&mut t) + .unwrap(); + + let genesis_config = pallet_evm_chain_id::GenesisConfig:: { + chain_id: self.chain_id, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let genesis_config = pallet_evm::GenesisConfig:: { + accounts: self.evm_accounts, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let genesis_config = pallet_ethereum::GenesisConfig:: { + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let genesis_config = pallet_xcm::GenesisConfig:: { + safe_xcm_version: self.safe_xcm_version, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + let local_assets = self.local_assets.clone(); + let xcm_assets = self.xcm_assets.clone(); + ext.execute_with(|| { + // If any local assets specified, we create them here + for (asset_id, balances, owner) in local_assets.clone() { + LocalAssets::force_create(root_origin(), asset_id.into(), owner, true, 1).unwrap(); + for (account, balance) in balances { + LocalAssets::mint(origin_of(owner.into()), asset_id.into(), account, balance) + .unwrap(); + } + } + // If any xcm assets specified, we register them here + for xcm_asset_initialization in xcm_assets { + let asset_id: AssetId = xcm_asset_initialization.asset_type.clone().into(); + AssetManager::register_foreign_asset( + root_origin(), + xcm_asset_initialization.asset_type, + xcm_asset_initialization.metadata, + 1, + xcm_asset_initialization.is_sufficient, + ) + .unwrap(); + for (account, balance) in xcm_asset_initialization.balances { + Assets::mint( + origin_of(AssetManager::account_id()), + asset_id.into(), + account, + balance, + ) + .unwrap(); + } + } + System::set_block_number(1); + }); + ext + } +} + +pub const CHAIN_ID: u64 = 1281; +pub const ALICE: [u8; 20] = [4u8; 20]; +pub const ALICE_NIMBUS: [u8; 32] = [4u8; 32]; +pub const BOB: [u8; 20] = [5u8; 20]; +pub const CHARLIE: [u8; 20] = [6u8; 20]; +pub const DAVE: [u8; 20] = [7u8; 20]; +pub const EVM_CONTRACT: [u8; 20] = [8u8; 20]; + +pub fn origin_of(account_id: AccountId) -> ::RuntimeOrigin { + ::RuntimeOrigin::signed(account_id) +} + +pub fn inherent_origin() -> ::RuntimeOrigin { + ::RuntimeOrigin::none() +} + +pub fn root_origin() -> ::RuntimeOrigin { + ::RuntimeOrigin::root() +} + +/// Mock the inherent that sets validation data in ParachainSystem, which +/// contains the `relay_chain_block_number`, which is used in `author-filter` as a +/// source of randomness to filter valid authors at each block. +pub fn set_parachain_inherent_data() { + use cumulus_primitives_core::PersistedValidationData; + use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; + let (relay_parent_storage_root, relay_chain_state) = + RelayStateSproofBuilder::default().into_state_root_and_proof(); + let vfp = PersistedValidationData { + relay_parent_number: 1u32, + relay_parent_storage_root, + ..Default::default() + }; + let parachain_inherent_data = ParachainInherentData { + validation_data: vfp, + relay_chain_state: relay_chain_state, + downward_messages: Default::default(), + horizontal_messages: Default::default(), + }; + assert_ok!(RuntimeCall::ParachainSystem( + cumulus_pallet_parachain_system::Call::::set_validation_data { + data: parachain_inherent_data + } + ) + .dispatch(inherent_origin())); +} + +pub fn unchecked_eth_tx(raw_hex_tx: &str) -> UncheckedExtrinsic { + let converter = TransactionConverter; + converter.convert_transaction(ethereum_transaction(raw_hex_tx)) +} + +pub fn ethereum_transaction(raw_hex_tx: &str) -> pallet_ethereum::Transaction { + let bytes = hex::decode(raw_hex_tx).expect("Transaction bytes."); + let transaction = ethereum::EnvelopedDecodable::decode(&bytes[..]); + assert!(transaction.is_ok()); + transaction.unwrap() +} diff --git a/tracing/2601/runtime/moonbeam/tests/evm_tracing.rs b/tracing/2601/runtime/moonbeam/tests/evm_tracing.rs new file mode 100644 index 00000000..b023e947 --- /dev/null +++ b/tracing/2601/runtime/moonbeam/tests/evm_tracing.rs @@ -0,0 +1,94 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Moonbeam EVM tracing Integration Tests + +mod common; + +#[cfg(test)] +#[cfg(feature = "evm-tracing")] +mod tests { + use super::common::*; + + use pallet_evm::AddressMapping; + use sp_core::H160; + + use moonbeam_rpc_primitives_debug::runtime_decl_for_debug_runtime_api::DebugRuntimeApi; + use std::str::FromStr; + + #[test] + fn debug_runtime_api_trace_transaction() { + let alith = ::AddressMapping::into_account_id( + H160::from_str("6be02d1d3665660d22ff9624b7be0551ee1ac91b") + .expect("internal H160 is valid; qed"), + ); + ExtBuilder::default() + .with_balances(vec![ + (alith, 2_000 * GLMR), + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .build() + .execute_with(|| { + let non_eth_uxt = UncheckedExtrinsic::new_unsigned( + pallet_balances::Call::::transfer { + dest: AccountId::from(BOB), + value: 1 * GLMR, + } + .into(), + ); + let transaction = ethereum_transaction(VALID_ETH_TX); + let eth_uxt = unchecked_eth_tx(VALID_ETH_TX); + assert!(Runtime::trace_transaction( + vec![non_eth_uxt.clone(), eth_uxt, non_eth_uxt.clone()], + &transaction + ) + .is_ok()); + }); + } + + #[test] + fn debug_runtime_api_trace_block() { + let alith = ::AddressMapping::into_account_id( + H160::from_str("6be02d1d3665660d22ff9624b7be0551ee1ac91b") + .expect("internal H160 is valid; qed"), + ); + ExtBuilder::default() + .with_balances(vec![ + (alith, 2_000 * GLMR), + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .build() + .execute_with(|| { + let non_eth_uxt = UncheckedExtrinsic::new_unsigned( + pallet_balances::Call::::transfer { + dest: AccountId::from(BOB), + value: 1 * GLMR, + } + .into(), + ); + let eth_uxt = unchecked_eth_tx(VALID_ETH_TX); + let eth_tx = ethereum_transaction(VALID_ETH_TX); + let eth_extrinsic_hash = eth_tx.hash(); + assert!(Runtime::trace_block( + vec![non_eth_uxt.clone(), eth_uxt.clone(), non_eth_uxt, eth_uxt], + vec![eth_extrinsic_hash, eth_extrinsic_hash] + ) + .is_ok()); + }); + } +} diff --git a/tracing/2601/runtime/moonbeam/tests/integration_test.rs b/tracing/2601/runtime/moonbeam/tests/integration_test.rs new file mode 100644 index 00000000..ed3ea40e --- /dev/null +++ b/tracing/2601/runtime/moonbeam/tests/integration_test.rs @@ -0,0 +1,2823 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Moonbeam Runtime Integration Tests + +#![cfg(test)] + +mod common; +use common::*; + +use fp_evm::{Context, IsPrecompileResult}; +use frame_support::{ + assert_noop, assert_ok, + dispatch::DispatchClass, + traits::{ + fungible::Inspect, Currency as CurrencyT, EnsureOrigin, PalletInfo, StorageInfo, + StorageInfoTrait, + }, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, + StorageHasher, Twox128, +}; +use moonbeam_runtime::{ + asset_config::LocalAssetInstance, + currency::GLMR, + xcm_config::{CurrencyId, SelfReserve}, + AccountId, Balances, CouncilCollective, CrowdloanRewards, OpenTechCommitteeCollective, + ParachainStaking, PolkadotXcm, Precompiles, Runtime, RuntimeBlockWeights, RuntimeCall, + RuntimeEvent, System, TechCommitteeCollective, TransactionPayment, TreasuryCouncilCollective, + XTokens, XcmTransactor, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, +}; +use moonbeam_xcm_benchmarks::weights::XcmWeight; +use nimbus_primitives::NimbusId; +use pallet_evm::PrecompileSet; +use pallet_evm_precompileset_assets_erc20::{ + AccountIdAssetIdConversion, IsLocal, SELECTOR_LOG_APPROVAL, SELECTOR_LOG_TRANSFER, +}; +use pallet_transaction_payment::Multiplier; +use pallet_xcm_transactor::{Currency, CurrencyPayment, TransactWeights}; +use parity_scale_codec::Encode; +use polkadot_parachain::primitives::Sibling; +use precompile_utils::{ + precompile_set::{is_precompile_or_fail, IsActivePrecompile}, + prelude::*, + testing::*, +}; +use sha3::{Digest, Keccak256}; +use sp_core::{ByteArray, Pair, H160, U256}; +use sp_runtime::{ + traits::{Convert, Dispatchable}, + BuildStorage, DispatchError, ModuleError, +}; +use std::str::from_utf8; +use xcm::latest::prelude::*; +use xcm::{VersionedMultiAsset, VersionedMultiAssets, VersionedMultiLocation}; +use xcm_builder::{ParentIsPreset, SiblingParachainConvertsVia}; +use xcm_executor::traits::ConvertLocation; + +type BatchPCall = pallet_evm_precompile_batch::BatchPrecompileCall; +type CrowdloanRewardsPCall = + pallet_evm_precompile_crowdloan_rewards::CrowdloanRewardsPrecompileCall; +type XcmUtilsPCall = pallet_evm_precompile_xcm_utils::XcmUtilsPrecompileCall< + Runtime, + moonbeam_runtime::xcm_config::XcmExecutorConfig, +>; +type XtokensPCall = pallet_evm_precompile_xtokens::XtokensPrecompileCall; +type LocalAssetsPCall = pallet_evm_precompileset_assets_erc20::Erc20AssetsPrecompileSetCall< + Runtime, + IsLocal, + LocalAssetInstance, +>; +type XcmTransactorV2PCall = + pallet_evm_precompile_xcm_transactor::v2::XcmTransactorPrecompileV2Call; + +const BASE_FEE_GENESIS: u128 = 10000 * GIGAWEI; + +#[test] +fn xcmp_queue_controller_origin_is_root() { + // important for the XcmExecutionManager impl of PauseExecution which uses root origin + // to suspend/resume XCM execution in xcmp_queue::on_idle + assert_ok!( + ::ControllerOrigin::ensure_origin(root_origin()) + ); +} + +#[test] +fn fast_track_available() { + assert!(moonbeam_runtime::get!( + pallet_democracy, + InstantAllowed, + bool + )); +} + +#[test] +fn verify_pallet_prefixes() { + fn is_pallet_prefix(name: &str) { + // Compares the unhashed pallet prefix in the `StorageInstance` implementation by every + // storage item in the pallet P. This pallet prefix is used in conjunction with the + // item name to get the unique storage key: hash(PalletPrefix) + hash(StorageName) + // https://github.com/paritytech/substrate/blob/master/frame/support/procedural/src/pallet/ + // expand/storage.rs#L389-L401 + assert_eq!( + ::PalletInfo::name::

(), + Some(name) + ); + } + // TODO: use StorageInfoTrait once https://github.com/paritytech/substrate/pull/9246 + // is pulled in substrate deps. + is_pallet_prefix::("System"); + is_pallet_prefix::("Utility"); + is_pallet_prefix::("ParachainSystem"); + is_pallet_prefix::("TransactionPayment"); + is_pallet_prefix::("ParachainInfo"); + is_pallet_prefix::("EthereumChainId"); + is_pallet_prefix::("EVM"); + is_pallet_prefix::("Ethereum"); + is_pallet_prefix::("ParachainStaking"); + is_pallet_prefix::("Scheduler"); + is_pallet_prefix::("Democracy"); + is_pallet_prefix::("CouncilCollective"); + is_pallet_prefix::("TechCommitteeCollective"); + is_pallet_prefix::( + "OpenTechCommitteeCollective", + ); + is_pallet_prefix::("Treasury"); + is_pallet_prefix::("AuthorInherent"); + is_pallet_prefix::("AuthorFilter"); + is_pallet_prefix::("CrowdloanRewards"); + is_pallet_prefix::("AuthorMapping"); + is_pallet_prefix::("MaintenanceMode"); + is_pallet_prefix::("Identity"); + is_pallet_prefix::("XcmpQueue"); + is_pallet_prefix::("CumulusXcm"); + is_pallet_prefix::("DmpQueue"); + is_pallet_prefix::("PolkadotXcm"); + is_pallet_prefix::("Assets"); + is_pallet_prefix::("XTokens"); + is_pallet_prefix::("AssetManager"); + is_pallet_prefix::("Migrations"); + is_pallet_prefix::("XcmTransactor"); + is_pallet_prefix::("ProxyGenesisCompanion"); + is_pallet_prefix::("LocalAssets"); + is_pallet_prefix::("MoonbeamOrbiters"); + is_pallet_prefix::("TreasuryCouncilCollective"); + let prefix = |pallet_name, storage_name| { + let mut res = [0u8; 32]; + res[0..16].copy_from_slice(&Twox128::hash(pallet_name)); + res[16..32].copy_from_slice(&Twox128::hash(storage_name)); + res.to_vec() + }; + assert_eq!( + ::storage_info(), + vec![ + StorageInfo { + pallet_name: b"Timestamp".to_vec(), + storage_name: b"Now".to_vec(), + prefix: prefix(b"Timestamp", b"Now"), + max_values: Some(1), + max_size: Some(8), + }, + StorageInfo { + pallet_name: b"Timestamp".to_vec(), + storage_name: b"DidUpdate".to_vec(), + prefix: prefix(b"Timestamp", b"DidUpdate"), + max_values: Some(1), + max_size: Some(1), + } + ] + ); + assert_eq!( + ::storage_info(), + vec![ + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"TotalIssuance".to_vec(), + prefix: prefix(b"Balances", b"TotalIssuance"), + max_values: Some(1), + max_size: Some(16), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"InactiveIssuance".to_vec(), + prefix: prefix(b"Balances", b"InactiveIssuance"), + max_values: Some(1), + max_size: Some(16), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Account".to_vec(), + prefix: prefix(b"Balances", b"Account"), + max_values: None, + max_size: Some(100), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Locks".to_vec(), + prefix: prefix(b"Balances", b"Locks"), + max_values: None, + max_size: Some(1287), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Reserves".to_vec(), + prefix: prefix(b"Balances", b"Reserves"), + max_values: None, + max_size: Some(1037), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Holds".to_vec(), + prefix: prefix(b"Balances", b"Holds"), + max_values: None, + max_size: Some(37), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Freezes".to_vec(), + prefix: prefix(b"Balances", b"Freezes"), + max_values: None, + max_size: Some(37), + }, + ] + ); + assert_eq!( + ::storage_info(), + vec![ + StorageInfo { + pallet_name: b"Proxy".to_vec(), + storage_name: b"Proxies".to_vec(), + prefix: prefix(b"Proxy", b"Proxies"), + max_values: None, + max_size: Some(845), + }, + StorageInfo { + pallet_name: b"Proxy".to_vec(), + storage_name: b"Announcements".to_vec(), + prefix: prefix(b"Proxy", b"Announcements"), + max_values: None, + max_size: Some(1837), + } + ] + ); + assert_eq!( + ::storage_info(), + vec![StorageInfo { + pallet_name: b"MaintenanceMode".to_vec(), + storage_name: b"MaintenanceMode".to_vec(), + prefix: prefix(b"MaintenanceMode", b"MaintenanceMode"), + max_values: Some(1), + max_size: None, + },] + ); +} + +#[test] +fn test_collectives_storage_item_prefixes() { + for StorageInfo { pallet_name, .. } in + ::storage_info() + { + assert_eq!(pallet_name, b"CouncilCollective".to_vec()); + } + + for StorageInfo { pallet_name, .. } in + ::storage_info() + { + assert_eq!(pallet_name, b"TechCommitteeCollective".to_vec()); + } + + for StorageInfo { pallet_name, .. } in + ::storage_info() + { + assert_eq!(pallet_name, b"TreasuryCouncilCollective".to_vec()); + } + + for StorageInfo { pallet_name, .. } in + ::storage_info() + { + assert_eq!(pallet_name, b"OpenTechCommitteeCollective".to_vec()); + } +} + +#[test] +fn collective_set_members_root_origin_works() { + ExtBuilder::default().build().execute_with(|| { + // CouncilCollective + assert_ok!(CouncilCollective::set_members( + ::RuntimeOrigin::root(), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + )); + // TechCommitteeCollective + assert_ok!(TechCommitteeCollective::set_members( + ::RuntimeOrigin::root(), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + )); + // TreasuryCouncilCollective + assert_ok!(TreasuryCouncilCollective::set_members( + ::RuntimeOrigin::root(), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + )); + // OpenTechCommitteeCollective + assert_ok!(OpenTechCommitteeCollective::set_members( + ::RuntimeOrigin::root(), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + )); + }); +} + +#[test] +fn collective_set_members_general_admin_origin_works() { + use moonbeam_runtime::{ + governance::custom_origins::Origin as CustomOrigin, OriginCaller, Utility, + }; + + ExtBuilder::default().build().execute_with(|| { + let root_caller = ::RuntimeOrigin::root(); + let alice = AccountId::from(ALICE); + + // CouncilCollective + let _ = Utility::dispatch_as( + root_caller.clone(), + Box::new(OriginCaller::Origins(CustomOrigin::GeneralAdmin)), + Box::new( + pallet_collective::Call::::set_members { + new_members: vec![alice, AccountId::from(BOB)], + prime: Some(alice), + old_count: 2, + } + .into(), + ), + ); + // TechCommitteeCollective + let _ = Utility::dispatch_as( + root_caller.clone(), + Box::new(OriginCaller::Origins(CustomOrigin::GeneralAdmin)), + Box::new( + pallet_collective::Call::::set_members { + new_members: vec![alice, AccountId::from(BOB)], + prime: Some(alice), + old_count: 2, + } + .into(), + ), + ); + // TreasuryCouncilCollective + let _ = Utility::dispatch_as( + root_caller.clone(), + Box::new(OriginCaller::Origins(CustomOrigin::GeneralAdmin)), + Box::new( + pallet_collective::Call::::set_members { + new_members: vec![alice, AccountId::from(BOB)], + prime: Some(alice), + old_count: 2, + } + .into(), + ), + ); + // OpenTechCommitteeCollective + let _ = Utility::dispatch_as( + root_caller, + Box::new(OriginCaller::Origins(CustomOrigin::GeneralAdmin)), + Box::new( + pallet_collective::Call::::set_members { + new_members: vec![alice, AccountId::from(BOB)], + prime: Some(alice), + old_count: 2, + } + .into(), + ), + ); + + assert_eq!( + System::events() + .into_iter() + .filter_map(|r| { + match r.event { + RuntimeEvent::Utility(pallet_utility::Event::DispatchedAs { result }) + if result.is_ok() => + { + Some(true) + } + _ => None, + } + }) + .collect::>() + .len(), + 4 + ) + }); +} + +#[test] +fn collective_set_members_signed_origin_does_not_work() { + let alice = AccountId::from(ALICE); + ExtBuilder::default().build().execute_with(|| { + // CouncilCollective + assert!(CouncilCollective::set_members( + ::RuntimeOrigin::signed(alice), + vec![alice, AccountId::from(BOB)], + Some(alice), + 2 + ) + .is_err()); + // TechCommitteeCollective + assert!(TechCommitteeCollective::set_members( + ::RuntimeOrigin::signed(alice), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + ) + .is_err()); + // TreasuryCouncilCollective + assert!(TreasuryCouncilCollective::set_members( + ::RuntimeOrigin::signed(alice), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + ) + .is_err()); + // OpenTechCommitteeCollective + assert!(OpenTechCommitteeCollective::set_members( + ::RuntimeOrigin::signed(alice), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + ) + .is_err()); + }); +} + +#[test] +fn verify_pallet_indices() { + fn is_pallet_index(index: usize) { + assert_eq!( + ::PalletInfo::index::

(), + Some(index) + ); + } + + // System support + is_pallet_index::(0); + is_pallet_index::(1); + is_pallet_index::(3); + is_pallet_index::(4); + // Monetary + is_pallet_index::(10); + is_pallet_index::(11); + // Consensus support + is_pallet_index::(20); + is_pallet_index::(21); + is_pallet_index::(22); + is_pallet_index::(23); + is_pallet_index::(24); + // Handy utilities + is_pallet_index::(30); + is_pallet_index::(31); + is_pallet_index::(32); + is_pallet_index::(33); + is_pallet_index::(34); + is_pallet_index::(35); + // Ethereum compatibility + is_pallet_index::(50); + is_pallet_index::(51); + is_pallet_index::(52); + // Governance + is_pallet_index::(60); + is_pallet_index::(61); + // Council + is_pallet_index::(70); + is_pallet_index::(71); + is_pallet_index::(72); + is_pallet_index::(73); + // Treasury + is_pallet_index::(80); + // Crowdloan + is_pallet_index::(90); + // XCM Stuff + is_pallet_index::(100); + is_pallet_index::(101); + is_pallet_index::(102); + is_pallet_index::(103); + is_pallet_index::(104); + is_pallet_index::(105); + is_pallet_index::(106); + is_pallet_index::(107); + is_pallet_index::(108); +} + +#[test] +fn verify_reserved_indices() { + use frame_metadata::*; + let metadata = moonbeam_runtime::Runtime::metadata(); + let metadata = match metadata.1 { + RuntimeMetadata::V14(metadata) => metadata, + _ => panic!("metadata has been bumped, test needs to be updated"), + }; + // 40: Sudo + // 53: BaseFee + let reserved = vec![40, 53]; + let existing = metadata + .pallets + .iter() + .map(|p| p.index) + .collect::>(); + assert!(reserved.iter().all(|index| !existing.contains(index))); +} + +#[test] +fn verify_proxy_type_indices() { + assert_eq!(moonbeam_runtime::ProxyType::Any as u8, 0); + assert_eq!(moonbeam_runtime::ProxyType::NonTransfer as u8, 1); + assert_eq!(moonbeam_runtime::ProxyType::Governance as u8, 2); + assert_eq!(moonbeam_runtime::ProxyType::Staking as u8, 3); + assert_eq!(moonbeam_runtime::ProxyType::CancelProxy as u8, 4); + assert_eq!(moonbeam_runtime::ProxyType::Balances as u8, 5); + assert_eq!(moonbeam_runtime::ProxyType::AuthorMapping as u8, 6); + assert_eq!(moonbeam_runtime::ProxyType::IdentityJudgement as u8, 7); +} + +#[test] +fn join_collator_candidates() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 10_000_000 * GLMR), + (AccountId::from(BOB), 10_000_000 * GLMR), + (AccountId::from(CHARLIE), 10_000_000 * GLMR), + (AccountId::from(DAVE), 10_000_000 * GLMR), + ]) + .with_collators(vec![ + (AccountId::from(ALICE), 2_000_000 * GLMR), + (AccountId::from(BOB), 2_000_000 * GLMR), + ]) + .with_delegations(vec![ + ( + AccountId::from(CHARLIE), + AccountId::from(ALICE), + 5_000 * GLMR, + ), + (AccountId::from(CHARLIE), AccountId::from(BOB), 5_000 * GLMR), + ]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates( + origin_of(AccountId::from(ALICE)), + 2_000_000 * GLMR, + 2u32 + ), + pallet_parachain_staking::Error::::CandidateExists + ); + assert_noop!( + ParachainStaking::join_candidates( + origin_of(AccountId::from(CHARLIE)), + 2_000_000 * GLMR, + 2u32 + ), + pallet_parachain_staking::Error::::DelegatorExists + ); + assert!(System::events().is_empty()); + assert_ok!(ParachainStaking::join_candidates( + origin_of(AccountId::from(DAVE)), + 2_000_000 * GLMR, + 2u32 + )); + assert_eq!( + last_event(), + RuntimeEvent::ParachainStaking( + pallet_parachain_staking::Event::JoinedCollatorCandidates { + account: AccountId::from(DAVE), + amount_locked: 2_000_000 * GLMR, + new_total_amt_locked: 6_010_000 * GLMR + } + ) + ); + let candidates = ParachainStaking::candidate_pool(); + assert_eq!(candidates.0[0].owner, AccountId::from(ALICE)); + assert_eq!(candidates.0[0].amount, 2_005_000 * GLMR); + assert_eq!(candidates.0[1].owner, AccountId::from(BOB)); + assert_eq!(candidates.0[1].amount, 2_005_000 * GLMR); + assert_eq!(candidates.0[2].owner, AccountId::from(DAVE)); + assert_eq!(candidates.0[2].amount, 2_000_000 * GLMR); + }); +} + +#[test] +fn transfer_through_evm_to_stake() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 10_000_000 * GLMR)]) + .build() + .execute_with(|| { + // Charlie has no balance => fails to stake + assert_noop!( + ParachainStaking::join_candidates( + origin_of(AccountId::from(CHARLIE)), + 2_000_000 * GLMR, + 2u32 + ), + DispatchError::Module(ModuleError { + index: 20, + error: [8, 0, 0, 0], + message: Some("InsufficientBalance") + }) + ); + // Alice transfer from free balance 3_000_000 GLMR to Bob + assert_ok!(Balances::transfer( + origin_of(AccountId::from(ALICE)), + AccountId::from(BOB), + 3_000_000 * GLMR, + )); + assert_eq!( + Balances::free_balance(AccountId::from(BOB)), + 3_000_000 * GLMR + ); + + let gas_limit = 100000u64; + let gas_price: U256 = BASE_FEE_GENESIS.into(); + // Bob transfers 2_000_000 GLMR to Charlie via EVM + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(CHARLIE), + input: vec![], + value: (2_000_000 * GLMR).into(), + gas_limit, + max_fee_per_gas: gas_price, + max_priority_fee_per_gas: None, + nonce: None, + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + assert_eq!( + Balances::free_balance(AccountId::from(CHARLIE)), + 2_000_000 * GLMR, + ); + + // Charlie can stake now + assert_ok!(ParachainStaking::join_candidates( + origin_of(AccountId::from(CHARLIE)), + 2_000_000 * GLMR, + 2u32 + ),); + let candidates = ParachainStaking::candidate_pool(); + assert_eq!(candidates.0[0].owner, AccountId::from(CHARLIE)); + assert_eq!(candidates.0[0].amount, 2_000_000 * GLMR); + }); +} + +#[test] +fn reward_block_authors() { + ExtBuilder::default() + .with_balances(vec![ + // Alice gets 10k extra tokens for her mapping deposit + (AccountId::from(ALICE), 10_010_000 * GLMR), + (AccountId::from(BOB), 10_000_000 * GLMR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 2_000_000 * GLMR)]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 50_000 * GLMR, + )]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + for x in 2..3599 { + run_to_block(x, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + } + // no rewards doled out yet + assert_eq!( + Balances::usable_balance(AccountId::from(ALICE)), + 8_010_000 * GLMR, + ); + assert_eq!( + Balances::usable_balance(AccountId::from(BOB)), + 9_950_000 * GLMR, + ); + run_to_block(3601, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + // rewards minted and distributed + assert_eq!( + Balances::usable_balance(AccountId::from(ALICE)), + 8990978048702400000000000, + ); + assert_eq!( + Balances::usable_balance(AccountId::from(BOB)), + 9969521950497200000000000, + ); + }); +} + +#[test] +fn reward_block_authors_with_parachain_bond_reserved() { + ExtBuilder::default() + .with_balances(vec![ + // Alice gets 10k extra tokens for her mapping deposit + (AccountId::from(ALICE), 10_010_000 * GLMR), + (AccountId::from(BOB), 10_000_000 * GLMR), + (AccountId::from(CHARLIE), 10_000 * GLMR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 2_000_000 * GLMR)]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 50_000 * GLMR, + )]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + assert_ok!(ParachainStaking::set_parachain_bond_account( + root_origin(), + AccountId::from(CHARLIE), + ),); + for x in 2..3599 { + run_to_block(x, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + } + // no rewards doled out yet + assert_eq!( + Balances::usable_balance(AccountId::from(ALICE)), + 8_010_000 * GLMR, + ); + assert_eq!( + Balances::usable_balance(AccountId::from(BOB)), + 9_950_000 * GLMR, + ); + assert_eq!( + Balances::usable_balance(AccountId::from(CHARLIE)), + 10_000 * GLMR, + ); + run_to_block(3601, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + // rewards minted and distributed + assert_eq!( + Balances::usable_balance(AccountId::from(ALICE)), + 8698492682878000000000000, + ); + assert_eq!( + Balances::usable_balance(AccountId::from(BOB)), + 9962207316621500000000000, + ); + // 30% reserved for parachain bond + assert_eq!( + Balances::usable_balance(AccountId::from(CHARLIE)), + 310300000000000000000000, + ); + }); +} + +#[test] +fn initialize_crowdloan_addresses_with_batch_and_pay() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 200_000 * GLMR), + (AccountId::from(BOB), 100_000 * GLMR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 100_000 * GLMR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(300_000_000 * GLMR) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 150_000_000 * GLMR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 150_000_000 * GLMR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + // 30 percent initial payout + assert_eq!( + Balances::balance(&AccountId::from(CHARLIE)), + 45_000_000 * GLMR + ); + // 30 percent initial payout + assert_eq!(Balances::balance(&AccountId::from(DAVE)), 45_000_000 * GLMR); + let expected = RuntimeEvent::Utility(pallet_utility::Event::BatchCompleted); + assert_eq!(last_event(), expected); + // This one should fail, as we already filled our data + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch { + calls: vec![RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(ALICE)), + 43_200_000 + )] + } + )] + }) + .dispatch(root_origin()) + ); + let expected_fail = RuntimeEvent::Utility(pallet_utility::Event::BatchInterrupted { + index: 0, + error: DispatchError::Module(ModuleError { + index: 90, + error: [8, 0, 0, 0], + message: None, + }), + }); + assert_eq!(last_event(), expected_fail); + // Claim 1 block. + assert_ok!(CrowdloanRewards::claim(origin_of(AccountId::from(CHARLIE)))); + assert_ok!(CrowdloanRewards::claim(origin_of(AccountId::from(DAVE)))); + + let vesting_period = 4 * WEEKS as u128; + let per_block = (105_000_000 * GLMR) / vesting_period; + + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(CHARLIE)) + .unwrap() + .claimed_reward, + (45_000_000 * GLMR) + per_block + ); + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(DAVE)) + .unwrap() + .claimed_reward, + (45_000_000 * GLMR) + per_block + ); + // The total claimed reward should be equal to the account balance at this point. + assert_eq!( + Balances::balance(&AccountId::from(CHARLIE)), + (45_000_000 * GLMR) + per_block + ); + assert_eq!( + Balances::balance(&AccountId::from(DAVE)), + (45_000_000 * GLMR) + per_block + ); + assert_noop!( + CrowdloanRewards::claim(origin_of(AccountId::from(ALICE))), + pallet_crowdloan_rewards::Error::::NoAssociatedClaim + ); + }); +} + +#[test] +fn initialize_crowdloan_address_and_change_with_relay_key_sig() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * GLMR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * GLMR) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + + let (pair1, _) = sp_core::sr25519::Pair::generate(); + let (pair2, _) = sp_core::sr25519::Pair::generate(); + + let public1 = pair1.public(); + let public2 = pair2.public(); + + // signature is new_account || previous_account + let mut message = pallet_crowdloan_rewards::WRAPPED_BYTES_PREFIX.to_vec(); + message.append(&mut b"moonbeam-".to_vec()); + message.append(&mut AccountId::from(DAVE).encode()); + message.append(&mut AccountId::from(CHARLIE).encode()); + message.append(&mut pallet_crowdloan_rewards::WRAPPED_BYTES_POSTFIX.to_vec()); + let signature1 = pair1.sign(&message); + let signature2 = pair2.sign(&message); + + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + // two relay accounts pointing at the same reward account + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + public1.into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * GLMR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + public2.into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * GLMR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + // 30 percent initial payout + assert_eq!(Balances::balance(&AccountId::from(CHARLIE)), 900_000 * GLMR); + + // this should fail, as we are only providing one signature + assert_noop!( + CrowdloanRewards::change_association_with_relay_keys( + origin_of(AccountId::from(CHARLIE)), + AccountId::from(DAVE), + AccountId::from(CHARLIE), + vec![(public1.into(), signature1.clone().into())] + ), + pallet_crowdloan_rewards::Error::::InsufficientNumberOfValidProofs + ); + + // this should be valid + assert_ok!(CrowdloanRewards::change_association_with_relay_keys( + origin_of(AccountId::from(CHARLIE)), + AccountId::from(DAVE), + AccountId::from(CHARLIE), + vec![ + (public1.into(), signature1.into()), + (public2.into(), signature2.into()) + ] + )); + + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(DAVE)) + .unwrap() + .claimed_reward, + (900_000 * GLMR) + ); + }); +} + +#[test] +fn claim_via_precompile() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * GLMR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * GLMR) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * GLMR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 1_500_000 * GLMR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + + assert!(CrowdloanRewards::initialized()); + + // 30 percent initial payout + assert_eq!(Balances::balance(&AccountId::from(CHARLIE)), 450_000 * GLMR); + // 30 percent initial payout + assert_eq!(Balances::balance(&AccountId::from(DAVE)), 450_000 * GLMR); + + let crowdloan_precompile_address = H160::from_low_u64_be(2049); + + // Alice uses the crowdloan precompile to claim through the EVM + let gas_limit = 100000u64; + let gas_price: U256 = BASE_FEE_GENESIS.into(); + + // Construct the call data (selector, amount) + let mut call_data = Vec::::from([0u8; 4]); + call_data[0..4].copy_from_slice(&Keccak256::digest(b"claim()")[0..4]); + + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(CHARLIE), + target: crowdloan_precompile_address, + input: call_data, + value: U256::zero(), // No value sent in EVM + gas_limit, + max_fee_per_gas: gas_price, + max_priority_fee_per_gas: None, + nonce: None, // Use the next nonce + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let vesting_period = 4 * WEEKS as u128; + let per_block = (1_050_000 * GLMR) / vesting_period; + + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(CHARLIE)) + .unwrap() + .claimed_reward, + (450_000 * GLMR) + per_block + ); + }) +} + +#[test] +fn is_contributor_via_precompile() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 200_000 * GLMR), + (AccountId::from(BOB), 100_000 * GLMR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 100_000 * GLMR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000_000 * GLMR) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 1_500_000_000 * GLMR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 1_500_000_000 * GLMR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + + let crowdloan_precompile_address = H160::from_low_u64_be(2049); + + // Assert precompile reports Bob is not a contributor + Precompiles::new() + .prepare_test( + ALICE, + crowdloan_precompile_address, + CrowdloanRewardsPCall::is_contributor { + contributor: Address(AccountId::from(BOB).into()), + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(false); + + // Assert precompile reports Charlie is a nominator + Precompiles::new() + .prepare_test( + ALICE, + crowdloan_precompile_address, + CrowdloanRewardsPCall::is_contributor { + contributor: Address(AccountId::from(CHARLIE).into()), + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(true); + }) +} + +#[test] +fn reward_info_via_precompile() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 200_000 * GLMR), + (AccountId::from(BOB), 100_000 * GLMR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 100_000 * GLMR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * GLMR) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * GLMR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 1_500_000 * GLMR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + + let crowdloan_precompile_address = H160::from_low_u64_be(2049); + + let expected_total: U256 = (1_500_000 * GLMR).into(); + let expected_claimed: U256 = (450_000 * GLMR).into(); + + // Assert precompile reports correct Charlie reward info. + Precompiles::new() + .prepare_test( + ALICE, + crowdloan_precompile_address, + CrowdloanRewardsPCall::reward_info { + contributor: Address(AccountId::from(CHARLIE).into()), + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns((expected_total, expected_claimed)); + }) +} + +#[test] +fn update_reward_address_via_precompile() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * GLMR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * GLMR) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * GLMR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 1_500_000 * GLMR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + + let crowdloan_precompile_address = H160::from_low_u64_be(2049); + + // Charlie uses the crowdloan precompile to update address through the EVM + let gas_limit = 100000u64; + let gas_price: U256 = BASE_FEE_GENESIS.into(); + + // Construct the input data to check if Bob is a contributor + let mut call_data = Vec::::from([0u8; 36]); + call_data[0..4] + .copy_from_slice(&Keccak256::digest(b"update_reward_address(address)")[0..4]); + call_data[16..36].copy_from_slice(&ALICE); + + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(CHARLIE), + target: crowdloan_precompile_address, + input: call_data, + value: U256::zero(), // No value sent in EVM + gas_limit, + max_fee_per_gas: gas_price, + max_priority_fee_per_gas: None, + nonce: None, // Use the next nonce + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + assert!(CrowdloanRewards::accounts_payable(&AccountId::from(CHARLIE)).is_none()); + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(ALICE)) + .unwrap() + .claimed_reward, + (450_000 * GLMR) + ); + }) +} + +fn run_with_system_weight(w: Weight, mut assertions: F) +where + F: FnMut() -> (), +{ + let mut t: sp_io::TestExternalities = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap() + .into(); + t.execute_with(|| { + System::set_block_consumed_resources(w, 0); + assertions() + }); +} + +#[test] +#[rustfmt::skip] +fn length_fee_is_sensible() { + use sp_runtime::testing::TestXt; + + // tests that length fee is sensible for a few hypothetical transactions + ExtBuilder::default().build().execute_with(|| { + let call = frame_system::Call::remark:: { remark: vec![] }; + let uxt: TestXt<_, ()> = TestXt::new(call, Some((1u64, ()))); + + let calc_fee = |len: u32| -> Balance { + moonbeam_runtime::TransactionPayment::query_fee_details(uxt.clone(), len) + .inclusion_fee + .expect("fee should be calculated") + .len_fee + }; + + // editorconfig-checker-disable + // left: cost of length fee, right: size in bytes + // /------------- proportional component: O(N * 1B) + // | /- exponential component: O(N ** 3) + // | | + assert_eq!( 100_000_000_100, calc_fee(1)); + assert_eq!( 1_000_000_100_000, calc_fee(10)); + assert_eq!( 10_000_100_000_000, calc_fee(100)); + assert_eq!( 100_100_000_000_000, calc_fee(1_000)); + assert_eq!( 1_100_000_000_000_000, calc_fee(10_000)); // inflection point + assert_eq!( 110_000_000_000_000_000, calc_fee(100_000)); + assert_eq!( 100_100_000_000_000_000_000, calc_fee(1_000_000)); // 100 GLMR, ~ 1MB + assert_eq!( 100_001_000_000_000_000_000_000, calc_fee(10_000_000)); + assert_eq!(100_000_010_000_000_000_000_000_000, calc_fee(100_000_000)); + // editorconfig-checker-enable + }); +} + +#[test] +fn multiplier_can_grow_from_zero() { + use frame_support::traits::Get; + + let minimum_multiplier = moonbeam_runtime::MinimumMultiplier::get(); + let target = moonbeam_runtime::TargetBlockFullness::get() + * RuntimeBlockWeights::get() + .get(DispatchClass::Normal) + .max_total + .unwrap(); + // if the min is too small, then this will not change, and we are doomed forever. + // the weight is 1/100th bigger than target. + run_with_system_weight(target * 101 / 100, || { + let next = moonbeam_runtime::SlowAdjustingFeeUpdate::::convert(minimum_multiplier); + assert!( + next > minimum_multiplier, + "{:?} !>= {:?}", + next, + minimum_multiplier + ); + }) +} + +#[test] +fn ethereum_invalid_transaction() { + ExtBuilder::default().build().execute_with(|| { + // Ensure an extrinsic not containing enough gas limit to store the transaction + // on chain is rejected. + assert_eq!( + Executive::apply_extrinsic(unchecked_eth_tx(INVALID_ETH_TX)), + Err( + sp_runtime::transaction_validity::TransactionValidityError::Invalid( + sp_runtime::transaction_validity::InvalidTransaction::Custom(3u8) + ) + ) + ); + }); +} + +#[test] +fn initial_gas_fee_is_correct() { + use fp_evm::FeeCalculator; + + ExtBuilder::default().build().execute_with(|| { + let multiplier = TransactionPayment::next_fee_multiplier(); + assert_eq!(multiplier, Multiplier::from(1u128)); + + assert_eq!( + TransactionPaymentAsGasPrice::min_gas_price(), + ( + 125_000_000_000u128.into(), + Weight::from_parts(25_000_000u64, 0) + ) + ); + }); +} + +#[test] +fn min_gas_fee_is_correct() { + use fp_evm::FeeCalculator; + use frame_support::traits::Hooks; + + ExtBuilder::default().build().execute_with(|| { + pallet_transaction_payment::NextFeeMultiplier::::put(Multiplier::from(0)); + TransactionPayment::on_finalize(System::block_number()); // should trigger min to kick in + + let multiplier = TransactionPayment::next_fee_multiplier(); + assert_eq!(multiplier, Multiplier::from(1u128)); + + assert_eq!( + TransactionPaymentAsGasPrice::min_gas_price(), + ( + 125_000_000_000u128.into(), + Weight::from_parts(25_000_000u64, 0) + ) + ); + }); +} + +#[test] +fn transfer_ed_0_substrate() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), (1 * GLMR) + (1 * WEI)), + (AccountId::from(BOB), 0), + ]) + .build() + .execute_with(|| { + // Substrate transfer + assert_ok!(Balances::transfer( + origin_of(AccountId::from(ALICE)), + AccountId::from(BOB), + 1 * GLMR, + )); + // 1 WEI is left in the account + assert_eq!(Balances::free_balance(AccountId::from(ALICE)), 1 * WEI); + }); +} + +#[test] +fn transfer_ed_0_evm() { + ExtBuilder::default() + .with_balances(vec![ + ( + AccountId::from(ALICE), + ((1 * GLMR) + (21_000 * BASE_FEE_GENESIS)) + (1 * WEI), + ), + (AccountId::from(BOB), 0), + ]) + .build() + .execute_with(|| { + // EVM transfer + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(ALICE), + target: H160::from(BOB), + input: Vec::new(), + value: (1 * GLMR).into(), + gas_limit: 21_000u64, + max_fee_per_gas: BASE_FEE_GENESIS.into(), + max_priority_fee_per_gas: Some(BASE_FEE_GENESIS.into()), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + // 1 WEI is left in the account + assert_eq!(Balances::free_balance(AccountId::from(ALICE)), 1 * WEI,); + }); +} + +#[test] +fn refund_ed_0_evm() { + ExtBuilder::default() + .with_balances(vec![ + ( + AccountId::from(ALICE), + ((1 * GLMR) + (21_777 * BASE_FEE_GENESIS)), + ), + (AccountId::from(BOB), 0), + ]) + .build() + .execute_with(|| { + // EVM transfer that zeroes ALICE + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(ALICE), + target: H160::from(BOB), + input: Vec::new(), + value: (1 * GLMR).into(), + gas_limit: 21_777u64, + max_fee_per_gas: BASE_FEE_GENESIS.into(), + max_priority_fee_per_gas: Some(BASE_FEE_GENESIS.into()), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + // ALICE is refunded + assert_eq!( + Balances::free_balance(AccountId::from(ALICE)), + 777 * BASE_FEE_GENESIS, + ); + }); +} + +#[test] +fn author_does_not_receive_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * GLMR) + (21_000 * (500 * GIGAWEI)), + )]) + .build() + .execute_with(|| { + // Some block author as seen by pallet-evm. + let author = AccountId::from(>::find_author()); + // Currently the default impl of the evm uses `deposit_into_existing`. + // If we were to use this implementation, and for an author to receive eventual tips, + // the account needs to be somehow initialized, otherwise the deposit would fail. + Balances::make_free_balance_be(&author, 100 * GLMR); + + // EVM transfer. + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * GLMR).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(300 * GIGAWEI), + max_priority_fee_per_gas: Some(U256::from(200 * GIGAWEI)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + // Author free balance didn't change. + assert_eq!(Balances::free_balance(author), 100 * GLMR,); + }); +} + +#[test] +fn total_issuance_after_evm_transaction_with_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * GLMR) + (21_000 * (200 * GIGAWEI)), + )]) + .build() + .execute_with(|| { + let issuance_before = ::Currency::total_issuance(); + // EVM transfer. + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * GLMR).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(200 * GIGAWEI), + max_priority_fee_per_gas: Some(U256::from(100 * GIGAWEI)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let issuance_after = ::Currency::total_issuance(); + // Fee is 100 GWEI base fee + 100 GWEI tip. + let fee = ((200 * GIGAWEI) * 21_000) as f64; + // 80% was burned. + let expected_burn = (fee * 0.8) as u128; + assert_eq!(issuance_after, issuance_before - expected_burn,); + // 20% was sent to treasury. + let expected_treasury = (fee * 0.2) as u128; + assert_eq!(moonbeam_runtime::Treasury::pot(), expected_treasury); + }); +} + +#[test] +fn total_issuance_after_evm_transaction_without_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * GLMR) + (21_000 * BASE_FEE_GENESIS), + )]) + .build() + .execute_with(|| { + let issuance_before = ::Currency::total_issuance(); + // EVM transfer. + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * GLMR).into(), + gas_limit: 21_000u64, + max_fee_per_gas: BASE_FEE_GENESIS.into(), + max_priority_fee_per_gas: Some(BASE_FEE_GENESIS.into()), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let issuance_after = ::Currency::total_issuance(); + // Fee is 100 GWEI base fee. + let fee = (BASE_FEE_GENESIS * 21_000) as f64; + // 80% was burned. + let expected_burn = (fee * 0.8) as u128; + assert_eq!(issuance_after, issuance_before - expected_burn,); + // 20% was sent to treasury. + let expected_treasury = (fee * 0.2) as u128; + assert_eq!(moonbeam_runtime::Treasury::pot(), expected_treasury); + }); +} + +#[test] +fn root_can_change_default_xcm_vers() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .build() + .execute_with(|| { + let source_location = AssetType::Xcm(MultiLocation::parent()); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: [1u8; 32], + }), + }; + let source_id: moonbeam_runtime::AssetId = source_location.clone().into(); + // Default XCM version is not set yet, so xtokens should fail because it does not + // know with which version to send + assert_noop!( + XTokens::transfer( + origin_of(AccountId::from(ALICE)), + CurrencyId::ForeignAsset(source_id), + 100_000_000_000_000, + Box::new(xcm::VersionedMultiLocation::V3(dest.clone())), + WeightLimit::Limited(4000000000.into()) + ), + orml_xtokens::Error::::XcmExecutionFailed + ); + + // Root sets the defaultXcm + assert_ok!(PolkadotXcm::force_default_xcm_version( + root_origin(), + Some(2) + )); + + // Now transferring does not fail + assert_ok!(XTokens::transfer( + origin_of(AccountId::from(ALICE)), + CurrencyId::ForeignAsset(source_id), + 100_000_000_000_000, + Box::new(xcm::VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(4000000000.into()) + )); + }) +} + +#[test] +fn asset_can_be_registered() { + ExtBuilder::default().build().execute_with(|| { + let source_location = AssetType::Xcm(MultiLocation::parent()); + let source_id: moonbeam_runtime::AssetId = source_location.clone().into(); + let asset_metadata = AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }; + assert_ok!(AssetManager::register_foreign_asset( + moonbeam_runtime::RuntimeOrigin::root(), + source_location, + asset_metadata, + 1u128, + true + )); + assert!(AssetManager::asset_id_type(source_id).is_some()); + }); +} + +#[test] +fn local_assets_cannot_be_create_by_signed_origins() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR * SUPPLY_FACTOR), + (AccountId::from(BOB), 1_000 * GLMR * SUPPLY_FACTOR), + ]) + .build() + .execute_with(|| { + assert_noop!( + RuntimeCall::LocalAssets( + pallet_assets::Call::::create { + id: 11u128.into(), + admin: AccountId::from(ALICE), + min_balance: 1u128 + } + ) + .dispatch(::RuntimeOrigin::signed( + AccountId::from(ALICE) + )), + frame_system::Error::::CallFiltered + ); + }); +} + +#[test] +fn xcm_asset_erc20_precompiles_supply_and_balance() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000 * GLMR)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .build() + .execute_with(|| { + // We have the assetId that corresponds to the relay chain registered + let relay_asset_id: moonbeam_runtime::AssetId = + AssetType::Xcm(MultiLocation::parent()).into(); + + // Its address is + let asset_precompile_address = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + relay_asset_id, + ); + + // Assert the asset has been created with the correct supply + assert_eq!(Assets::total_supply(relay_asset_id), 1_000 * GLMR); + + // Access totalSupply through precompile. Important that the context is correct + Precompiles::new() + .prepare_test( + ALICE, + asset_precompile_address, + LocalAssetsPCall::total_supply {}, + ) + .expect_cost(2000) + .expect_no_logs() + .execute_returns(U256::from(1000 * GLMR)); + + // Access balanceOf through precompile + Precompiles::new() + .prepare_test( + ALICE, + asset_precompile_address, + LocalAssetsPCall::balance_of { + who: Address(ALICE.into()), + }, + ) + .expect_cost(2000) + .expect_no_logs() + .execute_returns(U256::from(1000 * GLMR)); + }); +} + +#[test] +fn xcm_asset_erc20_precompiles_transfer() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000 * GLMR)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .build() + .execute_with(|| { + // We have the assetId that corresponds to the relay chain registered + let relay_asset_id: moonbeam_runtime::AssetId = + AssetType::Xcm(MultiLocation::parent()).into(); + + // Its address is + let asset_precompile_address = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + relay_asset_id, + ); + + // Transfer tokens from Aice to Bob, 400 GLMR. + Precompiles::new() + .prepare_test( + ALICE, + asset_precompile_address, + LocalAssetsPCall::transfer { + to: Address(BOB.into()), + value: { 400 * GLMR }.into(), + }, + ) + .expect_cost(23763) + .expect_log(log3( + asset_precompile_address, + SELECTOR_LOG_TRANSFER, + H160::from(ALICE), + H160::from(BOB), + solidity::encode_event_data(U256::from(400 * GLMR)), + )) + .execute_returns(true); + + // Make sure BOB has 400 GLMR + Precompiles::new() + .prepare_test( + BOB, + asset_precompile_address, + LocalAssetsPCall::balance_of { + who: Address(BOB.into()), + }, + ) + .expect_cost(2000) + .expect_no_logs() + .execute_returns(U256::from(400 * GLMR)); + }); +} + +#[test] +fn xcm_asset_erc20_precompiles_approve() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000 * GLMR)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .build() + .execute_with(|| { + // We have the assetId that corresponds to the relay chain registered + let relay_asset_id: moonbeam_runtime::AssetId = + AssetType::Xcm(MultiLocation::parent()).into(); + + // Its address is + let asset_precompile_address = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + relay_asset_id, + ); + + // Aprove Bob for spending 400 GLMR from Alice + Precompiles::new() + .prepare_test( + ALICE, + asset_precompile_address, + LocalAssetsPCall::approve { + spender: Address(BOB.into()), + value: { 400 * GLMR }.into(), + }, + ) + .expect_cost(14210) + .expect_log(log3( + asset_precompile_address, + SELECTOR_LOG_APPROVAL, + H160::from(ALICE), + H160::from(BOB), + solidity::encode_event_data(U256::from(400 * GLMR)), + )) + .execute_returns(true); + + // Transfer tokens from Alice to Charlie by using BOB as origin + Precompiles::new() + .prepare_test( + BOB, + asset_precompile_address, + LocalAssetsPCall::transfer_from { + from: Address(ALICE.into()), + to: Address(CHARLIE.into()), + value: { 400 * GLMR }.into(), + }, + ) + .expect_cost(28991) + .expect_log(log3( + asset_precompile_address, + SELECTOR_LOG_TRANSFER, + H160::from(ALICE), + H160::from(CHARLIE), + solidity::encode_event_data(U256::from(400 * GLMR)), + )) + .execute_returns(true); + + // Make sure CHARLIE has 400 GLMR + Precompiles::new() + .prepare_test( + CHARLIE, + asset_precompile_address, + LocalAssetsPCall::balance_of { + who: Address(CHARLIE.into()), + }, + ) + .expect_cost(2000) + .expect_no_logs() + .execute_returns(U256::from(400 * GLMR)); + }); +} + +#[test] +fn xtokens_precompile_transfer() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + let xtokens_precompile_address = H160::from_low_u64_be(2052); + + // We have the assetId that corresponds to the relay chain registered + let relay_asset_id: moonbeam_runtime::AssetId = + AssetType::Xcm(MultiLocation::parent()).into(); + + // Its address is + let asset_precompile_address = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + relay_asset_id, + ); + + // Alice has 1000 tokens. She should be able to send through precompile + let destination = MultiLocation::new( + 1, + Junctions::X1(Junction::AccountId32 { + network: None, + id: [1u8; 32], + }), + ); + + // We use the address of the asset as an identifier of the asset we want to transfer + Precompiles::new() + .prepare_test( + ALICE, + xtokens_precompile_address, + XtokensPCall::transfer { + currency_address: Address(asset_precompile_address.into()), + amount: 500_000_000_000_000u128.into(), + destination: destination.clone(), + weight: 4_000_000, + }, + ) + .expect_cost(57639) + .expect_no_logs() + .execute_returns(()) + }) +} + +#[test] +fn xtokens_precompile_transfer_multiasset() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + let xtokens_precompile_address = H160::from_low_u64_be(2052); + + // Alice has 1000 tokens. She should be able to send through precompile + let destination = MultiLocation::new( + 1, + Junctions::X1(Junction::AccountId32 { + network: None, + id: [1u8; 32], + }), + ); + + // This time we transfer it through TransferMultiAsset + // Instead of the address, we encode directly the multilocation referencing the asset + Precompiles::new() + .prepare_test( + ALICE, + xtokens_precompile_address, + XtokensPCall::transfer_multiasset { + // We want to transfer the relay token + asset: MultiLocation::parent(), + amount: 500_000_000_000_000u128.into(), + destination: destination.clone(), + weight: 4_000_000, + }, + ) + .expect_cost(57639) + .expect_no_logs() + .execute_returns(()); + }) +} + +#[test] +fn make_sure_glmr_can_be_transferred_precompile() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * GLMR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: [1u8; 32], + }), + }; + assert_ok!(XTokens::transfer_multiasset( + origin_of(AccountId::from(ALICE)), + Box::new(VersionedMultiAsset::V3(MultiAsset { + id: Concrete(moonbeam_runtime::xcm_config::SelfReserve::get()), + fun: Fungible(1000) + })), + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(40000.into()) + )); + }); +} + +#[test] +fn make_sure_glmr_can_be_transferred() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * GLMR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: [1u8; 32], + }), + }; + assert_ok!(XTokens::transfer( + origin_of(AccountId::from(ALICE)), + CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(40000.into()) + )); + }); +} + +#[test] +fn make_sure_polkadot_xcm_cannot_be_called() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * GLMR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .build() + .execute_with(|| { + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: [1u8; 32], + }), + }; + let multiassets: MultiAssets = [MultiAsset { + id: Concrete(moonbeam_runtime::xcm_config::SelfLocation::get()), + fun: Fungible(1000), + }] + .to_vec() + .into(); + assert_noop!( + RuntimeCall::PolkadotXcm(pallet_xcm::Call::::reserve_transfer_assets { + dest: Box::new(VersionedMultiLocation::V3(dest.clone())), + beneficiary: Box::new(VersionedMultiLocation::V3(dest)), + assets: Box::new(VersionedMultiAssets::V3(multiassets)), + fee_asset_item: 0, + }) + .dispatch(::RuntimeOrigin::signed( + AccountId::from(ALICE) + )), + frame_system::Error::::CallFiltered + ); + }); +} + +#[test] +fn transact_through_signed_precompile_works_v2() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + // Destination + let dest = MultiLocation::parent(); + + let fee_payer_asset = MultiLocation::parent(); + + let bytes = vec![1u8, 2u8, 3u8]; + + let total_weight = 1_000_000_000u64; + + let xcm_transactor_v2_precompile_address = H160::from_low_u64_be(2061); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_transactor_v2_precompile_address, + XcmTransactorV2PCall::transact_through_signed_multilocation { + dest, + fee_asset: fee_payer_asset, + weight: 4_000_000, + call: bytes.into(), + fee_amount: u128::from(total_weight).into(), + overall_weight: total_weight, + }, + ) + .expect_cost(17149) + .expect_no_logs() + .execute_returns(()); + }); +} + +#[test] +fn transact_through_signed_cannot_send_to_local_chain() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + // Destination + let dest = MultiLocation::here(); + + let fee_payer_asset = MultiLocation::parent(); + + let bytes = vec![1u8, 2u8, 3u8]; + + let total_weight = 1_000_000_000u64; + + let xcm_transactor_v2_precompile_address = H160::from_low_u64_be(2061); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_transactor_v2_precompile_address, + XcmTransactorV2PCall::transact_through_signed_multilocation { + dest, + fee_asset: fee_payer_asset, + weight: 4_000_000, + call: bytes.into(), + fee_amount: u128::from(total_weight).into(), + overall_weight: total_weight, + }, + ) + .execute_reverts(|output| { + from_utf8(&output) + .unwrap() + .contains("Dispatched call failed with error:") + && from_utf8(&output).unwrap().contains("ErrorValidating") + }); + }); +} + +#[test] +fn transactor_cannot_use_more_than_max_weight() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .build() + .execute_with(|| { + let source_location = AssetType::Xcm(MultiLocation::parent()); + let source_id: moonbeam_runtime::AssetId = source_location.clone().into(); + assert_ok!(XcmTransactor::register( + root_origin(), + AccountId::from(ALICE), + 0, + )); + + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + root_origin(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + // Relay charges 1000 for every instruction, and we have 3, so 3000 + 3000.into(), + 20000.into(), + None + )); + + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + root_origin(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + 1, + )); + + assert_noop!( + XcmTransactor::transact_through_derivative( + origin_of(AccountId::from(ALICE)), + moonbeam_runtime::xcm_config::Transactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new( + xcm::VersionedMultiLocation::V3(MultiLocation::parent()) + )), + fee_amount: None + }, + vec![], + // 2000 is the max + TransactWeights { + transact_required_weight_at_most: 17001.into(), + overall_weight: None + }, + false + ), + pallet_xcm_transactor::Error::::MaxWeightTransactReached + ); + assert_noop!( + XcmTransactor::transact_through_derivative( + origin_of(AccountId::from(ALICE)), + moonbeam_runtime::xcm_config::Transactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsCurrencyId(CurrencyId::ForeignAsset(source_id)), + fee_amount: None + }, + vec![], + // 20000 is the max + TransactWeights { + transact_required_weight_at_most: 17001.into(), + overall_weight: None + }, + false + ), + pallet_xcm_transactor::Error::::MaxWeightTransactReached + ); + }) +} + +#[test] +fn call_xtokens_with_fee() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 1_000 * GLMR), + ]) + .with_safe_xcm_version(2) + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .build() + .execute_with(|| { + let source_location = AssetType::Xcm(MultiLocation::parent()); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: [1u8; 32], + }), + }; + let source_id: moonbeam_runtime::AssetId = source_location.clone().into(); + + let before_balance = Assets::balance(source_id, &AccountId::from(ALICE)); + + // We are able to transfer with fee + assert_ok!(XTokens::transfer_with_fee( + origin_of(AccountId::from(ALICE)), + CurrencyId::ForeignAsset(source_id), + 100_000_000_000_000, + 100, + Box::new(xcm::VersionedMultiLocation::V3(dest.clone())), + WeightLimit::Limited(4000000000.into()) + )); + + let after_balance = Assets::balance(source_id, &AccountId::from(ALICE)); + // At least these much (plus fees) should have been charged + assert_eq!(before_balance - 100_000_000_000_000 - 100, after_balance); + }); +} + +#[test] +fn test_xcm_utils_ml_tp_account() { + ExtBuilder::default().build().execute_with(|| { + let xcm_utils_precompile_address = H160::from_low_u64_be(2060); + let expected_address_parent: H160 = + ParentIsPreset::::convert_location(&MultiLocation::parent()) + .unwrap() + .into(); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_utils_precompile_address, + XcmUtilsPCall::multilocation_to_address { + multilocation: MultiLocation::parent(), + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(Address(expected_address_parent)); + + let parachain_2000_multilocation = MultiLocation::new(1, X1(Parachain(2000))); + let expected_address_parachain: H160 = + SiblingParachainConvertsVia::::convert_location( + ¶chain_2000_multilocation, + ) + .unwrap() + .into(); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_utils_precompile_address, + XcmUtilsPCall::multilocation_to_address { + multilocation: parachain_2000_multilocation, + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(Address(expected_address_parachain)); + + let alice_in_parachain_2000_multilocation = MultiLocation::new( + 1, + X2( + Parachain(2000), + AccountKey20 { + network: None, + key: ALICE, + }, + ), + ); + let expected_address_alice_in_parachain_2000: H160 = + xcm_builder::HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &alice_in_parachain_2000_multilocation, + ) + .unwrap() + .into(); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_utils_precompile_address, + XcmUtilsPCall::multilocation_to_address { + multilocation: alice_in_parachain_2000_multilocation, + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(Address(expected_address_alice_in_parachain_2000)); + }); +} + +#[test] +fn test_xcm_utils_weight_message() { + ExtBuilder::default().build().execute_with(|| { + let xcm_utils_precompile_address = H160::from_low_u64_be(2060); + let expected_weight = + XcmWeight::::clear_origin().ref_time(); + + let message: Vec = xcm::VersionedXcm::<()>::V3(Xcm(vec![ClearOrigin])).encode(); + + let input = XcmUtilsPCall::weight_message { + message: message.into(), + }; + + Precompiles::new() + .prepare_test(ALICE, xcm_utils_precompile_address, input) + .expect_cost(0) + .expect_no_logs() + .execute_returns(expected_weight); + }); +} + +#[test] +fn test_xcm_utils_get_units_per_second() { + ExtBuilder::default().build().execute_with(|| { + let xcm_utils_precompile_address = H160::from_low_u64_be(2060); + let multilocation = SelfReserve::get(); + + let input = XcmUtilsPCall::get_units_per_second { multilocation }; + + let expected_units = + WEIGHT_REF_TIME_PER_SECOND as u128 * moonbeam_runtime::currency::WEIGHT_FEE; + + Precompiles::new() + .prepare_test(ALICE, xcm_utils_precompile_address, input) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(expected_units); + }); +} + +#[test] +fn precompile_existence() { + ExtBuilder::default().build().execute_with(|| { + let precompiles = Precompiles::new(); + let precompile_addresses: std::collections::BTreeSet<_> = vec![ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 1024, 1025, 1026, 2048, 2049, 2050, 2051, 2052, 2053, 2054, + 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, + 2069, 2070, 2071, + ] + .into_iter() + .map(H160::from_low_u64_be) + .collect(); + + for i in 0..3000 { + let address = H160::from_low_u64_be(i); + + if precompile_addresses.contains(&address) { + assert!( + is_precompile_or_fail::(address, 100_000u64).expect("to be ok"), + "is_precompile({}) should return true", + i + ); + + assert!( + precompiles + .execute(&mut MockHandle::new( + address, + Context { + address, + caller: H160::zero(), + apparent_value: U256::zero() + } + ),) + .is_some(), + "execute({},..) should return Some(_)", + i + ); + } else { + assert!( + !is_precompile_or_fail::(address, 100_000u64).expect("to be ok"), + "is_precompile({}) should return false", + i + ); + + assert!( + precompiles + .execute(&mut MockHandle::new( + address, + Context { + address, + caller: H160::zero(), + apparent_value: U256::zero() + } + ),) + .is_none(), + "execute({},..) should return None", + i + ); + } + } + }); +} + +#[test] +fn removed_precompiles() { + ExtBuilder::default().build().execute_with(|| { + let precompiles = Precompiles::new(); + let removed_precompiles = [1025]; + + for i in 1..3000 { + let address = H160::from_low_u64_be(i); + + if !is_precompile_or_fail::(address, 100_000u64).expect("to be ok") { + continue; + } + + if !removed_precompiles.contains(&i) { + assert!( + match precompiles.is_active_precompile(address, 100_000u64) { + IsPrecompileResult::Answer { is_precompile, .. } => is_precompile, + _ => false, + }, + "{i} should be an active precompile" + ); + continue; + } + + assert!( + !match precompiles.is_active_precompile(address, 100_000u64) { + IsPrecompileResult::Answer { is_precompile, .. } => is_precompile, + _ => false, + }, + "{i} shouldn't be an active precompile" + ); + + precompiles + .prepare_test(Alice, address, []) + .execute_reverts(|out| out == b"Removed precompile"); + } + }) +} + +#[test] +fn deal_with_fees_handles_tip() { + use frame_support::traits::OnUnbalanced; + use moonbeam_runtime::{DealWithFees, Treasury}; + use pallet_balances::NegativeImbalance; + + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 10_000)]) + .build() + .execute_with(|| { + // Alice has 10_000, which makes inital supply 10_000. + // drop()ing the NegativeImbalance below will cause the total_supply to be decreased + // incorrectly (since there was never a withdraw to begin with), which in this case has + // the desired effect of showing that currency was burned. + let total_supply_before = Balances::total_issuance(); + assert_eq!(total_supply_before, 10_000); + + let fees_then_tips = vec![ + NegativeImbalance::::new(100), + NegativeImbalance::::new(1_000), + ]; + DealWithFees::on_unbalanceds(fees_then_tips.into_iter()); + + // treasury should have received 20% + assert_eq!(Balances::free_balance(&Treasury::account_id()), 220); + + // verify 80% burned + let total_supply_after = Balances::total_issuance(); + assert_eq!(total_supply_before - total_supply_after, 880); + }); +} + +#[test] +fn evm_revert_substrate_events() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 100_000 * GLMR)]) + .build() + .execute_with(|| { + let batch_precompile_address = H160::from_low_u64_be(2056); + + // Batch a transfer followed by an invalid call to batch. + // Thus BatchAll will revert the transfer. + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::call { + source: ALICE.into(), + target: batch_precompile_address, + + input: BatchPCall::batch_all { + to: vec![Address(BOB.into()), Address(batch_precompile_address)].into(), + value: vec![U256::from(1 * GLMR), U256::zero()].into(), + call_data: vec![].into(), + gas_limit: vec![].into() + } + .into(), + value: U256::zero(), // No value sent in EVM + gas_limit: 500_000, + max_fee_per_gas: BASE_FEE_GENESIS.into(), + max_priority_fee_per_gas: None, + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let transfer_count = System::events() + .iter() + .filter(|r| match r.event { + RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => true, + _ => false, + }) + .count(); + + assert_eq!(transfer_count, 0, "there should be no transfer event"); + }); +} + +#[test] +fn evm_success_keeps_substrate_events() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 100_000 * GLMR)]) + .build() + .execute_with(|| { + let batch_precompile_address = H160::from_low_u64_be(2056); + + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::call { + source: ALICE.into(), + target: batch_precompile_address, + input: BatchPCall::batch_all { + to: vec![Address(BOB.into())].into(), + value: vec![U256::from(1 * GLMR)].into(), + call_data: vec![].into(), + gas_limit: vec![].into() + } + .into(), + value: U256::zero(), // No value sent in EVM + gas_limit: 500_000, + max_fee_per_gas: BASE_FEE_GENESIS.into(), + max_priority_fee_per_gas: None, + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let transfer_count = System::events() + .iter() + .filter(|r| match r.event { + RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => true, + _ => false, + }) + .count(); + + assert_eq!(transfer_count, 1, "there should be 1 transfer event"); + }); +} + +#[cfg(test)] +mod fee_tests { + use super::*; + use frame_support::{ + traits::ConstU128, + weights::{ConstantMultiplier, WeightToFee}, + }; + use moonbeam_runtime::{ + currency, LengthToFee, MinimumMultiplier, RuntimeBlockWeights, SlowAdjustingFeeUpdate, + TargetBlockFullness, TransactionPayment, + }; + use sp_core::Get; + use sp_runtime::FixedPointNumber; + + fn run_with_system_weight(w: Weight, mut assertions: F) + where + F: FnMut() -> (), + { + let mut t: sp_io::TestExternalities = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap() + .into(); + t.execute_with(|| { + System::set_block_consumed_resources(w, 0); + assertions() + }); + } + + #[test] + fn test_multiplier_can_grow_from_zero() { + let minimum_multiplier = MinimumMultiplier::get(); + let target = TargetBlockFullness::get() + * RuntimeBlockWeights::get() + .get(DispatchClass::Normal) + .max_total + .unwrap(); + // if the min is too small, then this will not change, and we are doomed forever. + // the weight is 1/100th bigger than target. + run_with_system_weight(target * 101 / 100, || { + let next = SlowAdjustingFeeUpdate::::convert(minimum_multiplier); + assert!( + next > minimum_multiplier, + "{:?} !>= {:?}", + next, + minimum_multiplier + ); + }) + } + + #[test] + fn test_fee_calculation() { + let base_extrinsic = RuntimeBlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic; + let multiplier = sp_runtime::FixedU128::from_float(0.999000000000000000); + let extrinsic_len = 100u32; + let extrinsic_weight = 5_000u64; + let tip = 42u128; + type WeightToFeeImpl = ConstantMultiplier>; + type LengthToFeeImpl = LengthToFee; + + // base_fee + (multiplier * extrinsic_weight_fee) + extrinsic_length_fee + tip + let expected_fee = + WeightToFeeImpl::weight_to_fee(&base_extrinsic) + + multiplier.saturating_mul_int(WeightToFeeImpl::weight_to_fee( + &Weight::from_parts(extrinsic_weight, 1), + )) + LengthToFeeImpl::weight_to_fee(&Weight::from_parts(extrinsic_len as u64, 1)) + + tip; + + let mut t: sp_io::TestExternalities = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap() + .into(); + t.execute_with(|| { + pallet_transaction_payment::NextFeeMultiplier::::set(multiplier); + let actual_fee = TransactionPayment::compute_fee( + extrinsic_len, + &frame_support::dispatch::DispatchInfo { + class: DispatchClass::Normal, + pays_fee: frame_support::dispatch::Pays::Yes, + weight: Weight::from_parts(extrinsic_weight, 1), + }, + tip, + ); + + assert_eq!( + expected_fee, + actual_fee, + "The actual fee did not match the expected fee, diff {}", + actual_fee - expected_fee + ); + }); + } +} diff --git a/tracing/2601/runtime/moonbeam/tests/runtime_apis.rs b/tracing/2601/runtime/moonbeam/tests/runtime_apis.rs new file mode 100644 index 00000000..ba8eb937 --- /dev/null +++ b/tracing/2601/runtime/moonbeam/tests/runtime_apis.rs @@ -0,0 +1,393 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Moonbeam Runtime Api Integration Tests + +mod common; +use common::*; + +use fp_evm::GenesisAccount; +use frame_support::assert_ok; +use nimbus_primitives::NimbusId; +use pallet_evm::{Account as EVMAccount, AddressMapping, FeeCalculator}; +use sp_core::{ByteArray, H160, H256, U256}; + +use fp_rpc::runtime_decl_for_ethereum_runtime_rpc_api::EthereumRuntimeRPCApi; +use moonbeam_rpc_primitives_txpool::runtime_decl_for_tx_pool_runtime_api::TxPoolRuntimeApi; +use nimbus_primitives::runtime_decl_for_nimbus_api::NimbusApi; +use std::{collections::BTreeMap, str::FromStr}; + +#[test] +fn ethereum_runtime_rpc_api_chain_id() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Runtime::chain_id(), CHAIN_ID); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_account_basic() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 2_000 * GLMR)]) + .build() + .execute_with(|| { + assert_eq!( + Runtime::account_basic(H160::from(ALICE)), + EVMAccount { + balance: U256::from(2_000 * GLMR), + nonce: U256::zero() + } + ); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_gas_price() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!( + Runtime::gas_price(), + TransactionPaymentAsGasPrice::min_gas_price().0 + ); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_account_code_at() { + let address = H160::from(EVM_CONTRACT); + let code: Vec = vec![1, 2, 3, 4, 5]; + ExtBuilder::default() + .with_evm_accounts({ + let mut map = BTreeMap::new(); + map.insert( + address, + GenesisAccount { + balance: U256::zero(), + code: code.clone(), + nonce: Default::default(), + storage: Default::default(), + }, + ); + map + }) + .build() + .execute_with(|| { + assert_eq!(Runtime::account_code_at(address), code); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_author() { + ExtBuilder::default() + .with_collators(vec![(AccountId::from(ALICE), 100_000 * GLMR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_balances(vec![ + (AccountId::from(ALICE), 200_000 * GLMR), + (AccountId::from(BOB), 100_000 * GLMR), + ]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 50_000 * GLMR, + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + run_to_block(2, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + assert_eq!(Runtime::author(), H160::from(ALICE)); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_storage_at() { + let address = H160::from(EVM_CONTRACT); + let mut key = [0u8; 32]; + key[31..32].copy_from_slice(&[6u8][..]); + let mut value = [0u8; 32]; + value[31..32].copy_from_slice(&[7u8][..]); + let item = H256::from_slice(&key[..]); + let mut storage: BTreeMap = BTreeMap::new(); + storage.insert(H256::from_slice(&key[..]), item); + ExtBuilder::default() + .with_evm_accounts({ + let mut map = BTreeMap::new(); + map.insert( + address, + GenesisAccount { + balance: U256::zero(), + code: Vec::new(), + nonce: Default::default(), + storage: storage.clone(), + }, + ); + map + }) + .build() + .execute_with(|| { + assert_eq!(Runtime::storage_at(address, U256::from(6)), item); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_call() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * GLMR), + (AccountId::from(BOB), 2_000 * GLMR), + ]) + .build() + .execute_with(|| { + let execution_result = Runtime::call( + H160::from(ALICE), // from + H160::from(BOB), // to + Vec::new(), // data + U256::from(1000u64), // value + U256::from(100000u64), // gas_limit + None, // max_fee_per_gas + None, // max_priority_fee_per_gas + None, // nonce + false, // estimate + None, // access_list + ); + assert!(execution_result.is_ok()); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_create() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 2_000 * GLMR)]) + .build() + .execute_with(|| { + let execution_result = Runtime::create( + H160::from(ALICE), // from + vec![0, 1, 1, 0], // data + U256::zero(), // value + U256::from(100000u64), // gas_limit + None, // max_fee_per_gas + None, // max_priority_fee_per_gas + None, // nonce + false, // estimate + None, // access_list + ); + assert!(execution_result.is_ok()); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_current_transaction_statuses() { + let alith = ::AddressMapping::into_account_id( + H160::from_str("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac") + .expect("internal H160 is valid; qed"), + ); + ExtBuilder::default() + .with_collators(vec![(AccountId::from(ALICE), 100_000 * GLMR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_balances(vec![ + (alith, 200_000 * GLMR), + (AccountId::from(ALICE), 200_000 * GLMR), + (AccountId::from(BOB), 100_000 * GLMR), + ]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 50_000 * GLMR, + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + + let _result = Executive::apply_extrinsic(unchecked_eth_tx(VALID_ETH_TX)); + + rpc_run_to_block(2); + let statuses = + Runtime::current_transaction_statuses().expect("Transaction statuses result."); + assert_eq!(statuses.len(), 1); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_current_block() { + ExtBuilder::default() + .with_collators(vec![(AccountId::from(ALICE), 100_000 * GLMR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_balances(vec![ + (AccountId::from(ALICE), 200_000 * GLMR), + (AccountId::from(BOB), 100_000 * GLMR), + ]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 50_000 * GLMR, + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + rpc_run_to_block(2); + let block = Runtime::current_block().expect("Block result."); + assert_eq!(block.header.number, U256::from(1u8)); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_current_receipts() { + let alith = ::AddressMapping::into_account_id( + H160::from_str("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac") + .expect("internal H160 is valid; qed"), + ); + ExtBuilder::default() + .with_collators(vec![(AccountId::from(ALICE), 100_000 * GLMR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_balances(vec![ + (alith, 200_000 * GLMR), + (AccountId::from(ALICE), 200_000 * GLMR), + (AccountId::from(BOB), 100_000 * GLMR), + ]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 50_000 * GLMR, + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + + let _result = Executive::apply_extrinsic(unchecked_eth_tx(VALID_ETH_TX)); + + rpc_run_to_block(2); + let receipts = Runtime::current_receipts().expect("Receipts result."); + assert_eq!(receipts.len(), 1); + }); +} + +#[test] +fn txpool_runtime_api_extrinsic_filter() { + ExtBuilder::default().build().execute_with(|| { + let non_eth_uxt = UncheckedExtrinsic::new_unsigned( + pallet_balances::Call::::transfer { + dest: AccountId::from(BOB), + value: 1 * GLMR, + } + .into(), + ); + let eth_uxt = unchecked_eth_tx(VALID_ETH_TX); + let txpool = >::extrinsic_filter( + vec![eth_uxt.clone(), non_eth_uxt.clone()], + vec![unchecked_eth_tx(VALID_ETH_TX), non_eth_uxt], + ); + assert_eq!(txpool.ready.len(), 1); + assert_eq!(txpool.future.len(), 1); + }); +} + +#[test] +fn can_author_when_selected_is_empty() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 20_000_000 * GLMR), + (AccountId::from(BOB), 10_000_000 * GLMR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 2_000_000 * GLMR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + run_to_block(2, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + + assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); + + let slot_number = 0; + let parent = Header { + digest: Default::default(), + extrinsics_root: Default::default(), + number: Default::default(), + parent_hash: Default::default(), + state_root: Default::default(), + }; + + // Base case: ALICE can author blocks when she is the only candidate + let can_author_block = Runtime::can_author( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + slot_number, + &parent, + ); + + assert!(can_author_block); + + // Remove ALICE from candidate pool, leaving the candidate_pool empty + assert_ok!(ParachainStaking::go_offline(origin_of(AccountId::from( + ALICE + )))); + + // Need to fast forward to right before the next session, which is when selected candidates + // will be updated. We want to test the creation of the first block of the next session. + run_to_block(1799, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + + assert_eq!(ParachainStaking::candidate_pool().0.len(), 0); + + let slot_number = 0; + let parent = Header { + digest: Default::default(), + extrinsics_root: Default::default(), + number: 1799, + parent_hash: Default::default(), + state_root: Default::default(), + }; + + let can_author_block = Runtime::can_author( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + slot_number, + &parent, + ); + + assert!(can_author_block); + + // Check that it works as expected after session update + run_to_block(1800, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + + assert_eq!(ParachainStaking::candidate_pool().0.len(), 0); + + let slot_number = 0; + let parent = Header { + digest: Default::default(), + extrinsics_root: Default::default(), + number: 1800, + parent_hash: Default::default(), + state_root: Default::default(), + }; + + let can_author_block = Runtime::can_author( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + slot_number, + &parent, + ); + + assert!(can_author_block); + }); +} diff --git a/tracing/2601/runtime/moonbeam/tests/xcm_mock/mod.rs b/tracing/2601/runtime/moonbeam/tests/xcm_mock/mod.rs new file mode 100644 index 00000000..f1441c2e --- /dev/null +++ b/tracing/2601/runtime/moonbeam/tests/xcm_mock/mod.rs @@ -0,0 +1,272 @@ +// Copyright 2021 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 . + +pub mod parachain; +pub mod relay_chain; +pub mod statemint_like; + +use cumulus_primitives_core::ParaId; +use pallet_xcm_transactor::relay_indices::*; +use sp_runtime::traits::AccountIdConversion; +use sp_runtime::{AccountId32, BuildStorage}; +use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt}; + +use polkadot_runtime_parachains::configuration::{ + GenesisConfig as ConfigurationGenesisConfig, HostConfiguration, +}; +use polkadot_runtime_parachains::paras::{ + GenesisConfig as ParasGenesisConfig, ParaGenesisArgs, ParaKind, +}; +use sp_core::{H160, U256}; +use std::{collections::BTreeMap, str::FromStr}; + +pub const PARAALICE: [u8; 20] = [1u8; 20]; +pub const RELAYALICE: AccountId32 = AccountId32::new([0u8; 32]); +pub const RELAYBOB: AccountId32 = AccountId32::new([2u8; 32]); + +pub fn para_a_account() -> AccountId32 { + ParaId::from(1).into_account_truncating() +} + +pub fn para_b_account() -> AccountId32 { + ParaId::from(2).into_account_truncating() +} + +pub fn para_a_account_20() -> parachain::AccountId { + ParaId::from(1).into_account_truncating() +} + +pub fn evm_account() -> H160 { + H160::from_str("1000000000000000000000000000000000000001").unwrap() +} + +pub fn mock_para_genesis_info() -> ParaGenesisArgs { + ParaGenesisArgs { + genesis_head: vec![1u8].into(), + validation_code: vec![1u8].into(), + para_kind: ParaKind::Parachain, + } +} + +pub fn mock_relay_config() -> HostConfiguration { + HostConfiguration:: { + hrmp_channel_max_capacity: u32::MAX, + hrmp_channel_max_total_size: u32::MAX, + hrmp_max_parachain_inbound_channels: 10, + hrmp_max_parachain_outbound_channels: 10, + hrmp_channel_max_message_size: u32::MAX, + // Changed to avoid aritmetic errors within hrmp_close + max_downward_message_size: 100_000u32, + ..Default::default() + } +} + +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_parachain! { + pub struct ParaC { + Runtime = parachain::Runtime, + XcmpMessageHandler = parachain::MsgQueue, + DmpMessageHandler = parachain::MsgQueue, + new_ext = para_ext(3), + } +} + +decl_test_parachain! { + pub struct Statemint { + Runtime = statemint_like::Runtime, + XcmpMessageHandler = statemint_like::MsgQueue, + DmpMessageHandler = statemint_like::MsgQueue, + new_ext = statemint_ext(4), + } +} + +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(vec![1, 2, 3, 4]), + } +} + +decl_test_network! { + pub struct MockNet { + relay_chain = Relay, + parachains = vec![ + (1, ParaA), + (2, ParaB), + (3, ParaC), + (4, Statemint), + ], + } +} + +pub const INITIAL_BALANCE: u128 = 10_000_000_000_000_000; + +pub const INITIAL_EVM_BALANCE: u128 = 0; +pub const INITIAL_EVM_NONCE: u32 = 1; + +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![(PARAALICE.into(), INITIAL_BALANCE)], + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_xcm_transactor::GenesisConfig:: { + // match relay runtime construct_runtime order in xcm_mock::relay_chain + relay_indices: RelayChainIndices { + hrmp: 6u8, + init_open_channel: 0u8, + accept_open_channel: 1u8, + close_channel: 2u8, + cancel_open_request: 6u8, + ..Default::default() + }, + ..Default::default() + } + .assimilate_storage(&mut t) + .unwrap(); + + // EVM accounts are self-sufficient. + let mut evm_accounts = BTreeMap::new(); + evm_accounts.insert( + evm_account(), + fp_evm::GenesisAccount { + nonce: U256::from(INITIAL_EVM_NONCE), + balance: U256::from(INITIAL_EVM_BALANCE), + storage: Default::default(), + code: vec![ + 0x00, // STOP + ], + }, + ); + + let genesis_config = pallet_evm::GenesisConfig:: { + accounts: evm_accounts, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + MsgQueue::set_para_id(para_id.into()); + }); + ext +} + +pub fn statemint_ext(para_id: u32) -> sp_io::TestExternalities { + use statemint_like::{MsgQueue, Runtime, System}; + + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap(); + + pallet_balances::GenesisConfig:: { + balances: vec![ + (RELAYALICE.into(), INITIAL_BALANCE), + (RELAYBOB.into(), INITIAL_BALANCE), + ], + } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + MsgQueue::set_para_id(para_id.into()); + }); + ext +} + +pub fn relay_ext(paras: Vec) -> sp_io::TestExternalities { + use relay_chain::{Runtime, System}; + + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap(); + + pallet_balances::GenesisConfig:: { + balances: vec![(RELAYALICE, INITIAL_BALANCE)], + } + .assimilate_storage(&mut t) + .unwrap(); + + let para_genesis: Vec<(ParaId, ParaGenesisArgs)> = paras + .iter() + .map(|¶_id| (para_id.into(), mock_para_genesis_info())) + .collect(); + + let genesis_config = ConfigurationGenesisConfig:: { + config: mock_relay_config(), + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let genesis_config = ParasGenesisConfig:: { + paras: para_genesis, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + }); + ext +} + +pub type RelayChainPalletXcm = pallet_xcm::Pallet; +pub type Hrmp = polkadot_runtime_parachains::hrmp::Pallet; + +pub type StatemintBalances = pallet_balances::Pallet; +pub type StatemintChainPalletXcm = pallet_xcm::Pallet; +pub type StatemintAssets = pallet_assets::Pallet; + +pub type Assets = pallet_assets::Pallet; +pub type LocalAssets = pallet_assets::Pallet; +pub type Treasury = pallet_treasury::Pallet; +pub type AssetManager = pallet_asset_manager::Pallet; +pub type XTokens = orml_xtokens::Pallet; +pub type RelayBalances = pallet_balances::Pallet; +pub type ParaBalances = pallet_balances::Pallet; +pub type XcmTransactor = pallet_xcm_transactor::Pallet; diff --git a/tracing/2601/runtime/moonbeam/tests/xcm_mock/parachain.rs b/tracing/2601/runtime/moonbeam/tests/xcm_mock/parachain.rs new file mode 100644 index 00000000..8b6f8d3e --- /dev/null +++ b/tracing/2601/runtime/moonbeam/tests/xcm_mock/parachain.rs @@ -0,0 +1,1210 @@ +// Copyright 2021 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 frame_support::{ + construct_runtime, + dispatch::GetDispatchInfo, + ensure, parameter_types, + traits::{ + AsEnsureOriginWithArg, ConstU32, Everything, Get, InstanceFilter, Nothing, PalletInfoAccess, + }, + weights::Weight, + PalletId, +}; + +use cumulus_primitives_core::relay_chain::HrmpChannelId; +use frame_system::{pallet_prelude::BlockNumberFor, EnsureNever, EnsureRoot}; +use orml_traits::parameter_type_with_key; +use pallet_xcm::migration::v1::VersionUncheckedMigrateToV1; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use sp_core::H256; +use sp_runtime::{ + traits::{BlakeTwo256, Hash, IdentityLookup, MaybeEquivalence, Zero}, + Permill, +}; +use sp_std::{convert::TryFrom, prelude::*}; +use xcm::{latest::prelude::*, Version as XcmVersion, VersionedXcm}; + +use pallet_ethereum::PostLogContent; +use polkadot_core_primitives::BlockNumber as RelayBlockNumber; +use polkadot_parachain::primitives::{Id as ParaId, Sibling}; +use xcm::latest::{ + AssetId as XcmAssetId, Error as XcmError, ExecuteXcm, + Junction::{PalletInstance, Parachain}, + Junctions, MultiLocation, NetworkId, Outcome, Xcm, +}; +use xcm_builder::{ + AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, + CurrencyAdapter as XcmCurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, + FungiblesAdapter, IsConcrete, NoChecking, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountKey20AsNative, SovereignSignedViaLocation, TakeWeightCredit, WithComputedOrigin, +}; +use xcm_executor::{traits::JustTry, Config, XcmExecutor}; + +use scale_info::TypeInfo; +use xcm_simulator::{ + DmpMessageHandlerT as DmpMessageHandler, XcmpMessageFormat, + XcmpMessageHandlerT as XcmpMessageHandler, +}; + +pub type AccountId = moonbeam_core_primitives::AccountId; +pub type Balance = u128; +pub type AssetId = u128; +pub type BlockNumber = BlockNumberFor; + +parameter_types! { + pub const BlockHashCount: u32 = 250; +} + +impl frame_system::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Block = Block; + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + 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 = frame_support::traits::ConstU32<16>; +} + +parameter_types! { + pub ExistentialDeposit: Balance = 0; + 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 = (); + type FreezeIdentifier = (); + type MaxHolds = (); + type MaxFreezes = (); +} + +pub type ForeignAssetInstance = (); +pub type LocalAssetInstance = pallet_assets::Instance1; + +// Required for runtime benchmarks +pallet_assets::runtime_benchmarks_enabled! { + pub struct BenchmarkHelper; + impl pallet_assets::BenchmarkHelper for BenchmarkHelper + where + AssetIdParameter: From, + { + fn create_asset_id_parameter(id: u32) -> AssetIdParameter { + (id as u128).into() + } + } +} + +parameter_types! { + pub const AssetDeposit: Balance = 1; // Does not really matter as this will be only called by root + pub const ApprovalDeposit: Balance = 0; + pub const AssetsStringLimit: u32 = 50; + pub const MetadataDepositBase: Balance = 0; + pub const MetadataDepositPerByte: Balance = 0; + pub const AssetAccountDeposit: Balance = 0; +} + +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = AssetAccountDeposit; + type WeightInfo = pallet_assets::weights::SubstrateWeight; + type RemoveItemsLimit = ConstU32<656>; + type AssetIdParameter = AssetId; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = AssetAccountDeposit; + type WeightInfo = pallet_assets::weights::SubstrateWeight; + type RemoveItemsLimit = ConstU32<656>; + type AssetIdParameter = AssetId; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used +/// when determining ownership of accounts for asset transacting and when attempting to use XCM +/// `Transact` in order to determine the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the default `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + AccountKey20Aliases, + // Generate remote accounts according to polkadot standards + xcm_builder::HashedDescriptionDescribeFamilyAllTerminal, +); + +/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, +/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can +/// biases the kind of local `Origin` it will become. +pub type XcmOriginToTransactDispatchOrigin = ( + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // recognised. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognised. + SiblingParachainAsNative, + // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a + // transaction from the Root origin. + ParentAsSuperuser, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + pallet_xcm::XcmPassthrough, + SignedAccountKey20AsNative, +); + +parameter_types! { + pub const UnitWeightCost: Weight = Weight::from_parts(1u64, 1u64); + pub MaxInstructions: u32 = 100; +} + +// Instructing how incoming xcm assets will be handled +pub type ForeignFungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + Assets, + // Use this currency when it is a fungible asset matching the given location or name: + ( + ConvertedConcreteId< + AssetId, + Balance, + xcm_primitives::AsAssetType, + JustTry, + >, + ), + // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont allow teleports. + NoChecking, + // We dont track any teleports + (), +>; + +pub type LocalAssetTransactor = XcmCurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching any of the locations in + // SelfReserveRepresentations + IsConcrete, + // We can convert the MultiLocations with our converter above: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont allow teleport + (), +>; + +/// Means for transacting local assets besides the native currency on this chain. +pub type LocalFungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + LocalAssets, + // Use this currency when it is a fungible asset matching the given location or name: + ( + ConvertedConcreteId< + AssetId, + Balance, + AsPrefixedGeneralIndex, + JustTry, + >, + ), + // Convert an XCM MultiLocation into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont want to allow teleporting assets + NoChecking, + // The account to use for tracking teleports. + (), +>; + +// We use all transactors +pub type AssetTransactors = ( + LocalAssetTransactor, + ForeignFungiblesTransactor, + LocalFungiblesTransactor, +); +pub type XcmRouter = super::ParachainXcmRouter; + +pub type XcmBarrier = ( + // Weight that is paid for may be consumed. + TakeWeightCredit, + // Expected responses are OK. + AllowKnownQueryResponses, + WithComputedOrigin< + ( + // If the message is one that immediately attemps to pay for execution, then allow it. + AllowTopLevelPaidExecutionFrom, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, + ), + UniversalLocation, + ConstU32<8>, + >, +); + +parameter_types! { + /// Xcm fees will go to the treasury account + pub XcmFeesAccount: AccountId = Treasury::account_id(); +} + +/// This is the struct that will handle the revenue from xcm fees +pub type XcmFeesToAccount_ = xcm_primitives::XcmFeesToAccount< + Assets, + ( + ConvertedConcreteId< + AssetId, + Balance, + xcm_primitives::AsAssetType, + JustTry, + >, + ), + AccountId, + XcmFeesAccount, +>; + +parameter_types! { + // We cannot skip the native trader for some specific tests, so we will have to work with + // a native trader that charges same number of units as weight + pub ParaTokensPerSecond: (XcmAssetId, u128, u128) = + (Concrete(SelfReserve::get()), 1000000000000, 0); +} + +parameter_types! { + pub const RelayNetwork: NetworkId = NetworkId::Polkadot; + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + pub UniversalLocation: InteriorMultiLocation = + X2(GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())); + pub SelfReserve: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; + pub LocalAssetsPalletLocation: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; + pub const MaxAssetsIntoHolding: u32 = 64; +} + +use frame_system::RawOrigin; +use sp_runtime::traits::PostDispatchInfoOf; +use sp_runtime::DispatchErrorWithPostInfo; +use xcm_executor::traits::CallDispatcher; +moonbeam_runtime_common::impl_moonbeam_xcm_call!(); + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = AssetTransactors; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type IsReserve = orml_xcm_support::MultiNativeAsset< + xcm_primitives::AbsoluteAndRelativeReserve, + >; + type IsTeleporter = (); + type UniversalLocation = UniversalLocation; + type Barrier = XcmBarrier; + type Weigher = FixedWeightBounds; + // We use two traders + // When we receive the self-reserve asset, + // When we receive a non-reserve asset, we use AssetManager to fetch how many + // units per second we should charge + type Trader = ( + FixedRateOfFungible, + xcm_primitives::FirstAssetTrader, + ); + type ResponseHandler = PolkadotXcm; + type SubscriptionService = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type CallDispatcher = MoonbeamCall; + type AssetLocker = (); + type AssetExchanger = (); + type PalletInstancesInfo = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; + type SafeCallFilter = Everything; + type Aliasers = Nothing; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +// Our currencyId. We distinguish for now between SelfReserve, and Others, defined by their Id. +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum CurrencyId { + SelfReserve, + ForeignAsset(AssetId), + LocalAssetReserve(AssetId), +} + +// How to convert from CurrencyId to MultiLocation +pub struct CurrencyIdtoMultiLocation(sp_std::marker::PhantomData); +impl sp_runtime::traits::Convert> + for CurrencyIdtoMultiLocation +where + AssetXConverter: MaybeEquivalence, +{ + fn convert(currency: CurrencyId) -> Option { + match currency { + CurrencyId::SelfReserve => { + let multi: MultiLocation = SelfReserve::get(); + Some(multi) + } + CurrencyId::ForeignAsset(asset) => AssetXConverter::convert_back(&asset), + CurrencyId::LocalAssetReserve(asset) => { + let mut location = LocalAssetsPalletLocation::get(); + location.push_interior(Junction::GeneralIndex(asset)).ok(); + Some(location) + } + } + } +} + +parameter_types! { + pub const BaseXcmWeight: Weight = Weight::from_parts(100u64, 100u64); + pub const MaxAssetsForTransfer: usize = 2; + pub SelfLocation: MultiLocation = MultiLocation::here(); + pub SelfLocationAbsolute: MultiLocation = MultiLocation { + parents:1, + interior: Junctions::X1( + Parachain(MsgQueue::parachain_id().into()) + ) + }; +} + +parameter_type_with_key! { + pub ParachainMinFee: |location: MultiLocation| -> Option { + match (location.parents, location.first_interior()) { + (1, Some(Parachain(4u32))) => Some(50u128), + _ => None, + } + }; +} + +// The XCM message wrapper wrapper +impl orml_xtokens::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type CurrencyId = CurrencyId; + type AccountIdToMultiLocation = xcm_primitives::AccountIdToMultiLocation; + type CurrencyIdConvert = + CurrencyIdtoMultiLocation>; + type XcmExecutor = XcmExecutor; + type SelfLocation = SelfLocation; + type Weigher = xcm_builder::FixedWeightBounds; + type BaseXcmWeight = BaseXcmWeight; + type UniversalLocation = UniversalLocation; + type MaxAssetsForTransfer = MaxAssetsForTransfer; + type MinXcmFee = ParachainMinFee; + type MultiLocationsFilter = Everything; + type ReserveProvider = xcm_primitives::AbsoluteAndRelativeReserve; +} + +parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const ProposalBondMinimum: Balance = 0; + pub const SpendPeriod: u32 = 0; + pub const TreasuryId: PalletId = PalletId(*b"pc/trsry"); + pub const MaxApprovals: u32 = 100; +} + +impl pallet_treasury::Config for Runtime { + type PalletId = TreasuryId; + type Currency = Balances; + type ApproveOrigin = EnsureRoot; + type RejectOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type OnSlash = Treasury; + type ProposalBond = ProposalBond; + type ProposalBondMinimum = ProposalBondMinimum; + type SpendPeriod = SpendPeriod; + type Burn = (); + type BurnDestination = (); + type MaxApprovals = MaxApprovals; + type WeightInfo = (); + type SpendFunds = (); + type ProposalBondMaximum = (); + type SpendOrigin = frame_support::traits::NeverEnsureOrigin; // Same as Polkadot +} + +#[frame_support::pallet] +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] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn parachain_id)] + pub(super) type ParachainId = StorageValue<_, ParaId, 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 (result, event) = match Xcm::::try_from(xcm) { + Ok(xcm) => { + let location = MultiLocation::new(1, Junctions::X1(Parachain(sender.into()))); + let mut id = [0u8; 32]; + id.copy_from_slice(hash.as_ref()); + match T::XcmExecutor::execute_xcm(location, xcm, id, max_weight) { + Outcome::Error(e) => (Err(e.clone()), 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 (_i, (_sent_at, data)) in iter.enumerate() { + let id = sp_io::hashing::blake2_256(&data[..]); + let maybe_msg = VersionedXcm::::decode(&mut &data[..]) + .map(Xcm::::try_from); + match maybe_msg { + Err(_) => { + Self::deposit_event(Event::InvalidFormat(id)); + } + Ok(Err(())) => { + Self::deposit_event(Event::UnsupportedVersion(id)); + } + Ok(Ok(x)) => { + let outcome = T::XcmExecutor::execute_xcm(Parent, x, id, limit); + Self::deposit_event(Event::ExecutedDownward(id, outcome)); + } + } + } + limit + } + } +} + +// Pallet to provide the version, used to test runtime upgrade version changes +#[frame_support::pallet] +pub mod mock_version_changer { + use super::*; + use frame_support::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + } + + #[pallet::call] + impl Pallet {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn current_version)] + pub(super) type CurrentVersion = StorageValue<_, XcmVersion, ValueQuery>; + + impl Get for Pallet { + fn get() -> XcmVersion { + Self::current_version() + } + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + // XCMP + /// Some XCM was executed OK. + VersionChanged(XcmVersion), + } + + impl Pallet { + pub fn set_version(version: XcmVersion) { + CurrentVersion::::put(version); + Self::deposit_event(Event::VersionChanged(version)); + } + } +} + +impl mock_msg_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +impl mock_version_changer::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} + +pub type LocalOriginToLocation = + xcm_primitives::SignedToAccountId20; + +parameter_types! { + pub MatcherLocation: MultiLocation = MultiLocation::here(); +} + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parent.into()); +} + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = frame_support::traits::Nothing; + type XcmExecutor = XcmExecutor; + // Do not allow teleports + 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; + // We use a custom one to test runtime ugprades + type AdvertisedXcmVersion = XcmVersioner; + type Currency = Balances; + type CurrencyMatcher = IsConcrete; + type TrustedLockers = (); + type SovereignAccountOf = (); + type MaxLockers = ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type AdminOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; +} + +// Our AssetType. For now we only handle Xcm Assets +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum AssetType { + Xcm(MultiLocation), +} +impl Default for AssetType { + fn default() -> Self { + Self::Xcm(MultiLocation::here()) + } +} + +impl From for AssetType { + fn from(location: MultiLocation) -> Self { + Self::Xcm(location) + } +} + +impl Into> for AssetType { + fn into(self) -> Option { + match self { + Self::Xcm(location) => Some(location), + } + } +} + +// Implementation on how to retrieve the AssetId from an AssetType +// We simply hash the AssetType and take the lowest 128 bits +impl From for AssetId { + fn from(asset: AssetType) -> AssetId { + match asset { + AssetType::Xcm(id) => { + let mut result: [u8; 16] = [0u8; 16]; + let hash: H256 = id.using_encoded(::Hashing::hash); + result.copy_from_slice(&hash.as_fixed_bytes()[0..16]); + u128::from_le_bytes(result) + } + } + } +} + +// We instruct how to register the Assets +// In this case, we tell it to Create an Asset in pallet-assets +pub struct AssetRegistrar; +use frame_support::pallet_prelude::DispatchResult; +impl pallet_asset_manager::AssetRegistrar for AssetRegistrar { + fn create_foreign_asset( + asset: AssetId, + min_balance: Balance, + metadata: AssetMetadata, + is_sufficient: bool, + ) -> DispatchResult { + Assets::force_create( + RuntimeOrigin::root(), + asset, + AssetManager::account_id(), + is_sufficient, + min_balance, + )?; + + Assets::force_set_metadata( + RuntimeOrigin::root(), + asset, + metadata.name, + metadata.symbol, + metadata.decimals, + false, + ) + } + + fn create_local_asset( + asset: AssetId, + _creator: AccountId, + min_balance: Balance, + is_sufficient: bool, + owner: AccountId, + ) -> DispatchResult { + LocalAssets::force_create( + RuntimeOrigin::root(), + asset, + owner, + is_sufficient, + min_balance, + )?; + + // TODO uncomment when we feel comfortable + /* + // The asset has been created. Let's put the revert code in the precompile address + let precompile_address = Runtime::asset_id_to_account(ASSET_PRECOMPILE_ADDRESS_PREFIX, asset); + pallet_evm::AccountCodes::::insert( + precompile_address, + vec![0x60, 0x00, 0x60, 0x00, 0xfd], + );*/ + Ok(()) + } + + fn destroy_foreign_asset(asset: AssetId) -> DispatchResult { + // Mark the asset as destroying + Assets::start_destroy(RuntimeOrigin::root(), asset)?; + + Ok(()) + } + + fn destroy_local_asset(asset: AssetId) -> DispatchResult { + // Mark the asset as destroying + LocalAssets::start_destroy(RuntimeOrigin::root(), asset)?; + + Ok(()) + } + + fn destroy_asset_dispatch_info_weight(asset: AssetId) -> Weight { + RuntimeCall::Assets( + pallet_assets::Call::::start_destroy { + id: asset.into(), + }, + ) + .get_dispatch_info() + .weight + } +} + +#[derive(Clone, Default, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub struct AssetMetadata { + pub name: Vec, + pub symbol: Vec, + pub decimals: u8, +} + +pub struct LocalAssetIdCreator; +impl pallet_asset_manager::LocalAssetIdCreator for LocalAssetIdCreator { + fn create_asset_id_from_metadata(local_asset_counter: u128) -> AssetId { + // Our means of converting a local asset counter to an assetId + // We basically hash (local asset counter) + let mut result: [u8; 16] = [0u8; 16]; + let hash: H256 = + local_asset_counter.using_encoded(::Hashing::hash); + result.copy_from_slice(&hash.as_fixed_bytes()[0..16]); + u128::from_le_bytes(result) + } +} + +impl pallet_asset_manager::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type AssetRegistrarMetadata = AssetMetadata; + type ForeignAssetType = AssetType; + type AssetRegistrar = AssetRegistrar; + type ForeignAssetModifierOrigin = EnsureRoot; + type LocalAssetModifierOrigin = EnsureRoot; + type LocalAssetIdCreator = LocalAssetIdCreator; + type Currency = Balances; + type LocalAssetDeposit = AssetDeposit; + type WeightInfo = (); +} + +// 1 DOT should be enough +parameter_types! { + pub MaxHrmpRelayFee: MultiAsset = (MultiLocation::parent(), 1_000_000_000_000u128).into(); +} + +impl pallet_xcm_transactor::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type Transactor = MockTransactors; + type DerivativeAddressRegistrationOrigin = EnsureRoot; + type SovereignAccountDispatcherOrigin = frame_system::EnsureRoot; + type CurrencyId = CurrencyId; + type AccountIdToMultiLocation = xcm_primitives::AccountIdToMultiLocation; + type CurrencyIdToMultiLocation = + CurrencyIdtoMultiLocation>; + type SelfLocation = SelfLocation; + type Weigher = xcm_builder::FixedWeightBounds; + type UniversalLocation = UniversalLocation; + type XcmSender = XcmRouter; + type BaseXcmWeight = BaseXcmWeight; + type AssetTransactor = AssetTransactors; + type ReserveProvider = xcm_primitives::AbsoluteAndRelativeReserve; + type WeightInfo = (); + type HrmpManipulatorOrigin = EnsureRoot; + type MaxHrmpFee = xcm_builder::Case; +} + +parameter_types! { + pub const MinimumPeriod: u64 = 1000; +} +impl pallet_timestamp::Config for Runtime { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +use sp_core::U256; + +const MAX_POV_SIZE: u64 = 5 * 1024 * 1024; +/// Block storage limit in bytes. Set to 40 KB. +const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024; + +parameter_types! { + pub BlockGasLimit: U256 = U256::from(u64::MAX); + pub WeightPerGas: Weight = Weight::from_parts(1, 0); + pub GasLimitPovSizeRatio: u64 = { + let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64(); + block_gas_limit.saturating_div(MAX_POV_SIZE) + }; + pub GasLimitStorageGrowthRatio: u64 = + BlockGasLimit::get().min(u64::MAX.into()).low_u64().saturating_div(BLOCK_STORAGE_LIMIT); +} + +impl pallet_evm::Config for Runtime { + type FeeCalculator = (); + type GasWeightMapping = pallet_evm::FixedGasWeightMapping; + type WeightPerGas = WeightPerGas; + + type CallOrigin = pallet_evm::EnsureAddressRoot; + type WithdrawOrigin = pallet_evm::EnsureAddressNever; + + type AddressMapping = pallet_evm::IdentityAddressMapping; + type Currency = Balances; + type Runner = pallet_evm::runner::stack::Runner; + + type RuntimeEvent = RuntimeEvent; + type PrecompilesType = (); + type PrecompilesValue = (); + type ChainId = (); + type BlockGasLimit = BlockGasLimit; + type OnChargeTransaction = (); + type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping; + type FindAuthor = (); + type OnCreate = (); + type GasLimitPovSizeRatio = GasLimitPovSizeRatio; + type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio; + type Timestamp = Timestamp; + type WeightInfo = pallet_evm::weights::SubstrateWeight; +} + +pub struct NormalFilter; +impl frame_support::traits::Contains for NormalFilter { + fn contains(c: &RuntimeCall) -> bool { + match c { + _ => true, + } + } +} + +// We need to use the encoding from the relay mock runtime +#[derive(Encode, Decode)] +pub enum RelayCall { + #[codec(index = 5u8)] + // the index should match the position of the module in `construct_runtime!` + Utility(UtilityCall), + #[codec(index = 6u8)] + // the index should match the position of the module in `construct_runtime!` + Hrmp(HrmpCall), +} + +#[derive(Encode, Decode)] +pub enum UtilityCall { + #[codec(index = 1u8)] + AsDerivative(u16), +} + +// HRMP call encoding, needed for xcm transactor pallet +#[derive(Encode, Decode)] +pub enum HrmpCall { + #[codec(index = 0u8)] + InitOpenChannel(ParaId, u32, u32), + #[codec(index = 1u8)] + AcceptOpenChannel(ParaId), + #[codec(index = 2u8)] + CloseChannel(HrmpChannelId), + #[codec(index = 6u8)] + CancelOpenRequest(HrmpChannelId, u32), +} + +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum MockTransactors { + Relay, +} + +impl xcm_primitives::XcmTransact for MockTransactors { + fn destination(self) -> MultiLocation { + match self { + MockTransactors::Relay => MultiLocation::parent(), + } + } +} + +impl xcm_primitives::UtilityEncodeCall for MockTransactors { + fn encode_call(self, call: xcm_primitives::UtilityAvailableCalls) -> Vec { + match self { + MockTransactors::Relay => match call { + xcm_primitives::UtilityAvailableCalls::AsDerivative(a, b) => { + let mut call = + RelayCall::Utility(UtilityCall::AsDerivative(a.clone())).encode(); + call.append(&mut b.clone()); + call + } + }, + } + } +} + +pub struct MockHrmpEncoder; +impl xcm_primitives::HrmpEncodeCall for MockHrmpEncoder { + fn hrmp_encode_call( + call: xcm_primitives::HrmpAvailableCalls, + ) -> Result, xcm::latest::Error> { + match call { + xcm_primitives::HrmpAvailableCalls::InitOpenChannel(a, b, c) => Ok(RelayCall::Hrmp( + HrmpCall::InitOpenChannel(a.clone(), b.clone(), c.clone()), + ) + .encode()), + xcm_primitives::HrmpAvailableCalls::AcceptOpenChannel(a) => { + Ok(RelayCall::Hrmp(HrmpCall::AcceptOpenChannel(a.clone())).encode()) + } + xcm_primitives::HrmpAvailableCalls::CloseChannel(a) => { + Ok(RelayCall::Hrmp(HrmpCall::CloseChannel(a.clone())).encode()) + } + xcm_primitives::HrmpAvailableCalls::CancelOpenRequest(a, b) => { + Ok(RelayCall::Hrmp(HrmpCall::CancelOpenRequest(a.clone(), b.clone())).encode()) + } + } + } +} + +parameter_types! { + pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes; +} + +impl pallet_ethereum::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type StateRoot = pallet_ethereum::IntermediateStateRoot; + type PostLogContent = PostBlockAndTxnHashes; + type ExtraDataLength = ConstU32<30>; +} + +parameter_types! { + pub ReservedXcmpWeight: Weight = Weight::from_parts(u64::max_value(), 0); +} + +#[derive( + Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, MaxEncodedLen, TypeInfo, +)] +pub enum ProxyType { + NotAllowed = 0, + Any = 1, +} + +impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType {} + +impl InstanceFilter for ProxyType { + fn filter(&self, _c: &RuntimeCall) -> bool { + match self { + ProxyType::NotAllowed => false, + ProxyType::Any => true, + } + } + fn is_superset(&self, _o: &Self) -> bool { + false + } +} + +impl Default for ProxyType { + fn default() -> Self { + Self::NotAllowed + } +} + +parameter_types! { + pub const ProxyCost: u64 = 1; +} + +impl pallet_proxy::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type ProxyType = ProxyType; + type ProxyDepositBase = ProxyCost; + type ProxyDepositFactor = ProxyCost; + type MaxProxies = ConstU32<32>; + type WeightInfo = pallet_proxy::weights::SubstrateWeight; + type MaxPending = ConstU32<32>; + type CallHasher = BlakeTwo256; + type AnnouncementDepositBase = ProxyCost; + type AnnouncementDepositFactor = ProxyCost; +} + +pub struct EthereumXcmEnsureProxy; +impl xcm_primitives::EnsureProxy for EthereumXcmEnsureProxy { + fn ensure_ok(delegator: AccountId, delegatee: AccountId) -> Result<(), &'static str> { + // The EVM implicitely contains an Any proxy, so we only allow for "Any" proxies + let def: pallet_proxy::ProxyDefinition = + pallet_proxy::Pallet::::find_proxy( + &delegator, + &delegatee, + Some(ProxyType::Any), + ) + .map_err(|_| "proxy error: expected `ProxyType::Any`")?; + // We only allow to use it for delay zero proxies, as the call will iMmediatly be executed + ensure!(def.delay.is_zero(), "proxy delay is Non-zero`"); + Ok(()) + } +} + +impl pallet_ethereum_xcm::Config for Runtime { + type InvalidEvmTransactionError = pallet_ethereum::InvalidTransactionWrapper; + type ValidatedTransaction = pallet_ethereum::ValidatedTransaction; + type XcmEthereumOrigin = pallet_ethereum_xcm::EnsureXcmEthereumTransaction; + type ReservedXcmpWeight = ReservedXcmpWeight; + type EnsureProxy = EthereumXcmEnsureProxy; + type ControllerOrigin = EnsureRoot; +} + +type Block = frame_system::mocking::MockBlockU32; + +construct_runtime!( + pub enum Runtime { + System: frame_system, + Balances: pallet_balances, + MsgQueue: mock_msg_queue, + XcmVersioner: mock_version_changer, + + PolkadotXcm: pallet_xcm, + Assets: pallet_assets, + CumulusXcm: cumulus_pallet_xcm, + XTokens: orml_xtokens, + AssetManager: pallet_asset_manager, + XcmTransactor: pallet_xcm_transactor, + Treasury: pallet_treasury, + LocalAssets: pallet_assets::, + Proxy: pallet_proxy, + + Timestamp: pallet_timestamp, + EVM: pallet_evm, + Ethereum: pallet_ethereum, + EthereumXcm: pallet_ethereum_xcm, + } +); + +pub(crate) fn para_events() -> Vec { + System::events() + .into_iter() + .map(|r| r.event) + .filter_map(|e| Some(e)) + .collect::>() +} + +use frame_support::traits::{OnFinalize, OnInitialize, OnRuntimeUpgrade}; +pub(crate) fn on_runtime_upgrade() { + VersionUncheckedMigrateToV1::::on_runtime_upgrade(); +} + +pub(crate) fn para_roll_to(n: BlockNumber) { + while System::block_number() < n { + PolkadotXcm::on_finalize(System::block_number()); + Balances::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Balances::on_initialize(System::block_number()); + PolkadotXcm::on_initialize(System::block_number()); + } +} diff --git a/tracing/2601/runtime/moonbeam/tests/xcm_mock/relay_chain.rs b/tracing/2601/runtime/moonbeam/tests/xcm_mock/relay_chain.rs new file mode 100644 index 00000000..30c5537b --- /dev/null +++ b/tracing/2601/runtime/moonbeam/tests/xcm_mock/relay_chain.rs @@ -0,0 +1,406 @@ +// Copyright 2021 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::{Everything, Nothing, ProcessMessage, ProcessMessageError}, +}; +use frame_system::pallet_prelude::BlockNumberFor; +use sp_core::H256; +use sp_runtime::{ + traits::{ConstU32, IdentityLookup}, + AccountId32, +}; + +use frame_support::weights::{Weight, WeightMeter}; +use polkadot_parachain::primitives::Id as ParaId; +use polkadot_runtime_parachains::{ + configuration, dmp, hrmp, + inclusion::{AggregateMessageOrigin, UmpQueueId}, + origin, paras, shared, +}; +use sp_runtime::transaction_validity::TransactionPriority; +use sp_runtime::Permill; +use xcm::latest::prelude::*; +use xcm_builder::{ + Account32Hash, AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, ChildParachainAsNative, ChildParachainConvertsVia, + ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible, + FixedWeightBounds, IsConcrete, ProcessXcmMessage, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, WithComputedOrigin, +}; +use xcm_executor::{Config, XcmExecutor}; +pub type AccountId = AccountId32; +pub type Balance = u128; +pub type BlockNumber = BlockNumberFor; + +parameter_types! { + pub const BlockHashCount: u32 = 250; +} + +impl frame_system::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Block = Block; + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + 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 = (); + type FreezeIdentifier = (); + type MaxHolds = (); + type MaxFreezes = (); +} + +impl pallet_utility::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type WeightInfo = (); + type PalletsOrigin = OriginCaller; +} + +impl shared::Config for Runtime {} + +impl configuration::Config for Runtime { + type WeightInfo = configuration::TestWeightInfo; +} + +parameter_types! { + pub KsmLocation: MultiLocation = Here.into(); + pub const KusamaNetwork: NetworkId = NetworkId::Kusama; + pub const AnyNetwork: Option = None; + pub UniversalLocation: InteriorMultiLocation = Here; +} + +pub type SovereignAccountOf = ( + ChildParachainConvertsVia, + AccountId32Aliases, + // Not enabled in the relay per se, but we enable it to test + // the transact_through_signed extrinsic + Account32Hash, +); + +pub type LocalAssetTransactor = + XcmCurrencyAdapter, SovereignAccountOf, AccountId, ()>; + +type LocalOriginConverter = ( + SovereignSignedViaLocation, + ChildParachainAsNative, + SignedAccountId32AsNative, + ChildSystemParachainAsSuperuser, +); + +parameter_types! { + pub const BaseXcmWeight: Weight = Weight::from_parts(1000u64, 1000u64); + pub KsmPerSecond: (AssetId, u128, u128) = (Concrete(KsmLocation::get()), 1, 1); + pub const MaxInstructions: u32 = 100; + pub const MaxAssetsIntoHolding: u32 = 64; + pub MatcherLocation: MultiLocation = MultiLocation::here(); +} + +pub type XcmRouter = super::RelayChainXcmRouter; + +pub type XcmBarrier = ( + // Weight that is paid for may be consumed. + TakeWeightCredit, + // Expected responses are OK. + AllowKnownQueryResponses, + WithComputedOrigin< + ( + // If the message is one that immediately attemps to pay for execution, then allow it. + AllowTopLevelPaidExecutionFrom, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, + ), + UniversalLocation, + ConstU32<8>, + >, +); + +parameter_types! { + pub Kusama: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(KsmLocation::get()) }); + pub Statemine: MultiLocation = Parachain(4).into(); + pub KusamaForStatemine: (MultiAssetFilter, MultiLocation) = (Kusama::get(), Statemine::get()); +} + +pub type TrustedTeleporters = xcm_builder::Case; + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = LocalAssetTransactor; + type OriginConverter = LocalOriginConverter; + type IsReserve = (); + type IsTeleporter = TrustedTeleporters; + type UniversalLocation = UniversalLocation; + type Barrier = XcmBarrier; + type Weigher = FixedWeightBounds; + type Trader = FixedRateOfFungible; + type ResponseHandler = XcmPallet; + type AssetTrap = XcmPallet; + type AssetClaims = XcmPallet; + type SubscriptionService = XcmPallet; + type CallDispatcher = RuntimeCall; + type AssetLocker = (); + type AssetExchanger = (); + type PalletInstancesInfo = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; + type SafeCallFilter = Everything; + type Aliasers = Nothing; +} + +pub type LocalOriginToLocation = SignedToAccountId32; + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parent.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 = (); + type TrustedLockers = (); + type SovereignAccountOf = (); + type MaxLockers = ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type AdminOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; +} + +parameter_types! { + pub const FirstMessageFactorPercent: u64 = 100; +} + +parameter_types! { + pub const ParasUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); +} + +/// A very dumb implementation of `EstimateNextSessionRotation`. At the moment of writing, this +/// is more to satisfy type requirements rather than to test anything. +pub struct TestNextSessionRotation; + +impl frame_support::traits::EstimateNextSessionRotation for TestNextSessionRotation { + fn average_session_length() -> u32 { + 10 + } + + fn estimate_current_session_progress(_now: u32) -> (Option, Weight) { + (None, Weight::zero()) + } + + fn estimate_next_session_rotation(_now: u32) -> (Option, Weight) { + (None, Weight::zero()) + } +} + +impl paras::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = paras::TestWeightInfo; + type UnsignedPriority = ParasUnsignedPriority; + type NextSessionRotation = TestNextSessionRotation; + type QueueFootprinter = (); + type OnNewHead = (); +} + +impl dmp::Config for Runtime {} + +impl hrmp::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type WeightInfo = TestHrmpWeightInfo; + type ChannelManager = frame_system::EnsureRoot; +} + +impl frame_system::offchain::SendTransactionTypes for Runtime +where + RuntimeCall: From, +{ + type Extrinsic = UncheckedExtrinsic; + type OverarchingCall = RuntimeCall; +} + +impl origin::Config for Runtime {} + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlockU32; + +parameter_types! { + pub MessageQueueServiceWeight: Weight = Weight::from_parts(1_000_000_000, 1_000_000); + pub const MessageQueueHeapSize: u32 = 65_536; + pub const MessageQueueMaxStale: u32 = 16; +} + +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, + }; + ProcessXcmMessage::, 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 WeightInfo = (); + type QueuePausedQuery = (); +} + +construct_runtime!( + pub enum Runtime { + System: frame_system, + Balances: pallet_balances, + ParasOrigin: origin, + MessageQueue: pallet_message_queue, + XcmPallet: pallet_xcm, + Utility: pallet_utility, + Hrmp: hrmp, + Dmp: dmp, + Paras: paras, + Configuration: configuration, + } +); + +pub(crate) fn relay_events() -> Vec { + System::events() + .into_iter() + .map(|r| r.event) + .filter_map(|e| Some(e)) + .collect::>() +} + +use frame_support::traits::{OnFinalize, OnInitialize}; +pub(crate) fn relay_roll_to(n: BlockNumber) { + while System::block_number() < n { + XcmPallet::on_finalize(System::block_number()); + Balances::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Balances::on_initialize(System::block_number()); + XcmPallet::on_initialize(System::block_number()); + } +} + +/// A weight info that is only suitable for testing. +pub struct TestHrmpWeightInfo; + +impl hrmp::WeightInfo for TestHrmpWeightInfo { + fn hrmp_accept_open_channel() -> Weight { + Weight::from_parts(1, 0) + } + fn force_clean_hrmp(_: u32, _: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn force_process_hrmp_close(_: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn force_process_hrmp_open(_: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn hrmp_cancel_open_request(_: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn hrmp_close_channel() -> Weight { + Weight::from_parts(1, 0) + } + fn hrmp_init_open_channel() -> Weight { + Weight::from_parts(1, 0) + } + fn clean_open_channel_requests(_: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn force_open_hrmp_channel(_: u32) -> Weight { + Weight::from_parts(1, 0) + } +} diff --git a/tracing/2601/runtime/moonbeam/tests/xcm_mock/statemint_like.rs b/tracing/2601/runtime/moonbeam/tests/xcm_mock/statemint_like.rs new file mode 100644 index 00000000..8fb27ffb --- /dev/null +++ b/tracing/2601/runtime/moonbeam/tests/xcm_mock/statemint_like.rs @@ -0,0 +1,551 @@ +// Copyright 2021 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, match_types, parameter_types, + traits::{AsEnsureOriginWithArg, Everything, Nothing}, + weights::Weight, +}; +use frame_system::{EnsureRoot, EnsureSigned}; + +use sp_core::H256; +use sp_runtime::{ + traits::{ConstU32, Hash, IdentityLookup}, + AccountId32, +}; + +use polkadot_core_primitives::BlockNumber as RelayBlockNumber; + +use polkadot_parachain::primitives::Id as ParaId; +use polkadot_parachain::primitives::Sibling; +use sp_std::convert::TryFrom; +use xcm::latest::prelude::*; +use xcm::VersionedXcm; +use xcm_builder::{ + AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, AsPrefixedGeneralIndex, + ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, + FungiblesAdapter, IsConcrete, NoChecking, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, +}; +use xcm_executor::{traits::JustTry, Config, XcmExecutor}; +use xcm_simulator::{ + DmpMessageHandlerT as DmpMessageHandler, XcmpMessageFormat, + XcmpMessageHandlerT as XcmpMessageHandler, +}; +pub type AccountId = AccountId32; +pub type Balance = u128; +pub type AssetId = u128; + +parameter_types! { + pub const BlockHashCount: u32 = 250; +} + +impl frame_system::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Block = Block; + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + 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 = frame_support::traits::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 = (); + type FreezeIdentifier = (); + type MaxHolds = (); + type MaxFreezes = (); +} + +// Required for runtime benchmarks +pallet_assets::runtime_benchmarks_enabled! { + pub struct BenchmarkHelper; + impl pallet_assets::BenchmarkHelper for BenchmarkHelper + where + AssetIdParameter: From, + { + fn create_asset_id_parameter(id: u32) -> AssetIdParameter { + (id as u128).into() + } + } +} + +parameter_types! { + pub const AssetDeposit: Balance = 0; // 1 UNIT deposit to create asset + pub const ApprovalDeposit: Balance = 0; + pub const AssetsStringLimit: u32 = 50; + /// Key = 32 bytes, Value = 36 bytes (32+1+1+1+1) + // https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271 + pub const MetadataDepositBase: Balance = 0; + pub const MetadataDepositPerByte: Balance = 0; + pub const ExecutiveBody: BodyId = BodyId::Executive; + pub const AssetAccountDeposit: Balance = 0; +} + +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = AssetAccountDeposit; + type WeightInfo = (); + type RemoveItemsLimit = ConstU32<656>; + type AssetIdParameter = AssetId; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +parameter_types! { + pub const KsmLocation: MultiLocation = MultiLocation::parent(); + pub const RelayNetwork: NetworkId = NetworkId::Kusama; + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + pub UniversalLocation: InteriorMultiLocation = + X2(GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())); + pub Local: MultiLocation = Here.into(); + pub CheckingAccount: AccountId = PolkadotXcm::check_account(); + pub KsmPerSecond: (xcm::latest::prelude::AssetId, u128, u128) = + (Concrete(KsmLocation::get()), 1, 1); +} + +/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used +/// when determining ownership of accounts for asset transacting and when attempting to use XCM +/// `Transact` in order to determine the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the default `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // Straight up local `AccountId32` origins just alias directly to `AccountId`. + AccountId32Aliases, +); + +/// Means for transacting the native currency on this chain. +pub type CurrencyTransactor = CurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching the given location or name: + IsConcrete, + // Convert an XCM MultiLocation into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We don't track any teleports of `Balances`. + (), +>; + +/// Means for transacting assets besides the native currency on this chain. +pub type FungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + Assets, + // Use this currency when it is a fungible asset matching the given location or name: + ConvertedConcreteId< + AssetId, + Balance, + AsPrefixedGeneralIndex, + JustTry, + >, + // Convert an XCM MultiLocation into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We only want to allow teleports of known assets. We use non-zero issuance as an indication + // that this asset is known. + NoChecking, + // The account to use for tracking teleports. + CheckingAccount, +>; +/// Means for transacting assets on this chain. +pub type AssetTransactors = (CurrencyTransactor, FungiblesTransactor); + +/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, +/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can +/// biases the kind of local `Origin` it will become. +pub type XcmOriginToTransactDispatchOrigin = ( + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when + // recognised. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognised. + SiblingParachainAsNative, + // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a + // transaction from the Root origin. + ParentAsSuperuser, + // Native signed account converter; this just converts an `AccountId32` origin into a normal + // `RuntimeOrigin::signed` origin of the same 32-byte value. + SignedAccountId32AsNative, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + pallet_xcm::XcmPassthrough, +); + +parameter_types! { + // One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate. + pub UnitWeightCost: Weight = Weight::from_parts(100u64, 100u64); + pub const MaxInstructions: u32 = 100; +} + +match_types! { + pub type ParentOrParentsExecutivePlurality: impl Contains = { + MultiLocation { parents: 1, interior: Here } | + MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Executive, .. }) } + }; +} +match_types! { + pub type ParentOrSiblings: impl Contains = { + MultiLocation { parents: 1, interior: Here } | + MultiLocation { parents: 1, interior: X1(_) } + }; +} + +pub type Barrier = ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + // Parent and its exec plurality get free execution + AllowUnpaidExecutionFrom, + // Expected responses are OK. + AllowKnownQueryResponses, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, +); + +parameter_types! { + pub MatcherLocation: MultiLocation = MultiLocation::here(); + pub const MaxAssetsIntoHolding: u32 = 64; +} + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = AssetTransactors; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type IsReserve = + orml_xcm_support::MultiNativeAsset; + type IsTeleporter = (); + type UniversalLocation = UniversalLocation; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = FixedRateOfFungible; + type ResponseHandler = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type SubscriptionService = PolkadotXcm; + type CallDispatcher = RuntimeCall; + type AssetLocker = (); + type AssetExchanger = (); + type PalletInstancesInfo = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; + type SafeCallFilter = Everything; + type Aliasers = Nothing; +} + +/// No local origins on this chain are allowed to dispatch XCM sends/executions. +pub type LocalOriginToLocation = SignedToAccountId32; + +pub type XcmRouter = super::ParachainXcmRouter; + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parent.into()); +} + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = 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 = (); + type MaxLockers = ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type AdminOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +#[frame_support::pallet] +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] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn parachain_id)] + pub(super) type ParachainId = StorageValue<_, ParaId, 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 (result, event) = match Xcm::::try_from(xcm) { + Ok(xcm) => { + let location = MultiLocation::new(1, Junctions::X1(Parachain(sender.into()))); + let mut id = [0u8; 32]; + id.copy_from_slice(hash.as_ref()); + match T::XcmExecutor::execute_xcm(location, xcm, id, max_weight) { + Outcome::Error(e) => (Err(e.clone()), 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 (_i, (_sent_at, data)) in iter.enumerate() { + let id = sp_io::hashing::blake2_256(&data[..]); + let maybe_msg = VersionedXcm::::decode(&mut &data[..]) + .map(Xcm::::try_from); + match maybe_msg { + Err(_) => { + Self::deposit_event(Event::InvalidFormat(id)); + } + Ok(Err(())) => { + Self::deposit_event(Event::UnsupportedVersion(id)); + } + Ok(Ok(x)) => { + let outcome = T::XcmExecutor::execute_xcm(Parent, x, id, limit); + Self::deposit_event(Event::ExecutedDownward(id, outcome)); + } + } + } + limit + } + } +} +impl mock_msg_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +// Pallet to cover test cases for change https://github.com/paritytech/cumulus/pull/831 +#[frame_support::pallet] +pub mod mock_statemint_prefix { + use super::*; + use frame_support::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + } + + #[pallet::call] + impl Pallet {} + + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn current_prefix)] + pub(super) type CurrentPrefix = StorageValue<_, MultiLocation, ValueQuery>; + + impl Get for Pallet { + fn get() -> MultiLocation { + Self::current_prefix() + } + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + // Changed Prefix + PrefixChanged(MultiLocation), + } + + impl Pallet { + pub fn set_prefix(prefix: MultiLocation) { + CurrentPrefix::::put(&prefix); + Self::deposit_event(Event::PrefixChanged(prefix)); + } + } +} + +impl mock_statemint_prefix::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} + +type Block = frame_system::mocking::MockBlockU32; +construct_runtime!( + pub enum Runtime { + System: frame_system, + Balances: pallet_balances, + PolkadotXcm: pallet_xcm, + CumulusXcm: cumulus_pallet_xcm, + MsgQueue: mock_msg_queue, + Assets: pallet_assets, + PrefixChanger: mock_statemint_prefix, + + } +); diff --git a/tracing/2601/runtime/moonbeam/tests/xcm_tests.rs b/tracing/2601/runtime/moonbeam/tests/xcm_tests.rs new file mode 100644 index 00000000..0ea1d5ec --- /dev/null +++ b/tracing/2601/runtime/moonbeam/tests/xcm_tests.rs @@ -0,0 +1,3786 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Moonbeam Runtime Xcm Tests + +mod xcm_mock; + +use cumulus_primitives_core::relay_chain::HrmpChannelId; +use frame_support::{ + assert_ok, + traits::{PalletInfo, PalletInfoAccess}, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, + BoundedVec, +}; +use pallet_asset_manager::LocalAssetIdCreator; +use pallet_xcm_transactor::{ + Currency, CurrencyPayment, HrmpInitParams, HrmpOperation, TransactWeights, +}; +use sp_core::ConstU32; +use xcm::latest::prelude::*; +use xcm::{VersionedMultiLocation, WrapVersion}; +use xcm_builder::HashedDescriptionDescribeFamilyAllTerminal; +use xcm_executor::traits::ConvertLocation; +use xcm_mock::parachain; +use xcm_mock::relay_chain; +use xcm_mock::*; +use xcm_primitives::{UtilityEncodeCall, DEFAULT_PROOF_SIZE}; +use xcm_simulator::TestExt; + +// Send a relay asset (like DOT) to a parachain A +#[test] +fn receive_relay_asset_from_relay() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + // Register relay asset in paraA + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + // First send relay chain asset to Parachain + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // Verify that parachain received the asset + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 123); + }); +} + +// Send relay asset (like DOT) back from Parachain A to relaychain +#[test] +fn send_relay_asset_to_relay() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + // Register relay asset in paraA + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + // Free execution + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + let dest: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + // First send relay chain asset to Parachain like in previous test + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // Free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 123); + }); + + // Lets gather the balance before sending back money + let mut balance_before_sending = 0; + Relay::execute_with(|| { + balance_before_sending = RelayBalances::free_balance(&RELAYALICE); + }); + + // We now send back some money to the relay + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: RELAYALICE.into(), + }), + }; + + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 123, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // The balances in paraAlice should have been substracted + ParaA::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 0); + }); + + // Balances in the relay should have been received + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(&RELAYALICE) > balance_before_sending); + }); +} + +#[test] +fn send_relay_asset_to_para_b() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + // Register asset in paraA. Free execution + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata.clone(), + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location.clone(), + 0u128, + 0 + )); + }); + + // Register asset in paraB. Free execution + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + let dest: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 123); + }); + + // Now send relay asset from para A to para B + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // Para A balances should have been substracted + ParaA::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 23); + }); + + // Para B balances should have been credited + ParaB::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); +} + +#[test] +fn send_para_a_asset_to_para_b() { + MockNet::reset(); + + // This represents the asset in paraA + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + // Register asset in paraB. Free execution + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Send para A asset from para A to para B + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + // Native token is substracted in paraA + ParaA::execute_with(|| { + // Free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(800000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + // Asset is minted in paraB + ParaB::execute_with(|| { + // Free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); +} + +#[test] +fn send_para_a_asset_from_para_b_to_para_c() { + MockNet::reset(); + + // Represents para A asset + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + // Register para A asset in parachain B. Free execution + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata.clone(), + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location.clone(), + 0u128, + 0 + )); + }); + + // Register para A asset in parachain C. Free execution + ParaC::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // Para A balances have been substracted + ParaA::execute_with(|| { + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + // Para B balances have been credited + ParaB::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); + + // Send para A asset from para B to para C + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(3), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaB::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // The message passed through parachainA so we needed to pay since its the native token + ParaC::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 96); + }); +} + +#[test] +fn send_para_a_asset_to_para_b_and_back_to_para_a() { + MockNet::reset(); + + // para A asset + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + // Register para A asset in para B + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Send para A asset to para B + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // Balances have been substracted + ParaA::execute_with(|| { + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + // Para B balances have been credited + ParaB::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); + + // Send back para A asset to para A + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(1), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + ParaB::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // Weight used is 4 + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 4 + ); + }); +} + +#[test] +fn receive_relay_asset_with_trader() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + // This time we are gonna put a rather high number of units per second + // we know later we will divide by 1e12 + // Lets put 1e6 as units per second + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 2500000000000u128, + 0 + )); + }); + + let dest: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + // We are sending 100 tokens from relay. + // Amount spent in fees is Units per second * weight / 1_000_000_000_000 (weight per second) + // weight is 4 since we are executing 4 instructions with a unitweightcost of 1. + // Units per second should be 2_500_000_000_000_000 + // Therefore with no refund, we should receive 10 tokens less + // Native trader fails for this, and we use the asset trader + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 100).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // non-free execution, not full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 90); + // Fee should have been received by treasury + assert_eq!(Assets::balance(source_id, &Treasury::account_id()), 10); + }); +} + +#[test] +fn send_para_a_asset_to_para_b_with_trader() { + MockNet::reset(); + + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 2500000000000u128, + 0 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + // In destination chain, we only need 4 weight + // We put 10 weight, 6 of which should be refunded and 4 of which should go to treasury + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(10u64, DEFAULT_PROOF_SIZE)) + )); + }); + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + // We are sending 100 tokens from para A. + // Amount spent in fees is Units per second * weight / 1_000_000_000_000 (weight per second) + // weight is 4 since we are executing 4 instructions with a unitweightcost of 1. + // Units per second should be 2_500_000_000_000_000 + // Since we set 10 weight in destination chain, 25 will be charged upfront + // 15 of those will be refunded, while 10 will go to treasury as the true weight used + // will be 4 + ParaB::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 90); + // Fee should have been received by treasury + assert_eq!(Assets::balance(source_id, &Treasury::account_id()), 10); + }); +} + +#[test] +fn send_para_a_asset_to_para_b_with_trader_and_fee() { + MockNet::reset(); + + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + // With these units per second, 80K weight convrets to 1 asset unit + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 12500000u128, + 0 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + // we use transfer_with_fee + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer_with_fee( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + 1, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(800000u64, DEFAULT_PROOF_SIZE)) + )); + }); + ParaA::execute_with(|| { + // 100 tokens transferred plus 1 taken from fees + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 - 1 + ); + }); + + ParaB::execute_with(|| { + // free execution, full amount received because trully the xcm instruction does not cost + // what it is specified + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 101); + }); +} + +#[test] +fn error_when_not_paying_enough() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + let dest: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + // This time we are gonna put a rather high number of units per second + // we know later we will divide by 1e12 + // Lets put 1e6 as units per second + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 2500000000000u128, + 0 + )); + }); + + // We are sending 100 tokens from relay. + // If we set the dest weight to be 1e7, we know the buy_execution will spend 1e7*1e6/1e12 = 10 + // Therefore with no refund, we should receive 10 tokens less + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 5).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // amount not received as it is not paying enough + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 0); + }); +} + +#[test] +fn transact_through_derivative_multilocation() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + // Relay charges 1000 for every instruction, and we have 3, so 3000 + 3000.into(), + 20000000000.into(), + None + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + WEIGHT_REF_TIME_PER_SECOND as u128, + )); + }); + + // Let's construct the call to know how much weight it is going to require + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + // 4000000000 transact + 3000 correspond to 4000003000 tokens. 100 more for the transfer call + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000003100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000003000); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_derivative( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::MockTransactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: None + }, + encoded, + // 400000000 + 3000 we should have taken out 4000003000 tokens from the caller + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(®istered_address) == 0); + }); +} + +#[test] +fn transact_through_derivative_with_custom_fee_weight() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + }); + + // Let's construct the call to know how much weight it is going to require + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + // 4000000000 transact + 3000 correspond to 4000003000 tokens. 100 more for the transfer call + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000003100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000003000); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let overall_weight = 4000003000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_derivative( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::MockTransactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + // 1-1 fee weight mapping + fee_amount: Some(overall_weight as u128) + }, + // 4000000000 + 3000 we should have taken out 4000003000 tokens from the caller + encoded, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(overall_weight.into()) + }, + false + )); + let event_found: Option = parachain::para_events() + .iter() + .find_map(|event| match event.clone() { + parachain::RuntimeEvent::PolkadotXcm(pallet_xcm::Event::AssetsTrapped { + .. + }) => Some(event.clone()), + _ => None, + }); + // Assert that the events do not contain the assets being trapped + assert!(event_found.is_none()); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(®istered_address) == 0); + }); +} + +#[test] +fn transact_through_derivative_with_custom_fee_weight_refund() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + }); + + // Let's construct the call to know how much weight it is going to require + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + // 4000000000 transact + 9000 correspond to 4000009000 tokens. 100 more for the transfer call + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000009100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000009100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000009000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000009000); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let overall_weight = 4000009000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_derivative( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::MockTransactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + // 1-1 fee weight mapping + fee_amount: Some(overall_weight as u128) + }, + encoded, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(overall_weight.into()) + }, + true + )); + let event_found: Option = parachain::para_events() + .iter() + .find_map(|event| match event.clone() { + parachain::RuntimeEvent::PolkadotXcm(pallet_xcm::Event::AssetsTrapped { + .. + }) => Some(event.clone()), + _ => None, + }); + // Assert that the events do not contain the assets being trapped + assert!(event_found.is_none()); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + // 4000005186 refunded + 100 transferred = 4000005286 + assert_eq!(RelayBalances::free_balance(¶_a_account()), 4000005286); + assert_eq!(RelayBalances::free_balance(®istered_address), 0); + }); +} + +#[test] +fn transact_through_sovereign() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + // Relay charges 1000 for every instruction, and we have 3, so 3000 + 3000.into(), + 20000000000.into(), + None + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + WEIGHT_REF_TIME_PER_SECOND as u128, + )); + }); + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000003100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000003000); + 0 + }); + + // We send the xcm transact operation to parent + let dest = MultiLocation { + parents: 1, + interior: Here, + }; + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let utility_bytes = parachain::MockTransactors::Relay.encode_call( + xcm_primitives::UtilityAvailableCalls::AsDerivative(0, encoded), + ); + + // Root can directly pass the execution byes to the sovereign + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_sovereign( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(dest)), + PARAALICE.into(), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: None + }, + utility_bytes, + OriginKind::SovereignAccount, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(®istered_address) == 0); + }); +} + +#[test] +fn transact_through_sovereign_with_custom_fee_weight() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + }); + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000003100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000003000); + 0 + }); + + // We send the xcm transact operation to parent + let dest = MultiLocation { + parents: 1, + interior: Here, + }; + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let utility_bytes = parachain::MockTransactors::Relay.encode_call( + xcm_primitives::UtilityAvailableCalls::AsDerivative(0, encoded), + ); + + let total_weight = 4000003000u64; + // Root can directly pass the execution byes to the sovereign + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_sovereign( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(dest)), + PARAALICE.into(), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + // 1-1 fee-weight mapping + fee_amount: Some(total_weight as u128) + }, + utility_bytes, + OriginKind::SovereignAccount, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(total_weight.into()) + }, + false + )); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(®istered_address) == 0); + }); +} + +#[test] +fn transact_through_sovereign_with_custom_fee_weight_refund() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + }); + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000009100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000009100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000009000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000009000); + 0 + }); + + // We send the xcm transact operation to parent + let dest = MultiLocation { + parents: 1, + interior: Here, + }; + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let utility_bytes = parachain::MockTransactors::Relay.encode_call( + xcm_primitives::UtilityAvailableCalls::AsDerivative(0, encoded), + ); + + let total_weight = 4000009000u64; + // Root can directly pass the execution byes to the sovereign + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_sovereign( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(dest)), + PARAALICE.into(), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + // 1-1 fee-weight mapping + fee_amount: Some(total_weight as u128) + }, + utility_bytes, + OriginKind::SovereignAccount, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(total_weight.into()) + }, + true + )); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + // 4000005186 refunded + 100 transferred = 4000005286 + assert_eq!(RelayBalances::free_balance(¶_a_account()), 4000005286); + + assert_eq!(RelayBalances::free_balance(®istered_address), 0); + }); +} + +#[test] +fn test_automatic_versioning_on_runtime_upgrade_with_relay() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A and set XCM version to 1 + ParaA::execute_with(|| { + parachain::XcmVersioner::set_version(1); + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + let response = Response::Version(2); + let querier: MultiLocation = Here.into(); + + // This is irrelevant, nothing will be done with this message, + // but we need to pass a message as an argument to trigger the storage change + let mock_message: Xcm<()> = Xcm(vec![QueryResponse { + query_id: 0, + response, + max_weight: Weight::zero(), + querier: Some(querier), + }]); + // The router is mocked, and we cannot use WrapVersion in ChildParachainRouter. So we will force + // it directly here + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + Relay::execute_with(|| { + // This sets the default version, for not known destinations + assert_ok!(RelayChainPalletXcm::force_default_xcm_version( + relay_chain::RuntimeOrigin::root(), + Some(2) + )); + + // Wrap version, which sets VersionedStorage + // This is necessary because the mock router does not use wrap_version, but + // this is not necessary in prod + assert_ok!(::wrap_version( + &Parachain(1).into(), + mock_message + )); + + // Transfer assets. Since it is an unknown destination, it will query for version + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + + // Let's advance the relay. This should trigger the subscription message + relay_chain::relay_roll_to(2); + + // queries should have been updated + assert!(RelayChainPalletXcm::query(0).is_some()); + }); + + let expected_supported_version: relay_chain::RuntimeEvent = + pallet_xcm::Event::SupportedVersionChanged { + location: MultiLocation { + parents: 0, + interior: X1(Parachain(1)), + }, + version: 1, + } + .into(); + + Relay::execute_with(|| { + // Assert that the events vector contains the version change + assert!(relay_chain::relay_events().contains(&expected_supported_version)); + }); + + // ParaA changes version to 2, and calls on_runtime_upgrade. This should notify the targets + // of the new version change + ParaA::execute_with(|| { + // Set version + parachain::XcmVersioner::set_version(2); + // Do runtime upgrade + parachain::on_runtime_upgrade(); + // Initialize block, to call on_initialize and notify targets + parachain::para_roll_to(2); + // Expect the event in the parachain + assert!(parachain::para_events().iter().any(|e| matches!( + e, + parachain::RuntimeEvent::PolkadotXcm(pallet_xcm::Event::VersionChangeNotified { + result: 2, + .. + }) + ))); + }); + + // This event should have been seen in the relay + let expected_supported_version_2: relay_chain::RuntimeEvent = + pallet_xcm::Event::SupportedVersionChanged { + location: MultiLocation { + parents: 0, + interior: X1(Parachain(1)), + }, + version: 2, + } + .into(); + + Relay::execute_with(|| { + // Assert that the events vector contains the new version change + assert!(relay_chain::relay_events().contains(&expected_supported_version_2)); + }); +} + +#[test] +fn receive_asset_with_no_sufficients_not_possible_if_non_existent_account() { + MockNet::reset(); + + let fresh_account = [2u8; 20]; + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + false + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: fresh_account, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest.clone()).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // parachain should not have received assets + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &fresh_account.into()), 0); + }); + + // Send native token to fresh_account + ParaA::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + fresh_account.into(), + 100 + )); + }); + + // Re-send tokens + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // parachain should have received assets + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &fresh_account.into()), 123); + }); +} + +#[test] +fn receive_assets_with_sufficients_true_allows_non_funded_account_to_receive_assets() { + MockNet::reset(); + + let fresh_account = [2u8; 20]; + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: fresh_account, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest.clone()).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // parachain should have received assets + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &fresh_account.into()), 123); + }); +} + +#[test] +fn evm_account_receiving_assets_should_handle_sufficients_ref_count() { + MockNet::reset(); + + let mut sufficient_account = [0u8; 20]; + sufficient_account[0..20].copy_from_slice(&evm_account()[..]); + + let evm_account_id = parachain::AccountId::from(sufficient_account); + + // Evm account is self sufficient + ParaA::execute_with(|| { + assert_eq!(parachain::System::account(evm_account_id).sufficients, 1); + }); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: sufficient_account, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest.clone()).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // Evm account sufficient ref count increased by 1. + ParaA::execute_with(|| { + // TODO: since the suicided logic was introduced an smart contract account + // is not deleted completely until it's data is deleted. Data deletion + // will be implemented in a future release + // assert_eq!(parachain::System::account(evm_account_id).sufficients, 2); + }); + + ParaA::execute_with(|| { + // Remove the account from the evm context. + parachain::EVM::remove_account(&evm_account()); + // Evm account sufficient ref count decreased by 1. + // TODO: since the suicided logic was introduced an smart contract account + // is not deleted completely until it's data is deleted. Data deletion + // will be implemented in a future release + // assert_eq!(parachain::System::account(evm_account_id).sufficients, 1); + }); +} + +#[test] +fn empty_account_should_not_be_reset() { + MockNet::reset(); + + // Test account has nonce 1 on genesis. + let mut sufficient_account = [0u8; 20]; + sufficient_account[0..20].copy_from_slice(&evm_account()[..]); + + let evm_account_id = parachain::AccountId::from(sufficient_account); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + false + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Send native token to evm_account + ParaA::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + evm_account_id, + 100 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: sufficient_account, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest.clone()).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // Empty the assets from the account. + // As this makes the account go below the `min_balance`, the account is considered dead + // at eyes of pallet-assets, and the consumer reference is decreased by 1 and is now Zero. + assert_ok!(parachain::Assets::transfer( + parachain::RuntimeOrigin::signed(evm_account_id), + source_id, + PARAALICE.into(), + 123 + )); + // Verify account asset balance is Zero. + assert_eq!( + parachain::Assets::balance(source_id, &evm_account_id.into()), + 0 + ); + // Because we no longer have consumer references, we can set the balance to Zero. + // This would reset the account if our ED were to be > than Zero. + assert_ok!(ParaBalances::force_set_balance( + parachain::RuntimeOrigin::root(), + evm_account_id, + 0, + )); + // Verify account native balance is Zero. + assert_eq!(ParaBalances::free_balance(&evm_account_id), 0); + // Remove the account from the evm context. + // This decreases the sufficients reference by 1 and now is Zero. + parachain::EVM::remove_account(&evm_account()); + // Verify reference count. + let account = parachain::System::account(evm_account_id); + // TODO: since the suicided logic was introduced an smart contract account + // is not deleted completely until it's data is deleted. Data deletion + // will be implemented in a future release + // account.sufficients shall be 0 + assert_eq!(account.sufficients, 1); + assert_eq!(account.consumers, 0); + assert_eq!(account.providers, 1); + // We expect the account to be alive in a Zero ED context. + // TODO: since the suicided logic was introduced an smart contract account + // is not deleted completely until it's data is deleted. Data deletion + // will be implemented in a future release + // this shall be changed to 1 + assert_eq!(parachain::System::account_nonce(evm_account_id), 2); + }); +} + +#[test] +fn test_statemint_like() { + MockNet::reset(); + + let dest_para = MultiLocation::new(1, X1(Parachain(1))); + + let sov = xcm_builder::SiblingParachainConvertsVia::< + polkadot_parachain::primitives::Sibling, + statemint_like::AccountId, + >::convert_location(&dest_para) + .unwrap(); + + let statemint_asset_a_balances = MultiLocation::new( + 1, + X3( + Parachain(4), + PalletInstance(5), + xcm::latest::prelude::GeneralIndex(0u128), + ), + ); + let source_location = parachain::AssetType::Xcm(statemint_asset_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"StatemintToken".to_vec(), + symbol: b"StatemintToken".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata.clone(), + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + Statemint::execute_with(|| { + // Set new prefix + statemint_like::PrefixChanger::set_prefix( + PalletInstance(::index() as u8).into(), + ); + + assert_ok!(StatemintAssets::create( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + 0, + RELAYALICE, + 1 + )); + + assert_ok!(StatemintAssets::mint( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + 0, + RELAYALICE, + 300000000000000 + )); + + // This is needed, since the asset is created as non-sufficient + assert_ok!(StatemintBalances::transfer( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + sov, + 100000000000000 + )); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + // Send with new prefix + assert_ok!(StatemintChainPalletXcm::reserve_transfer_assets( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + Box::new(MultiLocation::new(1, X1(Parachain(1))).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new( + ( + X2( + xcm::latest::prelude::PalletInstance( + ::index() as u8 + ), + xcm::latest::prelude::GeneralIndex(0), + ), + 123 + ) + .into() + ), + 0, + )); + }); + + ParaA::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 123); + }); +} + +#[test] +fn send_para_a_local_asset_to_para_b() { + MockNet::reset(); + + let asset_id = parachain::LocalAssetIdCreator::create_asset_id_from_metadata(0); + let para_a_local_asset = MultiLocation::new( + 1, + X3(Parachain(1), PalletInstance(11u8), GeneralIndex(asset_id)), + ); + let source_location = parachain::AssetType::Xcm(para_a_local_asset); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaALocalAsset".to_vec(), + symbol: b"ParaALocalAsset".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_local_asset( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + PARAALICE.into(), + true, + 1 + )); + + assert_ok!(LocalAssets::mint( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + asset_id, + PARAALICE.into(), + 300000000000000 + )); + }); + + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::LocalAssetReserve(asset_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(800000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaB::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); +} + +#[test] +fn send_para_a_local_asset_to_para_b_and_send_it_back_together_with_some_glmr() { + MockNet::reset(); + + let asset_id = parachain::LocalAssetIdCreator::create_asset_id_from_metadata(0); + let para_a_local_asset = MultiLocation::new( + 1, + X3(Parachain(1), PalletInstance(11u8), GeneralIndex(asset_id)), + ); + let source_location_local_asset = parachain::AssetType::Xcm(para_a_local_asset); + let source_id_local_asset: parachain::AssetId = source_location_local_asset.clone().into(); + + let asset_metadata_local_asset = parachain::AssetMetadata { + name: b"ParaALocalAsset".to_vec(), + symbol: b"ParaALocalAsset".to_vec(), + decimals: 12, + }; + + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location_balances = parachain::AssetType::Xcm(para_a_balances); + let source_id_balances: parachain::AssetId = source_location_balances.clone().into(); + + let asset_metadata_balances = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location_local_asset.clone(), + asset_metadata_local_asset, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location_local_asset, + 0u128, + 0 + )); + + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location_balances.clone(), + asset_metadata_balances, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location_balances, + 0u128, + 1 + )); + }); + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_local_asset( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + PARAALICE.into(), + true, + 1 + )); + + assert_ok!(LocalAssets::mint( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + asset_id, + PARAALICE.into(), + 300000000000000 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer_multicurrencies( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + vec![ + (parachain::CurrencyId::LocalAssetReserve(asset_id), 100), + (parachain::CurrencyId::SelfReserve, 1000000) + ], + 0, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(800000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + let mut alith_balance_asset_before = 0; + let mut alith_balance_native_token_before = 0; + + ParaA::execute_with(|| { + alith_balance_asset_before = LocalAssets::balance(asset_id, &PARAALICE.into()); + alith_balance_native_token_before = ParaBalances::free_balance(&PARAALICE.into()); + }); + + let new_dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(1), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaB::execute_with(|| { + // free execution, full amount received + assert_eq!( + Assets::balance(source_id_local_asset, &PARAALICE.into()), + 100 + ); + assert_eq!( + Assets::balance(source_id_balances, &PARAALICE.into()), + 1000000 + ); + + // free execution, full amount received + assert_ok!(XTokens::transfer_multicurrencies( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + vec![ + (parachain::CurrencyId::ForeignAsset(source_id_balances), 4), + ( + parachain::CurrencyId::ForeignAsset(source_id_local_asset), + 50 + ) + ], + 0, + Box::new(VersionedMultiLocation::V3(new_dest)), + WeightLimit::Limited(4.into()) + )); + }); + + ParaA::execute_with(|| { + let alith_balance_asset_after = LocalAssets::balance(asset_id, &PARAALICE.into()); + let alith_balance_native_token_after = ParaBalances::free_balance(&PARAALICE.into()); + assert_eq!(alith_balance_asset_after, alith_balance_asset_before + 50); + assert_eq!( + alith_balance_native_token_before, + alith_balance_native_token_after + ); + }); +} + +#[test] +fn send_statemint_asset_from_para_a_to_statemint_with_relay_fee() { + MockNet::reset(); + + // Relay asset + let relay_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_relay_id: parachain::AssetId = relay_location.clone().into(); + + let relay_asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + // Statemint asset + let statemint_asset = MultiLocation::new( + 1, + X3(Parachain(4u32), PalletInstance(5u8), GeneralIndex(10u128)), + ); + let statemint_location_asset = parachain::AssetType::Xcm(statemint_asset); + let source_statemint_asset_id: parachain::AssetId = statemint_location_asset.clone().into(); + + let asset_metadata_statemint_asset = parachain::AssetMetadata { + name: b"USDC".to_vec(), + symbol: b"USDC".to_vec(), + decimals: 12, + }; + + let dest_para = MultiLocation::new(1, X1(Parachain(1))); + + let sov = xcm_builder::SiblingParachainConvertsVia::< + polkadot_parachain::primitives::Sibling, + statemint_like::AccountId, + >::convert_location(&dest_para) + .unwrap(); + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + relay_location.clone(), + relay_asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + relay_location, + 0u128, + 0 + )); + + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + statemint_location_asset.clone(), + asset_metadata_statemint_asset, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + statemint_location_asset, + 0u128, + 1 + )); + }); + + let parachain_beneficiary_from_relay: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + // Send relay chain asset to Alice in Parachain A + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new( + VersionedMultiLocation::V3(parachain_beneficiary_from_relay) + .clone() + .into() + ), + Box::new((Here, 200).into()), + 0, + )); + }); + + Statemint::execute_with(|| { + // Set new prefix + statemint_like::PrefixChanger::set_prefix( + PalletInstance(::index() as u8).into(), + ); + + assert_ok!(StatemintAssets::create( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + 10, + RELAYALICE, + 1 + )); + + assert_ok!(StatemintAssets::mint( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + 10, + RELAYALICE, + 300000000000000 + )); + + // Send some native statemint tokens to sovereign for fees. + // We can't pay fees with USDC as the asset is minted as non-sufficient. + assert_ok!(StatemintBalances::transfer( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + sov, + 100000000000000 + )); + + // Send statemint USDC asset to Alice in Parachain A + let parachain_beneficiary_from_statemint: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + // Send with new prefix + assert_ok!(StatemintChainPalletXcm::reserve_transfer_assets( + statemint_like::RuntimeOrigin::signed(RELAYALICE), + Box::new(MultiLocation::new(1, X1(Parachain(1))).into()), + Box::new( + VersionedMultiLocation::V3(parachain_beneficiary_from_statemint) + .clone() + .into() + ), + Box::new( + ( + X2( + xcm::latest::prelude::PalletInstance( + ::index() as u8 + ), + GeneralIndex(10), + ), + 125 + ) + .into() + ), + 0, + )); + }); + + let statemint_beneficiary = MultiLocation { + parents: 1, + interior: X2( + Parachain(4), + AccountId32 { + network: None, + id: RELAYBOB.into(), + }, + ), + }; + + ParaA::execute_with(|| { + // Alice has received 125 USDC + assert_eq!( + Assets::balance(source_statemint_asset_id, &PARAALICE.into()), + 125 + ); + + // Alice has received 200 Relay assets + assert_eq!(Assets::balance(source_relay_id, &PARAALICE.into()), 200); + }); + + Statemint::execute_with(|| { + // Check that BOB's balance is empty before the transfer + assert_eq!(StatemintAssets::account_balances(RELAYBOB), vec![]); + }); + + // Transfer USDC from Parachain A to Statemint using Relay asset as fee + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer_multicurrencies( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + vec![ + ( + parachain::CurrencyId::ForeignAsset(source_statemint_asset_id), + 100 + ), + (parachain::CurrencyId::ForeignAsset(source_relay_id), 100) + ], + 1, + Box::new(VersionedMultiLocation::V3(statemint_beneficiary)), + WeightLimit::Limited(Weight::from_parts(80_000_000u64, 100_000u64)) + )); + }); + + ParaA::execute_with(|| { + // Alice has 100 USDC less + assert_eq!( + Assets::balance(source_statemint_asset_id, &PARAALICE.into()), + 25 + ); + + // Alice has 100 relay asset less + assert_eq!(Assets::balance(source_relay_id, &PARAALICE.into()), 100); + }); + + Statemint::execute_with(|| { + println!("STATEMINT EVENTS: {:?}", parachain::para_events()); + // Check that BOB received 100 USDC on statemint + assert_eq!(StatemintAssets::account_balances(RELAYBOB), vec![(10, 100)]); + }); +} + +#[test] +fn transact_through_signed_multilocation() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + // Relay charges 1000 for every instruction, and we have 3, so 3000 + 3000.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4000.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + WEIGHT_REF_TIME_PER_SECOND as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the relay will see instead of us + descend_origin_multilocation + .reanchor(&MultiLocation::parent(), ancestry.interior) + .unwrap(); + + let derived = xcm_builder::Account32Hash::< + relay_chain::KusamaNetwork, + relay_chain::AccountId, + >::convert_location(&descend_origin_multilocation) + .unwrap(); + + Relay::execute_with(|| { + // free execution, full amount received + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + derived.clone(), + 4000004100u128, + )); + // derived account has all funds + assert!(RelayBalances::free_balance(&derived) == 4000004100); + // sovereign account has 0 funds + assert!(RelayBalances::free_balance(¶_a_account()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: None + }, + encoded, + // 4000000000 for transfer + 4000 for XCM + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + Relay::execute_with(|| { + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(&derived) == 0); + }); +} + +#[test] +fn transact_through_signed_multilocation_custom_fee_and_weight() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + ParaA::execute_with(|| { + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the relay will see instead of us + descend_origin_multilocation + .reanchor(&MultiLocation::parent(), ancestry.interior) + .unwrap(); + + let derived = xcm_builder::Account32Hash::< + relay_chain::KusamaNetwork, + relay_chain::AccountId, + >::convert_location(&descend_origin_multilocation) + .unwrap(); + + Relay::execute_with(|| { + // free execution, full amount received + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + derived.clone(), + 4000004100u128, + )); + // derived account has all funds + assert!(RelayBalances::free_balance(&derived) == 4000004100); + // sovereign account has 0 funds + assert!(RelayBalances::free_balance(¶_a_account()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let total_weight = 4000004000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_weight as u128) + }, + encoded, + // 4000000000 for transfer + 4000 for XCM + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(total_weight.into()) + }, + false + )); + }); + + Relay::execute_with(|| { + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(&derived) == 0); + }); +} + +#[test] +fn transact_through_signed_multilocation_custom_fee_and_weight_refund() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + ParaA::execute_with(|| { + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the relay will see instead of us + descend_origin_multilocation + .reanchor(&MultiLocation::parent(), ancestry.interior) + .unwrap(); + + let derived = xcm_builder::Account32Hash::< + relay_chain::KusamaNetwork, + relay_chain::AccountId, + >::convert_location(&descend_origin_multilocation) + .unwrap(); + + Relay::execute_with(|| { + // free execution, full amount received + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + derived.clone(), + 4000009100u128, + )); + // derived account has all funds + assert!(RelayBalances::free_balance(&derived) == 4000009100); + // sovereign account has 0 funds + assert!(RelayBalances::free_balance(¶_a_account()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let total_weight = 4000009000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_weight as u128) + }, + encoded, + // 4000000000 for transfer + 9000 for XCM + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(total_weight.into()) + }, + true + )); + }); + + Relay::execute_with(|| { + // 100 transferred + assert_eq!(RelayBalances::free_balance(¶_a_account()), 100); + + // 4000005186 refunded + assert_eq!(RelayBalances::free_balance(&derived), 4000005186); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + // ParaB + Box::new(xcm::VersionedMultiLocation::V3(para_b_location.clone())), + // Para charges 1000 for every instruction, and we have 3, so 3 + 3.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + ParaB::execute_with(|| { + // free execution, full amount received + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000000104u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000000104); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account_20(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: None + }, + encoded, + // 4000000000 for transfer + 4000 for XCM + // 1-1 to fee + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + ParaB::execute_with(|| { + assert!(ParaBalances::free_balance(&derived) == 0); + + assert!(ParaBalances::free_balance(¶_a_account_20()) == 100); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para_refund() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + ParaB::execute_with(|| { + // free execution, full amount received + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000009100u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000009100); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account_20(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let overall_weight = 4000009000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: Some(overall_weight as u128) + }, + encoded, + // 4000000000 for transfer + 9000 for XCM + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(overall_weight.into()) + }, + true + )); + }); + + ParaB::execute_with(|| { + // Check the derived account was refunded + assert_eq!(ParaBalances::free_balance(&derived), 8993); + + // Check the transfer was executed + assert_eq!(ParaBalances::free_balance(¶_a_account_20()), 100); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para_ethereum() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + // ParaB + Box::new(xcm::VersionedMultiLocation::V3(para_b_location.clone())), + // Para charges 1000 for every instruction, and we have 3, so 3 + 3.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + let mut parachain_b_alice_balances_before = 0; + ParaB::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000000104u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000000104); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + + parachain_b_alice_balances_before = ParaBalances::free_balance(&PARAALICE.into()) + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + use sp_core::U256; + // Let's do a EVM transfer + let eth_tx = + xcm_primitives::EthereumXcmTransaction::V1(xcm_primitives::EthereumXcmTransactionV1 { + gas_limit: U256::from(21000), + fee_payment: xcm_primitives::EthereumXcmFee::Auto, + action: pallet_ethereum::TransactionAction::Call(PARAALICE.into()), + value: U256::from(100), + input: BoundedVec::< + u8, + ConstU32<{ xcm_primitives::MAX_ETHEREUM_XCM_INPUT_SIZE }> + >::try_from(vec![]).unwrap(), + access_list: None, + }); + + // Then call bytes + let mut call_bytes = pallet_ethereum_xcm::Call::::transact { + xcm_transaction: eth_tx, + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: None + }, + encoded, + // 4000000000 for transfer + 4000 for XCM + // 1-1 to fee + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + ParaB::execute_with(|| { + // Make sure the EVM transfer went through + assert!( + ParaBalances::free_balance(&PARAALICE.into()) + == parachain_b_alice_balances_before + 100 + ); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para_ethereum_no_proxy_fails() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + // ParaB + Box::new(xcm::VersionedMultiLocation::V3(para_b_location.clone())), + // Para charges 1000 for every instruction, and we have 3, so 3 + 3.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + let mut parachain_b_alice_balances_before = 0; + ParaB::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000000104u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000000104); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + + parachain_b_alice_balances_before = ParaBalances::free_balance(&PARAALICE.into()) + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + use sp_core::U256; + // Let's do a EVM transfer + let eth_tx = + xcm_primitives::EthereumXcmTransaction::V1(xcm_primitives::EthereumXcmTransactionV1 { + gas_limit: U256::from(21000), + fee_payment: xcm_primitives::EthereumXcmFee::Auto, + action: pallet_ethereum::TransactionAction::Call(PARAALICE.into()), + value: U256::from(100), + input: BoundedVec::< + u8, + ConstU32<{ xcm_primitives::MAX_ETHEREUM_XCM_INPUT_SIZE }> + >::try_from(vec![]).unwrap(), + access_list: None, + }); + + // Then call bytes + let mut call_bytes = pallet_ethereum_xcm::Call::::transact_through_proxy { + transact_as: PARAALICE.into(), + xcm_transaction: eth_tx, + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: None + }, + encoded, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + ParaB::execute_with(|| { + // Make sure the EVM transfer wasn't executed + assert!(ParaBalances::free_balance(&PARAALICE.into()) == parachain_b_alice_balances_before); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para_ethereum_proxy_succeeds() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + // ParaB + Box::new(xcm::VersionedMultiLocation::V3(para_b_location.clone())), + // Para charges 1000 for every instruction, and we have 3, so 3 + 3.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + let transfer_recipient = evm_account(); + let mut transfer_recipient_balance_before = 0; + ParaB::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000000104u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000000104); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + + transfer_recipient_balance_before = ParaBalances::free_balance(&transfer_recipient.into()); + + // Add proxy ALICE -> derived + let _ = parachain::Proxy::add_proxy_delegate( + &PARAALICE.into(), + derived, + parachain::ProxyType::Any, + 0, + ); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + use sp_core::U256; + // Let's do a EVM transfer + let eth_tx = + xcm_primitives::EthereumXcmTransaction::V2(xcm_primitives::EthereumXcmTransactionV2 { + gas_limit: U256::from(21000), + action: pallet_ethereum::TransactionAction::Call(transfer_recipient.into()), + value: U256::from(100), + input: BoundedVec::< + u8, + ConstU32<{ xcm_primitives::MAX_ETHEREUM_XCM_INPUT_SIZE }> + >::try_from(vec![]).unwrap(), + access_list: None, + }); + + // Then call bytes + let mut call_bytes = pallet_ethereum_xcm::Call::::transact_through_proxy { + transact_as: PARAALICE.into(), + xcm_transaction: eth_tx, + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: None + }, + encoded, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + ParaB::execute_with(|| { + // Make sure the EVM transfer was executed + assert!( + ParaBalances::free_balance(&transfer_recipient.into()) + == transfer_recipient_balance_before + 100 + ); + }); +} + +#[test] +fn hrmp_init_accept_through_root() { + MockNet::reset(); + + Relay::execute_with(|| { + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + para_a_account(), + 1000u128 + )); + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + para_b_account(), + 1000u128 + )); + }); + + ParaA::execute_with(|| { + let total_fee = 1_000u128; + let total_weight: u64 = 1_000_000_000; + let tx_weight: u64 = 500_000_000; + // Root can send hrmp init channel + assert_ok!(XcmTransactor::hrmp_manage( + parachain::RuntimeOrigin::root(), + HrmpOperation::InitOpen(HrmpInitParams { + para_id: 2u32.into(), + proposed_max_capacity: 1, + proposed_max_message_size: 1 + }), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_fee) + }, + TransactWeights { + transact_required_weight_at_most: tx_weight.into(), + overall_weight: Some(total_weight.into()) + } + )); + }); + Relay::execute_with(|| { + let expected_event: relay_chain::RuntimeEvent = + polkadot_runtime_parachains::hrmp::Event::OpenChannelRequested( + 1u32.into(), + 2u32.into(), + 1u32, + 1u32, + ) + .into(); + assert!(relay_chain::relay_events().contains(&expected_event)); + }); + ParaB::execute_with(|| { + let total_fee = 1_000u128; + let total_weight: u64 = 1_000_000_000; + let tx_weight: u64 = 500_000_000; + // Root can send hrmp accept channel + assert_ok!(XcmTransactor::hrmp_manage( + parachain::RuntimeOrigin::root(), + HrmpOperation::Accept { + para_id: 1u32.into() + }, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_fee) + }, + TransactWeights { + transact_required_weight_at_most: tx_weight.into(), + overall_weight: Some(total_weight.into()) + } + )); + }); + + Relay::execute_with(|| { + let expected_event: relay_chain::RuntimeEvent = + polkadot_runtime_parachains::hrmp::Event::OpenChannelAccepted(1u32.into(), 2u32.into()) + .into(); + assert!(relay_chain::relay_events().contains(&expected_event)); + }); +} + +#[test] +fn hrmp_close_works() { + MockNet::reset(); + + Relay::execute_with(|| { + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + para_a_account(), + 1000u128 + )); + assert_ok!(Hrmp::force_open_hrmp_channel( + relay_chain::RuntimeOrigin::root(), + 1u32.into(), + 2u32.into(), + 1u32, + 1u32 + )); + assert_ok!(Hrmp::force_process_hrmp_open( + relay_chain::RuntimeOrigin::root(), + 0u32 + )); + }); + + ParaA::execute_with(|| { + let total_fee = 1_000u128; + let total_weight: u64 = 1_000_000_000; + let tx_weight: u64 = 500_000_000; + // Root can send hrmp close + assert_ok!(XcmTransactor::hrmp_manage( + parachain::RuntimeOrigin::root(), + HrmpOperation::Close(HrmpChannelId { + sender: 1u32.into(), + recipient: 2u32.into() + }), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_fee) + }, + TransactWeights { + transact_required_weight_at_most: tx_weight.into(), + overall_weight: Some(total_weight.into()) + } + )); + }); + Relay::execute_with(|| { + let expected_event: relay_chain::RuntimeEvent = + polkadot_runtime_parachains::hrmp::Event::ChannelClosed( + 1u32.into(), + HrmpChannelId { + sender: 1u32.into(), + recipient: 2u32.into(), + }, + ) + .into(); + assert!(relay_chain::relay_events().contains(&expected_event)); + }); +} + +use parity_scale_codec::{Decode, Encode}; +use sp_io::hashing::blake2_256; + +// Helper to derive accountIds +pub fn derivative_account_id(who: sp_runtime::AccountId32, index: u16) -> sp_runtime::AccountId32 { + let entropy = (b"modlpy/utilisuba", who, index).using_encoded(blake2_256); + sp_runtime::AccountId32::decode(&mut &entropy[..]).expect("valid account id") +} diff --git a/tracing/2601/runtime/moonriver/Cargo.toml b/tracing/2601/runtime/moonriver/Cargo.toml new file mode 100644 index 00000000..52a5ccd8 --- /dev/null +++ b/tracing/2601/runtime/moonriver/Cargo.toml @@ -0,0 +1,355 @@ +[package] +name = "moonriver-runtime" +authors = { workspace = true } +build = "build.rs" +description = "Moonriver Runtime" +edition = "2021" +homepage = "https://moonbeam.network" +license = "GPL-3.0-only" +version = "0.8.4" + +[dependencies] +hex-literal = { workspace = true, optional = true } +log = { workspace = true } +num_enum = { workspace = true } +rlp = { workspace = true, optional = true } +serde = { workspace = true, features = [ "derive" ] } +sha3 = { workspace = true, optional = true } +smallvec = { workspace = true } +strum = { workspace = true } +strum_macros = { workspace = true } + +# Moonbeam +account = { workspace = true } +moonbeam-core-primitives = { workspace = true } +moonbeam-relay-encoder = { workspace = true } +moonbeam-runtime-common = { workspace = true } +precompile-utils = { workspace = true } +session-keys-primitives = { workspace = true } +xcm-primitives = { workspace = true } + +# Moonbeam pallets +moonbeam-xcm-benchmarks = { workspace = true } +pallet-asset-manager = { workspace = true } +pallet-author-mapping = { workspace = true } +pallet-crowdloan-rewards = { workspace = true } +pallet-erc20-xcm-bridge = { workspace = true } +pallet-evm-chain-id = { workspace = true } +pallet-ethereum-xcm = { workspace = true } +pallet-maintenance-mode = { workspace = true, features = [ "xcm-support" ] } +pallet-migrations = { workspace = true } +pallet-moonbeam-orbiters = { workspace = true } +pallet-parachain-staking = { workspace = true } +pallet-proxy-genesis-companion = { workspace = true } +pallet-randomness = { workspace = true } +pallet-xcm-transactor = { workspace = true } + +# Moonbeam precompiles +pallet-evm-precompile-author-mapping = { workspace = true } +pallet-evm-precompile-balances-erc20 = { workspace = true } +pallet-evm-precompile-batch = { workspace = true } +pallet-evm-precompile-call-permit = { workspace = true } +pallet-evm-precompile-collective = { workspace = true } +pallet-evm-precompile-conviction-voting = { workspace = true } +pallet-evm-precompile-crowdloan-rewards = { workspace = true } +pallet-evm-precompile-democracy = { workspace = true } +pallet-evm-precompile-gmp = { workspace = true } +pallet-evm-precompile-parachain-staking = { workspace = true } +pallet-evm-precompile-preimage = { workspace = true } +pallet-evm-precompile-proxy = { workspace = true } +pallet-evm-precompile-randomness = { workspace = true } +pallet-evm-precompile-referenda = { workspace = true } +pallet-evm-precompile-registry = { workspace = true } +pallet-evm-precompile-relay-encoder = { workspace = true } +pallet-evm-precompile-xcm-transactor = { workspace = true } +pallet-evm-precompile-xcm-utils = { workspace = true } +pallet-evm-precompile-xtokens = { workspace = true } +pallet-evm-precompileset-assets-erc20 = { workspace = true } + +# Moonbeam tracing +evm-tracing-events = { workspace = true, optional = true } +moonbeam-evm-tracer = { workspace = true, optional = true } +moonbeam-rpc-primitives-debug = { workspace = true } +moonbeam-rpc-primitives-txpool = { workspace = true } + +# Substrate +frame-executive = { workspace = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +frame-system-rpc-runtime-api = { workspace = true } +pallet-assets = { workspace = true } +pallet-balances = { workspace = true, features = [ "insecure_zero_ed" ] } +pallet-collective = { workspace = true } +pallet-conviction-voting = { workspace = true } +pallet-democracy = { workspace = true } +pallet-identity = { workspace = true } +pallet-multisig = { workspace = true } +pallet-preimage = { workspace = true } +pallet-proxy = { workspace = true } +pallet-referenda = { workspace = true } +pallet-root-testing = { workspace = true } +pallet-scheduler = { workspace = true } +pallet-society = { workspace = true } +pallet-timestamp = { workspace = true } +pallet-transaction-payment = { workspace = true } +pallet-transaction-payment-rpc-runtime-api = { workspace = true } +pallet-treasury = { workspace = true } +pallet-utility = { workspace = true } +pallet-whitelist = { workspace = true } +parity-scale-codec = { workspace = true, features = [ + "derive", + "max-encoded-len", + "chain-error", +] } +scale-info = { workspace = true, features = [ "derive" ] } +sp-api = { workspace = true } +sp-block-builder = { workspace = true } +sp-core = { workspace = true } +sp-debug-derive = { workspace = true } +sp-inherents = { workspace = true } +sp-io = { workspace = true, features = [ "improved_panic_error_reporting" ] } +sp-offchain = { workspace = true } +sp-runtime = { workspace = true } +sp-session = { workspace = true } +sp-std = { workspace = true } +sp-transaction-pool = { workspace = true } +sp-version = { workspace = true } +sp-weights = { workspace = true } + +# Frontier +fp-evm = { workspace = true } +fp-rpc = { workspace = true } +fp-self-contained = { workspace = true, features = [ "serde" ] } +pallet-base-fee = { workspace = true } +pallet-ethereum = { workspace = true, features = [ "forbid-evm-reentrancy" ] } +pallet-evm = { workspace = true, features = [ "forbid-evm-reentrancy" ] } +pallet-evm-precompile-blake2 = { workspace = true } +pallet-evm-precompile-bn128 = { workspace = true } +pallet-evm-precompile-dispatch = { workspace = true } +pallet-evm-precompile-modexp = { workspace = true } +pallet-evm-precompile-sha3fips = { workspace = true } +pallet-evm-precompile-simple = { workspace = true } + +# Polkadot / XCM +orml-traits = { workspace = true } +orml-xcm-support = { workspace = true } +orml-xtokens = { workspace = true } +pallet-xcm = { workspace = true } +pallet-xcm-benchmarks = { workspace = true, optional = true } +polkadot-core-primitives = { workspace = true } +polkadot-parachain = { workspace = true } +xcm = { workspace = true } +xcm-builder = { workspace = true } +xcm-executor = { workspace = true } + +# Cumulus +cumulus-pallet-dmp-queue = { workspace = true } +cumulus-pallet-parachain-system = { workspace = true } +cumulus-pallet-xcm = { workspace = true } +cumulus-pallet-xcmp-queue = { workspace = true } +cumulus-primitives-core = { workspace = true } +cumulus-primitives-timestamp = { workspace = true } +cumulus-primitives-utility = { workspace = true } +parachain-info = { workspace = true } + +# Moonkit +moonkit-xcm-primitives = { workspace = true } +nimbus-primitives = { workspace = true } +pallet-author-inherent = { workspace = true } +pallet-author-slot-filter = { workspace = true } + +# Benchmarking +frame-benchmarking = { workspace = true, optional = true } +frame-system-benchmarking = { workspace = true, optional = true } +frame-try-runtime = { workspace = true, optional = true } + +[build-dependencies] +substrate-wasm-builder = { workspace = true } + +[features] +default = [ "std" , "evm-tracing"] +std = [ + "account/std", + "cumulus-pallet-dmp-queue/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-xcm/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-primitives-core/std", + "cumulus-primitives-timestamp/std", + "evm-tracing-events/std", + "fp-evm/std", + "fp-rpc/std", + "fp-self-contained/std", + "frame-benchmarking/std", + "frame-executive/std", + "frame-support/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "moonbeam-core-primitives/std", + "moonbeam-evm-tracer/std", + "moonbeam-relay-encoder/std", + "moonbeam-rpc-primitives-debug/std", + "moonbeam-rpc-primitives-txpool/std", + "moonbeam-runtime-common/std", + "moonbeam-xcm-benchmarks/std", + "moonkit-xcm-primitives/std", + "nimbus-primitives/std", + "orml-xtokens/std", + "pallet-asset-manager/std", + "pallet-assets/std", + "pallet-author-inherent/std", + "pallet-author-mapping/std", + "pallet-author-slot-filter/std", + "pallet-balances/std", + "pallet-base-fee/std", + "pallet-collective/std", + "pallet-conviction-voting/std", + "pallet-crowdloan-rewards/std", + "pallet-democracy/std", + "pallet-erc20-xcm-bridge/std", + "pallet-evm-chain-id/std", + "pallet-ethereum-xcm/std", + "pallet-ethereum/std", + "pallet-evm-precompile-author-mapping/std", + "pallet-evm-precompile-balances-erc20/std", + "pallet-evm-precompile-batch/std", + "pallet-evm-precompile-call-permit/std", + "pallet-evm-precompile-collective/std", + "pallet-evm-precompile-conviction-voting/std", + "pallet-evm-precompile-democracy/std", + "pallet-evm-precompile-parachain-staking/std", + "pallet-evm-precompile-preimage/std", + "pallet-evm-precompile-randomness/std", + "pallet-evm-precompile-referenda/std", + "pallet-evm-precompile-xcm-transactor/std", + "pallet-evm-precompile-xcm-utils/std", + "pallet-evm-precompile-xtokens/std", + "pallet-evm/std", + "pallet-identity/std", + "pallet-maintenance-mode/std", + "pallet-migrations/std", + "pallet-moonbeam-orbiters/std", + "pallet-multisig/std", + "pallet-parachain-staking/std", + "pallet-preimage/std", + "pallet-proxy-genesis-companion/std", + "pallet-proxy/std", + "pallet-randomness/std", + "pallet-referenda/std", + "pallet-root-testing/std", + "pallet-scheduler/std", + "pallet-society/std", + "pallet-timestamp/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", + "pallet-treasury/std", + "pallet-utility/std", + "pallet-whitelist/std", + "pallet-xcm-transactor/std", + "pallet-xcm/std", + "parachain-info/std", + "parity-scale-codec/std", + "precompile-utils/std", + "scale-info/std", + "session-keys-primitives/std", + "sp-api/std", + "sp-block-builder/std", + "sp-core/std", + "sp-inherents/std", + "sp-io/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-transaction-pool/std", + "sp-version/std", + "strum/std", + "xcm-builder/std", + "xcm-executor/std", + "xcm-primitives/std", + "xcm/std", +] + +# Must be enabled for tracing runtimes only +evm-tracing = [ "evm-tracing-events", "moonbeam-evm-tracer", "rlp", "sha3" ] + +# Allow to print logs details (no wasm:stripped) +force-debug = [ "sp-debug-derive/force-debug" ] + +# Will be enabled by the `wasm-builder` when building the runtime for WASM. +runtime-wasm = [] + +# A feature that should be enabled when the runtime should be build for on-chain +# deployment. This will disable stuff that shouldn't be part of the on-chain wasm +# to make it smaller like logging for example. +on-chain-release-build = [ "sp-api/disable-logging" ] + +runtime-benchmarks = [ + "cumulus-pallet-parachain-system/runtime-benchmarks", + "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "hex-literal", + "moonbeam-relay-encoder/runtime-benchmarks", + "moonbeam-runtime-common/runtime-benchmarks", + "moonbeam-xcm-benchmarks/runtime-benchmarks", + "pallet-asset-manager/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pallet-author-inherent/runtime-benchmarks", + "pallet-author-mapping/runtime-benchmarks", + "pallet-author-slot-filter/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-collective/runtime-benchmarks", + "pallet-conviction-voting/runtime-benchmarks", + "pallet-crowdloan-rewards/runtime-benchmarks", + "pallet-ethereum-xcm/runtime-benchmarks", + "pallet-ethereum/runtime-benchmarks", + "pallet-evm/runtime-benchmarks", + "pallet-identity/runtime-benchmarks", + "pallet-migrations/runtime-benchmarks", + "pallet-moonbeam-orbiters/runtime-benchmarks", + "pallet-multisig/runtime-benchmarks", + "pallet-parachain-staking/runtime-benchmarks", + "pallet-preimage/runtime-benchmarks", + "pallet-proxy/runtime-benchmarks", + "pallet-randomness/runtime-benchmarks", + "pallet-referenda/runtime-benchmarks", + "pallet-scheduler/runtime-benchmarks", + "pallet-society/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "pallet-treasury/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "pallet-whitelist/runtime-benchmarks", + "pallet-xcm-benchmarks", + "pallet-xcm-transactor/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "session-keys-primitives/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", +] +try-runtime = [ + "fp-self-contained/try-runtime", + "frame-executive/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime", + "moonbeam-runtime-common/try-runtime", + "pallet-asset-manager/try-runtime", + "pallet-author-mapping/try-runtime", + "pallet-author-slot-filter/try-runtime", + "pallet-balances/try-runtime", + "pallet-collective/try-runtime", + "pallet-conviction-voting/try-runtime", + "pallet-democracy/try-runtime", + "pallet-maintenance-mode/try-runtime", + "pallet-migrations/try-runtime", + "pallet-parachain-staking/try-runtime", + "pallet-preimage/try-runtime", + "pallet-referenda/try-runtime", + "pallet-root-testing/try-runtime", + "pallet-scheduler/try-runtime", + "pallet-society/try-runtime", + "pallet-timestamp/try-runtime", + "pallet-whitelist/try-runtime", +] diff --git a/tracing/2601/runtime/moonriver/build.rs b/tracing/2601/runtime/moonriver/build.rs new file mode 100644 index 00000000..3934b9c5 --- /dev/null +++ b/tracing/2601/runtime/moonriver/build.rs @@ -0,0 +1,25 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +use substrate_wasm_builder::WasmBuilder; + +fn main() { + WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build() +} diff --git a/tracing/2601/runtime/moonriver/src/asset_config.rs b/tracing/2601/runtime/moonriver/src/asset_config.rs new file mode 100644 index 00000000..f475e9ec --- /dev/null +++ b/tracing/2601/runtime/moonriver/src/asset_config.rs @@ -0,0 +1,343 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Asset configuration for Moonbase. +//! + +use super::{ + currency, governance, xcm_config, AccountId, AssetId, AssetManager, Assets, Balance, Balances, + CouncilInstance, LocalAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX, +}; + +use moonbeam_runtime_common::weights as moonbeam_weights; +use pallet_evm_precompileset_assets_erc20::AccountIdAssetIdConversion; +use sp_runtime::traits::Hash as THash; + +use frame_support::{ + dispatch::GetDispatchInfo, + parameter_types, + traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, EitherOfDiverse}, + weights::Weight, +}; +use frame_system::{EnsureNever, EnsureRoot}; +use sp_core::{H160, H256}; + +use parity_scale_codec::{Compact, Decode, Encode}; +use scale_info::TypeInfo; + +use sp_std::{ + convert::{From, Into}, + prelude::*, +}; + +// Number of items that can be destroyed with our configured max extrinsic proof size. +// x = (a - b) / c where: +// a: maxExtrinsic proof size +// b: base proof size for destroy_accounts in pallet_assets weights +// c: proof size for each item +// 656.87 = (3_407_872 - 8232) / 5180 +const REMOVE_ITEMS_LIMIT: u32 = 656; + +// Not to disrupt the previous asset instance, we assign () to Foreign +pub type ForeignAssetInstance = (); +pub type LocalAssetInstance = pallet_assets::Instance1; + +// For foreign assets, these parameters dont matter much +// as this will only be called by root with the forced arguments +// No deposit is substracted with those methods +// For local assets, they do matter. We use similar parameters +// to those in statemine (except for approval) +parameter_types! { + pub const AssetDeposit: Balance = 100 * currency::MOVR * currency::SUPPLY_FACTOR; + pub const ApprovalDeposit: Balance = 0; + pub const AssetsStringLimit: u32 = 50; + pub const MetadataDepositBase: Balance = currency::deposit(1,68); + pub const MetadataDepositPerByte: Balance = currency::deposit(0, 1); +} + +/// We allow root and Chain council to execute privileged asset operations. +pub type AssetsForceOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; + +// Required for runtime benchmarks +pallet_assets::runtime_benchmarks_enabled! { + pub struct BenchmarkHelper; + impl pallet_assets::BenchmarkHelper for BenchmarkHelper + where + AssetIdParameter: From, + { + fn create_asset_id_parameter(id: u32) -> AssetIdParameter { + (id as u128).into() + } + } +} + +// Foreign assets +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = AssetsForceOrigin; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = ConstU128<{ currency::deposit(1, 18) }>; + type WeightInfo = moonbeam_weights::pallet_assets::WeightInfo; + type RemoveItemsLimit = ConstU32<{ REMOVE_ITEMS_LIMIT }>; + type AssetIdParameter = Compact; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +// Local assets +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = EnsureNever; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = ConstU128<{ currency::deposit(1, 18) }>; + type WeightInfo = moonbeam_weights::pallet_assets::WeightInfo; + type RemoveItemsLimit = ConstU32<{ REMOVE_ITEMS_LIMIT }>; + type AssetIdParameter = Compact; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +// We instruct how to register the Assets +// In this case, we tell it to Create an Asset in pallet-assets +pub struct AssetRegistrar; +use frame_support::{pallet_prelude::DispatchResult, transactional}; + +impl pallet_asset_manager::AssetRegistrar for AssetRegistrar { + #[transactional] + fn create_foreign_asset( + asset: AssetId, + min_balance: Balance, + metadata: AssetRegistrarMetadata, + is_sufficient: bool, + ) -> DispatchResult { + Assets::force_create( + RuntimeOrigin::root(), + asset.into(), + AssetManager::account_id(), + is_sufficient, + min_balance, + )?; + + // TODO uncomment when we feel comfortable + /* + // The asset has been created. Let's put the revert code in the precompile address + let precompile_address = Runtime::asset_id_to_account(asset); + pallet_evm::AccountCodes::::insert( + precompile_address, + vec![0x60, 0x00, 0x60, 0x00, 0xfd], + );*/ + + // Lastly, the metadata + Assets::force_set_metadata( + RuntimeOrigin::root(), + asset.into(), + metadata.name, + metadata.symbol, + metadata.decimals, + metadata.is_frozen, + ) + } + + #[transactional] + fn create_local_asset( + asset: AssetId, + _creator: AccountId, + min_balance: Balance, + is_sufficient: bool, + owner: AccountId, + ) -> DispatchResult { + // We create with root, because we need to decide whether we want to create the asset + // as sufficient. Take into account this does not hold any reserved amount + // in pallet-assets + LocalAssets::force_create( + RuntimeOrigin::root(), + asset.into(), + owner, + is_sufficient, + min_balance, + )?; + + // No metadata needs to be set, as this can be set through regular calls + + // TODO: should we put the revert code? + // The asset has been created. Let's put the revert code in the precompile address + let precompile_address: H160 = + Runtime::asset_id_to_account(LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX, asset).into(); + pallet_evm::AccountCodes::::insert( + precompile_address, + vec![0x60, 0x00, 0x60, 0x00, 0xfd], + ); + Ok(()) + } + + #[transactional] + fn destroy_foreign_asset(asset: AssetId) -> DispatchResult { + // Mark the asset as destroying + Assets::start_destroy(RuntimeOrigin::root(), asset.into())?; + + // We remove the EVM revert code + // This does not panick even if there is no code in the address + let precompile_address: H160 = + Runtime::asset_id_to_account(FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, asset).into(); + pallet_evm::AccountCodes::::remove(precompile_address); + Ok(()) + } + + #[transactional] + fn destroy_local_asset(asset: AssetId) -> DispatchResult { + // Mark the asset as destroying + LocalAssets::start_destroy(RuntimeOrigin::root(), asset.into())?; + + // We remove the EVM revert code + // This does not panick even if there is no code in the address + let precompile_address: H160 = + Runtime::asset_id_to_account(LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX, asset).into(); + pallet_evm::AccountCodes::::remove(precompile_address); + Ok(()) + } + + fn destroy_asset_dispatch_info_weight(asset: AssetId) -> Weight { + // For us both of them (Foreign and Local) have the same annotated weight for a given + // witness + // We need to take the dispatch info from the destroy call, which is already annotated in + // the assets pallet + // Additionally, we need to add a DB write for removing the precompile revert code in the + // EVM + + // This is the dispatch info of destroy + let call_weight = RuntimeCall::Assets( + pallet_assets::Call::::start_destroy { + id: asset.into(), + }, + ) + .get_dispatch_info() + .weight; + + // This is the db write + call_weight.saturating_add(::DbWeight::get().writes(1)) + } +} + +pub struct LocalAssetIdCreator; +impl pallet_asset_manager::LocalAssetIdCreator for LocalAssetIdCreator { + fn create_asset_id_from_metadata(local_asset_counter: u128) -> AssetId { + // Our means of converting a local asset counter to an assetId + // We basically hash (local asset counter) + let mut result: [u8; 16] = [0u8; 16]; + let hash: H256 = + local_asset_counter.using_encoded(::Hashing::hash); + result.copy_from_slice(&hash.as_fixed_bytes()[0..16]); + u128::from_le_bytes(result) + } +} + +#[derive(Clone, Default, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub struct AssetRegistrarMetadata { + pub name: Vec, + pub symbol: Vec, + pub decimals: u8, + pub is_frozen: bool, +} + +pub type ForeignAssetModifierOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; +pub type LocalAssetModifierOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; + +impl pallet_asset_manager::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type AssetRegistrarMetadata = AssetRegistrarMetadata; + type ForeignAssetType = xcm_config::AssetType; + type AssetRegistrar = AssetRegistrar; + type ForeignAssetModifierOrigin = ForeignAssetModifierOrigin; + type LocalAssetModifierOrigin = LocalAssetModifierOrigin; + type LocalAssetIdCreator = LocalAssetIdCreator; + type Currency = Balances; + type LocalAssetDeposit = AssetDeposit; + type WeightInfo = moonbeam_weights::pallet_asset_manager::WeightInfo; +} + +// Instruct how to go from an H160 to an AssetID +// We just take the lowest 128 bits +impl AccountIdAssetIdConversion for Runtime { + /// The way to convert an account to assetId is by ensuring that the prefix is 0XFFFFFFFF + /// and by taking the lowest 128 bits as the assetId + fn account_to_asset_id(account: AccountId) -> Option<(Vec, AssetId)> { + let h160_account: H160 = account.into(); + let mut data = [0u8; 16]; + let (prefix_part, id_part) = h160_account.as_fixed_bytes().split_at(4); + if prefix_part == FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX + || prefix_part == LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX + { + data.copy_from_slice(id_part); + let asset_id: AssetId = u128::from_be_bytes(data).into(); + Some((prefix_part.to_vec(), asset_id)) + } else { + None + } + } + + // The opposite conversion + fn asset_id_to_account(prefix: &[u8], asset_id: AssetId) -> AccountId { + let mut data = [0u8; 20]; + data[0..4].copy_from_slice(prefix); + data[4..20].copy_from_slice(&asset_id.to_be_bytes()); + AccountId::from(data) + } +} diff --git a/tracing/2601/runtime/moonriver/src/governance/councils.rs b/tracing/2601/runtime/moonriver/src/governance/councils.rs new file mode 100644 index 00000000..694962a1 --- /dev/null +++ b/tracing/2601/runtime/moonriver/src/governance/councils.rs @@ -0,0 +1,97 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Councils for Gov1 and Gov2 + +use super::*; + +pub type CouncilInstance = pallet_collective::Instance1; +pub type TechCommitteeInstance = pallet_collective::Instance2; +pub type TreasuryCouncilInstance = pallet_collective::Instance3; +pub type OpenTechCommitteeInstance = pallet_collective::Instance4; + +parameter_types! { + // TODO: Check value of this parameter + pub MaxProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block; +} + +impl pallet_collective::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Proposal = RuntimeCall; + /// The maximum amount of time (in blocks) for council members to vote on motions. + /// Motions may end in fewer blocks if enough votes are cast to determine the result. + type MotionDuration = ConstU32<{ 3 * DAYS }>; + /// The maximum number of proposals that can be open in the council at once. + type MaxProposals = ConstU32<100>; + /// The maximum number of council members. + type MaxMembers = ConstU32<100>; + type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote; + type WeightInfo = moonbeam_weights::pallet_collective::WeightInfo; + type SetMembersOrigin = referenda::GeneralAdminOrRoot; + type MaxProposalWeight = MaxProposalWeight; +} + +impl pallet_collective::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Proposal = RuntimeCall; + /// The maximum amount of time (in blocks) for technical committee members to vote on motions. + /// Motions may end in fewer blocks if enough votes are cast to determine the result. + type MotionDuration = ConstU32<{ 3 * DAYS }>; + /// The maximum number of proposals that can be open in the technical committee at once. + type MaxProposals = ConstU32<100>; + /// The maximum number of technical committee members. + type MaxMembers = ConstU32<100>; + type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote; + type WeightInfo = moonbeam_weights::pallet_collective::WeightInfo; + type SetMembersOrigin = referenda::GeneralAdminOrRoot; + type MaxProposalWeight = MaxProposalWeight; +} + +impl pallet_collective::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Proposal = RuntimeCall; + /// The maximum amount of time (in blocks) for treasury council members to vote on motions. + /// Motions may end in fewer blocks if enough votes are cast to determine the result. + type MotionDuration = ConstU32<{ 3 * DAYS }>; + /// The maximum number of proposals that can be open in the treasury council at once. + type MaxProposals = ConstU32<20>; + /// The maximum number of treasury council members. + type MaxMembers = ConstU32<9>; + type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote; + type WeightInfo = moonbeam_weights::pallet_collective::WeightInfo; + type SetMembersOrigin = referenda::GeneralAdminOrRoot; + type MaxProposalWeight = MaxProposalWeight; +} + +impl pallet_collective::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Proposal = RuntimeCall; + /// The maximum amount of time (in blocks) for technical committee members to vote on motions. + /// Motions may end in fewer blocks if enough votes are cast to determine the result. + type MotionDuration = ConstU32<{ 14 * DAYS }>; + /// The maximum number of proposals that can be open in the technical committee at once. + type MaxProposals = ConstU32<100>; + /// The maximum number of technical committee members. + type MaxMembers = ConstU32<100>; + type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote; + type WeightInfo = moonbeam_weights::pallet_collective::WeightInfo; + type SetMembersOrigin = referenda::GeneralAdminOrRoot; + type MaxProposalWeight = MaxProposalWeight; +} diff --git a/tracing/2601/runtime/moonriver/src/governance/democracy.rs b/tracing/2601/runtime/moonriver/src/governance/democracy.rs new file mode 100644 index 00000000..fcaefbbe --- /dev/null +++ b/tracing/2601/runtime/moonriver/src/governance/democracy.rs @@ -0,0 +1,77 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Democracy config for Gov1 + +use super::councils::*; +use crate::*; + +// The purpose of this offset is to ensure that a democratic proposal will not apply in the same +// block as a round change. +const ENACTMENT_OFFSET: u32 = 300; + +impl pallet_democracy::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type EnactmentPeriod = ConstU32<{ 1 * DAYS + ENACTMENT_OFFSET }>; + type LaunchPeriod = ConstU32<{ 1 * DAYS }>; + type VotingPeriod = ConstU32<{ 5 * DAYS }>; + + type VoteLockingPeriod = ConstU32<{ 1 * DAYS }>; + type FastTrackVotingPeriod = ConstU32<{ 3 * HOURS }>; + type MinimumDeposit = ConstU128<{ 4 * currency::MOVR * currency::SUPPLY_FACTOR }>; + /// To decide what their next motion is. + type ExternalOrigin = + pallet_collective::EnsureProportionAtLeast; + /// To have the next scheduled referendum be a straight majority-carries vote. + type ExternalMajorityOrigin = + pallet_collective::EnsureProportionAtLeast; + /// To have the next scheduled referendum be a straight default-carries (NTB) vote. + type ExternalDefaultOrigin = + pallet_collective::EnsureProportionAtLeast; + /// To allow a shorter voting/enactment period for external proposals. + type FastTrackOrigin = + pallet_collective::EnsureProportionAtLeast; + /// To instant fast track. + type InstantOrigin = + pallet_collective::EnsureProportionAtLeast; + // To cancel a proposal which has been passed. + type CancellationOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, + >; + // To cancel a proposal before it has been passed. + type CancelProposalOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, + >; + type BlacklistOrigin = EnsureRoot; + // Any single technical committee member may veto a coming council proposal, however they can + // only do it once and it lasts only for the cooloff period. + type VetoOrigin = pallet_collective::EnsureMember; + type CooloffPeriod = ConstU32<{ 7 * DAYS }>; + type Slash = (); + type InstantAllowed = ConstBool; + type Scheduler = Scheduler; + type MaxVotes = ConstU32<100>; + type PalletsOrigin = OriginCaller; + type WeightInfo = moonbeam_weights::pallet_democracy::WeightInfo; + type MaxProposals = ConstU32<100>; + type Preimages = Preimage; + type MaxDeposits = ConstU32<100>; + type MaxBlacklisted = ConstU32<100>; + type SubmitOrigin = EnsureSigned; +} diff --git a/tracing/2601/runtime/moonriver/src/governance/mod.rs b/tracing/2601/runtime/moonriver/src/governance/mod.rs new file mode 100644 index 00000000..0367cdf0 --- /dev/null +++ b/tracing/2601/runtime/moonriver/src/governance/mod.rs @@ -0,0 +1,30 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Governance configurations + +pub mod councils; +mod democracy; +pub mod referenda; + +use super::*; + +mod origins; +pub use origins::{ + custom_origins, GeneralAdmin, ReferendumCanceller, ReferendumKiller, WhitelistedCaller, +}; +mod tracks; +pub use tracks::TracksInfo; diff --git a/tracing/2601/runtime/moonriver/src/governance/origins.rs b/tracing/2601/runtime/moonriver/src/governance/origins.rs new file mode 100644 index 00000000..a8a5a537 --- /dev/null +++ b/tracing/2601/runtime/moonriver/src/governance/origins.rs @@ -0,0 +1,82 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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. + +//! Custom origins for governance interventions. +#![cfg_attr(not(feature = "std"), no_std)] + +pub use custom_origins::*; + +#[frame_support::pallet] +pub mod custom_origins { + use frame_support::pallet_prelude::*; + use strum_macros::EnumString; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[derive( + PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug, EnumString, + )] + #[strum(serialize_all = "snake_case")] + #[pallet::origin] + pub enum Origin { + /// Origin able to dispatch a whitelisted call. + WhitelistedCaller, + /// General admin + GeneralAdmin, + /// Origin able to cancel referenda. + ReferendumCanceller, + /// Origin able to kill referenda. + ReferendumKiller, + } + + macro_rules! decl_unit_ensures { + ( $name:ident: $success_type:ty = $success:expr ) => { + pub struct $name; + impl> + From> + EnsureOrigin for $name + { + type Success = $success_type; + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + Origin::$name => Ok($success), + r => Err(O::from(r)), + }) + } + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin() -> Result { + Ok(O::from(Origin::$name)) + } + } + }; + ( $name:ident ) => { decl_unit_ensures! { $name : () = () } }; + ( $name:ident: $success_type:ty = $success:expr, $( $rest:tt )* ) => { + decl_unit_ensures! { $name: $success_type = $success } + decl_unit_ensures! { $( $rest )* } + }; + ( $name:ident, $( $rest:tt )* ) => { + decl_unit_ensures! { $name } + decl_unit_ensures! { $( $rest )* } + }; + () => {} + } + decl_unit_ensures!( + ReferendumCanceller, + ReferendumKiller, + WhitelistedCaller, + GeneralAdmin + ); +} diff --git a/tracing/2601/runtime/moonriver/src/governance/referenda.rs b/tracing/2601/runtime/moonriver/src/governance/referenda.rs new file mode 100644 index 00000000..48a326f7 --- /dev/null +++ b/tracing/2601/runtime/moonriver/src/governance/referenda.rs @@ -0,0 +1,98 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! # Gov2 config +//! Includes runtime configs for these substrate pallets: +//! 1. pallet-conviction-voting +//! 2. pallet-whitelist +//! 3. pallet-referenda + +use super::*; +use crate::currency::*; +use frame_support::traits::{EitherOf, MapSuccess}; +use frame_system::EnsureRootWithSuccess; +use sp_runtime::traits::Replace; + +parameter_types! { + pub const VoteLockingPeriod: BlockNumber = 1 * DAYS; +} + +impl pallet_conviction_voting::Config for Runtime { + type WeightInfo = moonbeam_weights::pallet_conviction_voting::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type Polls = Referenda; + type MaxTurnout = frame_support::traits::TotalIssuanceOf; + // Maximum number of concurrent votes an account may have + type MaxVotes = ConstU32<20>; + // Minimum period of vote locking + type VoteLockingPeriod = VoteLockingPeriod; +} + +parameter_types! { + pub const AlarmInterval: BlockNumber = 1; + pub const SubmissionDeposit: Balance = 10 * MOVR * SUPPLY_FACTOR; + pub const UndecidingTimeout: BlockNumber = 21 * DAYS; +} + +// Origin for general admin or root +pub type GeneralAdminOrRoot = EitherOf, origins::GeneralAdmin>; + +impl custom_origins::Config for Runtime {} + +// The purpose of this pallet is to queue calls to be dispatched as by root later => the Dispatch +// origin corresponds to the Gov2 Whitelist track. +impl pallet_whitelist::Config for Runtime { + type WeightInfo = moonbeam_weights::pallet_whitelist::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type WhitelistOrigin = EitherOf< + EnsureRootWithSuccess>, + MapSuccess< + pallet_collective::EnsureProportionAtLeast< + Self::AccountId, + OpenTechCommitteeInstance, + 5, + 9, + >, + Replace>, + >, + >; + type DispatchWhitelistedOrigin = EitherOf, WhitelistedCaller>; + type Preimages = Preimage; +} + +pallet_referenda::impl_tracksinfo_get!(TracksInfo, Balance, BlockNumber); + +impl pallet_referenda::Config for Runtime { + type WeightInfo = moonbeam_weights::pallet_referenda::WeightInfo; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type Scheduler = Scheduler; + type Currency = Balances; + type SubmitOrigin = frame_system::EnsureSigned; + type CancelOrigin = EitherOf, ReferendumCanceller>; + type KillOrigin = EitherOf, ReferendumKiller>; + type Slash = Treasury; + type Votes = pallet_conviction_voting::VotesOf; + type Tally = pallet_conviction_voting::TallyOf; + type SubmissionDeposit = SubmissionDeposit; + type MaxQueued = ConstU32<100>; + type UndecidingTimeout = UndecidingTimeout; + type AlarmInterval = AlarmInterval; + type Tracks = TracksInfo; + type Preimages = Preimage; +} diff --git a/tracing/2601/runtime/moonriver/src/governance/tracks.rs b/tracing/2601/runtime/moonriver/src/governance/tracks.rs new file mode 100644 index 00000000..b4e23ba0 --- /dev/null +++ b/tracing/2601/runtime/moonriver/src/governance/tracks.rs @@ -0,0 +1,179 @@ +// Copyright 2022 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 . + +//! Track configurations for governance. + +use super::*; +use crate::currency::{KILOMOVR, MOVR, SUPPLY_FACTOR}; +use sp_std::str::FromStr; + +const fn percent(x: i32) -> sp_runtime::FixedI64 { + sp_runtime::FixedI64::from_rational(x as u128, 100) +} +const fn permill(x: i32) -> sp_runtime::FixedI64 { + sp_runtime::FixedI64::from_rational(x as u128, 1000) +} + +use pallet_referenda::Curve; +const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 5] = [ + ( + 0, + pallet_referenda::TrackInfo { + // Name of this track. + name: "root", + // A limit for the number of referenda on this track that can be being decided at once. + // For Root origin this should generally be just one. + max_deciding: 5, + // Amount that must be placed on deposit before a decision can be made. + decision_deposit: 100 * KILOMOVR * SUPPLY_FACTOR, + // Amount of time this must be submitted for before a decision can be made. + prepare_period: 1 * DAYS, + // Amount of time that a decision may take to be approved prior to cancellation. + decision_period: 14 * DAYS, + // Amount of time that the approval criteria must hold before it can be approved. + confirm_period: 1 * DAYS, + // Minimum amount of time that an approved proposal must be in the dispatch queue. + min_enactment_period: 1 * DAYS, + // Minimum aye votes as percentage of overall conviction-weighted votes needed for + // approval as a function of time into decision period. + min_approval: Curve::make_reciprocal(4, 14, percent(80), percent(50), percent(100)), + // Minimum pre-conviction aye-votes ("support") as percentage of overall population that + // is needed for approval as a function of time into decision period. + min_support: Curve::make_linear(14, 14, permill(5), percent(25)), + }, + ), + ( + 1, + pallet_referenda::TrackInfo { + name: "whitelisted_caller", + max_deciding: 100, + decision_deposit: 10 * KILOMOVR * SUPPLY_FACTOR, + prepare_period: 10 * MINUTES, + decision_period: 14 * DAYS, + confirm_period: 10 * MINUTES, + min_enactment_period: 30 * MINUTES, + min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)), + min_support: Curve::make_reciprocal(1, 14 * 24, percent(1), percent(0), percent(2)), + }, + ), + ( + 2, + pallet_referenda::TrackInfo { + name: "general_admin", + max_deciding: 10, + decision_deposit: 500 * MOVR * SUPPLY_FACTOR, + prepare_period: 1 * HOURS, + decision_period: 14 * DAYS, + confirm_period: 1 * DAYS, + min_enactment_period: 1 * DAYS, + min_approval: Curve::make_reciprocal(4, 14, percent(80), percent(50), percent(100)), + min_support: Curve::make_reciprocal(7, 14, percent(10), percent(0), percent(50)), + }, + ), + ( + 3, + pallet_referenda::TrackInfo { + name: "referendum_canceller", + max_deciding: 20, + decision_deposit: 10 * KILOMOVR * SUPPLY_FACTOR, + prepare_period: 1 * HOURS, + decision_period: 14 * DAYS, + confirm_period: 3 * HOURS, + min_enactment_period: 10 * MINUTES, + min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)), + min_support: Curve::make_reciprocal(1, 14, percent(1), percent(0), percent(10)), + }, + ), + ( + 4, + pallet_referenda::TrackInfo { + name: "referendum_killer", + max_deciding: 100, + decision_deposit: 20 * KILOMOVR * SUPPLY_FACTOR, + prepare_period: 1 * HOURS, + decision_period: 14 * DAYS, + confirm_period: 3 * HOURS, + min_enactment_period: 10 * MINUTES, + min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)), + min_support: Curve::make_reciprocal(1, 14, percent(1), percent(0), percent(10)), + }, + ), +]; + +pub struct TracksInfo; +impl pallet_referenda::TracksInfo for TracksInfo { + type Id = u16; + type RuntimeOrigin = ::PalletsOrigin; + fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { + &TRACKS_DATA[..] + } + fn track_for(id: &Self::RuntimeOrigin) -> Result { + if let Ok(system_origin) = frame_system::RawOrigin::try_from(id.clone()) { + match system_origin { + frame_system::RawOrigin::Root => { + if let Some((track_id, _)) = Self::tracks() + .into_iter() + .find(|(_, track)| track.name == "root") + { + Ok(*track_id) + } else { + Err(()) + } + } + _ => Err(()), + } + } else if let Ok(custom_origin) = custom_origins::Origin::try_from(id.clone()) { + if let Some((track_id, _)) = Self::tracks().into_iter().find(|(_, track)| { + if let Ok(track_custom_origin) = custom_origins::Origin::from_str(track.name) { + track_custom_origin == custom_origin + } else { + false + } + }) { + Ok(*track_id) + } else { + Err(()) + } + } else { + Err(()) + } + } +} + +#[test] +/// To ensure voters are always locked into their vote +fn vote_locking_always_longer_than_enactment_period() { + for (_, track) in TRACKS_DATA { + assert!( + ::VoteLockingPeriod::get() + >= track.min_enactment_period, + "Track {} has enactment period {} < vote locking period {}", + track.name, + track.min_enactment_period, + ::VoteLockingPeriod::get(), + ); + } +} + +#[test] +fn all_tracks_have_origins() { + for (_, track) in TRACKS_DATA { + // check name.into() is successful either converts into "root" or custom origin + let track_is_root = track.name == "root"; + let track_has_custom_origin = custom_origins::Origin::from_str(track.name).is_ok(); + assert!(track_is_root || track_has_custom_origin); + } +} diff --git a/tracing/2601/runtime/moonriver/src/lib.rs b/tracing/2601/runtime/moonriver/src/lib.rs new file mode 100644 index 00000000..e4eca70a --- /dev/null +++ b/tracing/2601/runtime/moonriver/src/lib.rs @@ -0,0 +1,1830 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! The Moonriver Runtime. +//! +//! Primary features of this runtime include: +//! * Ethereum compatibility +//! * Moonriver tokenomics + +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +use account::AccountId20; +use cumulus_pallet_parachain_system::{RelayChainStateProof, RelaychainDataProvider}; +use cumulus_primitives_core::relay_chain; +use fp_rpc::TransactionStatus; + +// Re-export required by get! macro. +#[cfg(feature = "std")] +pub use fp_evm::GenesisAccount; +pub use frame_support::traits::Get; +use frame_support::{ + construct_runtime, + dispatch::{DispatchClass, GetDispatchInfo, PostDispatchInfo}, + ensure, + pallet_prelude::DispatchResult, + parameter_types, + traits::{ + ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, Contains, + Currency as CurrencyT, EitherOfDiverse, EqualPrivilegeOnly, Imbalance, InstanceFilter, + OffchainWorker, OnFinalize, OnIdle, OnInitialize, OnRuntimeUpgrade, OnUnbalanced, + }, + weights::{ + constants::{RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND}, + ConstantMultiplier, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, + WeightToFeePolynomial, + }, + PalletId, +}; +use frame_system::{EnsureRoot, EnsureSigned}; +pub use moonbeam_core_primitives::{ + AccountId, AccountIndex, Address, AssetId, Balance, BlockNumber, DigestItem, Hash, Header, + Index, Signature, +}; +use moonbeam_rpc_primitives_txpool::TxPoolResponse; +use moonbeam_runtime_common::weights as moonbeam_weights; +use pallet_balances::NegativeImbalance; +use pallet_ethereum::Call::transact; +use pallet_ethereum::{PostLogContent, Transaction as EthereumTransaction}; +use pallet_evm::{ + Account as EVMAccount, EVMCurrencyAdapter, EnsureAddressNever, EnsureAddressRoot, + FeeCalculator, GasWeightMapping, IdentityAddressMapping, + OnChargeEVMTransaction as OnChargeEVMTransactionT, Runner, +}; +pub use pallet_parachain_staking::{weights::WeightInfo, InflationInfo, Range}; +use pallet_transaction_payment::{CurrencyAdapter, Multiplier, TargetedFeeAdjustment}; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_api::impl_runtime_apis; +use sp_core::{OpaqueMetadata, H160, H256, U256}; +#[cfg(feature = "try-runtime")] +use sp_runtime::TryRuntimeError; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + serde::{Deserialize, Serialize}, + traits::{ + BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, IdentityLookup, + PostDispatchInfoOf, UniqueSaturatedInto, Zero, + }, + transaction_validity::{ + InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError, + }, + ApplyExtrinsicResult, DispatchErrorWithPostInfo, FixedPointNumber, Perbill, Permill, + Perquintill, SaturatedConversion, +}; +use sp_std::{convert::TryFrom, prelude::*}; + +use cumulus_primitives_core::{relay_chain::BlockNumber as RelayBlockNumber, DmpMessageHandler}; +use smallvec::smallvec; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; + +use nimbus_primitives::CanAuthor; + +mod precompiles; +pub use precompiles::{ + MoonriverPrecompiles, PrecompileName, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX, +}; + +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; + +pub type Precompiles = MoonriverPrecompiles; + +pub mod asset_config; +pub mod governance; +pub mod xcm_config; +use governance::councils::*; + +pub use governance::councils::*; + +/// MOVR, the native token, uses 18 decimals of precision. +pub mod currency { + use super::Balance; + + // Provide a common factor between runtimes based on a supply of 10_000_000 tokens. + pub const SUPPLY_FACTOR: Balance = 1; + + pub const WEI: Balance = 1; + pub const KILOWEI: Balance = 1_000; + pub const MEGAWEI: Balance = 1_000_000; + pub const GIGAWEI: Balance = 1_000_000_000; + pub const MICROMOVR: Balance = 1_000_000_000_000; + pub const MILLIMOVR: Balance = 1_000_000_000_000_000; + pub const MOVR: Balance = 1_000_000_000_000_000_000; + pub const KILOMOVR: Balance = 1_000_000_000_000_000_000_000; + + pub const TRANSACTION_BYTE_FEE: Balance = 1 * GIGAWEI * SUPPLY_FACTOR; + pub const STORAGE_BYTE_FEE: Balance = 100 * MICROMOVR * SUPPLY_FACTOR; + pub const WEIGHT_FEE: Balance = 50 * KILOWEI * SUPPLY_FACTOR; + + pub const fn deposit(items: u32, bytes: u32) -> Balance { + items as Balance * 1 * MOVR * SUPPLY_FACTOR + (bytes as Balance) * STORAGE_BYTE_FEE + } +} + +/// Maximum weight per block +pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND, u64::MAX) + .saturating_div(2) + .set_proof_size(cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64); + +pub const MILLISECS_PER_BLOCK: u64 = 12000; +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; +pub const WEEKS: BlockNumber = DAYS * 7; +/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know +/// the specifics of the runtime. They can then be made to be agnostic over specific formats +/// of data like extrinsics, allowing for them to continue syncing the network through upgrades +/// to even the core datastructures. +pub mod opaque { + use super::*; + + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + pub type Block = generic::Block; + + impl_opaque_keys! { + pub struct SessionKeys { + pub nimbus: AuthorInherent, + pub vrf: session_keys_primitives::VrfSessionKey, + } + } +} + +/// This runtime version. +/// The spec_version is composed of 2x2 digits. The first 2 digits represent major changes +/// that can't be skipped, such as data migration upgrades. The last 2 digits represent minor +/// changes which can be skipped. +#[sp_version::runtime_version] +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("moonriver"), + impl_name: create_runtime_str!("moonriver"), + authoring_version: 3, + spec_version: 2601, + impl_version: 0, + apis: RUNTIME_API_VERSIONS, + transaction_version: 2, + state_version: 0, +}; + +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); +pub const NORMAL_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_mul(3).saturating_div(4); +// Here we assume Ethereum's base fee of 21000 gas and convert to weight, but we +// subtract roughly the cost of a balance transfer from it (about 1/3 the cost) +// and some cost to account for per-byte-fee. +// TODO: we should use benchmarking's overhead feature to measure this +pub const EXTRINSIC_BASE_WEIGHT: Weight = Weight::from_parts(10000 * WEIGHT_PER_GAS, 0); + +pub struct RuntimeBlockWeights; +impl Get for RuntimeBlockWeights { + fn get() -> frame_system::limits::BlockWeights { + frame_system::limits::BlockWeights::builder() + .for_class(DispatchClass::Normal, |weights| { + weights.base_extrinsic = EXTRINSIC_BASE_WEIGHT; + weights.max_total = NORMAL_WEIGHT.into(); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = MAXIMUM_BLOCK_WEIGHT.into(); + weights.reserved = (MAXIMUM_BLOCK_WEIGHT - NORMAL_WEIGHT).into(); + }) + .avg_block_initialization(Perbill::from_percent(10)) + .build() + .expect("Provided BlockWeight definitions are valid, qed") + } +} + +parameter_types! { + pub const Version: RuntimeVersion = VERSION; + /// We allow for 5 MB blocks. + pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength + ::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); +} + +impl frame_system::Config for Runtime { + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = IdentityLookup; + /// The index type for storing how many extrinsics an account has signed. + type Nonce = Index; + /// The index type for blocks. + type Block = Block; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The output of the `Hashing` function. + type Hash = H256; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + /// The ubiquitous origin type. + type RuntimeOrigin = RuntimeOrigin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = ConstU32<256>; + /// Maximum weight of each block. With a default weight system of 1byte == 1weight, 4mb is ok. + type BlockWeights = RuntimeBlockWeights; + /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. + type BlockLength = BlockLength; + /// Runtime version. + type Version = Version; + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type DbWeight = RocksDbWeight; + type BaseCallFilter = MaintenanceMode; + type SystemWeightInfo = (); + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = ConstU16<1285>; + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl pallet_utility::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; + type WeightInfo = moonbeam_weights::pallet_utility::WeightInfo; +} + +impl pallet_timestamp::Config for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = ConstU64<6000>; + type WeightInfo = moonbeam_weights::pallet_timestamp::WeightInfo; +} + +impl pallet_balances::Config for Runtime { + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 4]; + type MaxLocks = ConstU32<50>; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ConstU128<0>; + type AccountStore = System; + type FreezeIdentifier = (); + type MaxFreezes = ConstU32<0>; + type RuntimeHoldReason = RuntimeHoldReason; + type MaxHolds = ConstU32<0>; + type WeightInfo = moonbeam_weights::pallet_balances::WeightInfo; +} + +pub struct DealWithFees(sp_std::marker::PhantomData); +impl OnUnbalanced> for DealWithFees +where + R: pallet_balances::Config + pallet_treasury::Config, + pallet_treasury::Pallet: OnUnbalanced>, +{ + // this seems to be called for substrate-based transactions + fn on_unbalanceds(mut fees_then_tips: impl Iterator>) { + if let Some(fees) = fees_then_tips.next() { + // for fees, 80% are burned, 20% to the treasury + let (_, to_treasury) = fees.ration(80, 20); + // Balances pallet automatically burns dropped Negative Imbalances by decreasing + // total_supply accordingly + as OnUnbalanced<_>>::on_unbalanced(to_treasury); + + // handle tip if there is one + if let Some(tip) = fees_then_tips.next() { + // for now we use the same burn/treasury strategy used for regular fees + let (_, to_treasury) = tip.ration(80, 20); + as OnUnbalanced<_>>::on_unbalanced(to_treasury); + } + } + } + + // this is called from pallet_evm for Ethereum-based transactions + // (technically, it calls on_unbalanced, which calls this when non-zero) + fn on_nonzero_unbalanced(amount: NegativeImbalance) { + // Balances pallet automatically burns dropped Negative Imbalances by decreasing + // total_supply accordingly + let (_, to_treasury) = amount.ration(80, 20); + as OnUnbalanced<_>>::on_unbalanced(to_treasury); + } +} + +pub struct LengthToFee; +impl WeightToFeePolynomial for LengthToFee { + type Balance = Balance; + + fn polynomial() -> WeightToFeeCoefficients { + smallvec![ + WeightToFeeCoefficient { + degree: 1, + coeff_frac: Perbill::zero(), + coeff_integer: currency::TRANSACTION_BYTE_FEE, + negative: false, + }, + WeightToFeeCoefficient { + degree: 3, + coeff_frac: Perbill::zero(), + coeff_integer: 1 * currency::SUPPLY_FACTOR, + negative: false, + }, + ] + } +} + +impl pallet_transaction_payment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = CurrencyAdapter>; + type OperationalFeeMultiplier = ConstU8<5>; + type WeightToFee = ConstantMultiplier>; + type LengthToFee = LengthToFee; + type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; +} + +impl pallet_evm_chain_id::Config for Runtime {} + +/// Current approximation of the gas/s consumption considering +/// EVM execution over compiled WASM (on 4.4Ghz CPU). +/// Given the 500ms Weight, from which 75% only are used for transactions, +/// the total EVM execution gas limit is: GAS_PER_SECOND * 0.500 * 0.75 ~= 15_000_000. +pub const GAS_PER_SECOND: u64 = 40_000_000; + +/// Approximate ratio of the amount of Weight per Gas. +/// u64 works for approximations because Weight is a very small unit compared to gas. +pub const WEIGHT_PER_GAS: u64 = WEIGHT_REF_TIME_PER_SECOND / GAS_PER_SECOND; + +parameter_types! { + pub BlockGasLimit: U256 + = U256::from(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT.ref_time() / WEIGHT_PER_GAS); + /// The portion of the `NORMAL_DISPATCH_RATIO` that we adjust the fees with. Blocks filled less + /// than this will decrease the weight and more will increase. + pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); + /// The adjustment variable of the runtime. Higher values will cause `TargetBlockFullness` to + /// change the fees more rapidly. This low value causes changes to occur slowly over time. + pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(4, 1_000); + /// Minimum amount of the multiplier. This value cannot be too low. A test case should ensure + /// that combined with `AdjustmentVariable`, we can recover from the minimum. + /// See `multiplier_can_grow_from_zero` in integration_tests.rs. + /// This value is currently only used by pallet-transaction-payment as an assertion that the + /// next multiplier is always > min value. + pub MinimumMultiplier: Multiplier = Multiplier::from(1u128); + /// Maximum multiplier. We pick a value that is expensive but not impossibly so; it should act + /// as a safety net. + pub MaximumMultiplier: Multiplier = Multiplier::from(100_000u128); + pub PrecompilesValue: MoonriverPrecompiles = MoonriverPrecompiles::<_>::new(); + pub WeightPerGas: Weight = Weight::from_parts(WEIGHT_PER_GAS, 0); + /// The amount of gas per pov. A ratio of 4 if we convert ref_time to gas and we compare + /// it with the pov_size for a block. E.g. + /// ceil( + /// (max_extrinsic.ref_time() / max_extrinsic.proof_size()) / WEIGHT_PER_GAS + /// ) + pub const GasLimitPovSizeRatio: u64 = 4; + /// The amount of gas per storage (in bytes): BLOCK_GAS_LIMIT / BLOCK_STORAGE_LIMIT + /// The current definition of BLOCK_STORAGE_LIMIT is 40 KB, resulting in a value of 366. + pub GasLimitStorageGrowthRatio: u64 = 366; +} + +pub struct TransactionPaymentAsGasPrice; +impl FeeCalculator for TransactionPaymentAsGasPrice { + fn min_gas_price() -> (U256, Weight) { + // note: transaction-payment differs from EIP-1559 in that its tip and length fees are not + // scaled by the multiplier, which means its multiplier will be overstated when + // applied to an ethereum transaction + // note: transaction-payment uses both a congestion modifier (next_fee_multiplier, which is + // updated once per block in on_finalize) and a 'WeightToFee' implementation. Our + // runtime implements this as a 'ConstantModifier', so we can get away with a simple + // multiplication here. + // It is imperative that `saturating_mul_int` be performed as late as possible in the + // expression since it involves fixed point multiplication with a division by a fixed + // divisor. This leads to truncation and subsequent precision loss if performed too early. + // This can lead to min_gas_price being same across blocks even if the multiplier changes. + // There's still some precision loss when the final `gas_price` (used_gas * min_gas_price) + // is computed in frontier, but that's currently unavoidable. + let min_gas_price = TransactionPayment::next_fee_multiplier() + .saturating_mul_int(currency::WEIGHT_FEE.saturating_mul(WEIGHT_PER_GAS as u128)); + ( + min_gas_price.into(), + ::DbWeight::get().reads(1), + ) + } +} + +/// Parameterized slow adjusting fee updated based on +/// https://w3f-research.readthedocs.io/en/latest/polkadot/overview/2-token-economics.html#-2.-slow-adjusting-mechanism // editorconfig-checker-disable-line +/// +/// The adjustment algorithm boils down to: +/// +/// diff = (previous_block_weight - target) / maximum_block_weight +/// next_multiplier = prev_multiplier * (1 + (v * diff) + ((v * diff)^2 / 2)) +/// assert(next_multiplier > min) +/// where: v is AdjustmentVariable +/// target is TargetBlockFullness +/// min is MinimumMultiplier +pub type SlowAdjustingFeeUpdate = TargetedFeeAdjustment< + R, + TargetBlockFullness, + AdjustmentVariable, + MinimumMultiplier, + MaximumMultiplier, +>; + +use frame_support::traits::FindAuthor; +//TODO It feels like this shold be able to work for any T: H160, but I tried for +// embarassingly long and couldn't figure that out. + +/// The author inherent provides a AccountId20, but pallet evm needs an H160. +/// This simple adapter makes the conversion. +pub struct FindAuthorAdapter(sp_std::marker::PhantomData); + +impl FindAuthor for FindAuthorAdapter +where + Inner: FindAuthor, +{ + fn find_author<'a, I>(digests: I) -> Option + where + I: 'a + IntoIterator, + { + Inner::find_author(digests).map(Into::into) + } +} + +moonbeam_runtime_common::impl_on_charge_evm_transaction!(); + +impl pallet_evm::Config for Runtime { + type FeeCalculator = TransactionPaymentAsGasPrice; + type GasWeightMapping = pallet_evm::FixedGasWeightMapping; + type WeightPerGas = WeightPerGas; + type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping; + type CallOrigin = EnsureAddressRoot; + type WithdrawOrigin = EnsureAddressNever; + type AddressMapping = IdentityAddressMapping; + type Currency = Balances; + type RuntimeEvent = RuntimeEvent; + type Runner = pallet_evm::runner::stack::Runner; + type PrecompilesType = MoonriverPrecompiles; + type PrecompilesValue = PrecompilesValue; + type ChainId = EthereumChainId; + type OnChargeTransaction = OnChargeEVMTransaction>; + type BlockGasLimit = BlockGasLimit; + type FindAuthor = FindAuthorAdapter; + type OnCreate = (); + type GasLimitPovSizeRatio = GasLimitPovSizeRatio; + type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio; + type Timestamp = Timestamp; + type WeightInfo = moonbeam_weights::pallet_evm::WeightInfo; +} + +parameter_types! { + pub MaximumSchedulerWeight: Weight = NORMAL_DISPATCH_RATIO * RuntimeBlockWeights::get().max_block; +} + +impl pallet_scheduler::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type MaximumWeight = MaximumSchedulerWeight; + type ScheduleOrigin = EnsureRoot; + type MaxScheduledPerBlock = ConstU32<50>; + type WeightInfo = moonbeam_weights::pallet_scheduler::WeightInfo; + type OriginPrivilegeCmp = EqualPrivilegeOnly; + type Preimages = Preimage; +} + +impl pallet_preimage::Config for Runtime { + type WeightInfo = moonbeam_weights::pallet_preimage::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type BaseDeposit = ConstU128<{ 5 * currency::MOVR * currency::SUPPLY_FACTOR }>; + type ByteDeposit = ConstU128<{ currency::STORAGE_BYTE_FEE }>; +} + +parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const TreasuryId: PalletId = PalletId(*b"py/trsry"); +} + +type TreasuryApproveOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, +>; + +type TreasuryRejectOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionMoreThan, +>; + +impl pallet_treasury::Config for Runtime { + type PalletId = TreasuryId; + type Currency = Balances; + // At least three-fifths majority of the council is required (or root) to approve a proposal + type ApproveOrigin = TreasuryApproveOrigin; + // More than half of the council is required (or root) to reject a proposal + type RejectOrigin = TreasuryRejectOrigin; + type RuntimeEvent = RuntimeEvent; + // If spending proposal rejected, transfer proposer bond to treasury + type OnSlash = Treasury; + type ProposalBond = ProposalBond; + type ProposalBondMinimum = ConstU128<{ 1 * currency::MOVR * currency::SUPPLY_FACTOR }>; + type SpendPeriod = ConstU32<{ 6 * DAYS }>; + type Burn = (); + type BurnDestination = (); + type MaxApprovals = ConstU32<100>; + type WeightInfo = moonbeam_weights::pallet_treasury::WeightInfo; + type SpendFunds = (); + type ProposalBondMaximum = (); + type SpendOrigin = frame_support::traits::NeverEnsureOrigin; // Same as Polkadot +} + +type IdentityForceOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; +type IdentityRegistrarOrigin = EitherOfDiverse< + EnsureRoot, + EitherOfDiverse< + pallet_collective::EnsureProportionMoreThan, + governance::custom_origins::GeneralAdmin, + >, +>; + +impl pallet_identity::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + // Add one item in storage and take 258 bytes + type BasicDeposit = ConstU128<{ currency::deposit(1, 258) }>; + // Not add any item to the storage but takes 66 bytes + type FieldDeposit = ConstU128<{ currency::deposit(0, 66) }>; + // Add one item in storage and take 53 bytes + type SubAccountDeposit = ConstU128<{ currency::deposit(1, 53) }>; + type MaxSubAccounts = ConstU32<100>; + type MaxAdditionalFields = ConstU32<100>; + type MaxRegistrars = ConstU32<20>; + type Slashed = Treasury; + type ForceOrigin = IdentityForceOrigin; + type RegistrarOrigin = IdentityRegistrarOrigin; + type WeightInfo = moonbeam_weights::pallet_identity::WeightInfo; +} + +pub struct TransactionConverter; + +impl fp_rpc::ConvertTransaction for TransactionConverter { + fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic { + UncheckedExtrinsic::new_unsigned( + pallet_ethereum::Call::::transact { transaction }.into(), + ) + } +} + +impl fp_rpc::ConvertTransaction for TransactionConverter { + fn convert_transaction( + &self, + transaction: pallet_ethereum::Transaction, + ) -> opaque::UncheckedExtrinsic { + let extrinsic = UncheckedExtrinsic::new_unsigned( + pallet_ethereum::Call::::transact { transaction }.into(), + ); + let encoded = extrinsic.encode(); + opaque::UncheckedExtrinsic::decode(&mut &encoded[..]) + .expect("Encoded extrinsic is always valid") + } +} + +parameter_types! { + pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes; +} + +impl pallet_ethereum::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type StateRoot = pallet_ethereum::IntermediateStateRoot; + type PostLogContent = PostBlockAndTxnHashes; + type ExtraDataLength = ConstU32<30>; +} + +pub struct EthereumXcmEnsureProxy; +impl xcm_primitives::EnsureProxy for EthereumXcmEnsureProxy { + fn ensure_ok(delegator: AccountId, delegatee: AccountId) -> Result<(), &'static str> { + // The EVM implicitely contains an Any proxy, so we only allow for "Any" proxies + let def: pallet_proxy::ProxyDefinition = + pallet_proxy::Pallet::::find_proxy( + &delegator, + &delegatee, + Some(ProxyType::Any), + ) + .map_err(|_| "proxy error: expected `ProxyType::Any`")?; + // We only allow to use it for delay zero proxies, as the call will immediatly be executed + ensure!(def.delay.is_zero(), "proxy delay is Non-zero`"); + Ok(()) + } +} + +impl pallet_ethereum_xcm::Config for Runtime { + type InvalidEvmTransactionError = pallet_ethereum::InvalidTransactionWrapper; + type ValidatedTransaction = pallet_ethereum::ValidatedTransaction; + type XcmEthereumOrigin = pallet_ethereum_xcm::EnsureXcmEthereumTransaction; + type ReservedXcmpWeight = ReservedXcmpWeight; + type EnsureProxy = EthereumXcmEnsureProxy; + type ControllerOrigin = EnsureRoot; +} + +parameter_types! { + pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); +} + +impl cumulus_pallet_parachain_system::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnSystemEvent = (); + type SelfParaId = ParachainInfo; + type DmpMessageHandler = MaintenanceMode; + type ReservedDmpWeight = ReservedDmpWeight; + type OutboundXcmpMessageSource = XcmpQueue; + type XcmpMessageHandler = XcmpQueue; + type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; +} + +impl parachain_info::Config for Runtime {} + +pub struct OnNewRound; +impl pallet_parachain_staking::OnNewRound for OnNewRound { + fn on_new_round(round_index: pallet_parachain_staking::RoundIndex) -> Weight { + MoonbeamOrbiters::on_new_round(round_index) + } +} +pub struct PayoutCollatorOrOrbiterReward; +impl pallet_parachain_staking::PayoutCollatorReward for PayoutCollatorOrOrbiterReward { + fn payout_collator_reward( + for_round: pallet_parachain_staking::RoundIndex, + collator_id: AccountId, + amount: Balance, + ) -> Weight { + let extra_weight = if MoonbeamOrbiters::is_orbiter(for_round, collator_id) { + MoonbeamOrbiters::distribute_rewards(for_round, collator_id, amount) + } else { + ParachainStaking::mint_collator_reward(for_round, collator_id, amount) + }; + + ::DbWeight::get() + .reads(1) + .saturating_add(extra_weight) + } +} + +pub struct OnInactiveCollator; +impl pallet_parachain_staking::OnInactiveCollator for OnInactiveCollator { + fn on_inactive_collator( + collator_id: AccountId, + round: pallet_parachain_staking::RoundIndex, + ) -> Result> { + let extra_weight = if !MoonbeamOrbiters::is_orbiter(round, collator_id.clone()) { + ParachainStaking::go_offline_inner(collator_id)?; + ::WeightInfo::go_offline( + pallet_parachain_staking::MAX_CANDIDATES, + ) + } else { + Weight::zero() + }; + + Ok(::DbWeight::get() + .reads(1) + .saturating_add(extra_weight)) + } +} + +type MonetaryGovernanceOrigin = + EitherOfDiverse, governance::custom_origins::GeneralAdmin>; + +impl pallet_parachain_staking::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type MonetaryGovernanceOrigin = MonetaryGovernanceOrigin; + /// Minimum round length is 2 minutes (10 * 12 second block times) + type MinBlocksPerRound = ConstU32<10>; + /// If a collator doesn't produce any block on this number of rounds, it is notified as inactive + type MaxOfflineRounds = ConstU32<2>; + /// Rounds before the collator leaving the candidates request can be executed + type LeaveCandidatesDelay = ConstU32<24>; + /// Rounds before the candidate bond increase/decrease can be executed + type CandidateBondLessDelay = ConstU32<24>; + /// Rounds before the delegator exit can be executed + type LeaveDelegatorsDelay = ConstU32<24>; + /// Rounds before the delegator revocation can be executed + type RevokeDelegationDelay = ConstU32<24>; + /// Rounds before the delegator bond increase/decrease can be executed + type DelegationBondLessDelay = ConstU32<24>; + /// Rounds before the reward is paid + type RewardPaymentDelay = ConstU32<2>; + /// Minimum collators selected per round, default at genesis and minimum forever after + type MinSelectedCandidates = ConstU32<8>; + /// Maximum top delegations per candidate + type MaxTopDelegationsPerCandidate = ConstU32<300>; + /// Maximum bottom delegations per candidate + type MaxBottomDelegationsPerCandidate = ConstU32<50>; + /// Maximum delegations per delegator + type MaxDelegationsPerDelegator = ConstU32<100>; + /// Minimum stake required to be reserved to be a candidate + type MinCandidateStk = ConstU128<{ 500 * currency::MOVR * currency::SUPPLY_FACTOR }>; + /// Minimum stake required to be reserved to be a delegator + type MinDelegation = ConstU128<{ 5 * currency::MOVR * currency::SUPPLY_FACTOR }>; + type BlockAuthor = AuthorInherent; + type OnCollatorPayout = (); + type PayoutCollatorReward = PayoutCollatorOrOrbiterReward; + type OnInactiveCollator = OnInactiveCollator; + type OnNewRound = OnNewRound; + type WeightInfo = moonbeam_weights::pallet_parachain_staking::WeightInfo; + type MaxCandidates = ConstU32<200>; +} + +impl pallet_author_inherent::Config for Runtime { + type SlotBeacon = RelaychainDataProvider; + type AccountLookup = MoonbeamOrbiters; + type CanAuthor = AuthorFilter; + type AuthorId = AccountId; + type WeightInfo = moonbeam_weights::pallet_author_inherent::WeightInfo; +} + +impl pallet_author_slot_filter::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RandomnessSource = Randomness; + type PotentialAuthors = ParachainStaking; + type WeightInfo = moonbeam_weights::pallet_author_slot_filter::WeightInfo; +} + +parameter_types! { + pub const InitializationPayment: Perbill = Perbill::from_percent(30); + pub const RelaySignaturesThreshold: Perbill = Perbill::from_percent(100); + pub const SignatureNetworkIdentifier: &'static [u8] = b"moonriver-"; + +} + +impl pallet_crowdloan_rewards::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Initialized = ConstBool; + type InitializationPayment = InitializationPayment; + type MaxInitContributors = ConstU32<500>; + type MinimumReward = ConstU128<0>; + type RewardCurrency = Balances; + type RelayChainAccountId = [u8; 32]; + type RewardAddressAssociateOrigin = EnsureSigned; + type RewardAddressChangeOrigin = EnsureSigned; + type RewardAddressRelayVoteThreshold = RelaySignaturesThreshold; + type SignatureNetworkIdentifier = SignatureNetworkIdentifier; + type VestingBlockNumber = relay_chain::BlockNumber; + type VestingBlockProvider = RelaychainDataProvider; + type WeightInfo = moonbeam_weights::pallet_crowdloan_rewards::WeightInfo; +} + +// This is a simple session key manager. It should probably either work with, or be replaced +// entirely by pallet sessions +impl pallet_author_mapping::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type DepositCurrency = Balances; + type DepositAmount = ConstU128<{ 100 * currency::MOVR * currency::SUPPLY_FACTOR }>; + type Keys = session_keys_primitives::VrfId; + type WeightInfo = moonbeam_weights::pallet_author_mapping::WeightInfo; +} + +/// The type used to represent the kinds of proxying allowed. +#[derive( + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + Debug, + MaxEncodedLen, + TypeInfo, + Serialize, + Deserialize, +)] +pub enum ProxyType { + /// All calls can be proxied. This is the trivial/most permissive filter. + Any = 0, + /// Only extrinsics that do not transfer funds. + NonTransfer = 1, + /// Only extrinsics related to governance (democracy and collectives). + Governance = 2, + /// Only extrinsics related to staking. + Staking = 3, + /// Allow to veto an announced proxy call. + CancelProxy = 4, + /// Allow extrinsic related to Balances. + Balances = 5, + /// Allow extrinsic related to AuthorMapping. + AuthorMapping = 6, + /// Allow extrinsic related to IdentityJudgement. + IdentityJudgement = 7, +} + +impl Default for ProxyType { + fn default() -> Self { + Self::Any + } +} + +fn is_governance_precompile(precompile_name: &precompiles::PrecompileName) -> bool { + matches!( + precompile_name, + PrecompileName::DemocracyPrecompile + | PrecompileName::CouncilInstance + | PrecompileName::TechCommitteeInstance + | PrecompileName::TreasuryCouncilInstance + | PrecompileName::PreimagePrecompile + | PrecompileName::ReferendaPrecompile + | PrecompileName::ConvictionVotingPrecompile + | PrecompileName::OpenTechCommitteeInstance + ) +} + +// Be careful: Each time this filter is modified, the substrate filter must also be modified +// consistently. +impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType { + fn is_evm_proxy_call_allowed( + &self, + call: &pallet_evm_precompile_proxy::EvmSubCall, + recipient_has_code: bool, + gas: u64, + ) -> precompile_utils::EvmResult { + Ok(match self { + ProxyType::Any => { + match PrecompileName::from_address(call.to.0) { + // Any precompile that can execute a subcall should be forbidden here, + // to ensure that unauthorized smart contract can't be called + // indirectly. + // To be safe, we only allow the precompiles we need. + Some( + PrecompileName::AuthorMappingPrecompile + | PrecompileName::ParachainStakingPrecompile, + ) => true, + Some(ref precompile) if is_governance_precompile(precompile) => true, + // All non-whitelisted precompiles are forbidden + Some(_) => false, + // Allow evm transfer to "simple" account (no code nor precompile) + // For the moment, no smart contract other than precompiles is allowed. + // In the future, we may create a dynamic whitelist to authorize some audited + // smart contracts through governance. + None => { + // If the address is not recognized, allow only evm transfert to "simple" + // accounts (no code nor precompile). + // Note: Checking the presence of the code is not enough because some + // precompiles have no code. + !recipient_has_code + && !precompile_utils::precompile_set::is_precompile_or_fail::( + call.to.0, gas, + )? + } + } + } + ProxyType::NonTransfer => { + call.value == U256::zero() + && match PrecompileName::from_address(call.to.0) { + Some( + PrecompileName::AuthorMappingPrecompile + | PrecompileName::ParachainStakingPrecompile, + ) => true, + Some(ref precompile) if is_governance_precompile(precompile) => true, + _ => false, + } + } + ProxyType::Governance => { + call.value == U256::zero() + && matches!( + PrecompileName::from_address(call.to.0), + Some(ref precompile) if is_governance_precompile(precompile) + ) + } + ProxyType::Staking => { + call.value == U256::zero() + && matches!( + PrecompileName::from_address(call.to.0), + Some( + PrecompileName::AuthorMappingPrecompile + | PrecompileName::ParachainStakingPrecompile + ) + ) + } + // The proxy precompile does not contain method cancel_proxy + ProxyType::CancelProxy => false, + ProxyType::Balances => { + // Allow only "simple" accounts as recipient (no code nor precompile). + // Note: Checking the presence of the code is not enough because some precompiles + // have no code. + !recipient_has_code + && !precompile_utils::precompile_set::is_precompile_or_fail::( + call.to.0, gas, + )? + } + ProxyType::AuthorMapping => { + call.value == U256::zero() + && matches!( + PrecompileName::from_address(call.to.0), + Some(PrecompileName::AuthorMappingPrecompile) + ) + } + // There is no identity precompile + ProxyType::IdentityJudgement => false, + }) + } +} + +// Be careful: Each time this filter is modified, the EVM filter must also be modified consistently. +impl InstanceFilter for ProxyType { + fn filter(&self, c: &RuntimeCall) -> bool { + match self { + ProxyType::Any => true, + ProxyType::NonTransfer => { + matches!( + c, + RuntimeCall::System(..) + | RuntimeCall::ParachainSystem(..) + | RuntimeCall::Timestamp(..) + | RuntimeCall::ParachainStaking(..) + | RuntimeCall::Democracy(..) + | RuntimeCall::Referenda(..) + | RuntimeCall::Preimage(..) + | RuntimeCall::ConvictionVoting(..) + | RuntimeCall::CouncilCollective(..) + | RuntimeCall::TreasuryCouncilCollective(..) + | RuntimeCall::TechCommitteeCollective(..) + | RuntimeCall::OpenTechCommitteeCollective(..) + | RuntimeCall::Identity(..) + | RuntimeCall::Utility(..) + | RuntimeCall::Proxy(..) | RuntimeCall::AuthorMapping(..) + | RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::claim { .. } + ) + ) + } + ProxyType::Governance => matches!( + c, + RuntimeCall::Democracy(..) + | RuntimeCall::Referenda(..) + | RuntimeCall::Preimage(..) + | RuntimeCall::ConvictionVoting(..) + | RuntimeCall::CouncilCollective(..) + | RuntimeCall::TreasuryCouncilCollective(..) + | RuntimeCall::TechCommitteeCollective(..) + | RuntimeCall::OpenTechCommitteeCollective(..) + | RuntimeCall::Utility(..) + ), + ProxyType::Staking => matches!( + c, + RuntimeCall::ParachainStaking(..) + | RuntimeCall::Utility(..) + | RuntimeCall::AuthorMapping(..) + | RuntimeCall::MoonbeamOrbiters(..) + ), + ProxyType::CancelProxy => matches!( + c, + RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) + ), + ProxyType::Balances => { + matches!(c, RuntimeCall::Balances(..) | RuntimeCall::Utility(..)) + } + ProxyType::AuthorMapping => matches!(c, RuntimeCall::AuthorMapping(..)), + ProxyType::IdentityJudgement => matches!( + c, + RuntimeCall::Identity(pallet_identity::Call::provide_judgement { .. }) + | RuntimeCall::Utility(..) + ), + } + } + + fn is_superset(&self, o: &Self) -> bool { + match (self, o) { + (x, y) if x == y => true, + (ProxyType::Any, _) => true, + (_, ProxyType::Any) => false, + _ => false, + } + } +} + +impl pallet_proxy::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type ProxyType = ProxyType; + // One storage item; key size 32, value size 8 + type ProxyDepositBase = ConstU128<{ currency::deposit(1, 8) }>; + // Additional storage item size of 21 bytes (20 bytes AccountId + 1 byte sizeof(ProxyType)). + type ProxyDepositFactor = ConstU128<{ currency::deposit(0, 21) }>; + type MaxProxies = ConstU32<32>; + type WeightInfo = moonbeam_weights::pallet_proxy::WeightInfo; + type MaxPending = ConstU32<32>; + type CallHasher = BlakeTwo256; + type AnnouncementDepositBase = ConstU128<{ currency::deposit(1, 8) }>; + // Additional storage item size of 56 bytes: + // - 20 bytes AccountId + // - 32 bytes Hasher (Blake2256) + // - 4 bytes BlockNumber (u32) + type AnnouncementDepositFactor = ConstU128<{ currency::deposit(0, 56) }>; +} + +use pallet_migrations::{GetMigrations, Migration}; +pub struct TransactorRelayIndexMigration(sp_std::marker::PhantomData); + +impl GetMigrations for TransactorRelayIndexMigration +where + Runtime: pallet_xcm_transactor::Config, +{ + fn get_migrations() -> Vec> { + vec![Box::new( + moonbeam_runtime_common::migrations::PopulateRelayIndices::( + moonbeam_relay_encoder::kusama::KUSAMA_RELAY_INDICES, + Default::default(), + ), + )] + } +} + +impl pallet_migrations::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type MigrationsList = ( + moonbeam_runtime_common::migrations::CommonMigrations< + Runtime, + CouncilCollective, + TechCommitteeCollective, + >, + moonbeam_runtime_common::migrations::ReferendaMigrations< + Runtime, + CouncilCollective, + TechCommitteeCollective, + >, + TransactorRelayIndexMigration, + ); + type XcmExecutionManager = XcmExecutionManager; +} + +/// Maintenance mode Call filter +pub struct MaintenanceFilter; +impl Contains for MaintenanceFilter { + fn contains(c: &RuntimeCall) -> bool { + match c { + RuntimeCall::Assets(_) => false, + RuntimeCall::LocalAssets(_) => false, + RuntimeCall::Balances(_) => false, + RuntimeCall::CrowdloanRewards(_) => false, + RuntimeCall::Ethereum(_) => false, + RuntimeCall::EVM(_) => false, + RuntimeCall::Identity(_) => false, + RuntimeCall::XTokens(_) => false, + RuntimeCall::ParachainStaking(_) => false, + RuntimeCall::MoonbeamOrbiters(_) => false, + RuntimeCall::PolkadotXcm(_) => false, + RuntimeCall::Treasury(_) => false, + RuntimeCall::XcmTransactor(_) => false, + RuntimeCall::EthereumXcm(_) => false, + _ => true, + } + } +} + +/// Normal Call Filter +/// We dont allow to create nor mint assets, this for now is disabled +/// We only allow transfers. For now creation of assets will go through +/// asset-manager, while minting/burning only happens through xcm messages +/// This can change in the future +pub struct NormalFilter; +impl Contains for NormalFilter { + fn contains(c: &RuntimeCall) -> bool { + match c { + RuntimeCall::Assets(method) => match method { + pallet_assets::Call::transfer { .. } => true, + pallet_assets::Call::transfer_keep_alive { .. } => true, + pallet_assets::Call::approve_transfer { .. } => true, + pallet_assets::Call::transfer_approved { .. } => true, + pallet_assets::Call::cancel_approval { .. } => true, + pallet_assets::Call::destroy_accounts { .. } => true, + pallet_assets::Call::destroy_approvals { .. } => true, + pallet_assets::Call::finish_destroy { .. } => true, + _ => false, + }, + // We want to disable create, as we dont want users to be choosing the + // assetId of their choice + // We also disable destroy, as we want to route destroy through the + // asset-manager, which guarantees the removal both at the EVM and + // substrate side of things + RuntimeCall::LocalAssets(method) => match method { + pallet_assets::Call::create { .. } => false, + pallet_assets::Call::start_destroy { .. } => false, + _ => true, + }, + // We just want to enable this in case of live chains, since the default version + // is populated at genesis + RuntimeCall::PolkadotXcm(method) => match method { + pallet_xcm::Call::force_default_xcm_version { .. } => true, + _ => false, + }, + // We filter anonymous proxy as they make "reserve" inconsistent + // See: https://github.com/paritytech/substrate/blob/37cca710eed3dadd4ed5364c7686608f5175cce1/frame/proxy/src/lib.rs#L270 // editorconfig-checker-disable-line + RuntimeCall::Proxy(method) => match method { + pallet_proxy::Call::create_pure { .. } => false, + pallet_proxy::Call::kill_pure { .. } => false, + pallet_proxy::Call::proxy { real, .. } => { + !pallet_evm::AccountCodes::::contains_key(H160::from(*real)) + } + _ => true, + }, + // Filtering the EVM prevents possible re-entrancy from the precompiles which could + // lead to unexpected scenarios. + // See https://github.com/PureStake/sr-moonbeam/issues/30 + // Note: It is also assumed that EVM calls are only allowed through `Origin::Root` so + // this can be seen as an additional security + RuntimeCall::EVM(_) => false, + _ => true, + } + } +} + +pub struct XcmExecutionManager; +impl moonkit_xcm_primitives::PauseXcmExecution for XcmExecutionManager { + fn suspend_xcm_execution() -> DispatchResult { + XcmpQueue::suspend_xcm_execution(RuntimeOrigin::root()) + } + fn resume_xcm_execution() -> DispatchResult { + XcmpQueue::resume_xcm_execution(RuntimeOrigin::root()) + } +} + +pub struct NormalDmpHandler; +impl DmpMessageHandler for NormalDmpHandler { + // This implementation makes messages be queued + // Since the limit is 0, messages are queued for next iteration + fn handle_dmp_messages( + iter: impl Iterator)>, + limit: Weight, + ) -> Weight { + (if Migrations::should_pause_xcm() { + DmpQueue::handle_dmp_messages(iter, Weight::zero()) + } else { + DmpQueue::handle_dmp_messages(iter, limit) + }) + ::DbWeight::get().reads(1) + } +} + +pub struct MaintenanceDmpHandler; +impl DmpMessageHandler for MaintenanceDmpHandler { + // This implementation makes messages be queued + // Since the limit is 0, messages are queued for next iteration + fn handle_dmp_messages( + iter: impl Iterator)>, + _limit: Weight, + ) -> Weight { + DmpQueue::handle_dmp_messages(iter, Weight::zero()) + } +} + +/// The hooks we wantt to run in Maintenance Mode +pub struct MaintenanceHooks; + +impl OnInitialize for MaintenanceHooks { + fn on_initialize(n: BlockNumber) -> Weight { + AllPalletsWithSystem::on_initialize(n) + } +} + +// return 0 +// For some reason using empty tuple () isnt working +// There exist only two pallets that use onIdle and these are xcmp and dmp queues +// For some reason putting an empty tumple does not work (transaction never finishes) +// We use an empty onIdle, if on the future we want one of the pallets to execute it +// we need to provide it here +impl OnIdle for MaintenanceHooks { + fn on_idle(_n: BlockNumber, _max_weight: Weight) -> Weight { + Weight::zero() + } +} + +impl OnRuntimeUpgrade for MaintenanceHooks { + fn on_runtime_upgrade() -> Weight { + AllPalletsWithSystem::on_runtime_upgrade() + } + + #[cfg(feature = "try-runtime")] + fn try_on_runtime_upgrade(checks: bool) -> Result { + AllPalletsWithSystem::try_on_runtime_upgrade(checks) + } +} + +impl OnFinalize for MaintenanceHooks { + fn on_finalize(n: BlockNumber) { + AllPalletsWithSystem::on_finalize(n) + } +} + +impl OffchainWorker for MaintenanceHooks { + fn offchain_worker(n: BlockNumber) { + AllPalletsWithSystem::offchain_worker(n) + } +} + +impl pallet_maintenance_mode::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type NormalCallFilter = NormalFilter; + type MaintenanceCallFilter = MaintenanceFilter; + type MaintenanceOrigin = + pallet_collective::EnsureProportionAtLeast; + type XcmExecutionManager = XcmExecutionManager; + type NormalDmpHandler = NormalDmpHandler; + type MaintenanceDmpHandler = MaintenanceDmpHandler; + // We use AllPalletsWithSystem because we dont want to change the hooks in normal + // operation + type NormalExecutiveHooks = AllPalletsWithSystem; + type MaintenanceExecutiveHooks = MaintenanceHooks; +} + +impl pallet_proxy_genesis_companion::Config for Runtime { + type ProxyType = ProxyType; +} + +parameter_types! { + pub OrbiterReserveIdentifier: [u8; 4] = [b'o', b'r', b'b', b'i']; +} + +type AddCollatorOrigin = + EitherOfDiverse, governance::custom_origins::GeneralAdmin>; +type DelCollatorOrigin = + EitherOfDiverse, governance::custom_origins::GeneralAdmin>; + +impl pallet_moonbeam_orbiters::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type AccountLookup = AuthorMapping; + type AddCollatorOrigin = AddCollatorOrigin; + type Currency = Balances; + type DelCollatorOrigin = DelCollatorOrigin; + /// Maximum number of orbiters per collator + type MaxPoolSize = ConstU32<8>; + /// Maximum number of round to keep on storage + type MaxRoundArchive = ConstU32<4>; + type OrbiterReserveIdentifier = OrbiterReserveIdentifier; + type RotatePeriod = ConstU32<3>; + /// Round index type. + type RoundIndex = pallet_parachain_staking::RoundIndex; + type WeightInfo = moonbeam_weights::pallet_moonbeam_orbiters::WeightInfo; +} + +/// Only callable after `set_validation_data` is called which forms this proof the same way +fn relay_chain_state_proof() -> RelayChainStateProof { + let relay_storage_root = ParachainSystem::validation_data() + .expect("set in `set_validation_data`") + .relay_parent_storage_root; + let relay_chain_state = + ParachainSystem::relay_state_proof().expect("set in `set_validation_data`"); + RelayChainStateProof::new(ParachainInfo::get(), relay_storage_root, relay_chain_state) + .expect("Invalid relay chain state proof, already constructed in `set_validation_data`") +} + +pub struct BabeDataGetter; +impl pallet_randomness::GetBabeData> for BabeDataGetter { + // Tolerate panic here because only ever called in inherent (so can be omitted) + fn get_epoch_index() -> u64 { + if cfg!(feature = "runtime-benchmarks") { + // storage reads as per actual reads + let _relay_storage_root = ParachainSystem::validation_data(); + let _relay_chain_state = ParachainSystem::relay_state_proof(); + const BENCHMARKING_NEW_EPOCH: u64 = 10u64; + return BENCHMARKING_NEW_EPOCH; + } + relay_chain_state_proof() + .read_optional_entry(relay_chain::well_known_keys::EPOCH_INDEX) + .ok() + .flatten() + .expect("expected to be able to read epoch index from relay chain state proof") + } + fn get_epoch_randomness() -> Option { + if cfg!(feature = "runtime-benchmarks") { + // storage reads as per actual reads + let _relay_storage_root = ParachainSystem::validation_data(); + let _relay_chain_state = ParachainSystem::relay_state_proof(); + let benchmarking_babe_output = Hash::default(); + return Some(benchmarking_babe_output); + } + relay_chain_state_proof() + .read_optional_entry(relay_chain::well_known_keys::ONE_EPOCH_AGO_RANDOMNESS) + .ok() + .flatten() + } +} + +impl pallet_randomness::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type AddressMapping = sp_runtime::traits::ConvertInto; + type Currency = Balances; + type BabeDataGetter = BabeDataGetter; + type VrfKeyLookup = AuthorMapping; + type Deposit = ConstU128<{ 1 * currency::MOVR * currency::SUPPLY_FACTOR }>; + type MaxRandomWords = ConstU8<100>; + type MinBlockDelay = ConstU32<2>; + type MaxBlockDelay = ConstU32<2_000>; + type BlockExpirationDelay = ConstU32<10_000>; + type EpochExpirationDelay = ConstU64<10_000>; + type WeightInfo = moonbeam_weights::pallet_randomness::WeightInfo; +} + +impl pallet_root_testing::Config for Runtime {} + +parameter_types! { + // One storage item; key size is 32 + 20; value is size 4+4+16+20 bytes = 44 bytes. + pub const DepositBase: Balance = currency::deposit(1, 96); + // Additional storage item size of 20 bytes. + pub const DepositFactor: Balance = currency::deposit(0, 20); + pub const MaxSignatories: u32 = 100; +} + +impl pallet_multisig::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type DepositBase = DepositBase; + type DepositFactor = DepositFactor; + type MaxSignatories = MaxSignatories; + type WeightInfo = moonbeam_weights::pallet_multisig::WeightInfo; +} + +construct_runtime! { + pub enum Runtime + { + // System support stuff. + System: frame_system::{Pallet, Call, Storage, Config, Event} = 0, + ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event} = 1, + // Previously 2: pallet_randomness_collective_flip + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 3, + ParachainInfo: parachain_info::{Pallet, Storage, Config} = 4, + RootTesting: pallet_root_testing::{Pallet, Call, Storage} = 5, + + // Monetary stuff. + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event} = 10, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Config, Event} = 11, + + // Consensus support. + ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Event, Config} = 20, + AuthorInherent: pallet_author_inherent::{Pallet, Call, Storage, Inherent} = 21, + AuthorFilter: pallet_author_slot_filter::{Pallet, Call, Storage, Event, Config} = 22, + AuthorMapping: pallet_author_mapping::{Pallet, Call, Config, Storage, Event} = 23, + MoonbeamOrbiters: pallet_moonbeam_orbiters::{Pallet, Call, Storage, Event} = 24, + + // Handy utilities. + Utility: pallet_utility::{Pallet, Call, Event} = 30, + Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 31, + MaintenanceMode: pallet_maintenance_mode::{Pallet, Call, Config, Storage, Event} = 32, + Identity: pallet_identity::{Pallet, Call, Storage, Event} = 33, + Migrations: pallet_migrations::{Pallet, Storage, Config, Event} = 34, + ProxyGenesisCompanion: pallet_proxy_genesis_companion::{Pallet, Config} = 35, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 36, + + // Sudo was previously index 40 + + // Ethereum compatibility + EthereumChainId: pallet_evm_chain_id::{Pallet, Storage, Config} = 50, + EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 51, + Ethereum: pallet_ethereum::{Pallet, Call, Storage, Event, Origin, Config} = 52, + + // Governance stuff. + Scheduler: pallet_scheduler::{Pallet, Storage, Event, Call} = 60, + Democracy: pallet_democracy::{Pallet, Storage, Config, Event, Call} = 61, + Preimage: pallet_preimage::{Pallet, Call, Storage, Event} = 62, + ConvictionVoting: pallet_conviction_voting::{Pallet, Call, Storage, Event} = 63, + Referenda: pallet_referenda::{Pallet, Call, Storage, Event} = 64, + Origins: governance::custom_origins::{Origin} = 65, + Whitelist: pallet_whitelist::{Pallet, Call, Storage, Event} = 66, + + // Council stuff. + CouncilCollective: + pallet_collective::::{Pallet, Call, Storage, Event, Origin, Config} = 70, + TechCommitteeCollective: + pallet_collective::::{Pallet, Call, Storage, Event, Origin, Config} = 71, + TreasuryCouncilCollective: + pallet_collective::::{Pallet, Call, Storage, Event, Origin, Config} = 72, + OpenTechCommitteeCollective: + pallet_collective::::{Pallet, Call, Storage, Event, Origin, Config} = 73, + + // Treasury stuff. + Treasury: pallet_treasury::{Pallet, Storage, Config, Event, Call} = 80, + + // Crowdloan stuff. + CrowdloanRewards: pallet_crowdloan_rewards::{Pallet, Call, Config, Storage, Event} = 90, + + // XCM Stuff + XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Storage, Event} = 100, + CumulusXcm: cumulus_pallet_xcm::{Pallet, Event, Origin} = 101, + DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 102, + PolkadotXcm: pallet_xcm::{Pallet, Storage, Call, Event, Origin, Config} = 103, + Assets: pallet_assets::{Pallet, Call, Storage, Event} = 104, + AssetManager: pallet_asset_manager::{Pallet, Call, Storage, Event} = 105, + XTokens: orml_xtokens::{Pallet, Call, Storage, Event} = 106, + XcmTransactor: pallet_xcm_transactor::{Pallet, Call, Storage, Event} = 107, + LocalAssets: pallet_assets::::{Pallet, Call, Storage, Event} = 108, + EthereumXcm: pallet_ethereum_xcm::{Pallet, Call, Storage, Origin} = 109, + Erc20XcmBridge: pallet_erc20_xcm_bridge::{Pallet} = 110, + + // Randomness + Randomness: pallet_randomness::{Pallet, Call, Storage, Event, Inherent} = 120, + } +} + +#[cfg(feature = "runtime-benchmarks")] +use { + moonbeam_xcm_benchmarks::generic::benchmarking as MoonbeamXcmBenchmarks, + MoonbeamXcmBenchmarks::XcmGenericBenchmarks as MoonbeamXcmGenericBench, +}; +#[cfg(feature = "runtime-benchmarks")] +mod benches { + frame_benchmarking::define_benchmarks!( + [pallet_utility, Utility] + [pallet_timestamp, Timestamp] + [pallet_balances, Balances] + [pallet_evm, EVM] + [pallet_assets, Assets] + [pallet_collective, CouncilCollective] + [pallet_parachain_staking, ParachainStaking] + [pallet_scheduler, Scheduler] + [pallet_democracy, Democracy] + [pallet_treasury, Treasury] + [pallet_author_inherent, AuthorInherent] + [pallet_author_slot_filter, AuthorFilter] + [pallet_crowdloan_rewards, CrowdloanRewards] + [pallet_author_mapping, AuthorMapping] + [pallet_proxy, Proxy] + [pallet_identity, Identity] + [cumulus_pallet_xcmp_queue, XcmpQueue] + [pallet_xcm, PolkadotXcm] + [pallet_asset_manager, AssetManager] + [pallet_xcm_transactor, XcmTransactor] + [pallet_moonbeam_orbiters, MoonbeamOrbiters] + [pallet_randomness, Randomness] + [pallet_conviction_voting, ConvictionVoting] + [pallet_referenda, Referenda] + [pallet_preimage, Preimage] + [pallet_whitelist, Whitelist] + [pallet_multisig, Multisig] + [moonbeam_xcm_benchmarks::weights::generic, MoonbeamXcmGenericBench::] + ); +} + +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; + +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckNonZeroSender, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, +); +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = + fp_self_contained::UncheckedExtrinsic; +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = + fp_self_contained::CheckedExtrinsic; +/// Executive: handles dispatch to the various pallets. +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + pallet_maintenance_mode::ExecutiveHooks, +>; + +// All of our runtimes share most of their Runtime API implementations. +// We use a macro to implement this common part and add runtime-specific additional implementations. +// This macro expands to : +// ``` +// impl_runtime_apis! { +// // All impl blocks shared between all runtimes. +// +// // Specific impls provided to the `impl_runtime_apis_plus_common!` macro. +// } +// ``` +moonbeam_runtime_common::impl_runtime_apis_plus_common! { + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction( + source: TransactionSource, + xt: ::Extrinsic, + block_hash: ::Hash, + ) -> TransactionValidity { + // Filtered calls should not enter the tx pool as they'll fail if inserted. + // If this call is not allowed, we return early. + if !::BaseCallFilter::contains(&xt.0.function) { + return InvalidTransaction::Call.into(); + } + + // This runtime uses Substrate's pallet transaction payment. This + // makes the chain feel like a standard Substrate chain when submitting + // frame transactions and using Substrate ecosystem tools. It has the downside that + // transaction are not prioritized by gas_price. The following code reprioritizes + // transactions to overcome this. + // + // A more elegant, ethereum-first solution is + // a pallet that replaces pallet transaction payment, and allows users + // to directly specify a gas price rather than computing an effective one. + // #HopefullySomeday + + // First we pass the transactions to the standard FRAME executive. This calculates all the + // necessary tags, longevity and other properties that we will leave unchanged. + // This also assigns some priority that we don't care about and will overwrite next. + let mut intermediate_valid = Executive::validate_transaction(source, xt.clone(), block_hash)?; + + let dispatch_info = xt.get_dispatch_info(); + + // If this is a pallet ethereum transaction, then its priority is already set + // according to gas price from pallet ethereum. If it is any other kind of transaction, + // we modify its priority. + Ok(match &xt.0.function { + RuntimeCall::Ethereum(transact { .. }) => intermediate_valid, + _ if dispatch_info.class != DispatchClass::Normal => intermediate_valid, + _ => { + let tip = match xt.0.signature { + None => 0, + Some((_, _, ref signed_extra)) => { + // Yuck, this depends on the index of charge transaction in Signed Extra + let charge_transaction = &signed_extra.7; + charge_transaction.tip() + } + }; + + // Calculate the fee that will be taken by pallet transaction payment + let fee: u64 = TransactionPayment::compute_fee( + xt.encode().len() as u32, + &dispatch_info, + tip, + ).saturated_into(); + + // Calculate how much gas this effectively uses according to the existing mapping + let effective_gas = + ::GasWeightMapping::weight_to_gas( + dispatch_info.weight + ); + + // Here we calculate an ethereum-style effective gas price using the + // current fee of the transaction. Because the weight -> gas conversion is + // lossy, we have to handle the case where a very low weight maps to zero gas. + let effective_gas_price = if effective_gas > 0 { + fee / effective_gas + } else { + // If the effective gas was zero, we just act like it was 1. + fee + }; + + // Overwrite the original prioritization with this ethereum one + intermediate_valid.priority = effective_gas_price; + intermediate_valid + } + }) + } + } +} + +// Check the timestamp and parachain inherents +struct CheckInherents; + +impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { + fn check_inherents( + block: &Block, + relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, + ) -> sp_inherents::CheckInherentsResult { + let relay_chain_slot = relay_state_proof + .read_slot() + .expect("Could not read the relay chain slot from the proof"); + + let inherent_data = + cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); + + inherent_data.check_extrinsics(&block) + } +} + +// Nimbus's Executive wrapper allows relay validators to verify the seal digest +cumulus_pallet_parachain_system::register_validate_block!( + Runtime = Runtime, + BlockExecutor = pallet_author_inherent::BlockExecutor::, + CheckInherents = CheckInherents, +); + +moonbeam_runtime_common::impl_self_contained_call!(); + +// Shorthand for a Get field of a pallet Config. +#[macro_export] +macro_rules! get { + ($pallet:ident, $name:ident, $type:ty) => { + <<$crate::Runtime as $pallet::Config>::$name as $crate::Get<$type>>::get() + }; +} + +#[cfg(test)] +mod tests { + use super::{currency::*, *}; + + #[test] + // Helps us to identify a Pallet Call in case it exceeds the 1kb limit. + // Hint: this should be a rare case. If that happens, one or more of the dispatchable arguments + // need to be Boxed. + fn call_max_size() { + const CALL_ALIGN: u32 = 1024; + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!( + std::mem::size_of::>() <= CALL_ALIGN as usize + ); + assert!(std::mem::size_of::>() <= CALL_ALIGN as usize); + assert!( + std::mem::size_of::>() + <= CALL_ALIGN as usize + ); + } + + #[test] + fn currency_constants_are_correct() { + assert_eq!(SUPPLY_FACTOR, 1); + + // txn fees + assert_eq!(TRANSACTION_BYTE_FEE, Balance::from(1 * GIGAWEI)); + assert_eq!( + get!(pallet_transaction_payment, OperationalFeeMultiplier, u8), + 5_u8 + ); + assert_eq!(STORAGE_BYTE_FEE, Balance::from(100 * MICROMOVR)); + + // democracy minimums + assert_eq!( + get!(pallet_democracy, MinimumDeposit, u128), + Balance::from(4 * MOVR) + ); + assert_eq!( + get!(pallet_preimage, ByteDeposit, u128), + Balance::from(100 * MICROMOVR) + ); + assert_eq!( + get!(pallet_treasury, ProposalBondMinimum, u128), + Balance::from(1 * MOVR) + ); + + // pallet_identity deposits + assert_eq!( + get!(pallet_identity, BasicDeposit, u128), + Balance::from(1 * MOVR + 25800 * MICROMOVR) + ); + assert_eq!( + get!(pallet_identity, FieldDeposit, u128), + Balance::from(6600 * MICROMOVR) + ); + assert_eq!( + get!(pallet_identity, SubAccountDeposit, u128), + Balance::from(1 * MOVR + 5300 * MICROMOVR) + ); + + // staking minimums + assert_eq!( + get!(pallet_parachain_staking, MinCandidateStk, u128), + Balance::from(500 * MOVR) + ); + assert_eq!( + get!(pallet_parachain_staking, MinDelegation, u128), + Balance::from(5 * MOVR) + ); + + // crowdloan min reward + assert_eq!( + get!(pallet_crowdloan_rewards, MinimumReward, u128), + Balance::from(0u128) + ); + + // deposit for AuthorMapping + assert_eq!( + get!(pallet_author_mapping, DepositAmount, u128), + Balance::from(100 * MOVR) + ); + + // proxy deposits + assert_eq!( + get!(pallet_proxy, ProxyDepositBase, u128), + Balance::from(1 * MOVR + 800 * MICROMOVR) + ); + assert_eq!( + get!(pallet_proxy, ProxyDepositFactor, u128), + Balance::from(2100 * MICROMOVR) + ); + assert_eq!( + get!(pallet_proxy, AnnouncementDepositBase, u128), + Balance::from(1 * MOVR + 800 * MICROMOVR) + ); + assert_eq!( + get!(pallet_proxy, AnnouncementDepositFactor, u128), + Balance::from(5600 * MICROMOVR) + ); + } + + #[test] + fn max_offline_rounds_lower_or_eq_than_reward_payment_delay() { + assert!( + get!(pallet_parachain_staking, MaxOfflineRounds, u32) + <= get!(pallet_parachain_staking, RewardPaymentDelay, u32) + ); + } + + #[test] + // Required migration is + // pallet_parachain_staking::migrations::IncreaseMaxTopDelegationsPerCandidate + // Purpose of this test is to remind of required migration if constant is ever changed + fn updating_maximum_delegators_per_candidate_requires_configuring_required_migration() { + assert_eq!( + get!(pallet_parachain_staking, MaxTopDelegationsPerCandidate, u32), + 300 + ); + assert_eq!( + get!( + pallet_parachain_staking, + MaxBottomDelegationsPerCandidate, + u32 + ), + 50 + ); + } + + #[test] + fn configured_base_extrinsic_weight_is_evm_compatible() { + let min_ethereum_transaction_weight = WeightPerGas::get() * 21_000; + let base_extrinsic = ::BlockWeights::get() + .get(frame_support::dispatch::DispatchClass::Normal) + .base_extrinsic; + assert!(base_extrinsic.ref_time() <= min_ethereum_transaction_weight.ref_time()); + } + + #[test] + fn test_storage_growth_ratio_is_correct() { + // This is the highest amount of new storage that can be created in a block 40 KB + let block_storage_limit = 40 * 1024; + let expected_storage_growth_ratio = BlockGasLimit::get() + .low_u64() + .saturating_div(block_storage_limit); + let actual_storage_growth_ratio = + ::GasLimitStorageGrowthRatio::get(); + assert_eq!( + expected_storage_growth_ratio, actual_storage_growth_ratio, + "Storage growth ratio is not correct" + ); + } +} diff --git a/tracing/2601/runtime/moonriver/src/precompiles.rs b/tracing/2601/runtime/moonriver/src/precompiles.rs new file mode 100644 index 00000000..efe024a9 --- /dev/null +++ b/tracing/2601/runtime/moonriver/src/precompiles.rs @@ -0,0 +1,267 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +use crate::{ + asset_config::{ForeignAssetInstance, LocalAssetInstance}, + xcm_config::XcmExecutorConfig, + CouncilInstance, OpenTechCommitteeInstance, TechCommitteeInstance, TreasuryCouncilInstance, +}; +use frame_support::parameter_types; +use pallet_evm_precompile_author_mapping::AuthorMappingPrecompile; +use pallet_evm_precompile_balances_erc20::{Erc20BalancesPrecompile, Erc20Metadata}; +use pallet_evm_precompile_batch::BatchPrecompile; +use pallet_evm_precompile_blake2::Blake2F; +use pallet_evm_precompile_bn128::{Bn128Add, Bn128Mul, Bn128Pairing}; +use pallet_evm_precompile_call_permit::CallPermitPrecompile; +use pallet_evm_precompile_collective::CollectivePrecompile; +use pallet_evm_precompile_conviction_voting::ConvictionVotingPrecompile; +use pallet_evm_precompile_crowdloan_rewards::CrowdloanRewardsPrecompile; +use pallet_evm_precompile_democracy::DemocracyPrecompile; +use pallet_evm_precompile_gmp::GmpPrecompile; +use pallet_evm_precompile_modexp::Modexp; +use pallet_evm_precompile_parachain_staking::ParachainStakingPrecompile; +use pallet_evm_precompile_preimage::PreimagePrecompile; +use pallet_evm_precompile_proxy::{OnlyIsProxyAndProxy, ProxyPrecompile}; +use pallet_evm_precompile_randomness::RandomnessPrecompile; +use pallet_evm_precompile_referenda::ReferendaPrecompile; +use pallet_evm_precompile_registry::PrecompileRegistry; +use pallet_evm_precompile_relay_encoder::RelayEncoderPrecompile; +use pallet_evm_precompile_sha3fips::Sha3FIPS256; +use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; +use pallet_evm_precompile_xcm_transactor::{ + v1::XcmTransactorPrecompileV1, v2::XcmTransactorPrecompileV2, v3::XcmTransactorPrecompileV3, +}; +use pallet_evm_precompile_xcm_utils::XcmUtilsPrecompile; +use pallet_evm_precompile_xtokens::XtokensPrecompile; +use pallet_evm_precompileset_assets_erc20::{Erc20AssetsPrecompileSet, IsForeign, IsLocal}; +use precompile_utils::precompile_set::*; + +pub struct NativeErc20Metadata; + +/// ERC20 metadata for the native token. +impl Erc20Metadata for NativeErc20Metadata { + /// Returns the name of the token. + fn name() -> &'static str { + "MOVR token" + } + + /// Returns the symbol of the token. + fn symbol() -> &'static str { + "MOVR" + } + + /// Returns the decimals places of the token. + fn decimals() -> u8 { + 18 + } + + /// Must return `true` only if it represents the main native currency of + /// the network. It must be the currency used in `pallet_evm`. + fn is_native_currency() -> bool { + true + } +} + +/// The asset precompile address prefix. Addresses that match against this prefix will be routed +/// to Erc20AssetsPrecompileSet being marked as foreign +pub const FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 4]; +/// The asset precompile address prefix. Addresses that match against this prefix will be routed +/// to Erc20AssetsPrecompileSet being marked as local +pub const LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8, 255u8, 255u8, 254u8]; + +parameter_types! { + pub ForeignAssetPrefix: &'static [u8] = FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX; + pub LocalAssetPrefix: &'static [u8] = LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX; +} + +type EthereumPrecompilesChecks = (AcceptDelegateCall, CallableByContract, CallableByPrecompile); + +#[precompile_utils::precompile_name_from_address] +type MoonriverPrecompilesAt = ( + // Ethereum precompiles: + // We allow DELEGATECALL to stay compliant with Ethereum behavior. + PrecompileAt, ECRecover, EthereumPrecompilesChecks>, + PrecompileAt, Sha256, EthereumPrecompilesChecks>, + PrecompileAt, Ripemd160, EthereumPrecompilesChecks>, + PrecompileAt, Identity, EthereumPrecompilesChecks>, + PrecompileAt, Modexp, EthereumPrecompilesChecks>, + PrecompileAt, Bn128Add, EthereumPrecompilesChecks>, + PrecompileAt, Bn128Mul, EthereumPrecompilesChecks>, + PrecompileAt, Bn128Pairing, EthereumPrecompilesChecks>, + PrecompileAt, Blake2F, EthereumPrecompilesChecks>, + // Non-Moonbeam specific nor Ethereum precompiles : + PrecompileAt, Sha3FIPS256, (CallableByContract, CallableByPrecompile)>, + RemovedPrecompileAt>, // Dispatch + PrecompileAt, ECRecoverPublicKey, (CallableByContract, CallableByPrecompile)>, + // Moonbeam specific precompiles: + PrecompileAt< + AddressU64<2048>, + ParachainStakingPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2049>, + CrowdloanRewardsPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2050>, + Erc20BalancesPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2051>, + DemocracyPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2052>, + XtokensPrecompile, + ( + SubcallWithMaxNesting<1>, + CallableByContract, + CallableByPrecompile, + ), + >, + PrecompileAt< + AddressU64<2053>, + RelayEncoderPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2054>, + XcmTransactorPrecompileV1, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2055>, + AuthorMappingPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2056>, + BatchPrecompile, + ( + SubcallWithMaxNesting<2>, + // Batch is the only precompile allowed to call Batch. + CallableByPrecompile>>, + ), + >, + PrecompileAt< + AddressU64<2057>, + RandomnessPrecompile, + (SubcallWithMaxNesting<0>, CallableByContract), + >, + PrecompileAt< + AddressU64<2058>, + CallPermitPrecompile, + (SubcallWithMaxNesting<0>, CallableByContract), + >, + PrecompileAt< + AddressU64<2059>, + ProxyPrecompile, + ( + CallableByContract>, + SubcallWithMaxNesting<0>, + // Batch is the only precompile allowed to call Proxy. + CallableByPrecompile>>, + ), + >, + PrecompileAt< + AddressU64<2060>, + XcmUtilsPrecompile, + CallableByContract< + pallet_evm_precompile_xcm_utils::AllExceptXcmExecute, + >, + >, + PrecompileAt< + AddressU64<2061>, + XcmTransactorPrecompileV2, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2062>, + CollectivePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2063>, + CollectivePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2064>, + CollectivePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2065>, + ReferendaPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2066>, + ConvictionVotingPrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2067>, + PreimagePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2068>, + CollectivePrecompile, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt< + AddressU64<2069>, + PrecompileRegistry, + (CallableByContract, CallableByPrecompile), + >, + PrecompileAt, GmpPrecompile, SubcallWithMaxNesting<0>>, + PrecompileAt< + AddressU64<2071>, + XcmTransactorPrecompileV3, + (CallableByContract, CallableByPrecompile), + >, +); + +/// The PrecompileSet installed in the Moonriver runtime. +/// We include the nine Istanbul precompiles +/// (https://github.com/ethereum/go-ethereum/blob/3c46f557/core/vm/contracts.go#L69) +/// The following distribution has been decided for the precompiles +/// 0-1023: Ethereum Mainnet Precompiles +/// 1024-2047 Precompiles that are not in Ethereum Mainnet but are neither Moonbeam specific +/// 2048-4095 Moonbeam specific precompiles +pub type MoonriverPrecompiles = PrecompileSetBuilder< + R, + ( + // Skip precompiles if out of range. + PrecompilesInRangeInclusive<(AddressU64<1>, AddressU64<4095>), MoonriverPrecompilesAt>, + // Prefixed precompile sets (XC20) + PrecompileSetStartingWith< + ForeignAssetPrefix, + Erc20AssetsPrecompileSet, + CallableByContract, + >, + PrecompileSetStartingWith< + LocalAssetPrefix, + Erc20AssetsPrecompileSet, + CallableByContract, + >, + ), +>; diff --git a/tracing/2601/runtime/moonriver/src/xcm_config.rs b/tracing/2601/runtime/moonriver/src/xcm_config.rs new file mode 100644 index 00000000..434cdbaa --- /dev/null +++ b/tracing/2601/runtime/moonriver/src/xcm_config.rs @@ -0,0 +1,704 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! XCM configuration for Moonbase. +//! + +use super::{ + governance, AccountId, AssetId, AssetManager, Assets, Balance, Balances, DealWithFees, + Erc20XcmBridge, LocalAssets, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, + RuntimeEvent, RuntimeOrigin, Treasury, XcmpQueue, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, +}; + +use frame_support::{ + parameter_types, + traits::{EitherOfDiverse, Everything, Nothing, PalletInfoAccess}, +}; +use moonbeam_runtime_common::weights as moonbeam_weights; +use pallet_evm_precompileset_assets_erc20::AccountIdAssetIdConversion; +use sp_runtime::{ + traits::{Hash as THash, MaybeEquivalence, PostDispatchInfoOf}, + DispatchErrorWithPostInfo, +}; +use sp_weights::Weight; + +use frame_system::{EnsureRoot, RawOrigin}; +use sp_core::{ConstU32, H160, H256}; + +use xcm_builder::{ + AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, + CurrencyAdapter as XcmCurrencyAdapter, EnsureXcmOrigin, FungiblesAdapter, NoChecking, + ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountKey20AsNative, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, + WeightInfoBounds, WithComputedOrigin, +}; + +use xcm::latest::prelude::*; +use xcm_executor::traits::{CallDispatcher, ConvertLocation, JustTry}; + +use orml_xcm_support::MultiNativeAsset; +use xcm_primitives::{ + AbsoluteAndRelativeReserve, AccountIdToCurrencyId, AccountIdToMultiLocation, AsAssetType, + FirstAssetTrader, SignedToAccountId20, UtilityAvailableCalls, UtilityEncodeCall, XcmTransact, +}; + +use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; + +use sp_std::{ + convert::{From, Into, TryFrom}, + prelude::*, +}; + +use orml_traits::parameter_type_with_key; + +use crate::governance::referenda::GeneralAdminOrRoot; + +parameter_types! { + // The network Id of the relay + pub const RelayNetwork: NetworkId = NetworkId::Kusama; + // The relay chain Origin type + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + // The universal location within the global consensus system + pub UniversalLocation: InteriorMultiLocation = + X2(GlobalConsensus(RelayNetwork::get()), Parachain(ParachainInfo::parachain_id().into())); + + // Self Reserve location, defines the multilocation identifiying the self-reserve currency + // This is used to match it also against our Balances pallet when we receive such + // a MultiLocation: (Self Balances pallet index) + // We use the RELATIVE multilocation + pub SelfReserve: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; + + // This is the relative view of our local assets. + // Indentified by thix prefix + generalIndex(assetId) + // We use the RELATIVE multilocation + pub LocalAssetsPalletLocation: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; +} + +/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used +/// when determining ownership of accounts for asset transacting and when attempting to use XCM +/// `Transact` in order to determine the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the default `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // If we receive a MultiLocation of type AccountKey20, just generate a native account + AccountKey20Aliases, + // Generate remote accounts according to polkadot standards + xcm_builder::HashedDescriptionDescribeFamilyAllTerminal, +); + +/// Wrapper type around `LocationToAccountId` to convert an `AccountId` to type `H160`. +pub struct LocationToH160; +impl ConvertLocation for LocationToH160 { + fn convert_location(location: &MultiLocation) -> Option { + >::convert_location(location) + .map(Into::into) + } +} + +// The non-reserve fungible transactor type +// It will use pallet-assets, and the Id will be matched against AsAssetType +pub type ForeignFungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + Assets, + // Use this currency when it is a fungible asset matching the given location or name: + ( + ConvertedConcreteId< + AssetId, + Balance, + AsAssetType, + JustTry, + >, + ), + // Do a simple punn to convert an AccountId20 MultiLocation into a native chain account ID: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont allow teleports. + NoChecking, + // We dont track any teleports + (), +>; + +/// The transactor for our own chain currency. +pub type LocalAssetTransactor = XcmCurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching any of the locations in + // SelfReserveRepresentations + xcm_builder::IsConcrete, + // We can convert the MultiLocations with our converter above: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont allow teleport + (), +>; + +/// Means for transacting local assets besides the native currency on this chain. +pub type LocalFungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + LocalAssets, + // Use this currency when it is a fungible asset matching the given location or name: + ( + ConvertedConcreteId< + AssetId, + Balance, + // This just tells to convert an assetId into a GeneralIndex junction prepended + // by LocalAssetsPalletLocationNewReanchor + AsPrefixedGeneralIndex, + JustTry, + >, + ), + // Convert an XCM MultiLocation into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont want to allow teleporting assets + NoChecking, + // The account to use for tracking teleports. + (), +>; + +// We use all transactors +// These correspond to +// SelfReserve asset, both pre and post 0.9.16 +// Foreign assets +// Local assets, both pre and post 0.9.16 +// We can remove the Old reanchor once +// we import https://github.com/open-web3-stack/open-runtime-module-library/pull/708 +pub type AssetTransactors = ( + LocalAssetTransactor, + ForeignFungiblesTransactor, + LocalFungiblesTransactor, + Erc20XcmBridge, +); + +/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, +/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can +/// biases the kind of local `Origin` it will become. +pub type XcmOriginToTransactDispatchOrigin = ( + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // recognised. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognised. + SiblingParachainAsNative, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + pallet_xcm::XcmPassthrough, + // Xcm Origins defined by a Multilocation of type AccountKey20 can be converted to a 20 byte- + // account local origin + SignedAccountKey20AsNative, +); + +parameter_types! { + /// The amount of weight an XCM operation takes. This is safe overestimate. + pub UnitWeightCost: Weight = Weight::from_parts(200_000_000u64, 0); + /// Maximum number of instructions in a single XCM fragment. A sanity check against + /// weight caculations getting too crazy. + pub MaxInstructions: u32 = 100; +} + +/// Xcm Weigher shared between multiple Xcm-related configs. +pub type XcmWeigher = WeightInfoBounds< + moonbeam_xcm_benchmarks::weights::XcmWeight, + RuntimeCall, + MaxInstructions, +>; + +pub type XcmBarrier = ( + // Weight that is paid for may be consumed. + TakeWeightCredit, + // Expected responses are OK. + AllowKnownQueryResponses, + WithComputedOrigin< + ( + // If the message is one that immediately attemps to pay for execution, then allow it. + AllowTopLevelPaidExecutionFrom, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, + ), + UniversalLocation, + ConstU32<8>, + >, +); + +parameter_types! { + /// Xcm fees will go to the treasury account + pub XcmFeesAccount: AccountId = Treasury::account_id(); +} + +/// This is the struct that will handle the revenue from xcm fees +/// We do not burn anything because we want to mimic exactly what +/// the sovereign account has +pub type XcmFeesToAccount = xcm_primitives::XcmFeesToAccount< + Assets, + ( + ConvertedConcreteId< + AssetId, + Balance, + AsAssetType, + JustTry, + >, + ), + AccountId, + XcmFeesAccount, +>; + +pub struct SafeCallFilter; +impl frame_support::traits::Contains for SafeCallFilter { + fn contains(_call: &RuntimeCall) -> bool { + // TODO review + // This needs to be addressed at EVM level + true + } +} + +parameter_types! { + pub const MaxAssetsIntoHolding: u32 = xcm_primitives::MAX_ASSETS; +} + +// Our implementation of the Moonbeam Call +// Attachs the right origin in case the call is made to pallet-ethereum-xcm +#[cfg(not(feature = "evm-tracing"))] +moonbeam_runtime_common::impl_moonbeam_xcm_call!(); +#[cfg(feature = "evm-tracing")] +moonbeam_runtime_common::impl_moonbeam_xcm_call_tracing!(); + +moonbeam_runtime_common::impl_evm_runner_precompile_or_eth_xcm!(); + +pub struct XcmExecutorConfig; +impl xcm_executor::Config for XcmExecutorConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + // How to withdraw and deposit an asset. + type AssetTransactor = AssetTransactors; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + // Filter to the reserve withdraw operations + // Whenever the reserve matches the relative or absolute value + // of our chain, we always return the relative reserve + type IsReserve = MultiNativeAsset>; + type IsTeleporter = (); // No teleport + type UniversalLocation = UniversalLocation; + type Barrier = XcmBarrier; + type Weigher = XcmWeigher; + // We use two traders + // When we receive the relative representation of the self-reserve asset, + // we use UsingComponents and the local way of handling fees + // When we receive a non-reserve asset, we use AssetManager to fetch how many + // units per second we should charge + type Trader = ( + UsingComponents< + ::WeightToFee, + SelfReserve, + AccountId, + Balances, + DealWithFees, + >, + FirstAssetTrader, + ); + type ResponseHandler = PolkadotXcm; + type SubscriptionService = PolkadotXcm; + type AssetTrap = pallet_erc20_xcm_bridge::AssetTrapWrapper; + type AssetClaims = PolkadotXcm; + type CallDispatcher = MoonbeamCall; + type PalletInstancesInfo = crate::AllPalletsWithSystem; + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type AssetLocker = (); + type AssetExchanger = (); + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; + type SafeCallFilter = SafeCallFilter; + type Aliasers = Nothing; +} + +type XcmExecutor = pallet_erc20_xcm_bridge::XcmExecutorWrapper< + RuntimeCall, + xcm_executor::XcmExecutor, +>; + +// Converts a Signed Local Origin into a MultiLocation +pub type LocalOriginToLocation = SignedToAccountId20; + +/// The means for routing XCM messages which are not for local execution into the right message +/// queues. +pub type XcmRouter = ( + // Two routers - use UMP to communicate with the relay chain: + cumulus_primitives_utility::ParentAsUmp, + // ..and XCMP to communicate with the sibling chains. + XcmpQueue, +); + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parent.into()); +} + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = Nothing; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = Nothing; + type XcmReserveTransferFilter = Everything; + type Weigher = XcmWeigher; + 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 = (); + type SovereignAccountOf = LocationToAccountId; + type MaxLockers = ConstU32<8>; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + // TODO pallet-xcm weights + type WeightInfo = moonbeam_weights::pallet_xcm::WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + type AdminOrigin = EnsureRoot; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +impl cumulus_pallet_xcmp_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; + type ChannelInfo = ParachainSystem; + type VersionWrapper = PolkadotXcm; + type ExecuteOverweightOrigin = EnsureRoot; + type ControllerOrigin = EnsureRoot; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; + type WeightInfo = moonbeam_weights::cumulus_pallet_xcmp_queue::WeightInfo; + type PriceForSiblingDelivery = (); +} + +impl cumulus_pallet_dmp_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; + type ExecuteOverweightOrigin = EnsureRoot; +} + +// Our AssetType. For now we only handle Xcm Assets +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum AssetType { + Xcm(MultiLocation), +} +impl Default for AssetType { + fn default() -> Self { + Self::Xcm(MultiLocation::here()) + } +} + +impl From for AssetType { + fn from(location: MultiLocation) -> Self { + Self::Xcm(location) + } +} +impl Into> for AssetType { + fn into(self) -> Option { + match self { + Self::Xcm(location) => Some(location), + } + } +} + +// Implementation on how to retrieve the AssetId from an AssetType +// We simply hash the AssetType and take the lowest 128 bits +impl From for AssetId { + fn from(asset: AssetType) -> AssetId { + match asset { + AssetType::Xcm(id) => { + let mut result: [u8; 16] = [0u8; 16]; + let hash: H256 = id.using_encoded(::Hashing::hash); + result.copy_from_slice(&hash.as_fixed_bytes()[0..16]); + u128::from_le_bytes(result) + } + } + } +} + +// Our currencyId. We distinguish for now between SelfReserve, and Others, defined by their Id. +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum CurrencyId { + // Our native token + SelfReserve, + // Assets representing other chains native tokens + ForeignAsset(AssetId), + // Our local assets + LocalAssetReserve(AssetId), + // Erc20 token + Erc20 { contract_address: H160 }, +} + +impl AccountIdToCurrencyId for Runtime { + fn account_to_currency_id(account: AccountId) -> Option { + Some(match account { + // the self-reserve currency is identified by the pallet-balances address + a if a == H160::from_low_u64_be(2050).into() => CurrencyId::SelfReserve, + // the rest of the currencies, by their corresponding erc20 address + _ => match Runtime::account_to_asset_id(account) { + // We distinguish by prefix, and depending on it we create either + // Foreign or Local + Some((prefix, asset_id)) => { + if prefix == FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX.to_vec() { + CurrencyId::ForeignAsset(asset_id) + } else { + CurrencyId::LocalAssetReserve(asset_id) + } + } + // If no known prefix is identified, we consider that it's a "real" erc20 token + // (i.e. managed by a real smart contract) + None => CurrencyId::Erc20 { + contract_address: account.into(), + }, + }, + }) + } +} + +// How to convert from CurrencyId to MultiLocation +pub struct CurrencyIdtoMultiLocation(sp_std::marker::PhantomData); +impl sp_runtime::traits::Convert> + for CurrencyIdtoMultiLocation +where + AssetXConverter: MaybeEquivalence, +{ + fn convert(currency: CurrencyId) -> Option { + match currency { + // For now and until Xtokens is adapted to handle 0.9.16 version we use + // the old anchoring here + // This is not a problem in either cases, since the view of the destination + // chain does not change + // TODO! change this to NewAnchoringSelfReserve once xtokens is adapted for it + CurrencyId::SelfReserve => { + let multi: MultiLocation = SelfReserve::get(); + Some(multi) + } + CurrencyId::ForeignAsset(asset) => AssetXConverter::convert_back(&asset), + CurrencyId::LocalAssetReserve(asset) => { + let mut location = LocalAssetsPalletLocation::get(); + location.push_interior(Junction::GeneralIndex(asset)).ok(); + Some(location) + } + CurrencyId::Erc20 { contract_address } => { + let mut location = Erc20XcmBridgePalletLocation::get(); + location + .push_interior(Junction::AccountKey20 { + key: contract_address.0, + network: None, + }) + .ok(); + Some(location) + } + } + } +} + +parameter_types! { + pub const BaseXcmWeight: Weight = Weight::from_parts(200_000_000u64, 0); + pub const MaxAssetsForTransfer: usize = 2; + + // This is how we are going to detect whether the asset is a Reserve asset + // This however is the chain part only + pub SelfLocation: MultiLocation = MultiLocation::here(); + // We need this to be able to catch when someone is trying to execute a non- + // cross-chain transfer in xtokens through the absolute path way + pub SelfLocationAbsolute: MultiLocation = MultiLocation { + parents:1, + interior: Junctions::X1( + Parachain(ParachainInfo::parachain_id().into()) + ) + }; +} + +parameter_type_with_key! { + pub ParachainMinFee: |location: MultiLocation| -> Option { + match (location.parents, location.first_interior()) { + // Kusama AssetHub fee + (1, Some(Parachain(1000u32))) => Some(50_000_000u128), + _ => None, + } + }; +} + +impl orml_xtokens::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type CurrencyId = CurrencyId; + type AccountIdToMultiLocation = AccountIdToMultiLocation; + type CurrencyIdConvert = + CurrencyIdtoMultiLocation>; + type XcmExecutor = XcmExecutor; + type SelfLocation = SelfLocation; + type Weigher = XcmWeigher; + type BaseXcmWeight = BaseXcmWeight; + type UniversalLocation = UniversalLocation; + type MaxAssetsForTransfer = MaxAssetsForTransfer; + type MinXcmFee = ParachainMinFee; + type MultiLocationsFilter = Everything; + type ReserveProvider = AbsoluteAndRelativeReserve; +} + +// 1 KSM should be enough +parameter_types! { + pub MaxHrmpRelayFee: MultiAsset = (MultiLocation::parent(), 1_000_000_000_000u128).into(); +} + +// For now we only allow to transact in the relay, although this might change in the future +// Transactors just defines the chains in which we allow transactions to be issued through +// xcm +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum Transactors { + Relay, +} + +// Default for benchmarking +#[cfg(feature = "runtime-benchmarks")] +impl Default for Transactors { + fn default() -> Self { + Transactors::Relay + } +} + +impl TryFrom for Transactors { + type Error = (); + fn try_from(value: u8) -> Result { + match value { + 0u8 => Ok(Transactors::Relay), + _ => Err(()), + } + } +} + +impl UtilityEncodeCall for Transactors { + fn encode_call(self, call: UtilityAvailableCalls) -> Vec { + match self { + Transactors::Relay => pallet_xcm_transactor::Pallet::::encode_call( + pallet_xcm_transactor::Pallet(sp_std::marker::PhantomData::), + call, + ), + } + } +} + +impl XcmTransact for Transactors { + fn destination(self) -> MultiLocation { + match self { + Transactors::Relay => MultiLocation::parent(), + } + } +} + +pub type DerivativeAddressRegistrationOrigin = + EitherOfDiverse, governance::custom_origins::GeneralAdmin>; + +impl pallet_xcm_transactor::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type Transactor = Transactors; + type DerivativeAddressRegistrationOrigin = DerivativeAddressRegistrationOrigin; + type SovereignAccountDispatcherOrigin = EnsureRoot; + type CurrencyId = CurrencyId; + type AccountIdToMultiLocation = AccountIdToMultiLocation; + type CurrencyIdToMultiLocation = + CurrencyIdtoMultiLocation>; + type XcmSender = XcmRouter; + type SelfLocation = SelfLocation; + type Weigher = XcmWeigher; + type UniversalLocation = UniversalLocation; + type BaseXcmWeight = BaseXcmWeight; + type AssetTransactor = AssetTransactors; + type ReserveProvider = AbsoluteAndRelativeReserve; + type WeightInfo = moonbeam_weights::pallet_xcm_transactor::WeightInfo; + type HrmpManipulatorOrigin = GeneralAdminOrRoot; + type MaxHrmpFee = xcm_builder::Case; +} + +parameter_types! { + // This is the relative view of erc20 assets. + // Identified by this prefix + AccountKey20(contractAddress) + // We use the RELATIVE multilocation + pub Erc20XcmBridgePalletLocation: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; + + // To be able to support almost all erc20 implementations, + // we provide a sufficiently hight gas limit. + pub Erc20XcmBridgeTransferGasLimit: u64 = 200_000; +} + +impl pallet_erc20_xcm_bridge::Config for Runtime { + type AccountIdConverter = LocationToH160; + type Erc20MultilocationPrefix = Erc20XcmBridgePalletLocation; + type Erc20TransferGasLimit = Erc20XcmBridgeTransferGasLimit; + type EvmRunner = EvmRunnerPrecompileOrEthXcm; +} + +#[cfg(feature = "runtime-benchmarks")] +mod testing { + use super::*; + + /// This From exists for benchmarking purposes. It has the potential side-effect of calling + /// AssetManager::set_asset_type_asset_id() and should NOT be used in any production code. + impl From for CurrencyId { + fn from(location: MultiLocation) -> CurrencyId { + use xcm_primitives::AssetTypeGetter; + + // If it does not exist, for benchmarking purposes, we create the association + let asset_id = if let Some(asset_id) = + AsAssetType::::convert_location(&location) + { + asset_id + } else { + let asset_type = AssetType::Xcm(location); + let asset_id: AssetId = asset_type.clone().into(); + AssetManager::set_asset_type_asset_id(asset_type, asset_id); + asset_id + }; + + CurrencyId::ForeignAsset(asset_id) + } + } +} diff --git a/tracing/2601/runtime/moonriver/tests/common/mod.rs b/tracing/2601/runtime/moonriver/tests/common/mod.rs new file mode 100644 index 00000000..8c20a49b --- /dev/null +++ b/tracing/2601/runtime/moonriver/tests/common/mod.rs @@ -0,0 +1,394 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +#![allow(dead_code)] + +use cumulus_primitives_parachain_inherent::ParachainInherentData; +use fp_evm::GenesisAccount; +use frame_support::{ + assert_ok, + traits::{OnFinalize, OnInitialize}, +}; +pub use moonriver_runtime::{ + asset_config::AssetRegistrarMetadata, + currency::{GIGAWEI, MOVR, SUPPLY_FACTOR, WEI}, + xcm_config::AssetType, + AccountId, AssetId, AssetManager, Assets, AuthorInherent, Balance, Balances, CrowdloanRewards, + Ethereum, Executive, Header, InflationInfo, LocalAssets, ParachainStaking, Range, Runtime, + RuntimeCall, RuntimeEvent, System, TransactionConverter, TransactionPaymentAsGasPrice, + UncheckedExtrinsic, HOURS, WEEKS, +}; +use nimbus_primitives::{NimbusId, NIMBUS_ENGINE_ID}; +use sp_core::{Encode, H160}; +use sp_runtime::{traits::Dispatchable, BuildStorage, Digest, DigestItem, Perbill, Percent}; + +use std::collections::BTreeMap; + +use fp_rpc::ConvertTransaction; +use pallet_transaction_payment::Multiplier; + +// A valid signed Alice transfer. +pub const VALID_ETH_TX: &str = + "02f86d8205018085174876e80085e8d4a5100082520894f24ff3a9cf04c71dbc94d0b566f7a27b9456\ + 6cac8080c001a0e1094e1a52520a75c0255db96132076dd0f1263089f838bea548cbdbfc64a4d19f031c\ + 92a8cb04e2d68d20a6158d542a07ac440cc8d07b6e36af02db046d92df"; + +// An invalid signed Alice transfer with a gas limit artifically set to 0. +pub const INVALID_ETH_TX: &str = + "f86180843b9aca00809412cb274aad8251c875c0bf6872b67d9983e53fdd01801ca00e28ba2dd3c5a\ + 3fd467d4afd7aefb4a34b373314fff470bb9db743a84d674a0aa06e5994f2d07eafe1c37b4ce5471ca\ + ecec29011f6f5bf0b1a552c55ea348df35f"; + +pub fn rpc_run_to_block(n: u32) { + while System::block_number() < n { + Ethereum::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + Ethereum::on_initialize(System::block_number()); + } +} + +/// Utility function that advances the chain to the desired block number. +/// If an author is provided, that author information is injected to all the blocks in the meantime. +pub fn run_to_block(n: u32, author: Option) { + // Finalize the first block + Ethereum::on_finalize(System::block_number()); + AuthorInherent::on_finalize(System::block_number()); + while System::block_number() < n { + // Set the new block number and author + match author { + Some(ref author) => { + let pre_digest = Digest { + logs: vec![DigestItem::PreRuntime(NIMBUS_ENGINE_ID, author.encode())], + }; + System::reset_events(); + System::initialize( + &(System::block_number() + 1), + &System::parent_hash(), + &pre_digest, + ); + } + None => { + System::set_block_number(System::block_number() + 1); + } + } + + // Initialize the new block + AuthorInherent::on_initialize(System::block_number()); + ParachainStaking::on_initialize(System::block_number()); + Ethereum::on_initialize(System::block_number()); + + // Finalize the block + Ethereum::on_finalize(System::block_number()); + AuthorInherent::on_finalize(System::block_number()); + ParachainStaking::on_finalize(System::block_number()); + } +} + +pub fn last_event() -> RuntimeEvent { + System::events().pop().expect("Event expected").event +} + +// Helper function to give a simple evm context suitable for tests. +// We can remove this once https://github.com/rust-blockchain/evm/pull/35 +// is in our dependency graph. +pub fn evm_test_context() -> fp_evm::Context { + fp_evm::Context { + address: Default::default(), + caller: Default::default(), + apparent_value: From::from(0), + } +} + +// Test struct with the purpose of initializing xcm assets +#[derive(Clone)] +pub struct XcmAssetInitialization { + pub asset_type: AssetType, + pub metadata: AssetRegistrarMetadata, + pub balances: Vec<(AccountId, Balance)>, + pub is_sufficient: bool, +} + +pub struct ExtBuilder { + // [asset, Vec, owner] + local_assets: Vec<(AssetId, Vec<(AccountId, Balance)>, AccountId)>, + // endowed accounts with balances + balances: Vec<(AccountId, Balance)>, + // [collator, amount] + collators: Vec<(AccountId, Balance)>, + // [delegator, collator, nomination_amount] + delegations: Vec<(AccountId, AccountId, Balance, Percent)>, + // per-round inflation config + inflation: InflationInfo, + // AuthorId -> AccoutId mappings + mappings: Vec<(NimbusId, AccountId)>, + // Crowdloan fund + crowdloan_fund: Balance, + // Chain id + chain_id: u64, + // EVM genesis accounts + evm_accounts: BTreeMap, + // [assettype, metadata, Vec, is_sufficient] + xcm_assets: Vec, + safe_xcm_version: Option, +} + +impl Default for ExtBuilder { + fn default() -> ExtBuilder { + ExtBuilder { + local_assets: vec![], + balances: vec![], + delegations: vec![], + collators: vec![], + inflation: InflationInfo { + expect: Range { + min: 100_000 * MOVR, + ideal: 200_000 * MOVR, + max: 500_000 * MOVR, + }, + // not used + annual: Range { + min: Perbill::from_percent(50), + ideal: Perbill::from_percent(50), + max: Perbill::from_percent(50), + }, + // unrealistically high parameterization, only for testing + round: Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }, + }, + mappings: vec![], + crowdloan_fund: 0, + chain_id: CHAIN_ID, + evm_accounts: BTreeMap::new(), + xcm_assets: vec![], + safe_xcm_version: None, + } + } +} + +impl ExtBuilder { + pub fn with_evm_accounts(mut self, accounts: BTreeMap) -> Self { + self.evm_accounts = accounts; + self + } + + pub fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { + self.balances = balances; + self + } + + pub fn with_collators(mut self, collators: Vec<(AccountId, Balance)>) -> Self { + self.collators = collators; + self + } + + pub fn with_delegations(mut self, delegations: Vec<(AccountId, AccountId, Balance)>) -> Self { + self.delegations = delegations + .into_iter() + .map(|d| (d.0, d.1, d.2, Percent::zero())) + .collect(); + self + } + + pub fn with_crowdloan_fund(mut self, crowdloan_fund: Balance) -> Self { + self.crowdloan_fund = crowdloan_fund; + self + } + + pub fn with_mappings(mut self, mappings: Vec<(NimbusId, AccountId)>) -> Self { + self.mappings = mappings; + self + } + + #[allow(dead_code)] + pub fn with_inflation(mut self, inflation: InflationInfo) -> Self { + self.inflation = inflation; + self + } + + pub fn with_xcm_assets(mut self, xcm_assets: Vec) -> Self { + self.xcm_assets = xcm_assets; + self + } + + pub fn with_safe_xcm_version(mut self, safe_xcm_version: u32) -> Self { + self.safe_xcm_version = Some(safe_xcm_version); + self + } + + pub fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap(); + + pallet_balances::GenesisConfig:: { + balances: self.balances, + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_parachain_staking::GenesisConfig:: { + candidates: self.collators, + delegations: self.delegations, + inflation_config: self.inflation, + collator_commission: Perbill::from_percent(20), + parachain_bond_reserve_percent: Percent::from_percent(30), + blocks_per_round: 2 * HOURS, + num_selected_candidates: 8, + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_crowdloan_rewards::GenesisConfig:: { + funded_amount: self.crowdloan_fund, + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_author_mapping::GenesisConfig:: { + mappings: self.mappings, + } + .assimilate_storage(&mut t) + .unwrap(); + + let genesis_config = pallet_evm_chain_id::GenesisConfig:: { + chain_id: self.chain_id, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let genesis_config = pallet_evm::GenesisConfig:: { + accounts: self.evm_accounts, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let genesis_config = pallet_ethereum::GenesisConfig:: { + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let genesis_config = pallet_xcm::GenesisConfig:: { + safe_xcm_version: self.safe_xcm_version, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let genesis_config = pallet_transaction_payment::GenesisConfig:: { + multiplier: Multiplier::from(10u128), + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + let local_assets = self.local_assets.clone(); + let xcm_assets = self.xcm_assets.clone(); + ext.execute_with(|| { + // If any local assets specified, we create them here + for (asset_id, balances, owner) in local_assets.clone() { + LocalAssets::force_create(root_origin(), asset_id.into(), owner, true, 1).unwrap(); + for (account, balance) in balances { + LocalAssets::mint(origin_of(owner.into()), asset_id.into(), account, balance) + .unwrap(); + } + } + // If any xcm assets specified, we register them here + for xcm_asset_initialization in xcm_assets { + let asset_id: AssetId = xcm_asset_initialization.asset_type.clone().into(); + AssetManager::register_foreign_asset( + root_origin(), + xcm_asset_initialization.asset_type, + xcm_asset_initialization.metadata, + 1, + xcm_asset_initialization.is_sufficient, + ) + .unwrap(); + for (account, balance) in xcm_asset_initialization.balances { + Assets::mint( + origin_of(AssetManager::account_id()), + asset_id.into(), + account, + balance, + ) + .unwrap(); + } + } + System::set_block_number(1); + }); + ext + } +} + +pub const CHAIN_ID: u64 = 1281; +pub const ALICE: [u8; 20] = [4u8; 20]; +pub const ALICE_NIMBUS: [u8; 32] = [4u8; 32]; +pub const BOB: [u8; 20] = [5u8; 20]; +pub const CHARLIE: [u8; 20] = [6u8; 20]; +pub const DAVE: [u8; 20] = [7u8; 20]; +pub const EVM_CONTRACT: [u8; 20] = [8u8; 20]; + +pub fn origin_of(account_id: AccountId) -> ::RuntimeOrigin { + ::RuntimeOrigin::signed(account_id) +} + +pub fn inherent_origin() -> ::RuntimeOrigin { + ::RuntimeOrigin::none() +} + +pub fn root_origin() -> ::RuntimeOrigin { + ::RuntimeOrigin::root() +} + +/// Mock the inherent that sets validation data in ParachainSystem, which +/// contains the `relay_chain_block_number`, which is used in `author-filter` as a +/// source of randomness to filter valid authors at each block. +pub fn set_parachain_inherent_data() { + use cumulus_primitives_core::PersistedValidationData; + use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; + let (relay_parent_storage_root, relay_chain_state) = + RelayStateSproofBuilder::default().into_state_root_and_proof(); + let vfp = PersistedValidationData { + relay_parent_number: 1u32, + relay_parent_storage_root, + ..Default::default() + }; + let parachain_inherent_data = ParachainInherentData { + validation_data: vfp, + relay_chain_state: relay_chain_state, + downward_messages: Default::default(), + horizontal_messages: Default::default(), + }; + assert_ok!(RuntimeCall::ParachainSystem( + cumulus_pallet_parachain_system::Call::::set_validation_data { + data: parachain_inherent_data + } + ) + .dispatch(inherent_origin())); +} + +pub fn unchecked_eth_tx(raw_hex_tx: &str) -> UncheckedExtrinsic { + let converter = TransactionConverter; + converter.convert_transaction(ethereum_transaction(raw_hex_tx)) +} + +pub fn ethereum_transaction(raw_hex_tx: &str) -> pallet_ethereum::Transaction { + let bytes = hex::decode(raw_hex_tx).expect("Transaction bytes."); + let transaction = ethereum::EnvelopedDecodable::decode(&bytes[..]); + assert!(transaction.is_ok()); + transaction.unwrap() +} diff --git a/tracing/2601/runtime/moonriver/tests/evm_tracing.rs b/tracing/2601/runtime/moonriver/tests/evm_tracing.rs new file mode 100644 index 00000000..12fab581 --- /dev/null +++ b/tracing/2601/runtime/moonriver/tests/evm_tracing.rs @@ -0,0 +1,94 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Moonriver EVM tracing Integration Tests + +mod common; + +#[cfg(test)] +#[cfg(feature = "evm-tracing")] +mod tests { + use super::common::*; + + use pallet_evm::AddressMapping; + use sp_core::H160; + + use moonbeam_rpc_primitives_debug::runtime_decl_for_debug_runtime_api::DebugRuntimeApi; + use std::str::FromStr; + + #[test] + fn debug_runtime_api_trace_transaction() { + let alith = ::AddressMapping::into_account_id( + H160::from_str("6be02d1d3665660d22ff9624b7be0551ee1ac91b") + .expect("internal H160 is valid; qed"), + ); + ExtBuilder::default() + .with_balances(vec![ + (alith, 2_000 * MOVR), + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .build() + .execute_with(|| { + let non_eth_uxt = UncheckedExtrinsic::new_unsigned( + pallet_balances::Call::::transfer { + dest: AccountId::from(BOB), + value: 1 * MOVR, + } + .into(), + ); + let transaction = ethereum_transaction(VALID_ETH_TX); + let eth_uxt = unchecked_eth_tx(VALID_ETH_TX); + assert!(Runtime::trace_transaction( + vec![non_eth_uxt.clone(), eth_uxt, non_eth_uxt.clone()], + &transaction + ) + .is_ok()); + }); + } + + #[test] + fn debug_runtime_api_trace_block() { + let alith = ::AddressMapping::into_account_id( + H160::from_str("6be02d1d3665660d22ff9624b7be0551ee1ac91b") + .expect("internal H160 is valid; qed"), + ); + ExtBuilder::default() + .with_balances(vec![ + (alith, 2_000 * MOVR), + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .build() + .execute_with(|| { + let non_eth_uxt = UncheckedExtrinsic::new_unsigned( + pallet_balances::Call::::transfer { + dest: AccountId::from(BOB), + value: 1 * MOVR, + } + .into(), + ); + let eth_uxt = unchecked_eth_tx(VALID_ETH_TX); + let eth_tx = ethereum_transaction(VALID_ETH_TX); + let eth_extrinsic_hash = eth_tx.hash(); + assert!(Runtime::trace_block( + vec![non_eth_uxt.clone(), eth_uxt.clone(), non_eth_uxt, eth_uxt], + vec![eth_extrinsic_hash, eth_extrinsic_hash] + ) + .is_ok()); + }); + } +} diff --git a/tracing/2601/runtime/moonriver/tests/integration_test.rs b/tracing/2601/runtime/moonriver/tests/integration_test.rs new file mode 100644 index 00000000..47cd212b --- /dev/null +++ b/tracing/2601/runtime/moonriver/tests/integration_test.rs @@ -0,0 +1,2726 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Moonriver Runtime Integration Tests + +#![cfg(test)] + +mod common; +use common::*; + +use fp_evm::{Context, IsPrecompileResult}; +use frame_support::{ + assert_noop, assert_ok, + dispatch::DispatchClass, + traits::{ + fungible::Inspect, Currency as CurrencyT, EnsureOrigin, PalletInfo, StorageInfo, + StorageInfoTrait, + }, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, + StorageHasher, Twox128, +}; +use moonbeam_xcm_benchmarks::weights::XcmWeight; +use moonriver_runtime::{ + asset_config::LocalAssetInstance, + xcm_config::{CurrencyId, SelfReserve}, + AssetId, CouncilCollective, OpenTechCommitteeCollective, PolkadotXcm, Precompiles, + RuntimeBlockWeights, TechCommitteeCollective, TransactionPayment, TreasuryCouncilCollective, + XTokens, XcmTransactor, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, +}; +use nimbus_primitives::NimbusId; +use pallet_evm::PrecompileSet; +use pallet_evm_precompileset_assets_erc20::{ + AccountIdAssetIdConversion, IsLocal, SELECTOR_LOG_APPROVAL, SELECTOR_LOG_TRANSFER, +}; +use pallet_transaction_payment::Multiplier; +use pallet_xcm_transactor::{Currency, CurrencyPayment, TransactWeights}; +use parity_scale_codec::Encode; +use polkadot_parachain::primitives::Sibling; +use precompile_utils::{ + precompile_set::{is_precompile_or_fail, IsActivePrecompile}, + prelude::*, + testing::*, +}; +use sha3::{Digest, Keccak256}; +use sp_core::{ByteArray, Pair, H160, U256}; +use sp_runtime::{ + traits::{Convert, Dispatchable}, + BuildStorage, DispatchError, ModuleError, +}; +use std::str::from_utf8; +use xcm::latest::prelude::*; +use xcm::{VersionedMultiAssets, VersionedMultiLocation}; +use xcm_builder::{ParentIsPreset, SiblingParachainConvertsVia}; +use xcm_executor::traits::ConvertLocation; + +type BatchPCall = pallet_evm_precompile_batch::BatchPrecompileCall; +type CrowdloanRewardsPCall = + pallet_evm_precompile_crowdloan_rewards::CrowdloanRewardsPrecompileCall; +type XcmUtilsPCall = pallet_evm_precompile_xcm_utils::XcmUtilsPrecompileCall< + Runtime, + moonriver_runtime::xcm_config::XcmExecutorConfig, +>; +type XtokensPCall = pallet_evm_precompile_xtokens::XtokensPrecompileCall; +type LocalAssetsPCall = pallet_evm_precompileset_assets_erc20::Erc20AssetsPrecompileSetCall< + Runtime, + IsLocal, + LocalAssetInstance, +>; +type XcmTransactorV2PCall = + pallet_evm_precompile_xcm_transactor::v2::XcmTransactorPrecompileV2Call; + +const BASE_FEE_GENESIS: u128 = 100 * GIGAWEI; + +#[test] +fn xcmp_queue_controller_origin_is_root() { + // important for the XcmExecutionManager impl of PauseExecution which uses root origin + // to suspend/resume XCM execution in xcmp_queue::on_idle + assert_ok!( + ::ControllerOrigin::ensure_origin(root_origin()) + ); +} + +#[test] +fn fast_track_available() { + assert!(moonriver_runtime::get!( + pallet_democracy, + InstantAllowed, + bool + )); +} + +#[test] +fn verify_pallet_prefixes() { + fn is_pallet_prefix(name: &str) { + // Compares the unhashed pallet prefix in the `StorageInstance` implementation by every + // storage item in the pallet P. This pallet prefix is used in conjunction with the + // item name to get the unique storage key: hash(PalletPrefix) + hash(StorageName) + // https://github.com/paritytech/substrate/blob/master/frame/support/procedural/src/pallet/ + // expand/storage.rs#L389-L401 + assert_eq!( + ::PalletInfo::name::

(), + Some(name) + ); + } + // TODO: use StorageInfoTrait from https://github.com/paritytech/substrate/pull/9246 + // This is now available with polkadot-v0.9.9 dependencies + is_pallet_prefix::("System"); + is_pallet_prefix::("Utility"); + is_pallet_prefix::("ParachainSystem"); + is_pallet_prefix::("TransactionPayment"); + is_pallet_prefix::("ParachainInfo"); + is_pallet_prefix::("EthereumChainId"); + is_pallet_prefix::("EVM"); + is_pallet_prefix::("Ethereum"); + is_pallet_prefix::("ParachainStaking"); + is_pallet_prefix::("MaintenanceMode"); + is_pallet_prefix::("Scheduler"); + is_pallet_prefix::("Democracy"); + is_pallet_prefix::("CouncilCollective"); + is_pallet_prefix::("TechCommitteeCollective"); + is_pallet_prefix::( + "OpenTechCommitteeCollective", + ); + is_pallet_prefix::("Treasury"); + is_pallet_prefix::("AuthorInherent"); + is_pallet_prefix::("AuthorFilter"); + is_pallet_prefix::("CrowdloanRewards"); + is_pallet_prefix::("AuthorMapping"); + is_pallet_prefix::("Identity"); + is_pallet_prefix::("XcmpQueue"); + is_pallet_prefix::("CumulusXcm"); + is_pallet_prefix::("DmpQueue"); + is_pallet_prefix::("PolkadotXcm"); + is_pallet_prefix::("Assets"); + is_pallet_prefix::("XTokens"); + is_pallet_prefix::("AssetManager"); + is_pallet_prefix::("Migrations"); + is_pallet_prefix::("XcmTransactor"); + is_pallet_prefix::("ProxyGenesisCompanion"); + is_pallet_prefix::("LocalAssets"); + is_pallet_prefix::("MoonbeamOrbiters"); + is_pallet_prefix::("TreasuryCouncilCollective"); + + let prefix = |pallet_name, storage_name| { + let mut res = [0u8; 32]; + res[0..16].copy_from_slice(&Twox128::hash(pallet_name)); + res[16..32].copy_from_slice(&Twox128::hash(storage_name)); + res.to_vec() + }; + assert_eq!( + ::storage_info(), + vec![ + StorageInfo { + pallet_name: b"Timestamp".to_vec(), + storage_name: b"Now".to_vec(), + prefix: prefix(b"Timestamp", b"Now"), + max_values: Some(1), + max_size: Some(8), + }, + StorageInfo { + pallet_name: b"Timestamp".to_vec(), + storage_name: b"DidUpdate".to_vec(), + prefix: prefix(b"Timestamp", b"DidUpdate"), + max_values: Some(1), + max_size: Some(1), + } + ] + ); + assert_eq!( + ::storage_info(), + vec![ + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"TotalIssuance".to_vec(), + prefix: prefix(b"Balances", b"TotalIssuance"), + max_values: Some(1), + max_size: Some(16), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"InactiveIssuance".to_vec(), + prefix: prefix(b"Balances", b"InactiveIssuance"), + max_values: Some(1), + max_size: Some(16), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Account".to_vec(), + prefix: prefix(b"Balances", b"Account"), + max_values: None, + max_size: Some(100), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Locks".to_vec(), + prefix: prefix(b"Balances", b"Locks"), + max_values: None, + max_size: Some(1287), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Reserves".to_vec(), + prefix: prefix(b"Balances", b"Reserves"), + max_values: None, + max_size: Some(1037), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Holds".to_vec(), + prefix: prefix(b"Balances", b"Holds"), + max_values: None, + max_size: Some(37), + }, + StorageInfo { + pallet_name: b"Balances".to_vec(), + storage_name: b"Freezes".to_vec(), + prefix: prefix(b"Balances", b"Freezes"), + max_values: None, + max_size: Some(37), + }, + ] + ); + assert_eq!( + ::storage_info(), + vec![ + StorageInfo { + pallet_name: b"Proxy".to_vec(), + storage_name: b"Proxies".to_vec(), + prefix: prefix(b"Proxy", b"Proxies"), + max_values: None, + max_size: Some(845), + }, + StorageInfo { + pallet_name: b"Proxy".to_vec(), + storage_name: b"Announcements".to_vec(), + prefix: prefix(b"Proxy", b"Announcements"), + max_values: None, + max_size: Some(1837), + } + ] + ); + assert_eq!( + ::storage_info(), + vec![StorageInfo { + pallet_name: b"MaintenanceMode".to_vec(), + storage_name: b"MaintenanceMode".to_vec(), + prefix: prefix(b"MaintenanceMode", b"MaintenanceMode"), + max_values: Some(1), + max_size: None, + },] + ); +} + +#[test] +fn test_collectives_storage_item_prefixes() { + for StorageInfo { pallet_name, .. } in + ::storage_info() + { + assert_eq!(pallet_name, b"CouncilCollective".to_vec()); + } + + for StorageInfo { pallet_name, .. } in + ::storage_info() + { + assert_eq!(pallet_name, b"TechCommitteeCollective".to_vec()); + } + + for StorageInfo { pallet_name, .. } in + ::storage_info() + { + assert_eq!(pallet_name, b"TreasuryCouncilCollective".to_vec()); + } + + for StorageInfo { pallet_name, .. } in + ::storage_info() + { + assert_eq!(pallet_name, b"OpenTechCommitteeCollective".to_vec()); + } +} + +#[test] +fn collective_set_members_root_origin_works() { + ExtBuilder::default().build().execute_with(|| { + // CouncilCollective + assert_ok!(CouncilCollective::set_members( + ::RuntimeOrigin::root(), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + )); + // TechCommitteeCollective + assert_ok!(TechCommitteeCollective::set_members( + ::RuntimeOrigin::root(), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + )); + // TreasuryCouncilCollective + assert_ok!(TreasuryCouncilCollective::set_members( + ::RuntimeOrigin::root(), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + )); + // OpenTechCommitteeCollective + assert_ok!(OpenTechCommitteeCollective::set_members( + ::RuntimeOrigin::root(), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + )); + }); +} + +#[test] +fn collective_set_members_general_admin_origin_works() { + use moonriver_runtime::{ + governance::custom_origins::Origin as CustomOrigin, OriginCaller, Utility, + }; + + ExtBuilder::default().build().execute_with(|| { + let root_caller = ::RuntimeOrigin::root(); + let alice = AccountId::from(ALICE); + + // CouncilCollective + let _ = Utility::dispatch_as( + root_caller.clone(), + Box::new(OriginCaller::Origins(CustomOrigin::GeneralAdmin)), + Box::new( + pallet_collective::Call::::set_members { + new_members: vec![alice, AccountId::from(BOB)], + prime: Some(alice), + old_count: 2, + } + .into(), + ), + ); + // TechCommitteeCollective + let _ = Utility::dispatch_as( + root_caller.clone(), + Box::new(OriginCaller::Origins(CustomOrigin::GeneralAdmin)), + Box::new( + pallet_collective::Call::::set_members { + new_members: vec![alice, AccountId::from(BOB)], + prime: Some(alice), + old_count: 2, + } + .into(), + ), + ); + // TreasuryCouncilCollective + let _ = Utility::dispatch_as( + root_caller.clone(), + Box::new(OriginCaller::Origins(CustomOrigin::GeneralAdmin)), + Box::new( + pallet_collective::Call::::set_members { + new_members: vec![alice, AccountId::from(BOB)], + prime: Some(alice), + old_count: 2, + } + .into(), + ), + ); + // OpenTechCommitteeCollective + let _ = Utility::dispatch_as( + root_caller, + Box::new(OriginCaller::Origins(CustomOrigin::GeneralAdmin)), + Box::new( + pallet_collective::Call::::set_members { + new_members: vec![alice, AccountId::from(BOB)], + prime: Some(alice), + old_count: 2, + } + .into(), + ), + ); + + assert_eq!( + System::events() + .into_iter() + .filter_map(|r| { + match r.event { + RuntimeEvent::Utility(pallet_utility::Event::DispatchedAs { result }) + if result.is_ok() => + { + Some(true) + } + _ => None, + } + }) + .collect::>() + .len(), + 4 + ) + }); +} + +#[test] +fn collective_set_members_signed_origin_does_not_work() { + let alice = AccountId::from(ALICE); + ExtBuilder::default().build().execute_with(|| { + // CouncilCollective + assert!(CouncilCollective::set_members( + ::RuntimeOrigin::signed(alice), + vec![alice, AccountId::from(BOB)], + Some(alice), + 2 + ) + .is_err()); + // TechCommitteeCollective + assert!(TechCommitteeCollective::set_members( + ::RuntimeOrigin::signed(alice), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + ) + .is_err()); + // TreasuryCouncilCollective + assert!(TreasuryCouncilCollective::set_members( + ::RuntimeOrigin::signed(alice), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + ) + .is_err()); + // OpenTechCommitteeCollective + assert!(OpenTechCommitteeCollective::set_members( + ::RuntimeOrigin::signed(alice), + vec![AccountId::from(ALICE), AccountId::from(BOB)], + Some(AccountId::from(ALICE)), + 2 + ) + .is_err()); + }); +} + +#[test] +fn verify_pallet_indices() { + fn is_pallet_index(index: usize) { + assert_eq!( + ::PalletInfo::index::

(), + Some(index) + ); + } + // System support + is_pallet_index::(0); + is_pallet_index::(1); + is_pallet_index::(3); + is_pallet_index::(4); + // Monetary + is_pallet_index::(10); + is_pallet_index::(11); + // Consensus support + is_pallet_index::(20); + is_pallet_index::(21); + is_pallet_index::(22); + is_pallet_index::(23); + is_pallet_index::(24); + // Handy utilities + is_pallet_index::(30); + is_pallet_index::(31); + is_pallet_index::(32); + is_pallet_index::(33); + is_pallet_index::(34); + is_pallet_index::(35); + // Ethereum compatibility + is_pallet_index::(50); + is_pallet_index::(51); + is_pallet_index::(52); + // Governance + is_pallet_index::(60); + is_pallet_index::(61); + // Council + is_pallet_index::(70); + is_pallet_index::(71); + is_pallet_index::(72); + is_pallet_index::(73); + // Treasury + is_pallet_index::(80); + // Crowdloan + is_pallet_index::(90); + // XCM Stuff + is_pallet_index::(100); + is_pallet_index::(101); + is_pallet_index::(102); + is_pallet_index::(103); + is_pallet_index::(104); + is_pallet_index::(105); + is_pallet_index::(106); + is_pallet_index::(107); + is_pallet_index::(108); +} + +#[test] +fn verify_reserved_indices() { + use frame_metadata::*; + let metadata = moonriver_runtime::Runtime::metadata(); + let metadata = match metadata.1 { + RuntimeMetadata::V14(metadata) => metadata, + _ => panic!("metadata has been bumped, test needs to be updated"), + }; + // 40: Sudo + // 53: BaseFee + let reserved = vec![40, 53]; + let existing = metadata + .pallets + .iter() + .map(|p| p.index) + .collect::>(); + assert!(reserved.iter().all(|index| !existing.contains(index))); +} + +#[test] +fn verify_proxy_type_indices() { + assert_eq!(moonriver_runtime::ProxyType::Any as u8, 0); + assert_eq!(moonriver_runtime::ProxyType::NonTransfer as u8, 1); + assert_eq!(moonriver_runtime::ProxyType::Governance as u8, 2); + assert_eq!(moonriver_runtime::ProxyType::Staking as u8, 3); + assert_eq!(moonriver_runtime::ProxyType::CancelProxy as u8, 4); + assert_eq!(moonriver_runtime::ProxyType::Balances as u8, 5); + assert_eq!(moonriver_runtime::ProxyType::AuthorMapping as u8, 6); + assert_eq!(moonriver_runtime::ProxyType::IdentityJudgement as u8, 7); +} + +#[test] +fn join_collator_candidates() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 20_000 * MOVR), + (AccountId::from(BOB), 20_000 * MOVR), + (AccountId::from(CHARLIE), 10_100 * MOVR), + (AccountId::from(DAVE), 10_000 * MOVR), + ]) + .with_collators(vec![ + (AccountId::from(ALICE), 10_000 * MOVR), + (AccountId::from(BOB), 10_000 * MOVR), + ]) + .with_delegations(vec![ + (AccountId::from(CHARLIE), AccountId::from(ALICE), 50 * MOVR), + (AccountId::from(CHARLIE), AccountId::from(BOB), 50 * MOVR), + ]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates( + origin_of(AccountId::from(ALICE)), + 10_000 * MOVR, + 2u32 + ), + pallet_parachain_staking::Error::::CandidateExists + ); + assert_noop!( + ParachainStaking::join_candidates( + origin_of(AccountId::from(CHARLIE)), + 10_000 * MOVR, + 2u32 + ), + pallet_parachain_staking::Error::::DelegatorExists + ); + assert!(System::events().is_empty()); + assert_ok!(ParachainStaking::join_candidates( + origin_of(AccountId::from(DAVE)), + 10_000 * MOVR, + 2u32 + )); + assert_eq!( + last_event(), + RuntimeEvent::ParachainStaking( + pallet_parachain_staking::Event::JoinedCollatorCandidates { + account: AccountId::from(DAVE), + amount_locked: 10_000 * MOVR, + new_total_amt_locked: 30_100 * MOVR + } + ) + ); + let candidates = ParachainStaking::candidate_pool(); + assert_eq!(candidates.0[0].owner, AccountId::from(ALICE)); + assert_eq!(candidates.0[0].amount, 10_050 * MOVR); + assert_eq!(candidates.0[1].owner, AccountId::from(BOB)); + assert_eq!(candidates.0[1].amount, 10_050 * MOVR); + assert_eq!(candidates.0[2].owner, AccountId::from(DAVE)); + assert_eq!(candidates.0[2].amount, 10_000 * MOVR); + }); +} + +#[test] +fn transfer_through_evm_to_stake() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 20_000 * MOVR)]) + .build() + .execute_with(|| { + // Charlie has no balance => fails to stake + assert_noop!( + ParachainStaking::join_candidates( + origin_of(AccountId::from(CHARLIE)), + 10_000 * MOVR, + 2u32 + ), + DispatchError::Module(ModuleError { + index: 20, + error: [8, 0, 0, 0], + message: Some("InsufficientBalance") + }) + ); + // Alice transfer from free balance 20000 MOVR to Bob + assert_ok!(Balances::transfer( + origin_of(AccountId::from(ALICE)), + AccountId::from(BOB), + 20_000 * MOVR, + )); + assert_eq!(Balances::free_balance(AccountId::from(BOB)), 20_000 * MOVR); + + let gas_limit = 100000u64; + let gas_price: U256 = BASE_FEE_GENESIS.into(); + // Bob transfers 10000 MOVR to Charlie via EVM + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(CHARLIE), + input: vec![], + value: (10_000 * MOVR).into(), + gas_limit, + max_fee_per_gas: gas_price, + max_priority_fee_per_gas: None, + nonce: None, + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + assert_eq!( + Balances::free_balance(AccountId::from(CHARLIE)), + 10_000 * MOVR, + ); + + // Charlie can stake now + assert_ok!(ParachainStaking::join_candidates( + origin_of(AccountId::from(CHARLIE)), + 10_000 * MOVR, + 2u32, + ),); + let candidates = ParachainStaking::candidate_pool(); + assert_eq!(candidates.0[0].owner, AccountId::from(CHARLIE)); + assert_eq!(candidates.0[0].amount, 10_000 * MOVR); + }); +} + +#[test] +fn reward_block_authors() { + ExtBuilder::default() + .with_balances(vec![ + // Alice gets 100 extra tokens for her mapping deposit + (AccountId::from(ALICE), 20_100 * MOVR), + (AccountId::from(BOB), 10_000 * MOVR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 10_000 * MOVR)]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 500 * MOVR, + )]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + for x in 2..1199 { + run_to_block(x, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + } + // no rewards doled out yet + assert_eq!( + Balances::usable_balance(AccountId::from(ALICE)), + 10_100 * MOVR, + ); + assert_eq!(Balances::usable_balance(AccountId::from(BOB)), 9500 * MOVR,); + run_to_block(1201, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + // rewards minted and distributed + assert_eq!( + Balances::usable_balance(AccountId::from(ALICE)), + 11547666666208000000000, + ); + assert_eq!( + Balances::usable_balance(AccountId::from(BOB)), + 9557333332588000000000, + ); + }); +} + +#[test] +fn reward_block_authors_with_parachain_bond_reserved() { + ExtBuilder::default() + .with_balances(vec![ + // Alice gets 100 extra tokens for her mapping deposit + (AccountId::from(ALICE), 20_100 * MOVR), + (AccountId::from(BOB), 10_000 * MOVR), + (AccountId::from(CHARLIE), MOVR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 10_000 * MOVR)]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 500 * MOVR, + )]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + assert_ok!(ParachainStaking::set_parachain_bond_account( + root_origin(), + AccountId::from(CHARLIE), + ),); + for x in 2..1199 { + run_to_block(x, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + } + // no rewards doled out yet + assert_eq!( + Balances::usable_balance(AccountId::from(ALICE)), + 10_100 * MOVR, + ); + assert_eq!(Balances::usable_balance(AccountId::from(BOB)), 9500 * MOVR,); + assert_eq!(Balances::usable_balance(AccountId::from(CHARLIE)), MOVR,); + run_to_block(1201, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + // rewards minted and distributed + assert_eq!( + Balances::usable_balance(AccountId::from(ALICE)), + 11117700475903800000000, + ); + assert_eq!( + Balances::usable_balance(AccountId::from(BOB)), + 9535834523343675000000, + ); + // 30% reserved for parachain bond + assert_eq!( + Balances::usable_balance(AccountId::from(CHARLIE)), + 452515000000000000000, + ); + }); +} + +#[test] +fn initialize_crowdloan_addresses_with_batch_and_pay() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * MOVR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * MOVR) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 48 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * MOVR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 1_500_000 * MOVR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + // 30 percent initial payout + assert_eq!(Balances::balance(&AccountId::from(CHARLIE)), 450_000 * MOVR); + // 30 percent initial payout + assert_eq!(Balances::balance(&AccountId::from(DAVE)), 450_000 * MOVR); + let expected = RuntimeEvent::Utility(pallet_utility::Event::BatchCompleted); + assert_eq!(last_event(), expected); + // This one should fail, as we already filled our data + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch { + calls: vec![RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![([4u8; 32].into(), Some(AccountId::from(ALICE)), 432000)] + } + )] + }) + .dispatch(root_origin()) + ); + let expected_fail = RuntimeEvent::Utility(pallet_utility::Event::BatchInterrupted { + index: 0, + error: DispatchError::Module(ModuleError { + index: 90, + error: [8, 0, 0, 0], + message: None, + }), + }); + assert_eq!(last_event(), expected_fail); + // Claim 1 block. + assert_ok!(CrowdloanRewards::claim(origin_of(AccountId::from(CHARLIE)))); + assert_ok!(CrowdloanRewards::claim(origin_of(AccountId::from(DAVE)))); + + let vesting_period = 48 * WEEKS as u128; + let per_block = (1_050_000 * MOVR) / vesting_period; + + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(CHARLIE)) + .unwrap() + .claimed_reward, + (450_000 * MOVR) + per_block + ); + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(DAVE)) + .unwrap() + .claimed_reward, + (450_000 * MOVR) + per_block + ); + // The total claimed reward should be equal to the account balance at this point. + assert_eq!( + Balances::balance(&AccountId::from(CHARLIE)), + (450_000 * MOVR) + per_block + ); + assert_eq!( + Balances::balance(&AccountId::from(DAVE)), + (450_000 * MOVR) + per_block + ); + assert_noop!( + CrowdloanRewards::claim(origin_of(AccountId::from(ALICE))), + pallet_crowdloan_rewards::Error::::NoAssociatedClaim + ); + }); +} + +#[test] +fn initialize_crowdloan_address_and_change_with_relay_key_sig() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * MOVR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * MOVR) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + + let (pair1, _) = sp_core::sr25519::Pair::generate(); + let (pair2, _) = sp_core::sr25519::Pair::generate(); + + let public1 = pair1.public(); + let public2 = pair2.public(); + + // signature: + // WRAP_BYTES|| NetworkIdentifier|| new_account || previous_account || WRAP_BYTES + let mut message = pallet_crowdloan_rewards::WRAPPED_BYTES_PREFIX.to_vec(); + message.append(&mut b"moonriver-".to_vec()); + message.append(&mut AccountId::from(DAVE).encode()); + message.append(&mut AccountId::from(CHARLIE).encode()); + message.append(&mut pallet_crowdloan_rewards::WRAPPED_BYTES_POSTFIX.to_vec()); + let signature1 = pair1.sign(&message); + let signature2 = pair2.sign(&message); + + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + // two relay accounts pointing at the same reward account + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + public1.into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * MOVR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + public2.into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * MOVR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + // 30 percent initial payout + assert_eq!(Balances::balance(&AccountId::from(CHARLIE)), 900_000 * MOVR); + + // this should fail, as we are only providing one signature + assert_noop!( + CrowdloanRewards::change_association_with_relay_keys( + origin_of(AccountId::from(CHARLIE)), + AccountId::from(DAVE), + AccountId::from(CHARLIE), + vec![(public1.into(), signature1.clone().into())] + ), + pallet_crowdloan_rewards::Error::::InsufficientNumberOfValidProofs + ); + + // this should be valid + assert_ok!(CrowdloanRewards::change_association_with_relay_keys( + origin_of(AccountId::from(CHARLIE)), + AccountId::from(DAVE), + AccountId::from(CHARLIE), + vec![ + (public1.into(), signature1.into()), + (public2.into(), signature2.into()) + ] + )); + + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(DAVE)) + .unwrap() + .claimed_reward, + (900_000 * MOVR) + ); + }); +} + +#[test] +fn claim_via_precompile() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * MOVR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * MOVR) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * MOVR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 1_500_000 * MOVR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + + assert!(CrowdloanRewards::initialized()); + + // 30 percent initial payout + assert_eq!(Balances::balance(&AccountId::from(CHARLIE)), 450_000 * MOVR); + // 30 percent initial payout + assert_eq!(Balances::balance(&AccountId::from(DAVE)), 450_000 * MOVR); + + let crowdloan_precompile_address = H160::from_low_u64_be(2049); + + // Alice uses the crowdloan precompile to claim through the EVM + let gas_limit = 100000u64; + let gas_price: U256 = BASE_FEE_GENESIS.into(); + + // Construct the call data (selector, amount) + let mut call_data = Vec::::from([0u8; 4]); + call_data[0..4].copy_from_slice(&Keccak256::digest(b"claim()")[0..4]); + + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(CHARLIE), + target: crowdloan_precompile_address, + input: call_data, + value: U256::zero(), // No value sent in EVM + gas_limit, + max_fee_per_gas: gas_price, + max_priority_fee_per_gas: None, + nonce: None, // Use the next nonce + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let vesting_period = 4 * WEEKS as u128; + let per_block = (1_050_000 * MOVR) / vesting_period; + + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(CHARLIE)) + .unwrap() + .claimed_reward, + (450_000 * MOVR) + per_block + ); + }) +} + +#[test] +fn is_contributor_via_precompile() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * MOVR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * MOVR) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * MOVR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 1_500_000 * MOVR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + + let crowdloan_precompile_address = H160::from_low_u64_be(2049); + + // Assert precompile reports Bob is not a contributor + Precompiles::new() + .prepare_test( + ALICE, + crowdloan_precompile_address, + CrowdloanRewardsPCall::is_contributor { + contributor: Address(AccountId::from(BOB).into()), + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(false); + + // Assert precompile reports Charlie is a nominator + Precompiles::new() + .prepare_test( + ALICE, + crowdloan_precompile_address, + CrowdloanRewardsPCall::is_contributor { + contributor: Address(AccountId::from(CHARLIE).into()), + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(true); + }) +} + +#[test] +fn reward_info_via_precompile() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * MOVR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * MOVR) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * MOVR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 1_500_000 * MOVR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + + let crowdloan_precompile_address = H160::from_low_u64_be(2049); + + let expected_total: U256 = (1_500_000 * MOVR).into(); + let expected_claimed: U256 = (450_000 * MOVR).into(); + + // Assert precompile reports correct Charlie reward info. + Precompiles::new() + .prepare_test( + ALICE, + crowdloan_precompile_address, + CrowdloanRewardsPCall::reward_info { + contributor: Address(AccountId::from(CHARLIE).into()), + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns((expected_total, expected_claimed)); + }) +} + +#[test] +fn update_reward_address_via_precompile() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * MOVR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_crowdloan_fund(3_000_000 * MOVR) + .build() + .execute_with(|| { + // set parachain inherent data + set_parachain_inherent_data(); + let init_block = CrowdloanRewards::init_vesting_block(); + // This matches the previous vesting + let end_block = init_block + 4 * WEEKS; + // Batch calls always succeed. We just need to check the inner event + assert_ok!( + RuntimeCall::Utility(pallet_utility::Call::::batch_all { + calls: vec![ + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [4u8; 32].into(), + Some(AccountId::from(CHARLIE)), + 1_500_000 * MOVR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::initialize_reward_vec { + rewards: vec![( + [5u8; 32].into(), + Some(AccountId::from(DAVE)), + 1_500_000 * MOVR + )] + } + ), + RuntimeCall::CrowdloanRewards( + pallet_crowdloan_rewards::Call::::complete_initialization { + lease_ending_block: end_block + } + ) + ] + }) + .dispatch(root_origin()) + ); + + let crowdloan_precompile_address = H160::from_low_u64_be(2049); + + // Charlie uses the crowdloan precompile to update address through the EVM + let gas_limit = 100000u64; + let gas_price: U256 = BASE_FEE_GENESIS.into(); + + // Construct the input data to check if Bob is a contributor + let mut call_data = Vec::::from([0u8; 36]); + call_data[0..4] + .copy_from_slice(&Keccak256::digest(b"update_reward_address(address)")[0..4]); + call_data[16..36].copy_from_slice(&ALICE); + + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(CHARLIE), + target: crowdloan_precompile_address, + input: call_data, + value: U256::zero(), // No value sent in EVM + gas_limit, + max_fee_per_gas: gas_price, + max_priority_fee_per_gas: None, + nonce: None, // Use the next nonce + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + assert!(CrowdloanRewards::accounts_payable(&AccountId::from(CHARLIE)).is_none()); + assert_eq!( + CrowdloanRewards::accounts_payable(&AccountId::from(ALICE)) + .unwrap() + .claimed_reward, + (450_000 * MOVR) + ); + }) +} + +fn run_with_system_weight(w: Weight, mut assertions: F) +where + F: FnMut() -> (), +{ + let mut t: sp_io::TestExternalities = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap() + .into(); + t.execute_with(|| { + System::set_block_consumed_resources(w, 0); + assertions() + }); +} + +#[test] +#[rustfmt::skip] +fn length_fee_is_sensible() { + use sp_runtime::testing::TestXt; + + // tests that length fee is sensible for a few hypothetical transactions + ExtBuilder::default().build().execute_with(|| { + let call = frame_system::Call::remark:: { remark: vec![] }; + let uxt: TestXt<_, ()> = TestXt::new(call, Some((1u64, ()))); + + let calc_fee = |len: u32| -> Balance { + moonriver_runtime::TransactionPayment::query_fee_details(uxt.clone(), len) + .inclusion_fee + .expect("fee should be calculated") + .len_fee + }; + + // editorconfig-checker-disable + // left: cost of length fee, right: size in bytes + // /------------- proportional component: O(N * 1B) + // | /- exponential component: O(N ** 3) + // | | + assert_eq!( 1_000_000_001, calc_fee(1)); + assert_eq!( 10_000_001_000, calc_fee(10)); + assert_eq!( 100_001_000_000, calc_fee(100)); + assert_eq!( 1_001_000_000_000, calc_fee(1_000)); + assert_eq!( 11_000_000_000_000, calc_fee(10_000)); // inflection point + assert_eq!( 1_100_000_000_000_000, calc_fee(100_000)); + assert_eq!( 1_001_000_000_000_000_000, calc_fee(1_000_000)); // one MOVR, ~ 1MB + assert_eq!( 1_000_010_000_000_000_000_000, calc_fee(10_000_000)); + assert_eq!(1_000_000_100_000_000_000_000_000, calc_fee(100_000_000)); + // editorconfig-checker-enable + }); +} + +#[test] +fn multiplier_can_grow_from_zero() { + use frame_support::traits::Get; + + let minimum_multiplier = moonriver_runtime::MinimumMultiplier::get(); + let target = moonriver_runtime::TargetBlockFullness::get() + * RuntimeBlockWeights::get() + .get(DispatchClass::Normal) + .max_total + .unwrap(); + // if the min is too small, then this will not change, and we are doomed forever. + // the weight is 1/100th bigger than target. + run_with_system_weight(target * 101 / 100, || { + let next = + moonriver_runtime::SlowAdjustingFeeUpdate::::convert(minimum_multiplier); + assert!( + next > minimum_multiplier, + "{:?} !>= {:?}", + next, + minimum_multiplier + ); + }) +} + +#[test] +fn ethereum_invalid_transaction() { + ExtBuilder::default().build().execute_with(|| { + // Ensure an extrinsic not containing enough gas limit to store the transaction + // on chain is rejected. + assert_eq!( + Executive::apply_extrinsic(unchecked_eth_tx(INVALID_ETH_TX)), + Err( + sp_runtime::transaction_validity::TransactionValidityError::Invalid( + sp_runtime::transaction_validity::InvalidTransaction::Custom(3u8) + ) + ) + ); + }); +} + +#[test] +fn initial_gas_fee_is_correct() { + use fp_evm::FeeCalculator; + + ExtBuilder::default().build().execute_with(|| { + let multiplier = TransactionPayment::next_fee_multiplier(); + assert_eq!(multiplier, Multiplier::from(10u128)); + + assert_eq!( + TransactionPaymentAsGasPrice::min_gas_price(), + ( + 12_500_000_000u128.into(), + Weight::from_parts(25_000_000u64, 0) + ) + ); + }); +} + +#[test] +fn min_gas_fee_is_correct() { + use fp_evm::FeeCalculator; + use frame_support::traits::Hooks; + + ExtBuilder::default().build().execute_with(|| { + pallet_transaction_payment::NextFeeMultiplier::::put(Multiplier::from(0)); + TransactionPayment::on_finalize(System::block_number()); // should trigger min to kick in + + let multiplier = TransactionPayment::next_fee_multiplier(); + assert_eq!(multiplier, Multiplier::from(1u128)); + + assert_eq!( + TransactionPaymentAsGasPrice::min_gas_price(), + ( + 1_250_000_000u128.into(), + Weight::from_parts(25_000_000u64, 0) + ) + ); + }); +} + +#[test] +fn transfer_ed_0_substrate() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), (1 * MOVR) + (1 * WEI)), + (AccountId::from(BOB), 0), + ]) + .build() + .execute_with(|| { + // Substrate transfer + assert_ok!(Balances::transfer( + origin_of(AccountId::from(ALICE)), + AccountId::from(BOB), + 1 * MOVR, + )); + // 1 WEI is left in the account + assert_eq!(Balances::free_balance(AccountId::from(ALICE)), 1 * WEI); + }); +} + +#[test] +fn transfer_ed_0_evm() { + ExtBuilder::default() + .with_balances(vec![ + ( + AccountId::from(ALICE), + ((1 * MOVR) + (21_000 * BASE_FEE_GENESIS)) + (1 * WEI), + ), + (AccountId::from(BOB), 0), + ]) + .build() + .execute_with(|| { + // EVM transfer + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(ALICE), + target: H160::from(BOB), + input: Vec::new(), + value: (1 * MOVR).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(BASE_FEE_GENESIS), + max_priority_fee_per_gas: Some(U256::from(BASE_FEE_GENESIS)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + // 1 WEI is left in the account + assert_eq!(Balances::free_balance(AccountId::from(ALICE)), 1 * WEI,); + }); +} + +#[test] +fn refund_ed_0_evm() { + ExtBuilder::default() + .with_balances(vec![ + ( + AccountId::from(ALICE), + ((1 * MOVR) + (21_777 * BASE_FEE_GENESIS)), + ), + (AccountId::from(BOB), 0), + ]) + .build() + .execute_with(|| { + // EVM transfer that zeroes ALICE + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(ALICE), + target: H160::from(BOB), + input: Vec::new(), + value: (1 * MOVR).into(), + gas_limit: 21_777u64, + max_fee_per_gas: U256::from(BASE_FEE_GENESIS), + max_priority_fee_per_gas: Some(U256::from(BASE_FEE_GENESIS)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + // ALICE is refunded + assert_eq!( + Balances::free_balance(AccountId::from(ALICE)), + 777 * BASE_FEE_GENESIS, + ); + }); +} + +#[test] +fn author_does_not_receive_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * MOVR) + (21_000 * (500 * GIGAWEI)), + )]) + .build() + .execute_with(|| { + // Some block author as seen by pallet-evm. + let author = AccountId::from(>::find_author()); + // Currently the default impl of the evm uses `deposit_into_existing`. + // If we were to use this implementation, and for an author to receive eventual tips, + // the account needs to be somehow initialized, otherwise the deposit would fail. + Balances::make_free_balance_be(&author, 100 * MOVR); + + // EVM transfer. + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * MOVR).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(300 * GIGAWEI), + max_priority_fee_per_gas: Some(U256::from(200 * GIGAWEI)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + // Author free balance didn't change. + assert_eq!(Balances::free_balance(author), 100 * MOVR,); + }); +} + +#[test] +fn total_issuance_after_evm_transaction_with_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * MOVR) + (21_000 * (2 * BASE_FEE_GENESIS)), + )]) + .build() + .execute_with(|| { + let issuance_before = ::Currency::total_issuance(); + // EVM transfer. + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * MOVR).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(2u128 * BASE_FEE_GENESIS), + max_priority_fee_per_gas: Some(U256::from(2u128 * BASE_FEE_GENESIS)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let issuance_after = ::Currency::total_issuance(); + let fee = ((2 * BASE_FEE_GENESIS) * 21_000) as f64; + // 80% was burned. + let expected_burn = (fee * 0.8) as u128; + assert_eq!(issuance_after, issuance_before - expected_burn,); + // 20% was sent to treasury. + let expected_treasury = (fee * 0.2) as u128; + assert_eq!(moonriver_runtime::Treasury::pot(), expected_treasury); + }); +} + +#[test] +fn total_issuance_after_evm_transaction_without_priority_fee() { + ExtBuilder::default() + .with_balances(vec![( + AccountId::from(BOB), + (1 * MOVR) + (21_000 * (2 * BASE_FEE_GENESIS)), + )]) + .build() + .execute_with(|| { + let issuance_before = ::Currency::total_issuance(); + // EVM transfer. + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::::call { + source: H160::from(BOB), + target: H160::from(ALICE), + input: Vec::new(), + value: (1 * MOVR).into(), + gas_limit: 21_000u64, + max_fee_per_gas: U256::from(BASE_FEE_GENESIS), + max_priority_fee_per_gas: Some(U256::from(BASE_FEE_GENESIS)), + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let issuance_after = ::Currency::total_issuance(); + let fee = ((1 * BASE_FEE_GENESIS) * 21_000) as f64; + // 80% was burned. + let expected_burn = (fee * 0.8) as u128; + assert_eq!(issuance_after, issuance_before - expected_burn,); + // 20% was sent to treasury. + let expected_treasury = (fee * 0.2) as u128; + assert_eq!(moonriver_runtime::Treasury::pot(), expected_treasury); + }); +} + +#[test] +fn root_can_change_default_xcm_vers() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .build() + .execute_with(|| { + let source_location = AssetType::Xcm(MultiLocation::parent()); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: [1u8; 32], + }), + }; + let source_id: moonriver_runtime::AssetId = source_location.clone().into(); + // Default XCM version is not set yet, so xtokens should fail because it does not + // know with which version to send + assert_noop!( + XTokens::transfer( + origin_of(AccountId::from(ALICE)), + CurrencyId::ForeignAsset(source_id), + 100_000_000_000_000, + Box::new(xcm::VersionedMultiLocation::V3(dest.clone())), + WeightLimit::Limited(4000000000.into()) + ), + orml_xtokens::Error::::XcmExecutionFailed + ); + + // Root sets the defaultXcm + assert_ok!(PolkadotXcm::force_default_xcm_version( + root_origin(), + Some(2) + )); + + // Now transferring does not fail + assert_ok!(XTokens::transfer( + origin_of(AccountId::from(ALICE)), + CurrencyId::ForeignAsset(source_id), + 100_000_000_000_000, + Box::new(xcm::VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(4000000000.into()) + )); + }) +} + +#[test] +fn asset_can_be_registered() { + ExtBuilder::default().build().execute_with(|| { + let source_location = AssetType::Xcm(MultiLocation::parent()); + let source_id: moonriver_runtime::AssetId = source_location.clone().into(); + let asset_metadata = AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }; + assert_ok!(AssetManager::register_foreign_asset( + moonriver_runtime::RuntimeOrigin::root(), + source_location, + asset_metadata, + 1u128, + true + )); + assert!(AssetManager::asset_id_type(source_id).is_some()); + }); +} + +#[test] +fn local_assets_cannot_be_create_by_signed_origins() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR * SUPPLY_FACTOR), + (AccountId::from(BOB), 1_000 * MOVR * SUPPLY_FACTOR), + ]) + .build() + .execute_with(|| { + assert_noop!( + RuntimeCall::LocalAssets( + pallet_assets::Call::::create { + id: 11u128.into(), + admin: AccountId::from(ALICE), + min_balance: 1u128 + } + ) + .dispatch(::RuntimeOrigin::signed( + AccountId::from(ALICE) + )), + frame_system::Error::::CallFiltered + ); + }); +} + +#[test] +fn xcm_asset_erc20_precompiles_supply_and_balance() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000 * MOVR)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .build() + .execute_with(|| { + // We have the assetId that corresponds to the relay chain registered + let relay_asset_id: AssetId = AssetType::Xcm(MultiLocation::parent()).into(); + + // Its address is + let asset_precompile_address = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + relay_asset_id, + ); + + // Assert the asset has been created with the correct supply + assert_eq!(Assets::total_supply(relay_asset_id), 1_000 * MOVR); + + // Access totalSupply through precompile. Important that the context is correct + Precompiles::new() + .prepare_test( + ALICE, + asset_precompile_address, + LocalAssetsPCall::total_supply {}, + ) + .expect_cost(2000) + .expect_no_logs() + .execute_returns(U256::from(1000 * MOVR)); + + // Access balanceOf through precompile + Precompiles::new() + .prepare_test( + ALICE, + asset_precompile_address, + LocalAssetsPCall::balance_of { + who: Address(ALICE.into()), + }, + ) + .expect_cost(2000) + .expect_no_logs() + .execute_returns(U256::from(1000 * MOVR)); + }); +} + +#[test] +fn xcm_asset_erc20_precompiles_transfer() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000 * MOVR)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .build() + .execute_with(|| { + // We have the assetId that corresponds to the relay chain registered + let relay_asset_id: AssetId = AssetType::Xcm(MultiLocation::parent()).into(); + + // Its address is + let asset_precompile_address = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + relay_asset_id, + ); + + // Transfer tokens from Aice to Bob, 400 MOVR. + Precompiles::new() + .prepare_test( + ALICE, + asset_precompile_address, + LocalAssetsPCall::transfer { + to: Address(BOB.into()), + value: { 400 * MOVR }.into(), + }, + ) + .expect_cost(23763) + .expect_log(log3( + asset_precompile_address, + SELECTOR_LOG_TRANSFER, + H160::from(ALICE), + H160::from(BOB), + solidity::encode_event_data(U256::from(400 * MOVR)), + )) + .execute_returns(true); + + // Make sure BOB has 400 MOVR + Precompiles::new() + .prepare_test( + BOB, + asset_precompile_address, + LocalAssetsPCall::balance_of { + who: Address(BOB.into()), + }, + ) + .expect_cost(2000) + .expect_no_logs() + .execute_returns(U256::from(400 * MOVR)); + }); +} + +#[test] +fn xcm_asset_erc20_precompiles_approve() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000 * MOVR)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .build() + .execute_with(|| { + // We have the assetId that corresponds to the relay chain registered + let relay_asset_id: AssetId = AssetType::Xcm(MultiLocation::parent()).into(); + + // Its address is + let asset_precompile_address = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + relay_asset_id, + ); + + // Aprove Bob for spending 400 MOVR from Alice + Precompiles::new() + .prepare_test( + ALICE, + asset_precompile_address, + LocalAssetsPCall::approve { + spender: Address(BOB.into()), + value: { 400 * MOVR }.into(), + }, + ) + .expect_cost(14210) + .expect_log(log3( + asset_precompile_address, + SELECTOR_LOG_APPROVAL, + H160::from(ALICE), + H160::from(BOB), + solidity::encode_event_data(U256::from(400 * MOVR)), + )) + .execute_returns(true); + + // Transfer tokens from Alice to Charlie by using BOB as origin + Precompiles::new() + .prepare_test( + BOB, + asset_precompile_address, + LocalAssetsPCall::transfer_from { + from: Address(ALICE.into()), + to: Address(CHARLIE.into()), + value: { 400 * MOVR }.into(), + }, + ) + .expect_cost(28991) + .expect_log(log3( + asset_precompile_address, + SELECTOR_LOG_TRANSFER, + H160::from(ALICE), + H160::from(CHARLIE), + solidity::encode_event_data(U256::from(400 * MOVR)), + )) + .execute_returns(true); + + // Make sure CHARLIE has 400 MOVR + Precompiles::new() + .prepare_test( + CHARLIE, + asset_precompile_address, + LocalAssetsPCall::balance_of { + who: Address(CHARLIE.into()), + }, + ) + .expect_cost(2000) + .expect_no_logs() + .execute_returns(U256::from(400 * MOVR)); + }); +} + +#[test] +fn xtokens_precompiles_transfer() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + let xtokens_precompile_address = H160::from_low_u64_be(2052); + + // We have the assetId that corresponds to the relay chain registered + let relay_asset_id: moonriver_runtime::AssetId = + AssetType::Xcm(MultiLocation::parent()).into(); + + // Its address is + let asset_precompile_address = Runtime::asset_id_to_account( + FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX, + relay_asset_id, + ); + + // Alice has 1000 tokens. She should be able to send through precompile + let destination = MultiLocation::new( + 1, + Junctions::X1(Junction::AccountId32 { + network: None, + id: [1u8; 32], + }), + ); + + // We use the address of the asset as an identifier of the asset we want to transferS + Precompiles::new() + .prepare_test( + ALICE, + xtokens_precompile_address, + XtokensPCall::transfer { + currency_address: Address(asset_precompile_address.into()), + amount: 500_000_000_000_000u128.into(), + destination: destination.clone(), + weight: 4_000_000, + }, + ) + .expect_cost(57639) + .expect_no_logs() + .execute_returns(()) + }) +} + +#[test] +fn xtokens_precompiles_transfer_multiasset() { + ExtBuilder::default() + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + let xtokens_precompile_address = H160::from_low_u64_be(2052); + + // Alice has 1000 tokens. She should be able to send through precompile + let destination = MultiLocation::new( + 1, + Junctions::X1(Junction::AccountId32 { + network: None, + id: [1u8; 32], + }), + ); + + // This time we transfer it through TransferMultiAsset + // Instead of the address, we encode directly the multilocation referencing the asset + Precompiles::new() + .prepare_test( + ALICE, + xtokens_precompile_address, + XtokensPCall::transfer_multiasset { + // We want to transfer the relay token + asset: MultiLocation::parent(), + amount: 500_000_000_000_000u128.into(), + destination, + weight: 4_000_000, + }, + ) + .expect_cost(57639) + .expect_no_logs() + .execute_returns(()); + }) +} + +#[test] +fn make_sure_polkadot_xcm_cannot_be_called() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 1_000 * MOVR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .build() + .execute_with(|| { + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: [1u8; 32], + }), + }; + let multiassets: MultiAssets = [MultiAsset { + id: Concrete(moonriver_runtime::xcm_config::SelfLocation::get()), + fun: Fungible(1000), + }] + .to_vec() + .into(); + assert_noop!( + RuntimeCall::PolkadotXcm(pallet_xcm::Call::::reserve_transfer_assets { + dest: Box::new(VersionedMultiLocation::V3(dest.clone())), + beneficiary: Box::new(VersionedMultiLocation::V3(dest)), + assets: Box::new(VersionedMultiAssets::V3(multiassets)), + fee_asset_item: 0, + }) + .dispatch(::RuntimeOrigin::signed( + AccountId::from(ALICE) + )), + frame_system::Error::::CallFiltered + ); + }); +} + +#[test] +fn transactor_cannot_use_more_than_max_weight() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .build() + .execute_with(|| { + let source_location = AssetType::Xcm(MultiLocation::parent()); + let source_id: moonriver_runtime::AssetId = source_location.clone().into(); + assert_ok!(XcmTransactor::register( + root_origin(), + AccountId::from(ALICE), + 0, + )); + + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + root_origin(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + // Relay charges 1000 for every instruction, and we have 3, so 3000 + 3000.into(), + 20000.into(), + None + )); + + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + root_origin(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + 1 + )); + + assert_noop!( + XcmTransactor::transact_through_derivative( + origin_of(AccountId::from(ALICE)), + moonriver_runtime::xcm_config::Transactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new( + xcm::VersionedMultiLocation::V3(MultiLocation::parent()) + )), + fee_amount: None + }, + vec![], + // 2000 is the max + TransactWeights { + transact_required_weight_at_most: 17001.into(), + overall_weight: None + }, + false + ), + pallet_xcm_transactor::Error::::MaxWeightTransactReached + ); + assert_noop!( + XcmTransactor::transact_through_derivative( + origin_of(AccountId::from(ALICE)), + moonriver_runtime::xcm_config::Transactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsCurrencyId(CurrencyId::ForeignAsset(source_id)), + fee_amount: None + }, + vec![], + // 20000 is the max + TransactWeights { + transact_required_weight_at_most: 17001.into(), + overall_weight: None + }, + false + ), + pallet_xcm_transactor::Error::::MaxWeightTransactReached + ); + }) +} + +#[test] +fn transact_through_signed_precompile_works_v2() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + // Destination + let dest = MultiLocation::parent(); + + let fee_payer_asset = MultiLocation::parent(); + + let bytes = vec![1u8, 2u8, 3u8]; + + let total_weight = 1_000_000_000u64; + + let xcm_transactor_v2_precompile_address = H160::from_low_u64_be(2061); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_transactor_v2_precompile_address, + XcmTransactorV2PCall::transact_through_signed_multilocation { + dest, + fee_asset: fee_payer_asset, + weight: 4_000_000, + call: bytes.into(), + fee_amount: u128::from(total_weight).into(), + overall_weight: total_weight, + }, + ) + .expect_cost(17149) + .expect_no_logs() + .execute_returns(()); + }); +} + +#[test] +fn transact_through_signed_cannot_send_to_local_chain() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_safe_xcm_version(2) + .build() + .execute_with(|| { + // Destination + let dest = MultiLocation::here(); + + let fee_payer_asset = MultiLocation::parent(); + + let bytes = vec![1u8, 2u8, 3u8]; + + let total_weight = 1_000_000_000u64; + + let xcm_transactor_v2_precompile_address = H160::from_low_u64_be(2061); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_transactor_v2_precompile_address, + XcmTransactorV2PCall::transact_through_signed_multilocation { + dest, + fee_asset: fee_payer_asset, + weight: 4_000_000, + call: bytes.into(), + fee_amount: u128::from(total_weight).into(), + overall_weight: total_weight, + }, + ) + .execute_reverts(|output| { + from_utf8(&output) + .unwrap() + .contains("Dispatched call failed with error:") + && from_utf8(&output).unwrap().contains("ErrorValidating") + }); + }); +} + +#[test] +fn call_xtokens_with_fee() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_safe_xcm_version(2) + .with_xcm_assets(vec![XcmAssetInitialization { + asset_type: AssetType::Xcm(MultiLocation::parent()), + metadata: AssetRegistrarMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + is_frozen: false, + }, + balances: vec![(AccountId::from(ALICE), 1_000_000_000_000_000)], + is_sufficient: true, + }]) + .build() + .execute_with(|| { + let source_location = AssetType::Xcm(MultiLocation::parent()); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: [1u8; 32], + }), + }; + let source_id: moonriver_runtime::AssetId = source_location.clone().into(); + + let before_balance = Assets::balance(source_id, &AccountId::from(ALICE)); + + // We are able to transfer with fee + assert_ok!(XTokens::transfer_with_fee( + origin_of(AccountId::from(ALICE)), + CurrencyId::ForeignAsset(source_id), + 100_000_000_000_000, + 100, + Box::new(xcm::VersionedMultiLocation::V3(dest.clone())), + WeightLimit::Limited(4000000000.into()) + ),); + + let after_balance = Assets::balance(source_id, &AccountId::from(ALICE)); + // At least these much (plus fees) should have been charged + assert_eq!(before_balance - 100_000_000_000_000 - 100, after_balance); + }); +} + +#[test] +fn test_xcm_utils_ml_tp_account() { + ExtBuilder::default().build().execute_with(|| { + let xcm_utils_precompile_address = H160::from_low_u64_be(2060); + let expected_address_parent: H160 = + ParentIsPreset::::convert_location(&MultiLocation::parent()) + .unwrap() + .into(); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_utils_precompile_address, + XcmUtilsPCall::multilocation_to_address { + multilocation: MultiLocation::parent(), + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(Address(expected_address_parent)); + + let parachain_2000_multilocation = MultiLocation::new(1, X1(Parachain(2000))); + let expected_address_parachain: H160 = + SiblingParachainConvertsVia::::convert_location( + ¶chain_2000_multilocation, + ) + .unwrap() + .into(); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_utils_precompile_address, + XcmUtilsPCall::multilocation_to_address { + multilocation: parachain_2000_multilocation, + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(Address(expected_address_parachain)); + + let alice_in_parachain_2000_multilocation = MultiLocation::new( + 1, + X2( + Parachain(2000), + AccountKey20 { + network: None, + key: ALICE, + }, + ), + ); + let expected_address_alice_in_parachain_2000: H160 = + xcm_builder::HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &alice_in_parachain_2000_multilocation, + ) + .unwrap() + .into(); + + Precompiles::new() + .prepare_test( + ALICE, + xcm_utils_precompile_address, + XcmUtilsPCall::multilocation_to_address { + multilocation: alice_in_parachain_2000_multilocation, + }, + ) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(Address(expected_address_alice_in_parachain_2000)); + }); +} + +#[test] +fn test_xcm_utils_weight_message() { + ExtBuilder::default().build().execute_with(|| { + let xcm_utils_precompile_address = H160::from_low_u64_be(2060); + let expected_weight = + XcmWeight::::clear_origin().ref_time(); + + let message: Vec = xcm::VersionedXcm::<()>::V3(Xcm(vec![ClearOrigin])).encode(); + + let input = XcmUtilsPCall::weight_message { + message: message.into(), + }; + + Precompiles::new() + .prepare_test(ALICE, xcm_utils_precompile_address, input) + .expect_cost(0) + .expect_no_logs() + .execute_returns(expected_weight); + }); +} + +#[test] +fn test_xcm_utils_get_units_per_second() { + ExtBuilder::default().build().execute_with(|| { + let xcm_utils_precompile_address = H160::from_low_u64_be(2060); + let multilocation = SelfReserve::get(); + + let input = XcmUtilsPCall::get_units_per_second { multilocation }; + + let expected_units = + WEIGHT_REF_TIME_PER_SECOND as u128 * moonriver_runtime::currency::WEIGHT_FEE; + + Precompiles::new() + .prepare_test(ALICE, xcm_utils_precompile_address, input) + .expect_cost(1000) + .expect_no_logs() + .execute_returns(expected_units); + }); +} + +#[test] +fn precompile_existence() { + ExtBuilder::default().build().execute_with(|| { + let precompiles = Precompiles::new(); + let precompile_addresses: std::collections::BTreeSet<_> = vec![ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 1024, 1025, 1026, 2048, 2049, 2050, 2051, 2052, 2053, 2054, + 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, + 2069, 2070, 2071, + ] + .into_iter() + .map(H160::from_low_u64_be) + .collect(); + + for i in 0..3000 { + let address = H160::from_low_u64_be(i); + + if precompile_addresses.contains(&address) { + assert!( + is_precompile_or_fail::(address, 100_000u64).expect("to be ok"), + "is_precompile({}) should return true", + i + ); + + assert!( + precompiles + .execute(&mut MockHandle::new( + address, + Context { + address, + caller: H160::zero(), + apparent_value: U256::zero() + } + ),) + .is_some(), + "execute({},..) should return Some(_)", + i + ); + } else { + assert!( + !is_precompile_or_fail::(address, 100_000u64).expect("to be ok"), + "is_precompile({}) should return false", + i + ); + + assert!( + precompiles + .execute(&mut MockHandle::new( + address, + Context { + address, + caller: H160::zero(), + apparent_value: U256::zero() + } + ),) + .is_none(), + "execute({},..) should return None", + i + ); + } + } + }); +} + +#[test] +fn removed_precompiles() { + ExtBuilder::default().build().execute_with(|| { + let precompiles = Precompiles::new(); + let removed_precompiles = [1025]; + + for i in 1..3000 { + let address = H160::from_low_u64_be(i); + + if !is_precompile_or_fail::(address, 100_000u64).expect("to be ok") { + continue; + } + + if !removed_precompiles.contains(&i) { + assert!( + match precompiles.is_active_precompile(address, 100_000u64) { + IsPrecompileResult::Answer { is_precompile, .. } => is_precompile, + _ => false, + }, + "{i} should be an active precompile" + ); + continue; + } + + assert!( + !match precompiles.is_active_precompile(address, 100_000u64) { + IsPrecompileResult::Answer { is_precompile, .. } => is_precompile, + _ => false, + }, + "{i} shouldn't be an active precompile" + ); + + precompiles + .prepare_test(Alice, address, []) + .execute_reverts(|out| out == b"Removed precompile"); + } + }) +} + +#[test] +fn deal_with_fees_handles_tip() { + use frame_support::traits::OnUnbalanced; + use moonriver_runtime::{DealWithFees, Treasury}; + use pallet_balances::NegativeImbalance; + + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 10_000)]) + .build() + .execute_with(|| { + // Alice has 10_000, which makes inital supply 10_000. + // drop()ing the NegativeImbalance below will cause the total_supply to be decreased + // incorrectly (since there was never a withdraw to begin with), which in this case has + // the desired effect of showing that currency was burned. + let total_supply_before = Balances::total_issuance(); + assert_eq!(total_supply_before, 10_000); + + let fees_then_tips = vec![ + NegativeImbalance::::new(100), + NegativeImbalance::::new(1_000), + ]; + DealWithFees::on_unbalanceds(fees_then_tips.into_iter()); + + // treasury should have received 20% + assert_eq!(Balances::free_balance(&Treasury::account_id()), 220); + + // verify 80% burned + let total_supply_after = Balances::total_issuance(); + assert_eq!(total_supply_before - total_supply_after, 880); + }); +} + +#[test] +fn evm_revert_substrate_events() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 1_000 * MOVR)]) + .build() + .execute_with(|| { + let batch_precompile_address = H160::from_low_u64_be(2056); + + // Batch a transfer followed by an invalid call to batch. + // Thus BatchAll will revert the transfer. + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::call { + source: ALICE.into(), + target: batch_precompile_address, + input: BatchPCall::batch_all { + to: vec![Address(BOB.into()), Address(batch_precompile_address)].into(), + value: vec![U256::from(1 * MOVR), U256::zero()].into(), + call_data: vec![].into(), + gas_limit: vec![].into() + } + .into(), + value: U256::zero(), // No value sent in EVM + gas_limit: 500_000, + max_fee_per_gas: U256::from(BASE_FEE_GENESIS), + max_priority_fee_per_gas: None, + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let transfer_count = System::events() + .iter() + .filter(|r| match r.event { + RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => true, + _ => false, + }) + .count(); + + assert_eq!(transfer_count, 0, "there should be no transfer event"); + }); +} + +#[test] +fn evm_success_keeps_substrate_events() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 1_000 * MOVR)]) + .build() + .execute_with(|| { + let batch_precompile_address = H160::from_low_u64_be(2056); + + assert_ok!(RuntimeCall::EVM(pallet_evm::Call::call { + source: ALICE.into(), + target: batch_precompile_address, + input: BatchPCall::batch_all { + to: vec![Address(BOB.into())].into(), + value: vec![U256::from(1 * MOVR)].into(), + call_data: vec![].into(), + gas_limit: vec![].into() + } + .into(), + value: U256::zero(), // No value sent in EVM + gas_limit: 500_000, + max_fee_per_gas: U256::from(BASE_FEE_GENESIS), + max_priority_fee_per_gas: None, + nonce: Some(U256::from(0)), + access_list: Vec::new(), + }) + .dispatch(::RuntimeOrigin::root())); + + let transfer_count = System::events() + .iter() + .filter(|r| match r.event { + RuntimeEvent::Balances(pallet_balances::Event::Transfer { .. }) => true, + _ => false, + }) + .count(); + + assert_eq!(transfer_count, 1, "there should be 1 transfer event"); + }); +} + +#[cfg(test)] +mod fee_tests { + use super::*; + use frame_support::{ + traits::ConstU128, + weights::{ConstantMultiplier, WeightToFee}, + }; + use moonriver_runtime::{ + currency, LengthToFee, MinimumMultiplier, RuntimeBlockWeights, SlowAdjustingFeeUpdate, + TargetBlockFullness, TransactionPayment, + }; + use sp_core::Get; + use sp_runtime::FixedPointNumber; + + fn run_with_system_weight(w: Weight, mut assertions: F) + where + F: FnMut() -> (), + { + let mut t: sp_io::TestExternalities = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap() + .into(); + t.execute_with(|| { + System::set_block_consumed_resources(w, 0); + assertions() + }); + } + + #[test] + fn test_multiplier_can_grow_from_zero() { + let minimum_multiplier = MinimumMultiplier::get(); + let target = TargetBlockFullness::get() + * RuntimeBlockWeights::get() + .get(DispatchClass::Normal) + .max_total + .unwrap(); + // if the min is too small, then this will not change, and we are doomed forever. + // the weight is 1/100th bigger than target. + run_with_system_weight(target * 101 / 100, || { + let next = SlowAdjustingFeeUpdate::::convert(minimum_multiplier); + assert!( + next > minimum_multiplier, + "{:?} !>= {:?}", + next, + minimum_multiplier + ); + }) + } + + #[test] + fn test_fee_calculation() { + let base_extrinsic = RuntimeBlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic; + let multiplier = sp_runtime::FixedU128::from_float(0.999000000000000000); + let extrinsic_len = 100u32; + let extrinsic_weight = Weight::from_parts(5_000u64, 1); + let tip = 42u128; + type WeightToFeeImpl = ConstantMultiplier>; + type LengthToFeeImpl = LengthToFee; + + // base_fee + (multiplier * extrinsic_weight_fee) + extrinsic_length_fee + tip + let expected_fee = WeightToFeeImpl::weight_to_fee(&base_extrinsic) + + multiplier.saturating_mul_int(WeightToFeeImpl::weight_to_fee(&extrinsic_weight)) + + LengthToFeeImpl::weight_to_fee(&(Weight::from_parts(extrinsic_len as u64, 1))) + + tip; + + let mut t: sp_io::TestExternalities = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap() + .into(); + t.execute_with(|| { + pallet_transaction_payment::NextFeeMultiplier::::set(multiplier); + let actual_fee = TransactionPayment::compute_fee( + extrinsic_len, + &frame_support::dispatch::DispatchInfo { + class: DispatchClass::Normal, + pays_fee: frame_support::dispatch::Pays::Yes, + weight: extrinsic_weight, + }, + tip, + ); + + assert_eq!( + expected_fee, + actual_fee, + "The actual fee did not match the expected fee, diff {}", + actual_fee - expected_fee + ); + }); + } +} diff --git a/tracing/2601/runtime/moonriver/tests/runtime_apis.rs b/tracing/2601/runtime/moonriver/tests/runtime_apis.rs new file mode 100644 index 00000000..13819c10 --- /dev/null +++ b/tracing/2601/runtime/moonriver/tests/runtime_apis.rs @@ -0,0 +1,396 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Moonriver Runtime Api Integration Tests + +mod common; +use common::*; + +use fp_evm::GenesisAccount; +use frame_support::assert_ok; +use nimbus_primitives::NimbusId; +use pallet_evm::{Account as EVMAccount, AddressMapping, FeeCalculator}; +use sp_core::{ByteArray, H160, H256, U256}; + +use fp_rpc::runtime_decl_for_ethereum_runtime_rpc_api::EthereumRuntimeRPCApi; +use moonbeam_rpc_primitives_txpool::runtime_decl_for_tx_pool_runtime_api::TxPoolRuntimeApi; +use nimbus_primitives::runtime_decl_for_nimbus_api::NimbusApi; +use std::{collections::BTreeMap, str::FromStr}; + +#[test] +fn ethereum_runtime_rpc_api_chain_id() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Runtime::chain_id(), CHAIN_ID); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_account_basic() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 2_000 * MOVR)]) + .build() + .execute_with(|| { + assert_eq!( + Runtime::account_basic(H160::from(ALICE)), + EVMAccount { + balance: U256::from(2_000 * MOVR), + nonce: U256::zero() + } + ); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_gas_price() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!( + Runtime::gas_price(), + TransactionPaymentAsGasPrice::min_gas_price().0 + ); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_account_code_at() { + let address = H160::from(EVM_CONTRACT); + let code: Vec = vec![1, 2, 3, 4, 5]; + ExtBuilder::default() + .with_evm_accounts({ + let mut map = BTreeMap::new(); + map.insert( + address, + GenesisAccount { + balance: U256::zero(), + code: code.clone(), + nonce: Default::default(), + storage: Default::default(), + }, + ); + map + }) + .build() + .execute_with(|| { + assert_eq!(Runtime::account_code_at(address), code); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_author() { + ExtBuilder::default() + .with_collators(vec![(AccountId::from(ALICE), 1_000 * MOVR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 500 * MOVR, + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + run_to_block(2, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + assert_eq!(Runtime::author(), H160::from(ALICE)); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_storage_at() { + let address = H160::from(EVM_CONTRACT); + let mut key = [0u8; 32]; + key[31..32].copy_from_slice(&[6u8][..]); + let mut value = [0u8; 32]; + value[31..32].copy_from_slice(&[7u8][..]); + let item = H256::from_slice(&key[..]); + let mut storage: BTreeMap = BTreeMap::new(); + storage.insert(H256::from_slice(&key[..]), item); + ExtBuilder::default() + .with_evm_accounts({ + let mut map = BTreeMap::new(); + map.insert( + address, + GenesisAccount { + balance: U256::zero(), + code: Vec::new(), + nonce: Default::default(), + storage: storage.clone(), + }, + ); + map + }) + .build() + .execute_with(|| { + assert_eq!(Runtime::storage_at(address, U256::from(6)), item); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_call() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 2_000 * MOVR), + ]) + .build() + .execute_with(|| { + let execution_result = Runtime::call( + H160::from(ALICE), // from + H160::from(BOB), // to + Vec::new(), // data + U256::from(1000u64), // value + U256::from(100000u64), // gas_limit + None, // max_fee_per_gas + None, // max_priority_fee_per_gas + None, // nonce + false, // estimate + None, // access_list + ); + assert!(execution_result.is_ok()); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_create() { + ExtBuilder::default() + .with_balances(vec![(AccountId::from(ALICE), 2_000 * MOVR)]) + .build() + .execute_with(|| { + let execution_result = Runtime::create( + H160::from(ALICE), // from + vec![0, 1, 1, 0], // data + U256::zero(), // value + U256::from(100000u64), // gas_limit + None, // max_fee_per_gas + None, // max_priority_fee_per_gas + None, // nonce + false, // estimate + None, // access_list + ); + assert!(execution_result.is_ok()); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_current_transaction_statuses() { + let alith = ::AddressMapping::into_account_id( + H160::from_str("f24ff3a9cf04c71dbc94d0b566f7a27b94566cac") + .expect("internal H160 is valid; qed"), + ); + ExtBuilder::default() + .with_collators(vec![(AccountId::from(ALICE), 1_000 * MOVR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_balances(vec![ + (alith, 2_000 * MOVR), + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 500 * MOVR, + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + // set_author(NimbusId::from_slice(&ALICE_NIMBUS)); + let result = + Executive::apply_extrinsic(unchecked_eth_tx(VALID_ETH_TX)).expect("Apply result."); + assert_eq!(result, Ok(())); + rpc_run_to_block(2); + let statuses = + Runtime::current_transaction_statuses().expect("Transaction statuses result."); + assert_eq!(statuses.len(), 1); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_current_block() { + ExtBuilder::default() + .with_collators(vec![(AccountId::from(ALICE), 1_000 * MOVR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_balances(vec![ + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 500 * MOVR, + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + // set_author(NimbusId::from_slice(&ALICE_NIMBUS)); + rpc_run_to_block(2); + let block = Runtime::current_block().expect("Block result."); + assert_eq!(block.header.number, U256::from(1u8)); + }); +} + +#[test] +fn ethereum_runtime_rpc_api_current_receipts() { + let alith = ::AddressMapping::into_account_id( + H160::from_str("f24ff3a9cf04c71dbc94d0b566f7a27b94566cac") + .expect("internal H160 is valid; qed"), + ); + ExtBuilder::default() + .with_collators(vec![(AccountId::from(ALICE), 1_000 * MOVR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .with_balances(vec![ + (alith, 2_000 * MOVR), + (AccountId::from(ALICE), 2_000 * MOVR), + (AccountId::from(BOB), 1_000 * MOVR), + ]) + .with_delegations(vec![( + AccountId::from(BOB), + AccountId::from(ALICE), + 500 * MOVR, + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + // set_author(NimbusId::from_slice(&ALICE_NIMBUS)); + let result = + Executive::apply_extrinsic(unchecked_eth_tx(VALID_ETH_TX)).expect("Apply result."); + assert_eq!(result, Ok(())); + rpc_run_to_block(2); + let receipts = Runtime::current_receipts().expect("Receipts result."); + assert_eq!(receipts.len(), 1); + }); +} + +#[test] +fn txpool_runtime_api_extrinsic_filter() { + ExtBuilder::default().build().execute_with(|| { + let non_eth_uxt = UncheckedExtrinsic::new_unsigned( + pallet_balances::Call::::transfer { + dest: AccountId::from(BOB), + value: 1 * MOVR, + } + .into(), + ); + let eth_uxt = unchecked_eth_tx(VALID_ETH_TX); + let txpool = >::extrinsic_filter( + vec![eth_uxt.clone(), non_eth_uxt.clone()], + vec![unchecked_eth_tx(VALID_ETH_TX), non_eth_uxt], + ); + assert_eq!(txpool.ready.len(), 1); + assert_eq!(txpool.future.len(), 1); + }); +} + +#[test] +fn can_author_when_selected_is_empty() { + ExtBuilder::default() + .with_balances(vec![ + (AccountId::from(ALICE), 20_000_000 * MOVR), + (AccountId::from(BOB), 10_000_000 * MOVR), + ]) + .with_collators(vec![(AccountId::from(ALICE), 2_000_000 * MOVR)]) + .with_mappings(vec![( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + AccountId::from(ALICE), + )]) + .build() + .execute_with(|| { + set_parachain_inherent_data(); + run_to_block(2, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + + assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); + + let slot_number = 0; + let parent = Header { + digest: Default::default(), + extrinsics_root: Default::default(), + number: Default::default(), + parent_hash: Default::default(), + state_root: Default::default(), + }; + + // Base case: ALICE can author blocks when she is the only candidate + let can_author_block = Runtime::can_author( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + slot_number, + &parent, + ); + + assert!(can_author_block); + + // Remove ALICE from candidate pool, leaving the candidate_pool empty + assert_ok!(ParachainStaking::go_offline(origin_of(AccountId::from( + ALICE + )))); + + // Need to fast forward to right before the next session, which is when selected candidates + // will be updated. We want to test the creation of the first block of the next session. + run_to_block(1799, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + + assert_eq!(ParachainStaking::candidate_pool().0.len(), 0); + + let slot_number = 0; + let parent = Header { + digest: Default::default(), + extrinsics_root: Default::default(), + number: 1799, + parent_hash: Default::default(), + state_root: Default::default(), + }; + + let can_author_block = Runtime::can_author( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + slot_number, + &parent, + ); + + assert!(can_author_block); + + // Check that it works as expected after session update + run_to_block(1800, Some(NimbusId::from_slice(&ALICE_NIMBUS).unwrap())); + + assert_eq!(ParachainStaking::candidate_pool().0.len(), 0); + + let slot_number = 0; + let parent = Header { + digest: Default::default(), + extrinsics_root: Default::default(), + number: 1800, + parent_hash: Default::default(), + state_root: Default::default(), + }; + + let can_author_block = Runtime::can_author( + NimbusId::from_slice(&ALICE_NIMBUS).unwrap(), + slot_number, + &parent, + ); + + assert!(can_author_block); + }); +} diff --git a/tracing/2601/runtime/moonriver/tests/xcm_mock/mod.rs b/tracing/2601/runtime/moonriver/tests/xcm_mock/mod.rs new file mode 100644 index 00000000..b2910d17 --- /dev/null +++ b/tracing/2601/runtime/moonriver/tests/xcm_mock/mod.rs @@ -0,0 +1,275 @@ +// Copyright 2021 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 . + +pub mod parachain; +pub mod relay_chain; +pub mod statemine_like; + +use cumulus_primitives_core::ParaId; +use pallet_xcm_transactor::relay_indices::*; +use sp_runtime::traits::AccountIdConversion; +use sp_runtime::{AccountId32, BuildStorage}; +use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt}; + +use polkadot_runtime_parachains::configuration::{ + GenesisConfig as ConfigurationGenesisConfig, HostConfiguration, +}; +use polkadot_runtime_parachains::paras::{ + GenesisConfig as ParasGenesisConfig, ParaGenesisArgs, ParaKind, +}; +use sp_core::{H160, U256}; +use std::{collections::BTreeMap, str::FromStr}; + +pub const PARAALICE: [u8; 20] = [1u8; 20]; +pub const RELAYALICE: AccountId32 = AccountId32::new([0u8; 32]); +pub const RELAYBOB: AccountId32 = AccountId32::new([2u8; 32]); + +pub fn para_a_account() -> AccountId32 { + ParaId::from(1).into_account_truncating() +} + +pub fn para_b_account() -> AccountId32 { + ParaId::from(2).into_account_truncating() +} + +pub fn para_a_account_20() -> parachain::AccountId { + ParaId::from(1).into_account_truncating() +} + +pub fn evm_account() -> H160 { + H160::from_str("1000000000000000000000000000000000000001").unwrap() +} + +pub fn mock_para_genesis_info() -> ParaGenesisArgs { + ParaGenesisArgs { + genesis_head: vec![1u8].into(), + validation_code: vec![1u8].into(), + para_kind: ParaKind::Parachain, + } +} + +pub fn mock_relay_config() -> HostConfiguration { + HostConfiguration:: { + hrmp_channel_max_capacity: u32::MAX, + hrmp_channel_max_total_size: u32::MAX, + hrmp_max_parachain_inbound_channels: 10, + hrmp_max_parachain_outbound_channels: 10, + hrmp_channel_max_message_size: u32::MAX, + // Changed to avoid aritmetic errors within hrmp_close + max_downward_message_size: 100_000u32, + ..Default::default() + } +} + +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_parachain! { + pub struct ParaC { + Runtime = parachain::Runtime, + XcmpMessageHandler = parachain::MsgQueue, + DmpMessageHandler = parachain::MsgQueue, + new_ext = para_ext(3), + } +} + +decl_test_parachain! { + pub struct Statemine { + Runtime = statemine_like::Runtime, + XcmpMessageHandler = statemine_like::MsgQueue, + DmpMessageHandler = statemine_like::MsgQueue, + new_ext = statemine_ext(4), + } +} + +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(vec![1, 2, 3, 4]), + } +} + +decl_test_network! { + pub struct MockNet { + relay_chain = Relay, + parachains = vec![ + (1, ParaA), + (2, ParaB), + (3, ParaC), + (4, Statemine), + ], + } +} + +pub const INITIAL_BALANCE: u128 = 10_000_000_000_000_000; + +pub const INITIAL_EVM_BALANCE: u128 = 0; +pub const INITIAL_EVM_NONCE: u32 = 1; + +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![(PARAALICE.into(), INITIAL_BALANCE)], + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_xcm_transactor::GenesisConfig:: { + // match relay runtime construct_runtime order in xcm_mock::relay_chain + relay_indices: RelayChainIndices { + hrmp: 6u8, + init_open_channel: 0u8, + accept_open_channel: 1u8, + close_channel: 2u8, + cancel_open_request: 6u8, + ..Default::default() + }, + ..Default::default() + } + .assimilate_storage(&mut t) + .unwrap(); + + // EVM accounts are self-sufficient. + let mut evm_accounts = BTreeMap::new(); + evm_accounts.insert( + evm_account(), + fp_evm::GenesisAccount { + nonce: U256::from(INITIAL_EVM_NONCE), + balance: U256::from(INITIAL_EVM_BALANCE), + storage: Default::default(), + code: vec![ + 0x00, // STOP + ], + }, + ); + + let genesis_config = pallet_evm::GenesisConfig:: { + accounts: evm_accounts, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + MsgQueue::set_para_id(para_id.into()); + }); + ext +} + +pub fn statemine_ext(para_id: u32) -> sp_io::TestExternalities { + use statemine_like::{MsgQueue, Runtime, System}; + + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap(); + + pallet_balances::GenesisConfig:: { + balances: vec![ + (RELAYALICE.into(), INITIAL_BALANCE), + (RELAYBOB.into(), INITIAL_BALANCE), + ], + } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + MsgQueue::set_para_id(para_id.into()); + }); + ext +} + +pub fn relay_ext(paras: Vec) -> sp_io::TestExternalities { + use relay_chain::{Runtime, System}; + + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap(); + + pallet_balances::GenesisConfig:: { + balances: vec![(RELAYALICE, INITIAL_BALANCE)], + } + .assimilate_storage(&mut t) + .unwrap(); + + let para_genesis: Vec<(ParaId, ParaGenesisArgs)> = paras + .iter() + .map(|¶_id| (para_id.into(), mock_para_genesis_info())) + .collect(); + + let genesis_config = ConfigurationGenesisConfig:: { + config: mock_relay_config(), + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let genesis_config = ParasGenesisConfig:: { + paras: para_genesis, + ..Default::default() + }; + genesis_config.assimilate_storage(&mut t).unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + }); + ext +} + +pub type RelayChainPalletXcm = pallet_xcm::Pallet; +pub type Hrmp = polkadot_runtime_parachains::hrmp::Pallet; + +pub type StatemineBalances = pallet_balances::Pallet; +pub type StatemineChainPalletXcm = pallet_xcm::Pallet; +pub type StatemineAssets = pallet_assets::Pallet; + +pub type ParachainPalletXcm = pallet_xcm::Pallet; +pub type Assets = pallet_assets::Pallet; +pub type LocalAssets = pallet_assets::Pallet; + +pub type Balances = pallet_balances::Pallet; +pub type Treasury = pallet_treasury::Pallet; +pub type AssetManager = pallet_asset_manager::Pallet; +pub type XTokens = orml_xtokens::Pallet; +pub type RelayBalances = pallet_balances::Pallet; +pub type ParaBalances = pallet_balances::Pallet; +pub type XcmTransactor = pallet_xcm_transactor::Pallet; diff --git a/tracing/2601/runtime/moonriver/tests/xcm_mock/parachain.rs b/tracing/2601/runtime/moonriver/tests/xcm_mock/parachain.rs new file mode 100644 index 00000000..53fd07c3 --- /dev/null +++ b/tracing/2601/runtime/moonriver/tests/xcm_mock/parachain.rs @@ -0,0 +1,1220 @@ +// Copyright 2021 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 frame_support::{ + construct_runtime, + dispatch::GetDispatchInfo, + ensure, parameter_types, + traits::{ + AsEnsureOriginWithArg, ConstU32, Everything, Get, InstanceFilter, Nothing, PalletInfoAccess, + }, + weights::Weight, + PalletId, +}; +use frame_system::{pallet_prelude::BlockNumberFor, EnsureNever, EnsureRoot}; +use pallet_xcm::migration::v1::VersionUncheckedMigrateToV1; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use sp_core::H256; +use sp_runtime::{ + traits::{BlakeTwo256, Hash, IdentityLookup, MaybeEquivalence, Zero}, + Permill, +}; +use sp_std::{convert::TryFrom, prelude::*}; +use xcm::{latest::prelude::*, Version as XcmVersion, VersionedXcm}; + +use cumulus_primitives_core::relay_chain::HrmpChannelId; +use orml_traits::parameter_type_with_key; +use pallet_ethereum::PostLogContent; +use polkadot_core_primitives::BlockNumber as RelayBlockNumber; +use polkadot_parachain::primitives::{Id as ParaId, Sibling}; +use xcm::latest::{ + AssetId as XcmAssetId, Error as XcmError, ExecuteXcm, + Junction::{PalletInstance, Parachain}, + Junctions, MultiLocation, NetworkId, Outcome, Xcm, +}; +use xcm_builder::{ + AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, + CurrencyAdapter as XcmCurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, + FungiblesAdapter, IsConcrete, NoChecking, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountKey20AsNative, SovereignSignedViaLocation, TakeWeightCredit, WithComputedOrigin, +}; +use xcm_executor::{traits::JustTry, Config, XcmExecutor}; + +use scale_info::TypeInfo; +use xcm_simulator::{ + DmpMessageHandlerT as DmpMessageHandler, XcmpMessageFormat, + XcmpMessageHandlerT as XcmpMessageHandler, +}; + +pub type AccountId = moonbeam_core_primitives::AccountId; +pub type Balance = u128; +pub type AssetId = u128; +pub type BlockNumber = BlockNumberFor; + +parameter_types! { + pub const BlockHashCount: u32 = 250; +} + +impl frame_system::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Block = Block; + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + 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 = frame_support::traits::ConstU32<16>; +} + +parameter_types! { + pub ExistentialDeposit: Balance = 0; + 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 = (); + type FreezeIdentifier = (); + type MaxHolds = (); + type MaxFreezes = (); +} + +pub type ForeignAssetInstance = (); +pub type LocalAssetInstance = pallet_assets::Instance1; + +// Required for runtime benchmarks +pallet_assets::runtime_benchmarks_enabled! { + pub struct BenchmarkHelper; + impl pallet_assets::BenchmarkHelper for BenchmarkHelper + where + AssetIdParameter: From, + { + fn create_asset_id_parameter(id: u32) -> AssetIdParameter { + (id as u128).into() + } + } +} + +parameter_types! { + pub const AssetDeposit: Balance = 1; // Does not really matter as this will be only called by root + pub const ApprovalDeposit: Balance = 0; + pub const AssetsStringLimit: u32 = 50; + pub const MetadataDepositBase: Balance = 0; + pub const MetadataDepositPerByte: Balance = 0; + pub const AssetAccountDeposit: Balance = 0; +} + +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = AssetAccountDeposit; + type WeightInfo = pallet_assets::weights::SubstrateWeight; + type RemoveItemsLimit = ConstU32<656>; + type AssetIdParameter = AssetId; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = AssetAccountDeposit; + type WeightInfo = pallet_assets::weights::SubstrateWeight; + type RemoveItemsLimit = ConstU32<656>; + type AssetIdParameter = AssetId; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used +/// when determining ownership of accounts for asset transacting and when attempting to use XCM +/// `Transact` in order to determine the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the default `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + AccountKey20Aliases, + // Generate remote accounts according to polkadot standards + xcm_builder::HashedDescriptionDescribeFamilyAllTerminal, +); + +/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, +/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can +/// biases the kind of local `Origin` it will become. +pub type XcmOriginToTransactDispatchOrigin = ( + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // recognised. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognised. + SiblingParachainAsNative, + // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a + // transaction from the Root origin. + ParentAsSuperuser, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + pallet_xcm::XcmPassthrough, + SignedAccountKey20AsNative, +); + +parameter_types! { + pub const UnitWeightCost: Weight = Weight::from_parts(1u64, 1u64); + pub MaxInstructions: u32 = 100; +} + +// Instructing how incoming xcm assets will be handled +pub type ForeignFungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + Assets, + // Use this currency when it is a fungible asset matching the given location or name: + ( + ConvertedConcreteId< + AssetId, + Balance, + xcm_primitives::AsAssetType, + JustTry, + >, + ), + // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont allow teleports. + NoChecking, + // We dont track any teleports + (), +>; + +pub type LocalAssetTransactor = XcmCurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching any of the locations in + // SelfReserveRepresentations + IsConcrete, + // We can convert the MultiLocations with our converter above: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont allow teleport + (), +>; + +/// Means for transacting local assets besides the native currency on this chain. +pub type LocalFungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + LocalAssets, + // Use this currency when it is a fungible asset matching the given location or name: + ( + ConvertedConcreteId< + AssetId, + Balance, + AsPrefixedGeneralIndex, + JustTry, + >, + ), + // Convert an XCM MultiLocation into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We dont want to allow teleporting assets + NoChecking, + // The account to use for tracking teleports. + (), +>; + +// We use both transactors +pub type AssetTransactors = ( + LocalAssetTransactor, + ForeignFungiblesTransactor, + LocalFungiblesTransactor, +); + +pub type XcmRouter = super::ParachainXcmRouter; + +pub type XcmBarrier = ( + // Weight that is paid for may be consumed. + TakeWeightCredit, + // Expected responses are OK. + AllowKnownQueryResponses, + WithComputedOrigin< + ( + // If the message is one that immediately attemps to pay for execution, then allow it. + AllowTopLevelPaidExecutionFrom, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, + ), + UniversalLocation, + ConstU32<8>, + >, +); + +parameter_types! { + /// Xcm fees will go to the treasury account + pub XcmFeesAccount: AccountId = Treasury::account_id(); +} + +/// This is the struct that will handle the revenue from xcm fees +pub type XcmFeesToAccount_ = xcm_primitives::XcmFeesToAccount< + Assets, + ( + ConvertedConcreteId< + AssetId, + Balance, + xcm_primitives::AsAssetType, + JustTry, + >, + ), + AccountId, + XcmFeesAccount, +>; + +parameter_types! { + // We cannot skip the native trader for some specific tests, so we will have to work with + // a native trader that charges same number of units as weight + pub ParaTokensPerSecond: (XcmAssetId, u128, u128) = ( + Concrete(SelfReserve::get()), + 1000000000000, + 0, + ); +} + +parameter_types! { + pub const RelayNetwork: NetworkId = NetworkId::Polkadot; + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + pub UniversalLocation: InteriorMultiLocation = + X2(GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())); + + pub LocalAssetsPalletLocation: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; + + // This is used to match it against our Balances pallet when we receive such a MultiLocation + // (Parent, Self Para Id, Self Balances pallet index) + pub SelfReserve: MultiLocation = MultiLocation { + parents:0, + interior: Junctions::X1( + PalletInstance(::index() as u8) + ) + }; + pub const MaxAssetsIntoHolding: u32 = 64; +} + +use frame_system::RawOrigin; +use sp_runtime::traits::PostDispatchInfoOf; +use sp_runtime::DispatchErrorWithPostInfo; +use xcm_executor::traits::CallDispatcher; +moonbeam_runtime_common::impl_moonbeam_xcm_call!(); + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = AssetTransactors; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type IsReserve = orml_xcm_support::MultiNativeAsset< + xcm_primitives::AbsoluteAndRelativeReserve, + >; + type IsTeleporter = (); + type UniversalLocation = UniversalLocation; + type Barrier = XcmBarrier; + type Weigher = FixedWeightBounds; + // We use three traders + // When we receive either representation of the self-reserve asset, + // When we receive a non-reserve asset, we use AssetManager to fetch how many + // units per second we should charge + type Trader = ( + FixedRateOfFungible, + xcm_primitives::FirstAssetTrader, + ); + + type ResponseHandler = PolkadotXcm; + type SubscriptionService = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type CallDispatcher = MoonbeamCall; + type AssetLocker = (); + type AssetExchanger = (); + type PalletInstancesInfo = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; + type SafeCallFilter = Everything; + type Aliasers = Nothing; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +// Our currencyId. We distinguish for now between SelfReserve, and Others, defined by their Id. +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum CurrencyId { + SelfReserve, + ForeignAsset(AssetId), + LocalAssetReserve(AssetId), +} + +// How to convert from CurrencyId to MultiLocation +pub struct CurrencyIdtoMultiLocation(sp_std::marker::PhantomData); +impl sp_runtime::traits::Convert> + for CurrencyIdtoMultiLocation +where + AssetXConverter: MaybeEquivalence, +{ + fn convert(currency: CurrencyId) -> Option { + match currency { + CurrencyId::SelfReserve => { + // For now and until Xtokens is adapted to handle 0.9.16 version we use + // the old anchoring here + // This is not a problem in either cases, since the view of the destination + // chain does not change + // TODO! change this to NewAnchoringSelfReserve once xtokens is adapted for it + let multi: MultiLocation = SelfReserve::get(); + Some(multi) + } + CurrencyId::ForeignAsset(asset) => AssetXConverter::convert_back(&asset), + CurrencyId::LocalAssetReserve(asset) => { + let mut location = LocalAssetsPalletLocation::get(); + location.push_interior(Junction::GeneralIndex(asset)).ok(); + Some(location) + } + } + } +} + +parameter_types! { + pub const BaseXcmWeight: Weight = Weight::from_parts(100u64, 100u64); + pub const MaxAssetsForTransfer: usize = 2; + pub SelfLocation: MultiLocation = MultiLocation::here(); + pub SelfLocationAbsolute: MultiLocation = MultiLocation { + parents:1, + interior: Junctions::X1( + Parachain(MsgQueue::parachain_id().into()) + ) + }; +} + +parameter_type_with_key! { + pub ParachainMinFee: |location: MultiLocation| -> Option { + match (location.parents, location.first_interior()) { + (1, Some(Parachain(4u32))) => Some(50u128), + _ => None, + } + }; +} + +// The XCM message wrapper wrapper +impl orml_xtokens::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type CurrencyId = CurrencyId; + type AccountIdToMultiLocation = xcm_primitives::AccountIdToMultiLocation; + type CurrencyIdConvert = + CurrencyIdtoMultiLocation>; + type XcmExecutor = XcmExecutor; + type SelfLocation = SelfLocation; + type Weigher = xcm_builder::FixedWeightBounds; + type BaseXcmWeight = BaseXcmWeight; + type UniversalLocation = UniversalLocation; + type MaxAssetsForTransfer = MaxAssetsForTransfer; + type MinXcmFee = ParachainMinFee; + type MultiLocationsFilter = Everything; + type ReserveProvider = xcm_primitives::AbsoluteAndRelativeReserve; +} + +parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const ProposalBondMinimum: Balance = 0; + pub const SpendPeriod: u32 = 0; + pub const TreasuryId: PalletId = PalletId(*b"pc/trsry"); + pub const MaxApprovals: u32 = 100; +} + +impl pallet_treasury::Config for Runtime { + type PalletId = TreasuryId; + type Currency = Balances; + type ApproveOrigin = EnsureRoot; + type RejectOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type OnSlash = Treasury; + type ProposalBond = ProposalBond; + type ProposalBondMinimum = ProposalBondMinimum; + type SpendPeriod = SpendPeriod; + type Burn = (); + type BurnDestination = (); + type MaxApprovals = MaxApprovals; + type WeightInfo = (); + type SpendFunds = (); + type ProposalBondMaximum = (); + type SpendOrigin = frame_support::traits::NeverEnsureOrigin; // Same as Polkadot +} + +#[frame_support::pallet] +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] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn parachain_id)] + pub(super) type ParachainId = StorageValue<_, ParaId, 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 (result, event) = match Xcm::::try_from(xcm) { + Ok(xcm) => { + let location = MultiLocation::new(1, Junctions::X1(Parachain(sender.into()))); + let mut id = [0u8; 32]; + id.copy_from_slice(hash.as_ref()); + match T::XcmExecutor::execute_xcm(location, xcm, id, max_weight) { + Outcome::Error(e) => (Err(e.clone()), 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 (_i, (_sent_at, data)) in iter.enumerate() { + let id = sp_io::hashing::blake2_256(&data[..]); + let maybe_msg = VersionedXcm::::decode(&mut &data[..]) + .map(Xcm::::try_from); + match maybe_msg { + Err(_) => { + Self::deposit_event(Event::InvalidFormat(id)); + } + Ok(Err(())) => { + Self::deposit_event(Event::UnsupportedVersion(id)); + } + Ok(Ok(x)) => { + let outcome = T::XcmExecutor::execute_xcm(Parent, x, id, limit); + + Self::deposit_event(Event::ExecutedDownward(id, outcome)); + } + } + } + limit + } + } +} + +// Pallet to provide the version, used to test runtime upgrade version changes +#[frame_support::pallet] +pub mod mock_version_changer { + use super::*; + use frame_support::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + } + + #[pallet::call] + impl Pallet {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn current_version)] + pub(super) type CurrentVersion = StorageValue<_, XcmVersion, ValueQuery>; + + impl Get for Pallet { + fn get() -> XcmVersion { + Self::current_version() + } + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + // XCMP + /// Some XCM was executed OK. + VersionChanged(XcmVersion), + } + + impl Pallet { + pub fn set_version(version: XcmVersion) { + CurrentVersion::::put(version); + Self::deposit_event(Event::VersionChanged(version)); + } + } +} + +impl mock_msg_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +impl mock_version_changer::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} + +pub type LocalOriginToLocation = + xcm_primitives::SignedToAccountId20; + +parameter_types! { + pub MatcherLocation: MultiLocation = MultiLocation::here(); +} + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parent.into()); +} + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = frame_support::traits::Nothing; + type XcmExecutor = XcmExecutor; + // Do not allow teleports + 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; + // We use a custom one to test runtime ugprades + type AdvertisedXcmVersion = XcmVersioner; + type Currency = Balances; + type CurrencyMatcher = IsConcrete; + type TrustedLockers = (); + type SovereignAccountOf = (); + type MaxLockers = ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type AdminOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; +} + +// Our AssetType. For now we only handle Xcm Assets +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum AssetType { + Xcm(MultiLocation), +} +impl Default for AssetType { + fn default() -> Self { + Self::Xcm(MultiLocation::here()) + } +} + +impl From for AssetType { + fn from(location: MultiLocation) -> Self { + Self::Xcm(location) + } +} + +impl Into> for AssetType { + fn into(self) -> Option { + match self { + Self::Xcm(location) => Some(location), + } + } +} + +// Implementation on how to retrieve the AssetId from an AssetType +// We simply hash the AssetType and take the lowest 128 bits +impl From for AssetId { + fn from(asset: AssetType) -> AssetId { + match asset { + AssetType::Xcm(id) => { + let mut result: [u8; 16] = [0u8; 16]; + let hash: H256 = id.using_encoded(::Hashing::hash); + result.copy_from_slice(&hash.as_fixed_bytes()[0..16]); + u128::from_le_bytes(result) + } + } + } +} + +// We instruct how to register the Assets +// In this case, we tell it to Create an Asset in pallet-assets +pub struct AssetRegistrar; +use frame_support::pallet_prelude::DispatchResult; +impl pallet_asset_manager::AssetRegistrar for AssetRegistrar { + fn create_foreign_asset( + asset: AssetId, + min_balance: Balance, + metadata: AssetMetadata, + is_sufficient: bool, + ) -> DispatchResult { + Assets::force_create( + RuntimeOrigin::root(), + asset, + AssetManager::account_id(), + is_sufficient, + min_balance, + )?; + + Assets::force_set_metadata( + RuntimeOrigin::root(), + asset, + metadata.name, + metadata.symbol, + metadata.decimals, + false, + ) + } + + fn create_local_asset( + asset: AssetId, + _creator: AccountId, + min_balance: Balance, + is_sufficient: bool, + owner: AccountId, + ) -> DispatchResult { + LocalAssets::force_create( + RuntimeOrigin::root(), + asset, + owner, + is_sufficient, + min_balance, + )?; + + // TODO uncomment when we feel comfortable + /* + // The asset has been created. Let's put the revert code in the precompile address + let precompile_address = Runtime::asset_id_to_account(ASSET_PRECOMPILE_ADDRESS_PREFIX, asset); + pallet_evm::AccountCodes::::insert( + precompile_address, + vec![0x60, 0x00, 0x60, 0x00, 0xfd], + );*/ + Ok(()) + } + fn destroy_foreign_asset(asset: AssetId) -> DispatchResult { + // Mark the asset as destroying + Assets::start_destroy(RuntimeOrigin::root(), asset)?; + + Ok(()) + } + + fn destroy_local_asset(asset: AssetId) -> DispatchResult { + // Mark the asset as destroying + LocalAssets::start_destroy(RuntimeOrigin::root(), asset)?; + + Ok(()) + } + + fn destroy_asset_dispatch_info_weight(asset: AssetId) -> Weight { + RuntimeCall::Assets( + pallet_assets::Call::::start_destroy { id: asset }, + ) + .get_dispatch_info() + .weight + } +} + +#[derive(Clone, Default, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub struct AssetMetadata { + pub name: Vec, + pub symbol: Vec, + pub decimals: u8, +} +pub struct LocalAssetIdCreator; +impl pallet_asset_manager::LocalAssetIdCreator for LocalAssetIdCreator { + fn create_asset_id_from_metadata(local_asset_counter: u128) -> AssetId { + // Our means of converting a creator to an assetId + // We basically hash (local asset counter) + let mut result: [u8; 16] = [0u8; 16]; + let hash: H256 = + local_asset_counter.using_encoded(::Hashing::hash); + result.copy_from_slice(&hash.as_fixed_bytes()[0..16]); + u128::from_le_bytes(result) + } +} + +impl pallet_asset_manager::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type AssetRegistrarMetadata = AssetMetadata; + type ForeignAssetType = AssetType; + type AssetRegistrar = AssetRegistrar; + type ForeignAssetModifierOrigin = EnsureRoot; + type LocalAssetModifierOrigin = EnsureRoot; + type LocalAssetIdCreator = LocalAssetIdCreator; + type Currency = Balances; + type LocalAssetDeposit = AssetDeposit; + type WeightInfo = (); +} + +// 1 KSM should be enough +parameter_types! { + pub MaxHrmpRelayFee: MultiAsset = (MultiLocation::parent(), 1_000_000_000_000u128).into(); +} + +impl pallet_xcm_transactor::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type Transactor = MockTransactors; + type DerivativeAddressRegistrationOrigin = EnsureRoot; + type SovereignAccountDispatcherOrigin = frame_system::EnsureRoot; + type CurrencyId = CurrencyId; + type AccountIdToMultiLocation = xcm_primitives::AccountIdToMultiLocation; + type CurrencyIdToMultiLocation = + CurrencyIdtoMultiLocation>; + type SelfLocation = SelfLocation; + type Weigher = xcm_builder::FixedWeightBounds; + type UniversalLocation = UniversalLocation; + type XcmSender = XcmRouter; + type BaseXcmWeight = BaseXcmWeight; + type AssetTransactor = AssetTransactors; + type ReserveProvider = xcm_primitives::AbsoluteAndRelativeReserve; + type WeightInfo = (); + type HrmpManipulatorOrigin = EnsureRoot; + type MaxHrmpFee = xcm_builder::Case; +} + +parameter_types! { + pub const MinimumPeriod: u64 = 1000; +} +impl pallet_timestamp::Config for Runtime { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +use sp_core::U256; + +const MAX_POV_SIZE: u64 = 5 * 1024 * 1024; +/// Block storage limit in bytes. Set to 40 KB. +const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024; + +parameter_types! { + pub BlockGasLimit: U256 = U256::from(u64::MAX); + pub WeightPerGas: Weight = Weight::from_parts(1, 0); + pub GasLimitPovSizeRatio: u64 = { + let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64(); + block_gas_limit.saturating_div(MAX_POV_SIZE) + }; + pub GasLimitStorageGrowthRatio: u64 = + BlockGasLimit::get().min(u64::MAX.into()).low_u64().saturating_div(BLOCK_STORAGE_LIMIT); +} + +impl pallet_evm::Config for Runtime { + type FeeCalculator = (); + type GasWeightMapping = pallet_evm::FixedGasWeightMapping; + type WeightPerGas = WeightPerGas; + + type CallOrigin = pallet_evm::EnsureAddressRoot; + type WithdrawOrigin = pallet_evm::EnsureAddressNever; + + type AddressMapping = pallet_evm::IdentityAddressMapping; + type Currency = Balances; + type Runner = pallet_evm::runner::stack::Runner; + + type RuntimeEvent = RuntimeEvent; + type PrecompilesType = (); + type PrecompilesValue = (); + type ChainId = (); + type BlockGasLimit = BlockGasLimit; + type OnChargeTransaction = (); + type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping; + type FindAuthor = (); + type OnCreate = (); + type GasLimitPovSizeRatio = GasLimitPovSizeRatio; + type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio; + type Timestamp = Timestamp; + type WeightInfo = pallet_evm::weights::SubstrateWeight; +} + +pub struct NormalFilter; +impl frame_support::traits::Contains for NormalFilter { + fn contains(c: &RuntimeCall) -> bool { + match c { + _ => true, + } + } +} + +// We need to use the encoding from the relay mock runtime +#[derive(Encode, Decode)] +pub enum RelayCall { + #[codec(index = 5u8)] + // the index should match the position of the module in `construct_runtime!` + Utility(UtilityCall), + #[codec(index = 6u8)] + // the index should match the position of the module in `construct_runtime!` + Hrmp(HrmpCall), +} + +#[derive(Encode, Decode)] +pub enum UtilityCall { + #[codec(index = 1u8)] + AsDerivative(u16), +} + +// HRMP call encoding, needed for xcm transactor pallet +#[derive(Encode, Decode)] +pub enum HrmpCall { + #[codec(index = 0u8)] + InitOpenChannel(ParaId, u32, u32), + #[codec(index = 1u8)] + AcceptOpenChannel(ParaId), + #[codec(index = 2u8)] + CloseChannel(HrmpChannelId), + #[codec(index = 6u8)] + CancelOpenRequest(HrmpChannelId, u32), +} + +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum MockTransactors { + Relay, +} + +impl xcm_primitives::XcmTransact for MockTransactors { + fn destination(self) -> MultiLocation { + match self { + MockTransactors::Relay => MultiLocation::parent(), + } + } +} + +impl xcm_primitives::UtilityEncodeCall for MockTransactors { + fn encode_call(self, call: xcm_primitives::UtilityAvailableCalls) -> Vec { + match self { + MockTransactors::Relay => match call { + xcm_primitives::UtilityAvailableCalls::AsDerivative(a, b) => { + let mut call = + RelayCall::Utility(UtilityCall::AsDerivative(a.clone())).encode(); + call.append(&mut b.clone()); + call + } + }, + } + } +} + +pub struct MockHrmpEncoder; +impl xcm_primitives::HrmpEncodeCall for MockHrmpEncoder { + fn hrmp_encode_call( + call: xcm_primitives::HrmpAvailableCalls, + ) -> Result, xcm::latest::Error> { + match call { + xcm_primitives::HrmpAvailableCalls::InitOpenChannel(a, b, c) => Ok(RelayCall::Hrmp( + HrmpCall::InitOpenChannel(a.clone(), b.clone(), c.clone()), + ) + .encode()), + xcm_primitives::HrmpAvailableCalls::AcceptOpenChannel(a) => { + Ok(RelayCall::Hrmp(HrmpCall::AcceptOpenChannel(a.clone())).encode()) + } + xcm_primitives::HrmpAvailableCalls::CloseChannel(a) => { + Ok(RelayCall::Hrmp(HrmpCall::CloseChannel(a.clone())).encode()) + } + xcm_primitives::HrmpAvailableCalls::CancelOpenRequest(a, b) => { + Ok(RelayCall::Hrmp(HrmpCall::CancelOpenRequest(a.clone(), b.clone())).encode()) + } + } + } +} + +parameter_types! { + pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes; +} + +impl pallet_ethereum::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type StateRoot = pallet_ethereum::IntermediateStateRoot; + type PostLogContent = PostBlockAndTxnHashes; + type ExtraDataLength = ConstU32<30>; +} + +parameter_types! { + pub ReservedXcmpWeight: Weight = Weight::from_parts(u64::max_value(), 0); +} + +#[derive( + Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, MaxEncodedLen, TypeInfo, +)] +pub enum ProxyType { + NotAllowed = 0, + Any = 1, +} + +impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType {} + +impl InstanceFilter for ProxyType { + fn filter(&self, _c: &RuntimeCall) -> bool { + match self { + ProxyType::NotAllowed => false, + ProxyType::Any => true, + } + } + fn is_superset(&self, _o: &Self) -> bool { + false + } +} + +impl Default for ProxyType { + fn default() -> Self { + Self::NotAllowed + } +} + +parameter_types! { + pub const ProxyCost: u64 = 1; +} + +impl pallet_proxy::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type ProxyType = ProxyType; + type ProxyDepositBase = ProxyCost; + type ProxyDepositFactor = ProxyCost; + type MaxProxies = ConstU32<32>; + type WeightInfo = pallet_proxy::weights::SubstrateWeight; + type MaxPending = ConstU32<32>; + type CallHasher = BlakeTwo256; + type AnnouncementDepositBase = ProxyCost; + type AnnouncementDepositFactor = ProxyCost; +} + +pub struct EthereumXcmEnsureProxy; +impl xcm_primitives::EnsureProxy for EthereumXcmEnsureProxy { + fn ensure_ok(delegator: AccountId, delegatee: AccountId) -> Result<(), &'static str> { + // The EVM implicitely contains an Any proxy, so we only allow for "Any" proxies + let def: pallet_proxy::ProxyDefinition = + pallet_proxy::Pallet::::find_proxy( + &delegator, + &delegatee, + Some(ProxyType::Any), + ) + .map_err(|_| "proxy error: expected `ProxyType::Any`")?; + // We only allow to use it for delay zero proxies, as the call will iMmediatly be executed + ensure!(def.delay.is_zero(), "proxy delay is Non-zero`"); + Ok(()) + } +} + +impl pallet_ethereum_xcm::Config for Runtime { + type InvalidEvmTransactionError = pallet_ethereum::InvalidTransactionWrapper; + type ValidatedTransaction = pallet_ethereum::ValidatedTransaction; + type XcmEthereumOrigin = pallet_ethereum_xcm::EnsureXcmEthereumTransaction; + type ReservedXcmpWeight = ReservedXcmpWeight; + type EnsureProxy = EthereumXcmEnsureProxy; + type ControllerOrigin = EnsureRoot; +} + +type Block = frame_system::mocking::MockBlockU32; + +construct_runtime!( + pub enum Runtime { + System: frame_system, + Balances: pallet_balances, + MsgQueue: mock_msg_queue, + XcmVersioner: mock_version_changer, + + PolkadotXcm: pallet_xcm, + Assets: pallet_assets, + CumulusXcm: cumulus_pallet_xcm, + XTokens: orml_xtokens, + AssetManager: pallet_asset_manager, + XcmTransactor: pallet_xcm_transactor, + Treasury: pallet_treasury, + LocalAssets: pallet_assets::, + Proxy: pallet_proxy, + + Timestamp: pallet_timestamp, + EVM: pallet_evm, + Ethereum: pallet_ethereum, + EthereumXcm: pallet_ethereum_xcm, + } +); + +pub(crate) fn para_events() -> Vec { + System::events() + .into_iter() + .map(|r| r.event) + .filter_map(|e| Some(e)) + .collect::>() +} + +use frame_support::traits::{OnFinalize, OnInitialize, OnRuntimeUpgrade}; +pub(crate) fn on_runtime_upgrade() { + VersionUncheckedMigrateToV1::::on_runtime_upgrade(); +} + +pub(crate) fn para_roll_to(n: BlockNumber) { + while System::block_number() < n { + PolkadotXcm::on_finalize(System::block_number()); + Balances::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Balances::on_initialize(System::block_number()); + PolkadotXcm::on_initialize(System::block_number()); + } +} diff --git a/tracing/2601/runtime/moonriver/tests/xcm_mock/relay_chain.rs b/tracing/2601/runtime/moonriver/tests/xcm_mock/relay_chain.rs new file mode 100644 index 00000000..30c5537b --- /dev/null +++ b/tracing/2601/runtime/moonriver/tests/xcm_mock/relay_chain.rs @@ -0,0 +1,406 @@ +// Copyright 2021 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::{Everything, Nothing, ProcessMessage, ProcessMessageError}, +}; +use frame_system::pallet_prelude::BlockNumberFor; +use sp_core::H256; +use sp_runtime::{ + traits::{ConstU32, IdentityLookup}, + AccountId32, +}; + +use frame_support::weights::{Weight, WeightMeter}; +use polkadot_parachain::primitives::Id as ParaId; +use polkadot_runtime_parachains::{ + configuration, dmp, hrmp, + inclusion::{AggregateMessageOrigin, UmpQueueId}, + origin, paras, shared, +}; +use sp_runtime::transaction_validity::TransactionPriority; +use sp_runtime::Permill; +use xcm::latest::prelude::*; +use xcm_builder::{ + Account32Hash, AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, ChildParachainAsNative, ChildParachainConvertsVia, + ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible, + FixedWeightBounds, IsConcrete, ProcessXcmMessage, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, WithComputedOrigin, +}; +use xcm_executor::{Config, XcmExecutor}; +pub type AccountId = AccountId32; +pub type Balance = u128; +pub type BlockNumber = BlockNumberFor; + +parameter_types! { + pub const BlockHashCount: u32 = 250; +} + +impl frame_system::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Block = Block; + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + 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 = (); + type FreezeIdentifier = (); + type MaxHolds = (); + type MaxFreezes = (); +} + +impl pallet_utility::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type WeightInfo = (); + type PalletsOrigin = OriginCaller; +} + +impl shared::Config for Runtime {} + +impl configuration::Config for Runtime { + type WeightInfo = configuration::TestWeightInfo; +} + +parameter_types! { + pub KsmLocation: MultiLocation = Here.into(); + pub const KusamaNetwork: NetworkId = NetworkId::Kusama; + pub const AnyNetwork: Option = None; + pub UniversalLocation: InteriorMultiLocation = Here; +} + +pub type SovereignAccountOf = ( + ChildParachainConvertsVia, + AccountId32Aliases, + // Not enabled in the relay per se, but we enable it to test + // the transact_through_signed extrinsic + Account32Hash, +); + +pub type LocalAssetTransactor = + XcmCurrencyAdapter, SovereignAccountOf, AccountId, ()>; + +type LocalOriginConverter = ( + SovereignSignedViaLocation, + ChildParachainAsNative, + SignedAccountId32AsNative, + ChildSystemParachainAsSuperuser, +); + +parameter_types! { + pub const BaseXcmWeight: Weight = Weight::from_parts(1000u64, 1000u64); + pub KsmPerSecond: (AssetId, u128, u128) = (Concrete(KsmLocation::get()), 1, 1); + pub const MaxInstructions: u32 = 100; + pub const MaxAssetsIntoHolding: u32 = 64; + pub MatcherLocation: MultiLocation = MultiLocation::here(); +} + +pub type XcmRouter = super::RelayChainXcmRouter; + +pub type XcmBarrier = ( + // Weight that is paid for may be consumed. + TakeWeightCredit, + // Expected responses are OK. + AllowKnownQueryResponses, + WithComputedOrigin< + ( + // If the message is one that immediately attemps to pay for execution, then allow it. + AllowTopLevelPaidExecutionFrom, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, + ), + UniversalLocation, + ConstU32<8>, + >, +); + +parameter_types! { + pub Kusama: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(KsmLocation::get()) }); + pub Statemine: MultiLocation = Parachain(4).into(); + pub KusamaForStatemine: (MultiAssetFilter, MultiLocation) = (Kusama::get(), Statemine::get()); +} + +pub type TrustedTeleporters = xcm_builder::Case; + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = LocalAssetTransactor; + type OriginConverter = LocalOriginConverter; + type IsReserve = (); + type IsTeleporter = TrustedTeleporters; + type UniversalLocation = UniversalLocation; + type Barrier = XcmBarrier; + type Weigher = FixedWeightBounds; + type Trader = FixedRateOfFungible; + type ResponseHandler = XcmPallet; + type AssetTrap = XcmPallet; + type AssetClaims = XcmPallet; + type SubscriptionService = XcmPallet; + type CallDispatcher = RuntimeCall; + type AssetLocker = (); + type AssetExchanger = (); + type PalletInstancesInfo = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; + type SafeCallFilter = Everything; + type Aliasers = Nothing; +} + +pub type LocalOriginToLocation = SignedToAccountId32; + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parent.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 = (); + type TrustedLockers = (); + type SovereignAccountOf = (); + type MaxLockers = ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type AdminOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; +} + +parameter_types! { + pub const FirstMessageFactorPercent: u64 = 100; +} + +parameter_types! { + pub const ParasUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); +} + +/// A very dumb implementation of `EstimateNextSessionRotation`. At the moment of writing, this +/// is more to satisfy type requirements rather than to test anything. +pub struct TestNextSessionRotation; + +impl frame_support::traits::EstimateNextSessionRotation for TestNextSessionRotation { + fn average_session_length() -> u32 { + 10 + } + + fn estimate_current_session_progress(_now: u32) -> (Option, Weight) { + (None, Weight::zero()) + } + + fn estimate_next_session_rotation(_now: u32) -> (Option, Weight) { + (None, Weight::zero()) + } +} + +impl paras::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = paras::TestWeightInfo; + type UnsignedPriority = ParasUnsignedPriority; + type NextSessionRotation = TestNextSessionRotation; + type QueueFootprinter = (); + type OnNewHead = (); +} + +impl dmp::Config for Runtime {} + +impl hrmp::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type WeightInfo = TestHrmpWeightInfo; + type ChannelManager = frame_system::EnsureRoot; +} + +impl frame_system::offchain::SendTransactionTypes for Runtime +where + RuntimeCall: From, +{ + type Extrinsic = UncheckedExtrinsic; + type OverarchingCall = RuntimeCall; +} + +impl origin::Config for Runtime {} + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlockU32; + +parameter_types! { + pub MessageQueueServiceWeight: Weight = Weight::from_parts(1_000_000_000, 1_000_000); + pub const MessageQueueHeapSize: u32 = 65_536; + pub const MessageQueueMaxStale: u32 = 16; +} + +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, + }; + ProcessXcmMessage::, 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 WeightInfo = (); + type QueuePausedQuery = (); +} + +construct_runtime!( + pub enum Runtime { + System: frame_system, + Balances: pallet_balances, + ParasOrigin: origin, + MessageQueue: pallet_message_queue, + XcmPallet: pallet_xcm, + Utility: pallet_utility, + Hrmp: hrmp, + Dmp: dmp, + Paras: paras, + Configuration: configuration, + } +); + +pub(crate) fn relay_events() -> Vec { + System::events() + .into_iter() + .map(|r| r.event) + .filter_map(|e| Some(e)) + .collect::>() +} + +use frame_support::traits::{OnFinalize, OnInitialize}; +pub(crate) fn relay_roll_to(n: BlockNumber) { + while System::block_number() < n { + XcmPallet::on_finalize(System::block_number()); + Balances::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Balances::on_initialize(System::block_number()); + XcmPallet::on_initialize(System::block_number()); + } +} + +/// A weight info that is only suitable for testing. +pub struct TestHrmpWeightInfo; + +impl hrmp::WeightInfo for TestHrmpWeightInfo { + fn hrmp_accept_open_channel() -> Weight { + Weight::from_parts(1, 0) + } + fn force_clean_hrmp(_: u32, _: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn force_process_hrmp_close(_: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn force_process_hrmp_open(_: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn hrmp_cancel_open_request(_: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn hrmp_close_channel() -> Weight { + Weight::from_parts(1, 0) + } + fn hrmp_init_open_channel() -> Weight { + Weight::from_parts(1, 0) + } + fn clean_open_channel_requests(_: u32) -> Weight { + Weight::from_parts(1, 0) + } + fn force_open_hrmp_channel(_: u32) -> Weight { + Weight::from_parts(1, 0) + } +} diff --git a/tracing/2601/runtime/moonriver/tests/xcm_mock/statemine_like.rs b/tracing/2601/runtime/moonriver/tests/xcm_mock/statemine_like.rs new file mode 100644 index 00000000..b0223afe --- /dev/null +++ b/tracing/2601/runtime/moonriver/tests/xcm_mock/statemine_like.rs @@ -0,0 +1,552 @@ +// Copyright 2021 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, match_types, parameter_types, + traits::{AsEnsureOriginWithArg, Everything, Nothing}, + weights::Weight, +}; +use frame_system::{EnsureRoot, EnsureSigned}; + +use sp_core::H256; +use sp_runtime::{ + traits::{ConstU32, Hash, IdentityLookup}, + AccountId32, +}; + +use polkadot_core_primitives::BlockNumber as RelayBlockNumber; + +use polkadot_parachain::primitives::Id as ParaId; +use polkadot_parachain::primitives::Sibling; +use sp_std::convert::TryFrom; +use xcm::latest::prelude::*; +use xcm::VersionedXcm; +use xcm_builder::{ + AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, AsPrefixedGeneralIndex, + ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, + FungiblesAdapter, IsConcrete, NoChecking, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, +}; +use xcm_executor::{traits::JustTry, Config, XcmExecutor}; +use xcm_simulator::{ + DmpMessageHandlerT as DmpMessageHandler, XcmpMessageFormat, + XcmpMessageHandlerT as XcmpMessageHandler, +}; +pub type AccountId = AccountId32; +pub type Balance = u128; +pub type AssetId = u128; + +parameter_types! { + pub const BlockHashCount: u32 = 250; +} + +impl frame_system::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Block = Block; + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + 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 = frame_support::traits::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 = (); + type FreezeIdentifier = (); + type MaxHolds = (); + type MaxFreezes = (); +} + +// Required for runtime benchmarks +pallet_assets::runtime_benchmarks_enabled! { + pub struct BenchmarkHelper; + impl pallet_assets::BenchmarkHelper for BenchmarkHelper + where + AssetIdParameter: From, + { + fn create_asset_id_parameter(id: u32) -> AssetIdParameter { + (id as u128).into() + } + } +} + +parameter_types! { + pub const AssetDeposit: Balance = 0; // 1 UNIT deposit to create asset + pub const ApprovalDeposit: Balance = 0; + pub const AssetsStringLimit: u32 = 50; + /// Key = 32 bytes, Value = 36 bytes (32+1+1+1+1) + // https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271 + pub const MetadataDepositBase: Balance = 0; + pub const MetadataDepositPerByte: Balance = 0; + pub const ExecutiveBody: BodyId = BodyId::Executive; + pub const AssetAccountDeposit: Balance = 0; +} + +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type AssetDeposit = AssetDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type AssetAccountDeposit = AssetAccountDeposit; + type WeightInfo = (); + type RemoveItemsLimit = ConstU32<656>; + type AssetIdParameter = AssetId; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + pallet_assets::runtime_benchmarks_enabled! { + type BenchmarkHelper = BenchmarkHelper; + } +} + +parameter_types! { + pub const KsmLocation: MultiLocation = MultiLocation::parent(); + pub const RelayNetwork: NetworkId = NetworkId::Kusama; + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + pub UniversalLocation: InteriorMultiLocation = + X2(GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())); + pub Local: MultiLocation = Here.into(); + pub CheckingAccount: AccountId = PolkadotXcm::check_account(); + pub KsmPerSecond: (xcm::latest::prelude::AssetId, u128, u128) = + (Concrete(KsmLocation::get()), 1, 1); +} + +/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used +/// when determining ownership of accounts for asset transacting and when attempting to use XCM +/// `Transact` in order to determine the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the default `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // Straight up local `AccountId32` origins just alias directly to `AccountId`. + AccountId32Aliases, +); + +/// Means for transacting the native currency on this chain. +pub type CurrencyTransactor = CurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching the given location or name: + IsConcrete, + // Convert an XCM MultiLocation into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We don't track any teleports of `Balances`. + (), +>; + +/// Means for transacting assets besides the native currency on this chain. +pub type FungiblesTransactor = FungiblesAdapter< + // Use this fungibles implementation: + Assets, + // Use this currency when it is a fungible asset matching the given location or name: + ConvertedConcreteId< + AssetId, + Balance, + AsPrefixedGeneralIndex, + JustTry, + >, + // Convert an XCM MultiLocation into a local account id: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We only want to allow teleports of known assets. We use non-zero issuance as an indication + // that this asset is known. + NoChecking, + // The account to use for tracking teleports. + CheckingAccount, +>; +/// Means for transacting assets on this chain. +pub type AssetTransactors = (CurrencyTransactor, FungiblesTransactor); + +/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, +/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can +/// biases the kind of local `Origin` it will become. +pub type XcmOriginToTransactDispatchOrigin = ( + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when + // recognised. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognised. + SiblingParachainAsNative, + // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a + // transaction from the Root origin. + ParentAsSuperuser, + // Native signed account converter; this just converts an `AccountId32` origin into a normal + // `Origin::Signed` origin of the same 32-byte value. + SignedAccountId32AsNative, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + pallet_xcm::XcmPassthrough, +); + +parameter_types! { + // One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate. + pub UnitWeightCost: Weight = Weight::from_parts(100u64, 100u64); + pub const MaxInstructions: u32 = 100; +} + +match_types! { + pub type ParentOrParentsExecutivePlurality: impl Contains = { + MultiLocation { parents: 1, interior: Here } | + MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Executive, .. }) } + }; +} +match_types! { + pub type ParentOrSiblings: impl Contains = { + MultiLocation { parents: 1, interior: Here } | + MultiLocation { parents: 1, interior: X1(_) } + }; +} + +pub type Barrier = ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + // Parent and its exec plurality get free execution + AllowUnpaidExecutionFrom, + // Expected responses are OK. + AllowKnownQueryResponses, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, +); + +parameter_types! { + pub MatcherLocation: MultiLocation = MultiLocation::here(); + pub const MaxAssetsIntoHolding: u32 = 64; +} + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = AssetTransactors; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type IsReserve = + orml_xcm_support::MultiNativeAsset; + type IsTeleporter = (); + type UniversalLocation = UniversalLocation; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = FixedRateOfFungible; + type ResponseHandler = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type SubscriptionService = PolkadotXcm; + type CallDispatcher = RuntimeCall; + type AssetLocker = (); + type AssetExchanger = (); + type PalletInstancesInfo = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; + type SafeCallFilter = Everything; + type Aliasers = Nothing; +} + +/// No local origins on this chain are allowed to dispatch XCM sends/executions. +pub type LocalOriginToLocation = SignedToAccountId32; + +pub type XcmRouter = super::ParachainXcmRouter; + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parent.into()); +} + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = 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 = (); + type MaxLockers = ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type AdminOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +#[frame_support::pallet] +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] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn parachain_id)] + pub(super) type ParachainId = StorageValue<_, ParaId, 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 (result, event) = match Xcm::::try_from(xcm) { + Ok(xcm) => { + let location = MultiLocation::new(1, Junctions::X1(Parachain(sender.into()))); + let mut id = [0u8; 32]; + id.copy_from_slice(hash.as_ref()); + match T::XcmExecutor::execute_xcm(location, xcm, id, max_weight) { + Outcome::Error(e) => (Err(e.clone()), 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 (_i, (_sent_at, data)) in iter.enumerate() { + let id = sp_io::hashing::blake2_256(&data[..]); + let maybe_msg = VersionedXcm::::decode(&mut &data[..]) + .map(Xcm::::try_from); + match maybe_msg { + Err(_) => { + Self::deposit_event(Event::InvalidFormat(id)); + } + Ok(Err(())) => { + Self::deposit_event(Event::UnsupportedVersion(id)); + } + Ok(Ok(x)) => { + let outcome = T::XcmExecutor::execute_xcm(Parent, x, id, limit); + + Self::deposit_event(Event::ExecutedDownward(id, outcome)); + } + } + } + limit + } + } +} +impl mock_msg_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +// Pallet to cover test cases for change https://github.com/paritytech/cumulus/pull/831 +#[frame_support::pallet] +pub mod mock_statemine_prefix { + use super::*; + use frame_support::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + } + + #[pallet::call] + impl Pallet {} + + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn current_prefix)] + pub(super) type CurrentPrefix = StorageValue<_, MultiLocation, ValueQuery>; + + impl Get for Pallet { + fn get() -> MultiLocation { + Self::current_prefix() + } + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + // Changed Prefix + PrefixChanged(MultiLocation), + } + + impl Pallet { + pub fn set_prefix(prefix: MultiLocation) { + CurrentPrefix::::put(&prefix); + Self::deposit_event(Event::PrefixChanged(prefix)); + } + } +} + +impl mock_statemine_prefix::Config for Runtime { + type RuntimeEvent = RuntimeEvent; +} + +type Block = frame_system::mocking::MockBlockU32; +construct_runtime!( + pub enum Runtime { + System: frame_system, + Balances: pallet_balances, + PolkadotXcm: pallet_xcm, + CumulusXcm: cumulus_pallet_xcm, + MsgQueue: mock_msg_queue, + Assets: pallet_assets, + PrefixChanger: mock_statemine_prefix, + + } +); diff --git a/tracing/2601/runtime/moonriver/tests/xcm_tests.rs b/tracing/2601/runtime/moonriver/tests/xcm_tests.rs new file mode 100644 index 00000000..0da71138 --- /dev/null +++ b/tracing/2601/runtime/moonriver/tests/xcm_tests.rs @@ -0,0 +1,4092 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Moonriver Runtime Xcm Tests + +mod xcm_mock; +use frame_support::{ + assert_ok, + traits::{PalletInfo, PalletInfoAccess}, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, + BoundedVec, +}; +use pallet_asset_manager::LocalAssetIdCreator; +use sp_core::ConstU32; +use xcm::latest::prelude::*; +use xcm::{VersionedMultiLocation, WrapVersion}; +use xcm_builder::HashedDescriptionDescribeFamilyAllTerminal; +use xcm_executor::traits::ConvertLocation; +use xcm_mock::parachain; +use xcm_mock::relay_chain; +use xcm_mock::*; +use xcm_simulator::TestExt; +mod common; +use common::ExtBuilder; +use cumulus_primitives_core::relay_chain::HrmpChannelId; +use pallet_xcm_transactor::{ + Currency, CurrencyPayment, HrmpInitParams, HrmpOperation, TransactWeights, +}; +use xcm_primitives::{UtilityEncodeCall, DEFAULT_PROOF_SIZE}; + +// Send a relay asset (like DOT) to a parachain A +#[test] +fn receive_relay_asset_from_relay() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // Register relay asset in parachain A + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // Verify that parachain received the asset + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 123); + }); +} + +// Send relay asset (like DOT) back from Parachain A to relaychain +#[test] +fn send_relay_asset_to_relay() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + // Register relay asset in paraA + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + // free execution + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + let dest: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + // First send relay chain asset to Parachain like in previous test + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // Free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 123); + }); + + // Lets gather the balance before sending back money + let mut balance_before_sending = 0; + Relay::execute_with(|| { + balance_before_sending = RelayBalances::free_balance(&RELAYALICE); + }); + + // We now send back some money to the relay + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: RELAYALICE.into(), + }), + }; + + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 123, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // The balances in paraAlice should have been substracted + ParaA::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 0); + }); + + // Balances in the relay should have been received + Relay::execute_with(|| { + assert!(RelayBalances::free_balance(&RELAYALICE) > balance_before_sending); + }); +} + +#[test] +fn send_relay_asset_to_para_b() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + // Register asset in paraA. Free execution + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata.clone(), + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location.clone(), + 0u128, + 0 + )); + }); + + // Register asset in paraB. Free execution + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // First send relay chain asset to Parachain A like in previous test + let dest: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 123); + }); + + // Now send relay asset from para A to para B + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // Para A balances should have been substracted + ParaA::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 23); + }); + + // Para B balances should have been credited + ParaB::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); +} + +#[test] +fn send_para_a_asset_to_para_b() { + MockNet::reset(); + + // This represents the asset in paraA + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + // Register asset in paraB. Free execution + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Send para A asset from para A to para B + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(800000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // Native token is substracted in paraA + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + // Asset is minted in paraB + ParaB::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); +} + +#[test] +fn send_para_a_asset_from_para_b_to_para_c() { + MockNet::reset(); + + // Represents para A asset + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + // Register para A asset in parachain B. Free execution + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata.clone(), + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location.clone(), + 0u128, + 0 + )); + }); + + // Register para A asset in parachain C. Free execution + ParaC::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Send para A asset to para B + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // Para A balances have been substracted + ParaA::execute_with(|| { + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + // Para B balances have been credited + ParaB::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); + + // Send para A asset from para B to para C + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(3), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaB::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // The message passed through parachainA so we needed to pay since its the native token + ParaC::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 96); + }); +} + +#[test] +fn send_para_a_asset_to_para_b_and_back_to_para_a() { + MockNet::reset(); + + // Para A asset + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + // Register para A asset in para B + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Send para A asset to para B + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // Balances have been substracted + ParaA::execute_with(|| { + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + // Para B balances have been credited + ParaB::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); + + // Send back para A asset to para A + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(1), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + ParaB::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + }); + + // Para A asset has been credited + ParaA::execute_with(|| { + // Weight used is 4 + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 4 + ); + }); +} + +#[test] +fn send_para_a_asset_to_para_b_and_back_to_para_a_with_new_reanchoring() { + MockNet::reset(); + + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // Free execution, full amount received + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + ParaB::execute_with(|| { + // Free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); + + // This time we will force the new reanchoring by manually sending the + // Message through polkadotXCM pallet + + let dest = MultiLocation { + parents: 1, + interior: X1(Parachain(1)), + }; + + let reanchored_para_a_balances = MultiLocation::new(0, X1(PalletInstance(1u8))); + + let message = xcm::VersionedXcm::<()>::V3(Xcm(vec![ + WithdrawAsset((reanchored_para_a_balances.clone(), 100).into()), + ClearOrigin, + BuyExecution { + fees: (reanchored_para_a_balances, 100).into(), + weight_limit: Limited(80.into()), + }, + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation::new( + 0, + X1(AccountKey20 { + network: None, + key: PARAALICE, + }), + ), + }, + ])); + ParaB::execute_with(|| { + // Send a message to the sovereign account in ParaA to withdraw + // and deposit asset + assert_ok!(ParachainPalletXcm::send( + parachain::RuntimeOrigin::root(), + Box::new(dest.into()), + Box::new(message), + )); + }); + + ParaB::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); + + // This time we will force the new reanchoring by manually sending the + // Message through polkadotXCM pallet + + let dest = MultiLocation { + parents: 1, + interior: X1(Parachain(1)), + }; + + let reanchored_para_a_balances = MultiLocation::new(0, X1(PalletInstance(1u8))); + + let message = xcm::VersionedXcm::<()>::V3(Xcm(vec![ + WithdrawAsset((reanchored_para_a_balances.clone(), 100).into()), + ClearOrigin, + BuyExecution { + fees: (reanchored_para_a_balances, 100).into(), + weight_limit: Limited(80.into()), + }, + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation::new( + 0, + X1(AccountKey20 { + network: None, + key: PARAALICE, + }), + ), + }, + ])); + ParaB::execute_with(|| { + // Send a message to the sovereign account in ParaA to withdraw + // and deposit asset + assert_ok!(ParachainPalletXcm::send( + parachain::RuntimeOrigin::root(), + Box::new(dest.into()), + Box::new(message), + )); + }); + + ParaA::execute_with(|| { + // Weight used is 4 + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 4 + ); + }); +} + +#[test] +fn receive_relay_asset_with_trader() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + // This time we are gonna put a rather high number of units per second + // we know later we will divide by 1e12 + // Lets put 1e6 as units per second + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 2500000000000u128, + 0 + )); + }); + + let dest: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + // We are sending 100 tokens from relay. + // Amount spent in fees is Units per second * weight / 1_000_000_000_000 (weight per second) + // weight is 4 since we are executing 4 instructions with a unitweightcost of 1. + // Units per second should be 2_500_000_000_000_000 + // Therefore with no refund, we should receive 10 tokens less + // Native trader fails for this, and we use the asset trader + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 100).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // non-free execution, not full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 90); + // Fee should have been received by treasury + assert_eq!(Assets::balance(source_id, &Treasury::account_id()), 10); + }); +} + +#[test] +fn send_para_a_asset_to_para_b_with_trader() { + MockNet::reset(); + + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 2500000000000u128, + 0 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + // In destination chain, we only need 4 weight + // We put 10 weight, 6 of which should be refunded and 4 of which should go to treasury + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(10u64, DEFAULT_PROOF_SIZE)) + )); + }); + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + // We are sending 100 tokens from para A. + // Amount spent in fees is Units per second * weight / 1_000_000_000_000 (weight per second) + // weight is 4 since we are executing 4 instructions with a unitweightcost of 1. + // Units per second should be 2_500_000_000_000_000 + // Since we set 10 weight in destination chain, 25 will be charged upfront + // 15 of those will be refunded, while 10 will go to treasury as the true weight used + // will be 4 + ParaB::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 90); + // Fee should have been received by treasury + assert_eq!(Assets::balance(source_id, &Treasury::account_id()), 10); + }); +} + +#[test] +fn send_para_a_asset_to_para_b_with_trader_and_fee() { + MockNet::reset(); + + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + // With these units per second, 80K weight convrets to 1 asset unit + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 12500000u128, + 0 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + // we use transfer_with_fee + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer_with_fee( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + 1, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(800000u64, DEFAULT_PROOF_SIZE)) + )); + }); + ParaA::execute_with(|| { + // 100 tokens transferred plus 1 taken from fees + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 - 1 + ); + }); + + ParaB::execute_with(|| { + // free execution, full amount received because trully the xcm instruction does not cost + // what it is specified + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 101); + }); +} + +#[test] +fn error_when_not_paying_enough() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + let dest: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + // This time we are gonna put a rather high number of units per second + // we know later we will divide by 1e12 + // Lets put 1e6 as units per second + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 2500000000000u128, + 0 + )); + }); + + // We are sending 100 tokens from relay. + // If we set the dest weight to be 1e7, we know the buy_execution will spend 1e7*1e6/1e12 = 10 + // Therefore with no refund, we should receive 10 tokens less + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 5).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // amount not received as it is not paying enough + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 0); + }); +} + +#[test] +fn transact_through_derivative_multilocation() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + // Relay charges 1000 for every instruction, and we have 3, so 3000 + 3000.into(), + 20000000000.into(), + None + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + WEIGHT_REF_TIME_PER_SECOND as u128, + )); + }); + + // Let's construct the call to know how much weight it is going to require + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + // 4000000000 transact + 3000 correspond to 4000003000 tokens. 100 more for the transfer call + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000003100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000003000); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_derivative( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::MockTransactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: None + }, + encoded, + // 4000000000 + 3000 we should have taken out 4000003000 tokens from the caller + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(®istered_address) == 0); + }); +} + +#[test] +fn transact_through_derivative_with_custom_fee_weight() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + }); + + // Let's construct the call to know how much weight it is going to require + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + // 4000000000 transact + 3000 correspond to 4000003000 tokens. 100 more for the transfer call + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000003100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000003000); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let overall_weight = 4000003000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_derivative( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::MockTransactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + // 1-1 fee weight mapping + fee_amount: Some(overall_weight as u128) + }, + // 4000000000 + 3000 we should have taken out 4000003000 tokens from the caller + encoded, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(overall_weight.into()) + }, + false + )); + let event_found: Option = parachain::para_events() + .iter() + .find_map(|event| match event.clone() { + parachain::RuntimeEvent::PolkadotXcm(pallet_xcm::Event::AssetsTrapped { + .. + }) => Some(event.clone()), + _ => None, + }); + // Assert that the events do not contain the assets being trapped + assert!(event_found.is_none()); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(®istered_address) == 0); + }); +} + +#[test] +fn transact_through_derivative_with_custom_fee_weight_refund() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + }); + + // Let's construct the call to know how much weight it is going to require + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + // 4000000000 transact + 9000 correspond to 4000009000 tokens. 100 more for the transfer call + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000009100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000009100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000009000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000009000); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let overall_weight = 4000009000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_derivative( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::MockTransactors::Relay, + 0, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + // 1-1 fee weight mapping + fee_amount: Some(overall_weight as u128) + }, + encoded, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(overall_weight.into()) + }, + true + )); + let event_found: Option = parachain::para_events() + .iter() + .find_map(|event| match event.clone() { + parachain::RuntimeEvent::PolkadotXcm(pallet_xcm::Event::AssetsTrapped { + .. + }) => Some(event.clone()), + _ => None, + }); + // Assert that the events do not contain the assets being trapped + assert!(event_found.is_none()); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + // 4000005186 refunded + 100 transferred = 4000005286 + assert_eq!(RelayBalances::free_balance(¶_a_account()), 4000005286); + assert_eq!(RelayBalances::free_balance(®istered_address), 0); + }); +} + +#[test] +fn transact_through_sovereign() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + // Relay charges 1000 for every instruction, and we have 3, so 3000 + 3000.into(), + 20000000000.into(), + None + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + WEIGHT_REF_TIME_PER_SECOND as u128, + )); + }); + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000003100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000003000); + 0 + }); + + // We send the xcm transact operation to parent + let dest = MultiLocation { + parents: 1, + interior: Here, + }; + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let utility_bytes = parachain::MockTransactors::Relay.encode_call( + xcm_primitives::UtilityAvailableCalls::AsDerivative(0, encoded), + ); + + // Root can directly pass the execution byes to the sovereign + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_sovereign( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(dest)), + PARAALICE.into(), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: None + }, + utility_bytes, + OriginKind::SovereignAccount, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(®istered_address) == 0); + }); +} + +#[test] +fn transact_through_sovereign_with_custom_fee_weight() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + }); + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000003100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000003000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000003000); + 0 + }); + + // We send the xcm transact operation to parent + let dest = MultiLocation { + parents: 1, + interior: Here, + }; + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let utility_bytes = parachain::MockTransactors::Relay.encode_call( + xcm_primitives::UtilityAvailableCalls::AsDerivative(0, encoded), + ); + + let total_weight = 4000003000u64; + // Root can directly pass the execution byes to the sovereign + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_sovereign( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(dest)), + PARAALICE.into(), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + // 1-1 fee-weight mapping + fee_amount: Some(total_weight as u128) + }, + utility_bytes, + OriginKind::SovereignAccount, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(total_weight.into()) + }, + false + )); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(®istered_address) == 0); + }); +} + +#[test] +fn transact_through_sovereign_with_custom_fee_weight_refund() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 1u128, + 0 + )); + }); + + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 4000009100u128).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000009100); + }); + + // Register address + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::register( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + 0, + )); + }); + + // Send to registered address + let registered_address = derivative_account_id(para_a_account(), 0); + let dest = MultiLocation { + parents: 1, + interior: X1(AccountId32 { + network: None, + id: registered_address.clone().into(), + }), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::ForeignAsset(source_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(40000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 4000009000); + }); + + // What we will do now is transfer this relay tokens from the derived account to the sovereign + // again + Relay::execute_with(|| { + // free execution,x full amount received + assert!(RelayBalances::free_balance(¶_a_account()) == 4000009000); + 0 + }); + + // We send the xcm transact operation to parent + let dest = MultiLocation { + parents: 1, + interior: Here, + }; + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let utility_bytes = parachain::MockTransactors::Relay.encode_call( + xcm_primitives::UtilityAvailableCalls::AsDerivative(0, encoded), + ); + + let total_weight = 4000009000u64; + // Root can directly pass the execution byes to the sovereign + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_sovereign( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(dest)), + PARAALICE.into(), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + // 1-1 fee-weight mapping + fee_amount: Some(total_weight as u128) + }, + utility_bytes, + OriginKind::SovereignAccount, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(total_weight.into()) + }, + true + )); + }); + + Relay::execute_with(|| { + // free execution,x full amount received + // 4000005186 refunded + 100 transferred = 4000005286 + assert_eq!(RelayBalances::free_balance(¶_a_account()), 4000005286); + + assert_eq!(RelayBalances::free_balance(®istered_address), 0); + }); +} + +#[test] +fn test_automatic_versioning_on_runtime_upgrade_with_relay() { + MockNet::reset(); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A and set XCM version to 1 + ParaA::execute_with(|| { + parachain::XcmVersioner::set_version(1); + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + let response = Response::Version(2); + let querier: MultiLocation = Here.into(); + + // This is irrelevant, nothing will be done with this message, + // but we need to pass a message as an argument to trigger the storage change + let mock_message: Xcm<()> = Xcm(vec![QueryResponse { + query_id: 0, + response, + max_weight: Weight::zero(), + querier: Some(querier), + }]); + // The router is mocked, and we cannot use WrapVersion in ChildParachainRouter. So we will force + // it directly here + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + Relay::execute_with(|| { + // This sets the default version, for not known destinations + assert_ok!(RelayChainPalletXcm::force_default_xcm_version( + relay_chain::RuntimeOrigin::root(), + Some(2) + )); + + // Wrap version, which sets VersionedStorage + // This is necessary because the mock router does not use wrap_version, but + // this is not necessary in prod + assert_ok!(::wrap_version( + &Parachain(1).into(), + mock_message + )); + + // Transfer assets. Since it is an unknown destination, it will query for version + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + + // Let's advance the relay. This should trigger the subscription message + relay_chain::relay_roll_to(2); + + // queries should have been updated + assert!(RelayChainPalletXcm::query(0).is_some()); + }); + + let expected_supported_version: relay_chain::RuntimeEvent = + pallet_xcm::Event::SupportedVersionChanged { + location: MultiLocation { + parents: 0, + interior: X1(Parachain(1)), + }, + version: 1, + } + .into(); + + Relay::execute_with(|| { + // Assert that the events vector contains the version change + assert!(relay_chain::relay_events().contains(&expected_supported_version)); + }); + + // ParaA changes version to 2, and calls on_runtime_upgrade. This should notify the targets + // of the new version change + ParaA::execute_with(|| { + // Set version + parachain::XcmVersioner::set_version(2); + // Do runtime upgrade + parachain::on_runtime_upgrade(); + // Initialize block, to call on_initialize and notify targets + parachain::para_roll_to(2); + // Expect the event in the parachain + assert!(parachain::para_events().iter().any(|e| matches!( + e, + parachain::RuntimeEvent::PolkadotXcm(pallet_xcm::Event::VersionChangeNotified { + result: 2, + .. + }) + ))); + }); + + // This event should have been seen in the relay + let expected_supported_version_2: relay_chain::RuntimeEvent = + pallet_xcm::Event::SupportedVersionChanged { + location: MultiLocation { + parents: 0, + interior: X1(Parachain(1)), + }, + version: 2, + } + .into(); + + Relay::execute_with(|| { + // Assert that the events vector contains the new version change + assert!(relay_chain::relay_events().contains(&expected_supported_version_2)); + }); +} + +#[test] +fn test_automatic_versioning_on_runtime_upgrade_with_para_b() { + MockNet::reset(); + + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location = parachain::AssetType::Xcm(para_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + let response = Response::Version(2); + let querier: MultiLocation = Here.into(); + + // This is irrelevant, nothing will be done with this message, + // but we need to pass a message as an argument to trigger the storage change + let mock_message: Xcm<()> = Xcm(vec![QueryResponse { + query_id: 0, + response, + max_weight: Weight::zero(), + querier: Some(querier), + }]); + + ParaA::execute_with(|| { + // advertised version + parachain::XcmVersioner::set_version(2); + }); + + ParaB::execute_with(|| { + // Let's try with v0 + parachain::XcmVersioner::set_version(0); + + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + ParaA::execute_with(|| { + // This sets the default version, for not known destinations + assert_ok!(ParachainPalletXcm::force_default_xcm_version( + parachain::RuntimeOrigin::root(), + Some(2) + )); + // Wrap version, which sets VersionedStorage + assert_ok!(::wrap_version( + &MultiLocation::new(1, X1(Parachain(2))).into(), + mock_message + )); + + parachain::para_roll_to(2); + + // queries should have been updated + assert!(ParachainPalletXcm::query(0).is_some()); + }); + + let expected_supported_version: parachain::RuntimeEvent = + pallet_xcm::Event::SupportedVersionChanged { + location: MultiLocation { + parents: 1, + interior: X1(Parachain(2)), + }, + version: 0, + } + .into(); + + ParaA::execute_with(|| { + // Assert that the events vector contains the version change + assert!(parachain::para_events().contains(&expected_supported_version)); + }); + + // Let's ensure talking in v0 works + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::SelfReserve, + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(80u64, DEFAULT_PROOF_SIZE)) + )); + // free execution, full amount received + assert_eq!( + ParaBalances::free_balance(&PARAALICE.into()), + INITIAL_BALANCE - 100 + ); + }); + + ParaB::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); + + // ParaB changes version to 2, and calls on_runtime_upgrade. This should notify the targets + // of the new version change + ParaB::execute_with(|| { + // Set version + parachain::XcmVersioner::set_version(2); + // Do runtime upgrade + parachain::on_runtime_upgrade(); + // Initialize block, to call on_initialize and notify targets + parachain::para_roll_to(2); + // Expect the event in the parachain + assert!(parachain::para_events().iter().any(|e| matches!( + e, + parachain::RuntimeEvent::PolkadotXcm(pallet_xcm::Event::VersionChangeNotified { + result: 2, + .. + }) + ))); + }); + + // This event should have been seen in para A + let expected_supported_version_2: parachain::RuntimeEvent = + pallet_xcm::Event::SupportedVersionChanged { + location: MultiLocation { + parents: 1, + interior: X1(Parachain(2)), + }, + version: 2, + } + .into(); + + // Para A should have received the version change + ParaA::execute_with(|| { + // Assert that the events vector contains the new version change + assert!(parachain::para_events().contains(&expected_supported_version_2)); + }); +} + +#[test] +fn receive_asset_with_no_sufficients_not_possible_if_non_existent_account() { + MockNet::reset(); + + let fresh_account = [2u8; 20]; + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + false + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: fresh_account, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest.clone()).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // parachain should not have received assets + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &fresh_account.into()), 0); + }); + + // Send native token to fresh_account + ParaA::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + fresh_account.into(), + 100 + )); + }); + + // Re-send tokens + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // parachain should have received assets + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &fresh_account.into()), 123); + }); +} + +#[test] +fn receive_assets_with_sufficients_true_allows_non_funded_account_to_receive_assets() { + MockNet::reset(); + + let fresh_account = [2u8; 20]; + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: fresh_account, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest.clone()).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // parachain should have received assets + ParaA::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &fresh_account.into()), 123); + }); +} + +#[test] +fn evm_account_receiving_assets_should_handle_sufficients_ref_count() { + MockNet::reset(); + + let mut sufficient_account = [0u8; 20]; + sufficient_account[0..20].copy_from_slice(&evm_account()[..]); + + let evm_account_id = parachain::AccountId::from(sufficient_account); + + // Evm account is self sufficient + ParaA::execute_with(|| { + assert_eq!(parachain::System::account(evm_account_id).sufficients, 1); + }); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: sufficient_account, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest.clone()).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + // Evm account sufficient ref count increased by 1. + ParaA::execute_with(|| { + // TODO: since the suicided logic was introduced an smart contract account + // is not deleted completely until it's data is deleted. Data deletion + // will be implemented in a future release + // assert_eq!(parachain::System::account(evm_account_id).sufficients, 2); + }); + + ParaA::execute_with(|| { + // Remove the account from the evm context. + parachain::EVM::remove_account(&evm_account()); + // Evm account sufficient ref count decreased by 1. + // TODO: since the suicided logic was introduced an smart contract account + // is not deleted completely until it's data is deleted. Data deletion + // will be implemented in a future release + // assert_eq!(parachain::System::account(evm_account_id).sufficients, 1); + }); +} + +#[test] +fn empty_account_should_not_be_reset() { + MockNet::reset(); + + // Test account has nonce 1 on genesis. + let mut sufficient_account = [0u8; 20]; + sufficient_account[0..20].copy_from_slice(&evm_account()[..]); + + let evm_account_id = parachain::AccountId::from(sufficient_account); + + let source_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_id: parachain::AssetId = source_location.clone().into(); + let asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + // register relay asset in parachain A + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + false + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + // Send native token to evm_account + ParaA::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + evm_account_id, + 100 + )); + }); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: sufficient_account, + } + .into(); + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new(VersionedMultiLocation::V3(dest.clone()).clone().into()), + Box::new((Here, 123).into()), + 0, + )); + }); + + ParaA::execute_with(|| { + // Empty the assets from the account. + // As this makes the account go below the `min_balance`, the account is considered dead + // at eyes of pallet-assets, and the consumer reference is decreased by 1 and is now Zero. + assert_ok!(parachain::Assets::transfer( + parachain::RuntimeOrigin::signed(evm_account_id), + source_id, + PARAALICE.into(), + 123 + )); + // Verify account asset balance is Zero. + assert_eq!( + parachain::Assets::balance(source_id, &evm_account_id.into()), + 0 + ); + // Because we no longer have consumer references, we can set the balance to Zero. + // This would reset the account if our ED were to be > than Zero. + assert_ok!(ParaBalances::force_set_balance( + parachain::RuntimeOrigin::root(), + evm_account_id, + 0, + )); + // Verify account native balance is Zero. + assert_eq!(ParaBalances::free_balance(&evm_account_id), 0); + // Remove the account from the evm context. + // This decreases the sufficients reference by 1 and now is Zero. + parachain::EVM::remove_account(&evm_account()); + // Verify reference count. + let account = parachain::System::account(evm_account_id); + // TODO: since the suicided logic was introduced an smart contract account + // is not deleted completely until it's data is deleted. Data deletion + // will be implemented in a future release + // revert account.sufficients to 0 + assert_eq!(account.sufficients, 1); + assert_eq!(account.consumers, 0); + assert_eq!(account.providers, 1); + // We expect the account to be alive in a Zero ED context. + // TODO: since the suicided logic was introduced an smart contract account + // is not deleted completely until it's data is deleted. Data deletion + // will be implemented in a future release + // the following needs to be 1 + assert_eq!(parachain::System::account_nonce(evm_account_id), 2); + }); +} + +#[test] +fn test_statemine_like() { + MockNet::reset(); + + let dest_para = MultiLocation::new(1, X1(Parachain(1))); + + let sov = xcm_builder::SiblingParachainConvertsVia::< + polkadot_parachain::primitives::Sibling, + statemine_like::AccountId, + >::convert_location(&dest_para) + .unwrap(); + + let statemine_asset_a_balances = MultiLocation::new( + 1, + X3( + Parachain(4), + PalletInstance(5), + xcm::latest::prelude::GeneralIndex(0u128), + ), + ); + let source_location = parachain::AssetType::Xcm(statemine_asset_a_balances); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"StatemineToken".to_vec(), + symbol: b"StatemineToken".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata.clone(), + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + Statemine::execute_with(|| { + // Set new prefix + statemine_like::PrefixChanger::set_prefix( + PalletInstance(::index() as u8).into(), + ); + assert_ok!(StatemineAssets::create( + statemine_like::RuntimeOrigin::signed(RELAYALICE), + 0, + RELAYALICE, + 1 + )); + + assert_ok!(StatemineAssets::mint( + statemine_like::RuntimeOrigin::signed(RELAYALICE), + 0, + RELAYALICE, + 300000000000000 + )); + + // This is needed, since the asset is created as non-sufficient + assert_ok!(StatemineBalances::transfer( + statemine_like::RuntimeOrigin::signed(RELAYALICE), + sov, + 100000000000000 + )); + + // Actually send relay asset to parachain + let dest: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + // Send with new prefix + assert_ok!(StatemineChainPalletXcm::reserve_transfer_assets( + statemine_like::RuntimeOrigin::signed(RELAYALICE), + Box::new(MultiLocation::new(1, X1(Parachain(1))).into()), + Box::new(VersionedMultiLocation::V3(dest).clone().into()), + Box::new( + ( + X2( + xcm::latest::prelude::PalletInstance( + ::index() as u8 + ), + xcm::latest::prelude::GeneralIndex(0), + ), + 123 + ) + .into() + ), + 0, + )); + }); + + ParaA::execute_with(|| { + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 123); + }); +} + +#[test] +fn send_para_a_local_asset_to_para_b() { + ExtBuilder::default().build().execute_with(|| { + MockNet::reset(); + + let asset_id = parachain::LocalAssetIdCreator::create_asset_id_from_metadata(0); + let para_a_local_asset = MultiLocation::new( + 1, + X3(Parachain(1), PalletInstance(11u8), GeneralIndex(asset_id)), + ); + let source_location = parachain::AssetType::Xcm(para_a_local_asset); + let source_id: parachain::AssetId = source_location.clone().into(); + + let asset_metadata = parachain::AssetMetadata { + name: b"ParaALocalAsset".to_vec(), + symbol: b"ParaALocalAsset".to_vec(), + decimals: 12, + }; + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_local_asset( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + PARAALICE.into(), + true, + 1 + )); + + assert_ok!(LocalAssets::mint( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + asset_id, + PARAALICE.into(), + 300000000000000 + )); + }); + + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location.clone(), + asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location, + 0u128, + 0 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + parachain::CurrencyId::LocalAssetReserve(asset_id), + 100, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(800000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaB::execute_with(|| { + // free execution, full amount received + assert_eq!(Assets::balance(source_id, &PARAALICE.into()), 100); + }); + }); +} + +#[test] +fn send_para_a_local_asset_to_para_b_and_send_it_back_together_with_some_dev() { + ExtBuilder::default().build().execute_with(|| { + MockNet::reset(); + + let asset_id = parachain::LocalAssetIdCreator::create_asset_id_from_metadata(0); + let para_a_local_asset = MultiLocation::new( + 1, + X3(Parachain(1), PalletInstance(11u8), GeneralIndex(asset_id)), + ); + let source_location_local_asset = parachain::AssetType::Xcm(para_a_local_asset); + let source_id_local_asset: parachain::AssetId = source_location_local_asset.clone().into(); + + let asset_metadata_local_asset = parachain::AssetMetadata { + name: b"ParaALocalAsset".to_vec(), + symbol: b"ParaALocalAsset".to_vec(), + decimals: 12, + }; + + let para_a_balances = MultiLocation::new(1, X2(Parachain(1), PalletInstance(1u8))); + let source_location_balances = parachain::AssetType::Xcm(para_a_balances); + let source_id_balances: parachain::AssetId = source_location_balances.clone().into(); + + let asset_metadata_balances = parachain::AssetMetadata { + name: b"ParaAToken".to_vec(), + symbol: b"ParaA".to_vec(), + decimals: 18, + }; + + ParaB::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location_local_asset.clone(), + asset_metadata_local_asset, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location_local_asset, + 0u128, + 0 + )); + + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + source_location_balances.clone(), + asset_metadata_balances, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + source_location_balances, + 0u128, + 1 + )); + }); + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_local_asset( + parachain::RuntimeOrigin::root(), + PARAALICE.into(), + PARAALICE.into(), + true, + 1 + )); + + assert_ok!(LocalAssets::mint( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + asset_id, + PARAALICE.into(), + 300000000000000 + )); + }); + + let dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(2), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaA::execute_with(|| { + // free execution, full amount received + assert_ok!(XTokens::transfer_multicurrencies( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + vec![ + (parachain::CurrencyId::LocalAssetReserve(asset_id), 100), + (parachain::CurrencyId::SelfReserve, 1000000) + ], + 0, + Box::new(VersionedMultiLocation::V3(dest)), + WeightLimit::Limited(Weight::from_parts(800000u64, DEFAULT_PROOF_SIZE)) + )); + }); + + let mut alith_balance_asset_before = 0; + let mut alith_balance_native_token_before = 0; + + ParaA::execute_with(|| { + alith_balance_asset_before = LocalAssets::balance(asset_id, &PARAALICE.into()); + alith_balance_native_token_before = Balances::free_balance(&PARAALICE.into()); + }); + + let new_dest = MultiLocation { + parents: 1, + interior: X2( + Parachain(1), + AccountKey20 { + network: None, + key: PARAALICE.into(), + }, + ), + }; + + ParaB::execute_with(|| { + // free execution, full amount received + assert_eq!( + Assets::balance(source_id_local_asset, &PARAALICE.into()), + 100 + ); + assert_eq!( + Assets::balance(source_id_balances, &PARAALICE.into()), + 1000000 + ); + + // free execution, full amount received + assert_ok!(XTokens::transfer_multicurrencies( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + vec![ + (parachain::CurrencyId::ForeignAsset(source_id_balances), 4), + ( + parachain::CurrencyId::ForeignAsset(source_id_local_asset), + 50 + ) + ], + 0, + Box::new(VersionedMultiLocation::V3(new_dest)), + WeightLimit::Limited(Weight::from_parts(4u64, DEFAULT_PROOF_SIZE)) + )); + }); + + ParaA::execute_with(|| { + let alith_balance_asset_after = LocalAssets::balance(asset_id, &PARAALICE.into()); + let alith_balance_native_token_after = Balances::free_balance(&PARAALICE.into()); + assert_eq!(alith_balance_asset_after, alith_balance_asset_before + 50); + assert_eq!( + alith_balance_native_token_before, + alith_balance_native_token_after + ); + }); + }); +} + +#[test] +fn send_statemint_asset_from_para_a_to_statemine_with_relay_fee() { + MockNet::reset(); + + // Relay asset + let relay_location = parachain::AssetType::Xcm(MultiLocation::parent()); + let source_relay_id: parachain::AssetId = relay_location.clone().into(); + + let relay_asset_metadata = parachain::AssetMetadata { + name: b"RelayToken".to_vec(), + symbol: b"Relay".to_vec(), + decimals: 12, + }; + + // Statemine asset + let statemine_asset = MultiLocation::new( + 1, + X3(Parachain(4u32), PalletInstance(5u8), GeneralIndex(10u128)), + ); + let statemine_location_asset = parachain::AssetType::Xcm(statemine_asset); + let source_statemine_asset_id: parachain::AssetId = statemine_location_asset.clone().into(); + + let asset_metadata_statemine_asset = parachain::AssetMetadata { + name: b"USDC".to_vec(), + symbol: b"USDC".to_vec(), + decimals: 12, + }; + + let dest_para = MultiLocation::new(1, X1(Parachain(1))); + + let sov = xcm_builder::SiblingParachainConvertsVia::< + polkadot_parachain::primitives::Sibling, + statemine_like::AccountId, + >::convert_location(&dest_para) + .unwrap(); + + ParaA::execute_with(|| { + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + relay_location.clone(), + relay_asset_metadata, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + relay_location, + 0u128, + 0 + )); + + assert_ok!(AssetManager::register_foreign_asset( + parachain::RuntimeOrigin::root(), + statemine_location_asset.clone(), + asset_metadata_statemine_asset, + 1u128, + true + )); + assert_ok!(AssetManager::set_asset_units_per_second( + parachain::RuntimeOrigin::root(), + statemine_location_asset, + 0u128, + 1 + )); + }); + + let parachain_beneficiary_from_relay: MultiLocation = Junction::AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + // Send relay chain asset to Alice in Parachain A + Relay::execute_with(|| { + assert_ok!(RelayChainPalletXcm::reserve_transfer_assets( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + Box::new(Parachain(1).into()), + Box::new( + VersionedMultiLocation::V3(parachain_beneficiary_from_relay) + .clone() + .into() + ), + Box::new((Here, 200).into()), + 0, + )); + }); + + Statemine::execute_with(|| { + // Set new prefix + statemine_like::PrefixChanger::set_prefix( + PalletInstance(::index() as u8).into(), + ); + + assert_ok!(StatemineAssets::create( + statemine_like::RuntimeOrigin::signed(RELAYALICE), + 10, + RELAYALICE, + 1 + )); + + assert_ok!(StatemineAssets::mint( + statemine_like::RuntimeOrigin::signed(RELAYALICE), + 10, + RELAYALICE, + 300000000000000 + )); + + // Send some native statemine tokens to sovereign for fees. + // We can't pay fees with USDC as the asset is minted as non-sufficient. + assert_ok!(StatemineBalances::transfer( + statemine_like::RuntimeOrigin::signed(RELAYALICE), + sov, + 100000000000000 + )); + + // Send statemine USDC asset to Alice in Parachain A + let parachain_beneficiary_from_statemint: MultiLocation = AccountKey20 { + network: None, + key: PARAALICE, + } + .into(); + + // Send with new prefix + assert_ok!(StatemineChainPalletXcm::reserve_transfer_assets( + statemine_like::RuntimeOrigin::signed(RELAYALICE), + Box::new(MultiLocation::new(1, X1(Parachain(1))).into()), + Box::new( + VersionedMultiLocation::V3(parachain_beneficiary_from_statemint) + .clone() + .into() + ), + Box::new( + ( + X2( + xcm::latest::prelude::PalletInstance( + ::index() as u8 + ), + GeneralIndex(10), + ), + 125 + ) + .into() + ), + 0, + )); + }); + + let statemine_beneficiary = MultiLocation { + parents: 1, + interior: X2( + Parachain(4), + AccountId32 { + network: None, + id: RELAYBOB.into(), + }, + ), + }; + + ParaA::execute_with(|| { + // Alice has received 125 USDC + assert_eq!( + Assets::balance(source_statemine_asset_id, &PARAALICE.into()), + 125 + ); + + // Alice has received 200 Relay assets + assert_eq!(Assets::balance(source_relay_id, &PARAALICE.into()), 200); + }); + + Statemine::execute_with(|| { + // Check that BOB's balance is empty before the transfer + assert_eq!(StatemineAssets::account_balances(RELAYBOB), vec![]); + }); + + // Transfer USDC from Parachain A to Statemine using Relay asset as fee + ParaA::execute_with(|| { + assert_ok!(XTokens::transfer_multicurrencies( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + vec![ + ( + parachain::CurrencyId::ForeignAsset(source_statemine_asset_id), + 100 + ), + (parachain::CurrencyId::ForeignAsset(source_relay_id), 100) + ], + 1, + Box::new(VersionedMultiLocation::V3(statemine_beneficiary)), + WeightLimit::Limited(Weight::from_parts(80_000_000u64, 100_000u64)) + )); + }); + + ParaA::execute_with(|| { + // Alice has 100 USDC less + assert_eq!( + Assets::balance(source_statemine_asset_id, &PARAALICE.into()), + 25 + ); + + // Alice has 100 relay asset less + assert_eq!(Assets::balance(source_relay_id, &PARAALICE.into()), 100); + }); + + Statemine::execute_with(|| { + // Check that BOB received 100 USDC on statemine + assert_eq!(StatemineAssets::account_balances(RELAYBOB), vec![(10, 100)]); + }); +} + +#[test] +fn transact_through_signed_multilocation() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + // Relay charges 1000 for every instruction, and we have 3, so 3000 + 3000.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4000.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + WEIGHT_REF_TIME_PER_SECOND as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the relay will see instead of us + descend_origin_multilocation + .reanchor(&MultiLocation::parent(), ancestry.interior) + .unwrap(); + + let derived = xcm_builder::Account32Hash::< + relay_chain::KusamaNetwork, + relay_chain::AccountId, + >::convert_location(&descend_origin_multilocation) + .unwrap(); + + Relay::execute_with(|| { + // free execution, full amount received + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + derived.clone(), + 4000004100u128, + )); + // derived account has all funds + assert!(RelayBalances::free_balance(&derived) == 4000004100); + // sovereign account has 0 funds + assert!(RelayBalances::free_balance(¶_a_account()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: None + }, + encoded, + // 4000000000 for transfer + 4000 for XCM + // 1-1 to fee + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + Relay::execute_with(|| { + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(&derived) == 0); + }); +} + +#[test] +fn transact_through_signed_multilocation_custom_fee_and_weight() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + ParaA::execute_with(|| { + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the relay will see instead of us + descend_origin_multilocation + .reanchor(&MultiLocation::parent(), ancestry.interior) + .unwrap(); + + let derived = xcm_builder::Account32Hash::< + relay_chain::KusamaNetwork, + relay_chain::AccountId, + >::convert_location(&descend_origin_multilocation) + .unwrap(); + + Relay::execute_with(|| { + // free execution, full amount received + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + derived.clone(), + 4000004100u128, + )); + // derived account has all funds + assert!(RelayBalances::free_balance(&derived) == 4000004100); + // sovereign account has 0 funds + assert!(RelayBalances::free_balance(¶_a_account()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let total_weight = 4000004000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_weight as u128) + }, + encoded, + // 4000000000 for transfer + 4000 for XCM + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(total_weight.into()) + }, + false + )); + }); + + Relay::execute_with(|| { + assert!(RelayBalances::free_balance(¶_a_account()) == 100); + + assert!(RelayBalances::free_balance(&derived) == 0); + }); +} + +#[test] +fn transact_through_signed_multilocation_custom_fee_and_weight_refund() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + ParaA::execute_with(|| { + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the relay will see instead of us + descend_origin_multilocation + .reanchor(&MultiLocation::parent(), ancestry.interior) + .unwrap(); + + let derived = xcm_builder::Account32Hash::< + relay_chain::KusamaNetwork, + relay_chain::AccountId, + >::convert_location(&descend_origin_multilocation) + .unwrap(); + + Relay::execute_with(|| { + // free execution, full amount received + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + derived.clone(), + 4000009100u128, + )); + // derived account has all funds + assert!(RelayBalances::free_balance(&derived) == 4000009100); + // sovereign account has 0 funds + assert!(RelayBalances::free_balance(¶_a_account()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = ::PalletInfo::index::< + relay_chain::Balances, + >() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let total_weight = 4000009000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(MultiLocation::parent())), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_weight as u128) + }, + encoded, + // 4000000000 for transfer + 9000 for XCM + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(total_weight.into()) + }, + true + )); + }); + + Relay::execute_with(|| { + // 100 transferred + assert_eq!(RelayBalances::free_balance(¶_a_account()), 100); + + // 4000005186 refunded + assert_eq!(RelayBalances::free_balance(&derived), 4000005186); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + // ParaB + Box::new(xcm::VersionedMultiLocation::V3(para_b_location.clone())), + // Para charges 1000 for every instruction, and we have 3, so 3 + 3.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + ParaB::execute_with(|| { + // free execution, full amount received + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000000104u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000000104); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account_20(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: None + }, + encoded, + // 4000000000 for transfer + 4000 for XCM + // 1-1 to fee + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + ParaB::execute_with(|| { + assert!(ParaBalances::free_balance(&derived) == 0); + + assert!(ParaBalances::free_balance(¶_a_account_20()) == 100); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para_refund() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + ParaB::execute_with(|| { + // free execution, full amount received + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000009100u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000009100); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + // Then call bytes + let mut call_bytes = pallet_balances::Call::::transfer { + // 100 to sovereign + dest: para_a_account_20(), + value: 100u32.into(), + } + .encode(); + encoded.append(&mut call_bytes); + + let overall_weight = 4000009000u64; + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: Some(overall_weight as u128) + }, + encoded, + // 4000000000 for transfer + 9000 for XCM + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: Some(overall_weight.into()) + }, + true + )); + }); + + ParaB::execute_with(|| { + // Check the derived account was refunded + assert_eq!(ParaBalances::free_balance(&derived), 8993); + + // Check the transfer was executed + assert_eq!(ParaBalances::free_balance(¶_a_account_20()), 100); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para_ethereum() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + // ParaB + Box::new(xcm::VersionedMultiLocation::V3(para_b_location.clone())), + // Para charges 1000 for every instruction, and we have 3, so 3 + 3.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + let mut parachain_b_alice_balances_before = 0; + ParaB::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000000104u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000000104); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + + parachain_b_alice_balances_before = ParaBalances::free_balance(&PARAALICE.into()) + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + use sp_core::U256; + // Let's do a EVM transfer + let eth_tx = + xcm_primitives::EthereumXcmTransaction::V1(xcm_primitives::EthereumXcmTransactionV1 { + gas_limit: U256::from(21000), + fee_payment: xcm_primitives::EthereumXcmFee::Auto, + action: pallet_ethereum::TransactionAction::Call(PARAALICE.into()), + value: U256::from(100), + input: BoundedVec::< + u8, + ConstU32<{ xcm_primitives::MAX_ETHEREUM_XCM_INPUT_SIZE }> + >::try_from(vec![]).unwrap(), + access_list: None, + }); + + // Then call bytes + let mut call_bytes = pallet_ethereum_xcm::Call::::transact { + xcm_transaction: eth_tx, + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: None + }, + encoded, + // 4000000000 for transfer + 4000 for XCM + // 1-1 to fee + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + ParaB::execute_with(|| { + // Make sure the EVM transfer went through + assert!( + ParaBalances::free_balance(&PARAALICE.into()) + == parachain_b_alice_balances_before + 100 + ); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para_ethereum_no_proxy_fails() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + // ParaB + Box::new(xcm::VersionedMultiLocation::V3(para_b_location.clone())), + // Para charges 1000 for every instruction, and we have 3, so 3 + 3.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + let mut parachain_b_alice_balances_before = 0; + ParaB::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000000104u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000000104); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + + parachain_b_alice_balances_before = ParaBalances::free_balance(&PARAALICE.into()) + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + use sp_core::U256; + // Let's do a EVM transfer + let eth_tx = + xcm_primitives::EthereumXcmTransaction::V1(xcm_primitives::EthereumXcmTransactionV1 { + gas_limit: U256::from(21000), + fee_payment: xcm_primitives::EthereumXcmFee::Auto, + action: pallet_ethereum::TransactionAction::Call(PARAALICE.into()), + value: U256::from(100), + input: BoundedVec::< + u8, + ConstU32<{ xcm_primitives::MAX_ETHEREUM_XCM_INPUT_SIZE }> + >::try_from(vec![]).unwrap(), + access_list: None, + }); + + // Then call bytes + let mut call_bytes = pallet_ethereum_xcm::Call::::transact_through_proxy { + transact_as: PARAALICE.into(), + xcm_transaction: eth_tx, + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: None + }, + encoded, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + ParaB::execute_with(|| { + // Make sure the EVM transfer wasn't executed + assert!(ParaBalances::free_balance(&PARAALICE.into()) == parachain_b_alice_balances_before); + }); +} + +#[test] +fn transact_through_signed_multilocation_para_to_para_ethereum_proxy_succeeds() { + MockNet::reset(); + let mut ancestry = MultiLocation::parent(); + + let para_b_location = MultiLocation::new(1, X1(Parachain(2))); + + let para_b_balances = MultiLocation::new(1, X2(Parachain(2), PalletInstance(1u8))); + + ParaA::execute_with(|| { + // Root can set transact info + assert_ok!(XcmTransactor::set_transact_info( + parachain::RuntimeOrigin::root(), + // ParaB + Box::new(xcm::VersionedMultiLocation::V3(para_b_location.clone())), + // Para charges 1000 for every instruction, and we have 3, so 3 + 3.into(), + 20000000000.into(), + // 4 instructions in transact through signed + Some(4.into()) + )); + // Root can set transact info + assert_ok!(XcmTransactor::set_fee_per_second( + parachain::RuntimeOrigin::root(), + Box::new(xcm::VersionedMultiLocation::V3(para_b_balances.clone())), + parachain::ParaTokensPerSecond::get().1 as u128, + )); + ancestry = parachain::UniversalLocation::get().into(); + }); + + // Let's construct the Junction that we will append with DescendOrigin + let signed_origin: Junctions = X1(AccountKey20 { + network: None, + key: PARAALICE, + }); + + let mut descend_origin_multilocation = parachain::SelfLocation::get(); + descend_origin_multilocation + .append_with(signed_origin) + .unwrap(); + + // To convert it to what the paraB will see instead of us + descend_origin_multilocation + .reanchor(¶_b_location, ancestry.interior) + .unwrap(); + + let derived = + HashedDescriptionDescribeFamilyAllTerminal::::convert_location( + &descend_origin_multilocation, + ) + .unwrap(); + + let transfer_recipient = evm_account(); + let mut transfer_recipient_balance_before = 0; + ParaB::execute_with(|| { + assert_ok!(ParaBalances::transfer( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + derived.clone(), + 4000000104u128, + )); + // derived account has all funds + assert!(ParaBalances::free_balance(&derived) == 4000000104); + // sovereign account has 0 funds + assert!(ParaBalances::free_balance(¶_a_account_20()) == 0); + + transfer_recipient_balance_before = ParaBalances::free_balance(&transfer_recipient.into()); + + // Add proxy ALICE -> derived + let _ = parachain::Proxy::add_proxy_delegate( + &PARAALICE.into(), + derived, + parachain::ProxyType::Any, + 0, + ); + }); + + // Encode the call. Balances transact to para_a_account + // First index + let mut encoded: Vec = Vec::new(); + let index = + ::PalletInfo::index::() + .unwrap() as u8; + + encoded.push(index); + + use sp_core::U256; + // Let's do a EVM transfer + let eth_tx = + xcm_primitives::EthereumXcmTransaction::V2(xcm_primitives::EthereumXcmTransactionV2 { + gas_limit: U256::from(21000), + action: pallet_ethereum::TransactionAction::Call(transfer_recipient.into()), + value: U256::from(100), + input: BoundedVec::< + u8, + ConstU32<{ xcm_primitives::MAX_ETHEREUM_XCM_INPUT_SIZE }> + >::try_from(vec![]).unwrap(), + access_list: None, + }); + + // Then call bytes + let mut call_bytes = pallet_ethereum_xcm::Call::::transact_through_proxy { + transact_as: PARAALICE.into(), + xcm_transaction: eth_tx, + } + .encode(); + encoded.append(&mut call_bytes); + + ParaA::execute_with(|| { + assert_ok!(XcmTransactor::transact_through_signed( + parachain::RuntimeOrigin::signed(PARAALICE.into()), + Box::new(xcm::VersionedMultiLocation::V3(para_b_location)), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + para_b_balances + ))), + fee_amount: None + }, + encoded, + TransactWeights { + transact_required_weight_at_most: 4000000000.into(), + overall_weight: None + }, + false + )); + }); + + ParaB::execute_with(|| { + // Make sure the EVM transfer was executed + assert!( + ParaBalances::free_balance(&transfer_recipient.into()) + == transfer_recipient_balance_before + 100 + ); + }); +} + +#[test] +fn hrmp_init_accept_through_root() { + MockNet::reset(); + + Relay::execute_with(|| { + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + para_a_account(), + 1000u128 + )); + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + para_b_account(), + 1000u128 + )); + }); + + ParaA::execute_with(|| { + let total_fee = 1_000u128; + let total_weight: u64 = 1_000_000_000; + let tx_weight: u64 = 500_000_000; + // Root can send hrmp init channel + assert_ok!(XcmTransactor::hrmp_manage( + parachain::RuntimeOrigin::root(), + HrmpOperation::InitOpen(HrmpInitParams { + para_id: 2u32.into(), + proposed_max_capacity: 1, + proposed_max_message_size: 1 + }), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_fee) + }, + TransactWeights { + transact_required_weight_at_most: tx_weight.into(), + overall_weight: Some(total_weight.into()) + } + )); + }); + Relay::execute_with(|| { + let expected_event: relay_chain::RuntimeEvent = + polkadot_runtime_parachains::hrmp::Event::OpenChannelRequested( + 1u32.into(), + 2u32.into(), + 1u32, + 1u32, + ) + .into(); + assert!(relay_chain::relay_events().contains(&expected_event)); + }); + ParaB::execute_with(|| { + let total_fee = 1_000u128; + let total_weight: u64 = 1_000_000_000; + let tx_weight: u64 = 500_000_000; + // Root can send hrmp accept channel + assert_ok!(XcmTransactor::hrmp_manage( + parachain::RuntimeOrigin::root(), + HrmpOperation::Accept { + para_id: 1u32.into() + }, + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_fee) + }, + TransactWeights { + transact_required_weight_at_most: tx_weight.into(), + overall_weight: Some(total_weight.into()) + } + )); + }); + + Relay::execute_with(|| { + let expected_event: relay_chain::RuntimeEvent = + polkadot_runtime_parachains::hrmp::Event::OpenChannelAccepted(1u32.into(), 2u32.into()) + .into(); + assert!(relay_chain::relay_events().contains(&expected_event)); + }); +} + +#[test] +fn hrmp_close_works() { + MockNet::reset(); + + Relay::execute_with(|| { + assert_ok!(RelayBalances::transfer( + relay_chain::RuntimeOrigin::signed(RELAYALICE), + para_a_account(), + 1000u128 + )); + assert_ok!(Hrmp::force_open_hrmp_channel( + relay_chain::RuntimeOrigin::root(), + 1u32.into(), + 2u32.into(), + 1u32, + 1u32 + )); + assert_ok!(Hrmp::force_process_hrmp_open( + relay_chain::RuntimeOrigin::root(), + 0u32 + )); + }); + + ParaA::execute_with(|| { + let total_fee = 1_000u128; + let total_weight: u64 = 1_000_000_000; + let tx_weight: u64 = 500_000_000; + // Root can send hrmp close + assert_ok!(XcmTransactor::hrmp_manage( + parachain::RuntimeOrigin::root(), + HrmpOperation::Close(HrmpChannelId { + sender: 1u32.into(), + recipient: 2u32.into() + }), + CurrencyPayment { + currency: Currency::AsMultiLocation(Box::new(xcm::VersionedMultiLocation::V3( + MultiLocation::parent() + ))), + fee_amount: Some(total_fee) + }, + TransactWeights { + transact_required_weight_at_most: tx_weight.into(), + overall_weight: Some(total_weight.into()) + } + )); + }); + Relay::execute_with(|| { + let expected_event: relay_chain::RuntimeEvent = + polkadot_runtime_parachains::hrmp::Event::ChannelClosed( + 1u32.into(), + HrmpChannelId { + sender: 1u32.into(), + recipient: 2u32.into(), + }, + ) + .into(); + assert!(relay_chain::relay_events().contains(&expected_event)); + }); +} + +use parity_scale_codec::{Decode, Encode}; +use sp_io::hashing::blake2_256; + +// Helper to derive accountIds +pub fn derivative_account_id(who: sp_runtime::AccountId32, index: u16) -> sp_runtime::AccountId32 { + let entropy = (b"modlpy/utilisuba", who, index).using_encoded(blake2_256); + sp_runtime::AccountId32::decode(&mut &entropy[..]).expect("valid account id") +} diff --git a/tracing/2601/rust-toolchain b/tracing/2601/rust-toolchain new file mode 100644 index 00000000..a7267737 --- /dev/null +++ b/tracing/2601/rust-toolchain @@ -0,0 +1,5 @@ +[toolchain] +channel = "1.71.0" +components = [ "rustfmt", "clippy" ] +targets = [ "wasm32-unknown-unknown" ] +profile = "minimal" From 395fa8012782cafd5e0a1709f49929046098787d Mon Sep 17 00:00:00 2001 From: root Date: Mon, 13 Nov 2023 09:46:37 -0800 Subject: [PATCH 02/11] add tracing runtime build for 2601 --- ...nbase-runtime-2601-substitute-tracing.json | 1 + ...nbeam-runtime-2601-substitute-tracing.json | 1 + ...river-runtime-2601-substitute-tracing.json | 1 + ...nbase-runtime-2601-substitute-tracing.wasm | Bin 0 -> 1851387 bytes ...nbeam-runtime-2601-substitute-tracing.wasm | Bin 0 -> 1816781 bytes ...river-runtime-2601-substitute-tracing.wasm | Bin 0 -> 1815386 bytes 6 files changed, 3 insertions(+) create mode 100644 srtool-digest/moonbase-runtime-2601-substitute-tracing.json create mode 100644 srtool-digest/moonbeam-runtime-2601-substitute-tracing.json create mode 100644 srtool-digest/moonriver-runtime-2601-substitute-tracing.json create mode 100644 wasm/moonbase-runtime-2601-substitute-tracing.wasm create mode 100644 wasm/moonbeam-runtime-2601-substitute-tracing.wasm create mode 100644 wasm/moonriver-runtime-2601-substitute-tracing.wasm diff --git a/srtool-digest/moonbase-runtime-2601-substitute-tracing.json b/srtool-digest/moonbase-runtime-2601-substitute-tracing.json new file mode 100644 index 00000000..a2b06a02 --- /dev/null +++ b/srtool-digest/moonbase-runtime-2601-substitute-tracing.json @@ -0,0 +1 @@ +{"gen":"srtool v0.11.1","src":"zip","version":"0.8.4","commit":"","tag":"","branch":"","rustc":"rustc 1.70.0 (90c541806 2023-05-31)","pkg":"moonbase-runtime","tmsp":"2023-11-13T17:25:25Z","size":"1851387","prop":"0x1f6a52030bef12deff32a2a8843cb46038f6cf028fed36753111f68fb85c1209","authorize_upgrade_prop":"0xb81c1c8947d2b646184e23de786a4178c000a01b71d4d6fa58c168237fbf72e3","ipfs":"QmP4wAp2vLUMdryKj8GqPFPY4AUcjZ81ow7oEnP687prtC","sha256":"0x4ec2e397acad9e7d58382dc308871b4fe62a6dccf74e1e00e777043141e88b2d","wasm":"runtime/moonbase/target/srtool/release/wbuild/moonbase-runtime/moonbase_runtime.compact.compressed.wasm","info":{"generator":{"name":"srtool","version":"0.11.1"},"src":"zip","version":"0.8.4","git":{"commit":"","tag":"","branch":""},"rustc":"rustc 1.70.0 (90c541806 2023-05-31)","pkg":"moonbase-runtime","profile":"release"},"context":{"package":"moonbase-runtime","runtime_dir":"runtime/moonbase","docker":{"image":"paritytech/srtool","tag":"1.70.0"},"profile":"release"},"runtimes":{"compact":{"tmsp":"2023-11-13T17:25:03Z","size":"9077982","prop":"0xbbe019fe8c8b647bbe01027e170cd8abab18debbd1b1dc4c8fa05e888bf206b2","authorize_upgrade_prop":"0x1eaf57da9da2552016e3d95039afefcaa2661589eaf44c862b00dd680ddabe98","blake2_256":"0xdabba6fe9283e759ea6ad500023db95084b2872bcf057d48acb55a210fdcb011","ipfs":"QmdZRHGqFD1iMsSS6eKDifBcuSYvmg78VLNEYtLUxZF8cz","sha256":"0xe4bd7b07a25c735b0c5041af5e125bbf7ffda85f0dfa29564837f5d1a8831b98","wasm":"runtime/moonbase/target/srtool/release/wbuild/moonbase-runtime/moonbase_runtime.compact.wasm","subwasm":{"size":9077982,"compression":{"size_compressed":9077982,"size_decompressed":9077982,"compressed":false},"reserved_meta":[109,101,116,97],"reserved_meta_valid":true,"metadata_version":14,"core_version":{"specName":"moonbase","implName":"moonbase","authoringVersion":4,"specVersion":2601,"implVersion":0,"apis":[["0xd2bc9897eed08f15",3],["0xdf6acb689907609b",4],["0x37e397fc7c91f5e4",2],["0x40fe3ad401f8959a",6],["0xf78b278be53f454c",2],["0xab3c0572291feb8b",1],["0xbc9d89904f5b923f",1],["0xbd78255d4feeea1f",4],["0xa33d43f58731ad84",2],["0x582211f65bb14b89",5],["0xe65b00e46cedd0aa",2],["0x37c8bb1350a9a2a8",4],["0x2aa62120049dd2d2",1],["0xea93e3f16f3d6962",2],["0xba8173bf23b2e6f8",1]],"transactionVersion":2,"stateVersion":0},"proposal_hash":"0xbbe019fe8c8b647bbe01027e170cd8abab18debbd1b1dc4c8fa05e888bf206b2","parachain_authorize_upgrade_hash":"0x1eaf57da9da2552016e3d95039afefcaa2661589eaf44c862b00dd680ddabe98","ipfs_hash":"QmdZRHGqFD1iMsSS6eKDifBcuSYvmg78VLNEYtLUxZF8cz","blake2_256":"0xdabba6fe9283e759ea6ad500023db95084b2872bcf057d48acb55a210fdcb011"}},"compressed":{"tmsp":"2023-11-13T17:24:57Z","size":"1851387","prop":"0x1f6a52030bef12deff32a2a8843cb46038f6cf028fed36753111f68fb85c1209","authorize_upgrade_prop":"0xb81c1c8947d2b646184e23de786a4178c000a01b71d4d6fa58c168237fbf72e3","blake2_256":"0x08e6687b264b8887ff585076b73c4160d66c6f8fb4a4d4eddbf43aab0cded6b0","ipfs":"QmP4wAp2vLUMdryKj8GqPFPY4AUcjZ81ow7oEnP687prtC","sha256":"0x4ec2e397acad9e7d58382dc308871b4fe62a6dccf74e1e00e777043141e88b2d","wasm":"runtime/moonbase/target/srtool/release/wbuild/moonbase-runtime/moonbase_runtime.compact.compressed.wasm","subwasm":{"size":1851387,"compression":{"size_compressed":1851387,"size_decompressed":9077982,"compressed":true},"reserved_meta":[109,101,116,97],"reserved_meta_valid":true,"metadata_version":14,"core_version":{"specName":"moonbase","implName":"moonbase","authoringVersion":4,"specVersion":2601,"implVersion":0,"apis":[["0xd2bc9897eed08f15",3],["0xdf6acb689907609b",4],["0x37e397fc7c91f5e4",2],["0x40fe3ad401f8959a",6],["0xf78b278be53f454c",2],["0xab3c0572291feb8b",1],["0xbc9d89904f5b923f",1],["0xbd78255d4feeea1f",4],["0xa33d43f58731ad84",2],["0x582211f65bb14b89",5],["0xe65b00e46cedd0aa",2],["0x37c8bb1350a9a2a8",4],["0x2aa62120049dd2d2",1],["0xea93e3f16f3d6962",2],["0xba8173bf23b2e6f8",1]],"transactionVersion":2,"stateVersion":0},"proposal_hash":"0x1f6a52030bef12deff32a2a8843cb46038f6cf028fed36753111f68fb85c1209","parachain_authorize_upgrade_hash":"0xb81c1c8947d2b646184e23de786a4178c000a01b71d4d6fa58c168237fbf72e3","ipfs_hash":"QmP4wAp2vLUMdryKj8GqPFPY4AUcjZ81ow7oEnP687prtC","blake2_256":"0x08e6687b264b8887ff585076b73c4160d66c6f8fb4a4d4eddbf43aab0cded6b0"}}}} diff --git a/srtool-digest/moonbeam-runtime-2601-substitute-tracing.json b/srtool-digest/moonbeam-runtime-2601-substitute-tracing.json new file mode 100644 index 00000000..eb7cb33b --- /dev/null +++ b/srtool-digest/moonbeam-runtime-2601-substitute-tracing.json @@ -0,0 +1 @@ +{"gen":"srtool v0.11.1","src":"zip","version":"0.8.4","commit":"","tag":"","branch":"","rustc":"rustc 1.70.0 (90c541806 2023-05-31)","pkg":"moonbeam-runtime","tmsp":"2023-11-13T17:37:59Z","size":"1816781","prop":"0x9b4bdf1c412ece3c4af5d5c16407aca1b9adfdc5d59114a7690f5574e79eb99d","authorize_upgrade_prop":"0xb31f4f16f5c716f3fb05cd940adb05247be801f7509aa67b69be8337694ecc23","ipfs":"QmXwWHgHtxyN3YkFBQtrFiuU4tX47uToGhXebyrUNfpthp","sha256":"0x6025ab6f635ba34dbb2ce3cc24ca4b2c82a86e61bd720b5bd15a3eb6385729ce","wasm":"runtime/moonbeam/target/srtool/release/wbuild/moonbeam-runtime/moonbeam_runtime.compact.compressed.wasm","info":{"generator":{"name":"srtool","version":"0.11.1"},"src":"zip","version":"0.8.4","git":{"commit":"","tag":"","branch":""},"rustc":"rustc 1.70.0 (90c541806 2023-05-31)","pkg":"moonbeam-runtime","profile":"release"},"context":{"package":"moonbeam-runtime","runtime_dir":"runtime/moonbeam","docker":{"image":"paritytech/srtool","tag":"1.70.0"},"profile":"release"},"runtimes":{"compact":{"tmsp":"2023-11-13T17:37:39Z","size":"8878415","prop":"0x74c264d71da7bd0ba26e72e70ba90560d962bcef03bba736620e4ac7f1d39435","authorize_upgrade_prop":"0x57f2dc3964e9e0a2d534610805325412e27bd6d405fec1111e4f9b0c3d727b5f","blake2_256":"0x40f71401905adc3b0126781c62efb9229709594793104affb1b35fd13f5b1ba9","ipfs":"Qmbd7HEJPkrKV4zvHqCqRjP9S2y4NR6Qf7BE28Et191ZNE","sha256":"0x4aa83f37856bbddda4a132e85dd3839f67fe2a7e27be4d3d30d72b5bb8f1fd62","wasm":"runtime/moonbeam/target/srtool/release/wbuild/moonbeam-runtime/moonbeam_runtime.compact.wasm","subwasm":{"size":8878415,"compression":{"size_compressed":8878415,"size_decompressed":8878415,"compressed":false},"reserved_meta":[109,101,116,97],"reserved_meta_valid":true,"metadata_version":14,"core_version":{"specName":"moonbeam","implName":"moonbeam","authoringVersion":3,"specVersion":2601,"implVersion":0,"apis":[["0xd2bc9897eed08f15",3],["0xdf6acb689907609b",4],["0x37e397fc7c91f5e4",2],["0x40fe3ad401f8959a",6],["0xf78b278be53f454c",2],["0xab3c0572291feb8b",1],["0xbc9d89904f5b923f",1],["0xbd78255d4feeea1f",4],["0xa33d43f58731ad84",2],["0x582211f65bb14b89",5],["0xe65b00e46cedd0aa",2],["0x37c8bb1350a9a2a8",4],["0x2aa62120049dd2d2",1],["0xea93e3f16f3d6962",2],["0xba8173bf23b2e6f8",1]],"transactionVersion":2,"stateVersion":0},"proposal_hash":"0x74c264d71da7bd0ba26e72e70ba90560d962bcef03bba736620e4ac7f1d39435","parachain_authorize_upgrade_hash":"0x57f2dc3964e9e0a2d534610805325412e27bd6d405fec1111e4f9b0c3d727b5f","ipfs_hash":"Qmbd7HEJPkrKV4zvHqCqRjP9S2y4NR6Qf7BE28Et191ZNE","blake2_256":"0x40f71401905adc3b0126781c62efb9229709594793104affb1b35fd13f5b1ba9"}},"compressed":{"tmsp":"2023-11-13T17:36:02Z","size":"1816781","prop":"0x9b4bdf1c412ece3c4af5d5c16407aca1b9adfdc5d59114a7690f5574e79eb99d","authorize_upgrade_prop":"0xb31f4f16f5c716f3fb05cd940adb05247be801f7509aa67b69be8337694ecc23","blake2_256":"0xe83808964cf7da37fe8d779f8f700ea3adeea574fe840a890fd0a2db19788017","ipfs":"QmXwWHgHtxyN3YkFBQtrFiuU4tX47uToGhXebyrUNfpthp","sha256":"0x6025ab6f635ba34dbb2ce3cc24ca4b2c82a86e61bd720b5bd15a3eb6385729ce","wasm":"runtime/moonbeam/target/srtool/release/wbuild/moonbeam-runtime/moonbeam_runtime.compact.compressed.wasm","subwasm":{"size":1816781,"compression":{"size_compressed":1816781,"size_decompressed":8878415,"compressed":true},"reserved_meta":[109,101,116,97],"reserved_meta_valid":true,"metadata_version":14,"core_version":{"specName":"moonbeam","implName":"moonbeam","authoringVersion":3,"specVersion":2601,"implVersion":0,"apis":[["0xd2bc9897eed08f15",3],["0xdf6acb689907609b",4],["0x37e397fc7c91f5e4",2],["0x40fe3ad401f8959a",6],["0xf78b278be53f454c",2],["0xab3c0572291feb8b",1],["0xbc9d89904f5b923f",1],["0xbd78255d4feeea1f",4],["0xa33d43f58731ad84",2],["0x582211f65bb14b89",5],["0xe65b00e46cedd0aa",2],["0x37c8bb1350a9a2a8",4],["0x2aa62120049dd2d2",1],["0xea93e3f16f3d6962",2],["0xba8173bf23b2e6f8",1]],"transactionVersion":2,"stateVersion":0},"proposal_hash":"0x9b4bdf1c412ece3c4af5d5c16407aca1b9adfdc5d59114a7690f5574e79eb99d","parachain_authorize_upgrade_hash":"0xb31f4f16f5c716f3fb05cd940adb05247be801f7509aa67b69be8337694ecc23","ipfs_hash":"QmXwWHgHtxyN3YkFBQtrFiuU4tX47uToGhXebyrUNfpthp","blake2_256":"0xe83808964cf7da37fe8d779f8f700ea3adeea574fe840a890fd0a2db19788017"}}}} diff --git a/srtool-digest/moonriver-runtime-2601-substitute-tracing.json b/srtool-digest/moonriver-runtime-2601-substitute-tracing.json new file mode 100644 index 00000000..85d7bc5d --- /dev/null +++ b/srtool-digest/moonriver-runtime-2601-substitute-tracing.json @@ -0,0 +1 @@ +{"gen":"srtool v0.11.1","src":"zip","version":"0.8.4","commit":"","tag":"","branch":"","rustc":"rustc 1.70.0 (90c541806 2023-05-31)","pkg":"moonriver-runtime","tmsp":"2023-11-13T17:31:43Z","size":"1815386","prop":"0xf10241de1958c00134fbf05acc9e7daccac14d3d447e4e7012c6a1eea84a07d6","authorize_upgrade_prop":"0x803a4a63f96da99fc510adf65ae9eb81006ac78d2c3655da3f1f265350edf43a","ipfs":"QmegskDvTiT1ayVnHdh6eoDY2Rv8EiZWmFSC1cp1mgVwnt","sha256":"0x56b30af7cf0fc19ce0cd7437ff6df00f9463ac1846c57c6e33aaf262d239924c","wasm":"runtime/moonriver/target/srtool/release/wbuild/moonriver-runtime/moonriver_runtime.compact.compressed.wasm","info":{"generator":{"name":"srtool","version":"0.11.1"},"src":"zip","version":"0.8.4","git":{"commit":"","tag":"","branch":""},"rustc":"rustc 1.70.0 (90c541806 2023-05-31)","pkg":"moonriver-runtime","profile":"release"},"context":{"package":"moonriver-runtime","runtime_dir":"runtime/moonriver","docker":{"image":"paritytech/srtool","tag":"1.70.0"},"profile":"release"},"runtimes":{"compact":{"tmsp":"2023-11-13T17:31:21Z","size":"8840502","prop":"0x66e008e328d3af8bc9fabcef81a899dcfccfac6c9a993e6929a0b5764013ca7a","authorize_upgrade_prop":"0xa5fdc4aa6c5f3e2c69568c7153317873e8a966fcf0b94750854da349154fbbe0","blake2_256":"0x9964ec11ce38b4a7b5cdd73e3e662dc5243a76a50207ef867caaa17a7bd174e4","ipfs":"QmQXohgAJ7o4AS4tAU1yXFKEMX7xkYzvXbM2Tc6L7kjMaw","sha256":"0xa68c7fc72fc90743ae814a25c50c121ae23c530e2321260f8c383874cf20ae1d","wasm":"runtime/moonriver/target/srtool/release/wbuild/moonriver-runtime/moonriver_runtime.compact.wasm","subwasm":{"size":8840502,"compression":{"size_compressed":8840502,"size_decompressed":8840502,"compressed":false},"reserved_meta":[109,101,116,97],"reserved_meta_valid":true,"metadata_version":14,"core_version":{"specName":"moonriver","implName":"moonriver","authoringVersion":3,"specVersion":2601,"implVersion":0,"apis":[["0xd2bc9897eed08f15",3],["0xdf6acb689907609b",4],["0x37e397fc7c91f5e4",2],["0x40fe3ad401f8959a",6],["0xf78b278be53f454c",2],["0xab3c0572291feb8b",1],["0xbc9d89904f5b923f",1],["0xbd78255d4feeea1f",4],["0xa33d43f58731ad84",2],["0x582211f65bb14b89",5],["0xe65b00e46cedd0aa",2],["0x37c8bb1350a9a2a8",4],["0x2aa62120049dd2d2",1],["0xea93e3f16f3d6962",2],["0xba8173bf23b2e6f8",1]],"transactionVersion":2,"stateVersion":0},"proposal_hash":"0x66e008e328d3af8bc9fabcef81a899dcfccfac6c9a993e6929a0b5764013ca7a","parachain_authorize_upgrade_hash":"0xa5fdc4aa6c5f3e2c69568c7153317873e8a966fcf0b94750854da349154fbbe0","ipfs_hash":"QmQXohgAJ7o4AS4tAU1yXFKEMX7xkYzvXbM2Tc6L7kjMaw","blake2_256":"0x9964ec11ce38b4a7b5cdd73e3e662dc5243a76a50207ef867caaa17a7bd174e4"}},"compressed":{"tmsp":"2023-11-13T17:29:46Z","size":"1815386","prop":"0xf10241de1958c00134fbf05acc9e7daccac14d3d447e4e7012c6a1eea84a07d6","authorize_upgrade_prop":"0x803a4a63f96da99fc510adf65ae9eb81006ac78d2c3655da3f1f265350edf43a","blake2_256":"0xe03f64071a3ef5400d537babaf96654655a4994253651f7dd38c9840f78f5e12","ipfs":"QmegskDvTiT1ayVnHdh6eoDY2Rv8EiZWmFSC1cp1mgVwnt","sha256":"0x56b30af7cf0fc19ce0cd7437ff6df00f9463ac1846c57c6e33aaf262d239924c","wasm":"runtime/moonriver/target/srtool/release/wbuild/moonriver-runtime/moonriver_runtime.compact.compressed.wasm","subwasm":{"size":1815386,"compression":{"size_compressed":1815386,"size_decompressed":8840502,"compressed":true},"reserved_meta":[109,101,116,97],"reserved_meta_valid":true,"metadata_version":14,"core_version":{"specName":"moonriver","implName":"moonriver","authoringVersion":3,"specVersion":2601,"implVersion":0,"apis":[["0xd2bc9897eed08f15",3],["0xdf6acb689907609b",4],["0x37e397fc7c91f5e4",2],["0x40fe3ad401f8959a",6],["0xf78b278be53f454c",2],["0xab3c0572291feb8b",1],["0xbc9d89904f5b923f",1],["0xbd78255d4feeea1f",4],["0xa33d43f58731ad84",2],["0x582211f65bb14b89",5],["0xe65b00e46cedd0aa",2],["0x37c8bb1350a9a2a8",4],["0x2aa62120049dd2d2",1],["0xea93e3f16f3d6962",2],["0xba8173bf23b2e6f8",1]],"transactionVersion":2,"stateVersion":0},"proposal_hash":"0xf10241de1958c00134fbf05acc9e7daccac14d3d447e4e7012c6a1eea84a07d6","parachain_authorize_upgrade_hash":"0x803a4a63f96da99fc510adf65ae9eb81006ac78d2c3655da3f1f265350edf43a","ipfs_hash":"QmegskDvTiT1ayVnHdh6eoDY2Rv8EiZWmFSC1cp1mgVwnt","blake2_256":"0xe03f64071a3ef5400d537babaf96654655a4994253651f7dd38c9840f78f5e12"}}}} diff --git a/wasm/moonbase-runtime-2601-substitute-tracing.wasm b/wasm/moonbase-runtime-2601-substitute-tracing.wasm new file mode 100644 index 0000000000000000000000000000000000000000..29a9d87b28d8eff971a23ab593b7d2da9421479b GIT binary patch literal 1851387 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 z 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 lj6QuDTkcz7v_Dwk!|A(o$@_yS&i9mO3 zXze{wYS#Nxt@LPLaNZ?}?g?UdtM0??Z2sjVlz5+I08S`L7*yl3)j+r zfJ0Uf@jVCiZT;K)Q9E|Us*r(O-&9sNh&LI=VM>%8cRWXqXD}G=)Wk&1ulzc*gqFu% zFBLnEyJ>$GeEwV#Ts1}euY&(VmmP%{6Nnyx%|WLt)ddap*0LL@(zM5RH0z1(P={lm&BinP{`?8?h)}^g^>Wy{SfGn@T{h*siU2 z1ofJ6rd}g_AV8b@m;Tr-({1X#%+j0ZjJ;h_w8wzIVUegGSCBXX@5^QL40%%rC8^$B zXh)1H{`gxvFYIBVy}##EWC@t{h|igPHh9;QZ**&}RxFLiZKeNPfo1dQ^+k#7`CAi> zkdc6e3?r|qO~MAR!V2aJ^nVEO`ul^gV#KImMaiD3oAV~lN`AHlBc$4=sESj=s8*CA z!G8LJdNyhJmI<62YVD&yjdQW6Ho_3l9@GV%r_$CMq$4WyB8h|*z}rpv&1DQ)r6NN@ zLrgzZSkr>&A)5Z-}e-!*KL+DUZ4AtH;jLLmQ z(CLv~U^*tCoOk$lWHCOXzt8=FC$G(tw?*Opt+$1i(7c3#zIh#knY`?ZG`)a^uF{!$$xv-EJEt26JK!`*Hf)8do`1 ze^yRP$@zr*_|S9YzaR0x|ojg8&AT` zLSBZ<8EH81sm8LC_j!%75urY)jb@Tv*pZF?19E&_2~d|6M2kG(fIJJexPp}(To4>A zB5-?xR6~iPA3ch~le-5TDM*|lDI;=`uxY=ZMucH>k`-3S^|WMd)%liQY|ic7Lp~4` zUn%^NLrSGHT){hdUh)fFUAAR|2#JhSnokYCIRg4Cp%Bk~C7S^FM&Gz78v>jb=P+tq zpk&AEz^`&@22!u?+@0h4xQWr4EkJF`m2NSR7+CbU0oyFj1?~JPtrc_lv}mLGeu-|X%*-ITRQWTpE&rnt~<9og1S&Ju_ERtz?1*rb|JE-KFM z09Qb$zq;ODffCV~b-#E}%oTmsHaH$0$}QYjx6O6y_L`-4tlAV=0B4l8R|&z-N7@)15SzxIyS%vHUjBqBvGUxL|K#AuRkTKSboc zVIX&gX3)yiR?7Y@#GoqLiPSJ~Mop}^*t{p?jJN&ZbkkW!(*B{TadiQJjG_R9sX*fg zke2|TpRlwPFz<*ax6H4~iB2nm%8B-T3p+UQ|8g}Of)k4KWvdXgqUND*YyYhzG~q>i zjL-O7*D(&ZtZ#|`piOUmxUmuDi%;);?VWDooIUA{!%N;XMsip%{vd0Y5E%&kg&eDr z^+fD}Hm9}TRPvti%<%Upcw_HVuUiYe96IiUYe32~ zYqU=j5X~$=9EfrVZ>vQbX=Y4Fxxz|l>-~eTE!-q+kp2Oqi6$yLIEP%6g}@*PHHVzf z$EcCtx&U%l=q!g3sEQ4&P2jq~)@4CJBVEicCg&&@$gjC@-Uaxk;5taKeVD+ug6`Sd ztc+XWJx=I`-*<9%T|^>Rs}U8bpXUoebOBiSM*kf9I07$igX83WG{}H?r9GGGD5sWn%x zH(^AogI+5VVNn9G;v5C0G5KPg#oNgcZljcKKu3a@W?USBu^=V;(j_Ab)raZ4So;)a zTUD9Pjb~b;IKE-Q&Ir;P2#%FSLKT^e6QoWl5+C;hI4<}nm;^0A8b&I@>axUOPL3bR zXl$&EQ4+E(<2M*iw7o7>e=E8F@maYDS zS07B1QJxoK{h+A(P2RM^z5O)w}RB<8IY3 zZIdGX&PEX|cNAj{Uk&2vH(!+?AsfGC6hOlw@P~vRai~&6m^dO6zz**| zq#7XS;TR;wf{HV%YBgY66lR>7G~ct+qL5Iq zZPkqq@1Lql(k@D_snuJ2!I8kOC-k5b5`uezs@fG6_it3l-*AD#_8Wk=Q@c%g(C0e6 zoCeA$8?C5di%O|YzrJhWsWkv~61H>>?<9*&9EcA@^sNZ}+A(U0d&#kXKM-Vf&jAJA zGfNkwXNt;pWg+oFk)ui5?38efLyQXjnh-%4B5o-{LN`9B#*r$ne1jsOj7`jdgw6>P zW&R+%$vj2NqL!DXp!>M>3WRa9P-Ueu7ej= z5DH+fmyuFJNSZf>2|LDnz7$DkxZY5D{-s((LT1p+z*wj_z8o|F za0%=CpFu6q=ZxCTvg#r*#>Yz=&$ePBt+9yErz40B{%bIRMKhH_2bp(HE!AXIvIO_t z5<4L%vG}Ju9~mr}Fno%qn*Y!U0DP9C=cDT~Q)&(&;{%8+`v1`;Eq^Y}z(jnHXtJI} zzso5*M)HvSD&#Z=U}w5tC>GLCLV0j}l!mPd{$TalWTfPW%lbjx zOy0SDV-9UV{M+KE0?my6A3(Ahp|uIi+WXHB5Rc1Yo$E3T9b0_71c8ooKRnErDuMs4sCB6i~>(Xy2nBo#+rmXff<_A zy7&RqP#Wc-bpnyItpD2=x-7>Nh-`zMm9&RG-m%e(JBA!;PJ;(XF@XBm9@=Y){(>Bp z7zY@G!+W1~x7(nE6$HKU6h(XU zmz})-`*W0jKX~f(kCH#9oY5MlZOBO&1j1qi>?DLSe`_R5jHKXMe{0J~d~~a1QFVOZ zvn_jok5g{zcT7UMrsxFc1%Fa_@3nxac7JH|G%gsJ7{Av2qrFp&L7RKP)bL1??*!0P zSQ9KEGuu4$=oC!=d9k!k9iXf;22MrRW-9Mi5#^9}h5#Mr)4z0TQ@jkw(B^^$Y zpJX;uzfV+ojPt&O)zq-1)YO`6zX6{7z9mMH5#hANKE*>6SSP859xeeK)py@!&D+T# z7nwh*sVa3e;<|+6_dg~3H9BkuKs@&rF`WpFajlsd%QcQpHNQ*cJWEkXafs(4Dkgny zpy^!&g?AQ>C|pw`Sls>gQf?+;&SMz9jK0aGS6xB0;6-wcBp9@+=nKi>CT#&{J^RCN zp$oY336!cdauq;1Awb}jNM@fS@&GXlSeS(y7T)DGHVS8-Qm?e)iQ=YHW_G>-gVlSM zLl6^l&%dELt%L3-iRv*)ALPIkG56g)etUut1#c68F(tu>7Jy;8myK-Wf^DM7u%)gU zS953HDJ^RZL*6)ey&r!dl%t!QJ!%+TFi}f96KSJ`M%MSaRh$<}03^#RSy^y;9dZ0K zk&PkPAo2hkxgWPID<@}fLp6acx8b_&y&nu5ky4j~b6hAoAfT@6-)Cshz#E!_(kw_5 zT;5wJcrgkDEkN&Es*BD4@iWofDR-%xEU`{%_fWBVc`G4tROVRL;^83A>z*70clBT5 z!j&wZx*+(A!}b*vaH|}lL9dTT=4z)!0)zd6cF9xZ79#AOh;WVFmLd@W323Tm)^mI_ z#jY!U3&NO+nFYjIeWrofrj?-T$J<4TcM}fDh$>m%{b6IbV1ZPPAK} zfLOuc+vdea3-tMha)W(#OTdXZK|ST@yRvzph5>^zJPH8JhG1ggkh|oC$nZmcVs^=3 z*h^tKC>Nnp)Qkh|*kcUVP`^W|MOwd?LK|)!;?-qBCnC_=PrrDsJI-qe?+EN zm{Y=lw>0qk*3OwEfR^qiAbrA!oE-vi0CaC*327mCGckS9MO}f!GR0RWRAJX$A{uO7 z-n?6LHRz0$?R_IO6-+F9TM+{bK|E>_0Sz%-hm zs)2E;Mw)$0RmoGjy$H5+X3BOZ6;2ord^#e|RC3{V)UkDbyX~k=({eD0s}ktCBbj#J zp{@sqML0Vs6hX&`ihg~ER|aODJB1Glu3GJX-(87A_hP=yRZjqxQM#d?XG-fkDi(D^ zeR9{J-d*HyLr3R@)T}r~$rrV;%@7m+4l2B$WTHU-$7okDHMy%hjc`c%@;4C1akWeE zV=0kRIV30eg@BMS5NG}KLi|Zs7-kb#f9h&Gmsgf$$YA00Z@fsMx}rJ3c&{=Yug|SC zP%k4~=oiBZ0f^^w>>u5gS$e$fwG&=&SETUZOgrt2*8S0bSMWz)OZgwMnvi}zP3gtH<#texhEP1V`P35u0x*jZ5OHE((fWuSJ`5zV2NWgf`SrOY-a^k&Yd)<)NkWykxXowfJR*Twfn?0%pcNz zpnQ+9s)cn(6MfSTh>$LTf{Xc^z8^Q>ty@?^w)NzeJ9ygwZ0j$&WgN^rh}*1RB$IsH z^B)gUu`jeD08q#^cpuzVnXX});;t%FFI1W2?u01LlyV3a;-rB}m(J>y(B-af8v|e$ z$eSit;v%3lpjaJX)yBB-b~S3@GnjFR&*Ii^JG`aOsF#`E`SCeGgY+Wp?HU|ZwmBG7 zet2~^-EHFgmJ&|Qm&gdKAtCPp?x|oSqLC-ZXu4(UY53}4PJT!&?9~2?o5VWBNs+EC zps;t{Cw5HC;M4P=*M?g>;k`w^`Bqg13`h|8K3}w101nVtJ&?6hXAkZM4mLbjeDV@B z%GIeBJBUOJdS0PC;(qvTKbvX8n@{54mY2z%sHyDBH2VBi9F&`|wC#~=hEchk@>YNjP1vDlk{NSGP~Tf439nfbXEG6WGsMG~XQ6YcS%@d| z!Klnu)bVW(qG4faS4kSu{>7Rk;!4|h@eN#=h3*Bd4^kF^F~S`;uC!QU(7^m~)1HsF zkZ8sF&Yu3s4?+PSOHV+1=3DBML6Smn|uWs_f_` zY)c!@QWjf23($mAG#J>3Wl5&7LSnE!Xw5p^)1`uWfqk^6F+g=~CcKbwcGruzepVh7 zh}JRTvrm+7Du&y;PP7(}UZdmWu~jb5Z3O&t`OzFdy*+tb%h&!y97z6t7L~7&E#GL6 z4QDnbCr1)co9PzzeBLTN;Dme=vA_nn+@tm@H{kZqXU4^!zYa}bAh4X zf2{X%6ceh>QUEsK+C`GPfCQh=1o_qaYb-+;0Yd~*&)XBPQn~Xn1Y{_vUM7=93Hd!L z7}0C_)%eHC-Bza*ZPJ@8h|YWFHXL-KrQGSmQ2Me0S=)w_tVeMR%U^ZZ{76d)R7bZV z2!O4L$WT1YN@~FtH(IKS>TyL6g@-LP?^9p|RYXs>+mwes+8Qz0NIC@r5{}=f1lbfr z+AYRRO3K!lyVkQW5n_UrvXunnuK$@Y=^67xySOln9yRLgRDUYG(Jc^+PlkXgVGpFR zjnhK9cT&TkrUyo&iMvl&b3Ed!bP`=b6utdJDM`XGX%B z=~A3#p&$9me(nl!u1rlKW6P-Qw^DlWCbsR~pgH8bC-h$pnNvI`` z#n5sSRCNYIlKI=He@#sa9TWh=SfDY$qNTM4aM&g91bz^f;OX(R8}hnrTWgeJ z%mh-YTnH3(SemtkLs)F>@IY%T_Ga*CANPVv3K-8PK+wF63$s)LV#w&<=~PlKPnnS~ zc0rL$U3v=Qlz196AWUgzxWVU0($) zE6Bd;jPU!L1Tgs<^|y2Ub5Xb-U5=6A%n%h&?Zo-5!Xij0iNL!jBA7)BWCsa3crT(^ zpAHp;`#L@=XH!Rg_jtKe{^2E|$Y>4&Yvc{HwZXAjb6mZ>eq7N(6T`ocUb^HmFUJC7 zB|M(}EETlG{-vBgZA)x~h5WbfzBw*6je^<-KzXs@8Ae(=9;C)?$vYEc#)@*M&XFHxOTJ z;mj^H(L0@mhMdML*jCWk2}G#hhRqpj8A383qWT;OyBXslH~yCZZE6-Rhymrm$kY(c zs$Els9bcD+RASFU{Uje5G-|0OjkP$9SQ8OT*`BUN_1vUV&FV5-;DGzghz;F=Pj=IAOS$+={__!Ae-YWLce&(}LPQT$;5>R3Ia$Z_M1)y0d1}jWvg9!&WMUU>Yr{1Y-)|Z*C(8*p$?W z882V!M~C2DyPAemOz0}b$22}hh}FP*H2hV5sM`f1fR@NFeQCB47(Db{AO*2b?*#+(jy-PTG7?(V zL%bi{XY5iOMwz6Kx1rP2TRx;t-wEb~9m_`8y6?P|#CfFQQ zAM<)wIG9K3Gd`~f1@KHL{i}0CNy8y}r)p^pF&l_@dl}UJO@5)_2-WmdT{@~)kE{Ut zCg@QQN7~*a21NvGb825@#PXi4azUNtQv@?DpssUHX|u3_!?sens#3PH4GsY|3Oy2A z5v_J68AI+g+)r;D0t~LAp2xh7t9x?JVS9|#jwkK>M%34CfqBo~Vo7qavfAN8tgivC!jSC5)Wcl-F64DqSlHAy@y z6R=yM1vpbg@w6dOABC>9(`04vvI*ce%p`k8L9VT*HwXy4H?{$oaAO%ZuMNvOWD`)Y z^PQc*Xh|M#ZrP3qDDZpG$g<(#IyPYRovIkECE6c7$P!Sl zuyx(I8nYTq#TP!e?`QM_*(M}C5C97WNi0QH%Pu}V4bDmd)Ib>LdVvrJ4{SzFc@m3= zs&E8ZY+Qn|8Hc0UVNM9t8eN%5f@B9V@%v6m4z9tC@5NQ^4yC8nK_%}`a;p2677-mr z7D)&dV{KvlPzfoQS)@xWjt0Z2Ul>{$uRf^ZHJeKKao?4t;r+4>t0miXgNFDy|_go+s4q&N~_> z|4#0l7qgi;Id}xp72~T+#UW3X6cWic4q9tbrA{lpnoiDwV}TuZ^7YKhS8YpcjD=Ou zK~}kwwh$|ip#p<`LnRXAd?`$E^P8Yvq&(BhYImD_Z+Fm54_wq2#z74dgN>b-Hv8wQsnmMOfE7g`WyE!$lgfTDgiA zTi!+DC0SVjuEm<=S%l5ayN%0i3Kc;w+A4|-Jxa9WnkD%!* z7$`C$7MRC*N#B6-;D zpO>?XKRs}beiE|ItnQjp?{-uLAR&3LOXLBR*{f$lJL^wD}H?U>`sEV-M>b%Wu) zYDURm@6y9LZKtOQlA;%i5~9-~5@owE3dEp54Q(dYkW7JUzJ!ux3Owgxvzn*{rZc4X+KD;ueJvls6CImPBM!tnV`o+$% ze5hInSW7~qBk=0nFgl9}U-TbGvJ9@EhS$pltH-|hTf!zdO_exn)c=(+5AHxVCW;DI z%59jc9`NFwqfa3S#sajM5zU~g?L&99xfWXy@rh`{-!A!84)(&L8><=9|8%C%YDOjE zg**G7GCANhxWV{eYB00$Q12lo+8Q}&eg$taKjNfR)M4g-z z?L9LtbR*MHJmFiU-4-BVc=#cx;BaW5f{zqfV~d@g0GIC|T%)9hy?cc&hAA0Up{c1z z)I+5gt2G{-W83O}q<8Kn=}lUX2mzQLJ)etUh&`NO1_;b= z%8IW5YS(DQ0Yp7as){;EDm6;9$pWh!=%WdC}*S&x96OCydm1BM2A7zm;uDdys!$3izGgv zA6k2fk4gc%Y)_q+*C$d;^+L(47r_h&z>Vna8olVz9Pj0p=hgybUdNUC6-0x&zz!e}6IZ&On`J4UkO_raJ0ENH~ zDw=Bkv8(@CN}p9w6tB(Xwm#!so?-t#sD%d6J*kEeqX}=6)VR~}ur5V(=Zd<5xOtC0 zgqPn{qf0YS^!1@a!8ofu*@)B)B3ZA6GORCf6$>3X#M!YyB>OTHei|ut(%%gMOgusY zGY5k^b1X=jTDSbYSyUmQuhzA*zm&Sc3fxBxQx61*_ALGCtHK?%<}bL!1rC_S;PrDgmqhhv`&eAObq2l@t-l#QXG9$w(pQ(s z$Z;_op(ao&V$AQi%mOoG=Kq(uiq_&d)LF1+5f6wy-gHf64VM^cGnj!D*{1s_@wW3C z+A36U48foFI)lF8v`eLlo56}{GLruf38u>$dVu%!piTz}#j=`_fazm5rCv-Zdlv;& z4fQMtTvX&?L)~}+m&yei&b7k5MEMfx3@s!^2_KRWPLz=+V^pZ%<0aLCn=o*&+f2an zk)a?CddSJbUorVi= zo~y#IiS<#GOpxhGh4a@5#_y-1g4$Wj-eO4bJQgwWkOZolASe#0`&KGG`l--gbC9?J zX7GplzR@PWhMs$#aid_$Ud4;9dQYNp&b|Z{kFkg1R7lKo3gX+;wW_sA`-CD6{vh^B zM6_btGs$*++HSsD6z)WkpNqE`%!y8)OO~fvP{w&XcUME-7Rmse8XXr#Opy~H zM@WA>2bcFjb9mwX~Nx4Wje9pNp8>}NWVTW!KWW*p^DoqI**8`k}^ z4&+)H2mgW?y2;5f0eB8RjLfG{s0f+4*SccV#2}LN4ea=2_w~U`GXG%n{MlKO@7&$&-y^Bv zj1oG`#(f71&5p*xbkHlucK`nXaYG5VJuZ%gnL(@W)val4%?KSdi3x&AiUI^6W~kF3 z`w?2>SCFt4=RJ-gg$4msjO3{^P{$meCfG5VaWWR0Ae$wE#=~~*R?)mudE%6r36A2Q zVzi1^?<3&AS^E>bMmSL+zqfhO6ob4GD97pzDPm7@Fko}U1ZtAqV)kQT-{#n4Ku)Km z&X~-64Ok3+n+r8IKV%Qll6rPh{J?>cnJI(vV6NYEsbs_hQCymC={NUffSwt%^Cru+ z@g4!v{#iC;5k3jDr|{%q5Y))(j;S#{(E+|~9aBgV@OpN+9SaOxqY$??*&et>IdLyO z^a2LD_J&L7JM_EE|V%@B=9DZd(1`xR<#*IOaIxixf7eK{K>H!>1^#AVCpU zQ*|wmFfZd6KQVtqX*?)n9I1%yCJBU6x$dCbBtXIH_>$Y|M7}R&&kmty7hHCk96v*R z<<&qL!g6(TVF&AVyfMVvn)gaab%EP+c`;$OBtgRNO8?_+kD)zMdo?9^A~lAX+`AHP zlAsqY!T(ah@>)wlwWr2J*c!bZ+Je;H;(fArkR4`BqJZ-RkmI~E9}^Q&-A8%{*p%G+ z>-EtcXjhIc{fPoF}}(!-k5fYgvhC7)QHtzJsCZqsJHv{F_W1BDTP~Nzs3j>tRp%m4R8` z5!-Knh~InyI%XGaBVLvekWLDGajnixp_X5M&s08uO9G=24hbVN3?Vx=nMsG({HEBv zY8eNl-_8hYPbN>E*O>-(r87aF+w@ptLA5CNirN#CFkkZ6jeP9rSidTR)Syz>Z+a7U z$WF~%ikjzK(fLlL=$hezGr=h2f;eH4>Nvrl@2F;zrqGAIkq46^Mda>aZVLpC`|IFa zfSiDX*_v-1ih8bUH`+GC{GhXkX*d+bq2(tS2M`s z%$#R?gzF?Rph%%=GiaVx@L84m)=U#p*w8`8(XwzL204H?#g!}F_i`M9(=fq$-d zXao*ONM^ADR8fT1$4mIHltT#*MB%5y8kL3`ojDb_14}4SabMut;}=QRBtn3pV#Te| z8o7~iWK#w<>PmYWnw*`}$LLKF6OpnLP9^ZcZ9f2TsF_xwawqa9PhpMVkWexs z-6im5w>i+eBXF|{S+`Z?Ko}?iy%FCNg!|&+(gt~B{9-S^x=>v)R!OtJ9%84)c0XZ zm@HU@DJWn-BauFURsbX9mkHN8c|n`rD~@+1Xr#M#=Lkd_wDNa=tv>#ZY4m>FFv0k+ z&dm7aOOnS5#-->Gp23ZSG-tJXH2#;@64)3cU&X*JBj3Tr#T z8<;0B1C%s7V&cO!1*FM7i;(+3y5R_9*pJ?edy0=E4s)oA`h zKtOB zY)NK;f36l-IqQ|k&a?N|)>*W3>- zvnR0WyYA`Px1^UWl^@TYf6olZT< z@l8lfgPFpMPG#c?5wRs{LpFqrcQ(4ZjZttOD1yRygV{eOihl?pJ&lp96**=WP@FM2 z{X?L$RWUA?c*pf$Wq>`)oS~mYF4bUHKuA_4^Nw`Grs#!+oNN^pNE5cy&t-UiqXi~H zP{`7I)?67MUr{Hj1*^+b#0`4=^5FK!5C5O}RL#vD1&-M}45ahAWAZiNLB7*WVFXk# zZ&ECh_BR41xVHzGtGlLpoTp>0+pZ@gzvVR|jsijGZt<_#J+--KN^Ermq<=CN%tAs! z>u+V*l^7R-o*a0p(e)}tW6(fdAJ0~@o(yM(7_X_x0*X&aHFcx_Pt5{kS9Y~C5?*E0 zIHhl<*KN0whZFnNV^tR5D?PB>&=8n{Vt5zEpOo^foMpJ1}xPiQk zTH>OT;&Kj^?+gnV228FVXTt)YoyPl130f^SjXB%trX{+=8mYi2`z}w(-c*GxmIZ%+ zLtV4wjvudhbY+P`))x4&L?2m5Rr}9FX4#9*g*S1pbklkzBpJwWNip2Ha6`S$cirJo z_y6cm_rmTm&rHQNuWE_jCcb@wp^mXt4nIr3eQ^X$d;0}HD)1JuS>(!3p% zz$EeJg$Scg@xa#7nWUwlB9+KyGzUb&&+77lQkfTP8;{#UQs3H*x0iBanjPa08ywc@ z<>($O%iDR)1>Ak>WKsbDBxmHorX*d7h#vavK1MmEnQ~qA8vC@-tss8v3|B|F>V+iw4bDgM z*&EviDM(;-@??u_=uOMb29SH7!$Y*K=G2G$vR(=O+$I~q5CLAA`ZH|?clLm7cIwcO zh@YV=+D)Nucw@34+DN_SV^zFBRJ<7uH{6VYlt;R)K8o3L6wpUB<&2lnvkf8K@WTu$ z3BwJy_BIyDFZf?W$6#YIf`r#%IY0y{AbD^gqVdl5588qCW;3yeDX9Y>?Hp^WYmWm} zLo{!$&Jg-&)LrVap{w<=1_ijNt|L)(g8>8ncj*>mT@witPO^(Ch-+k z5+IT4$l0+O=ogAWGVwbwjqFR_-{!{%BeEM9khvXTblp_vRm?WNGl(8(#~Bu4H{k6N z>BE*FNH~b!H;wo0D^LiWo)T62R&At;A=az+k0uT)*9951U3vnPXk#}taBi|VuMex8 zEM2wSShSmNT2(+iE;0tsg{vV&`uAS5`7R?-xKW-ggFC(IaVw})H~#PFVHn|j$p|%^ zv?Q#gc-Yu&bu2E=fc=u)o|adIq`_y6b0aC_DIYc6HXo`D8Zbq2M^lSsC@cs*eT}m= zxibw2rViG?kx3;(>`HL$4yfFNiA7yqo=b`!Doto4U;{gJm^{5gw|%|AbJhmA@)F{V zO2W^?ZL`R{M#$kq4!;MC9izG%Vk{kvQqJJiF+@SyQ{@nbX zUu<8{Wn1ai*aRjHl7bQg0t`yKFMJ5=AcO;FVt(s1>gOjyJ^`f6u+H9&>6eSspaZt1 zKs$Y|5z@cz1kbWDAwZXPDM=aXy(E)DiM%6?_6v(_1Z`}o3XDG#;5#yGb*2iev_)+P zPGF3lRK?ffrjOnq12h16V(@iXW0=i^J}^2Fmuc)?ePKc=DGMr+-`Fr|t0lNVmW4qg z%@bqDIy{e_YSJE-jCeRg_NIWD6j*Wp>z^ZP0X4==LckW2k*p_1R;jLArBQ?Z#0O#s z4Y(}`B>c&lUvYop<8@J!x}%m#Qf2Hm)ZE7uV#8ulE_B?;;7b`Y9}y`7=FWz?x#uw& zF$)e6?QvxSE}2wNk0;TP5g0R5GLHmYM|>j#Io~{}4_-qnk|Tlqs|9&r3(8inGlXc9 zyG}U(dNTE!!Ch@@imE4Mwc%qYDp3|~eVvn2bQ5c0O?Vg+D zE=-CgWtXGap;*F9;G4Xr+;q78qs}zL@c@{tESm!FY^LRb%UmZ zbb=@%(7HV8^kMdF=@Gh7VkX3F>}Qb#;bo6Tp{k!0vvV4B32|UX7#;eiz;TSQ#=#O4 zc+T)Wm}*bzVNA*tZqV3X@GtTg717++4O-OV*kWPocc!}zfg;jNX3MOgCZhXMjFzD0 z7O7bS3*OmOQ)V3-g8yDPac|f#oe3SMx5ZgKaQS;|>sc{+DG(>$Z8+kdG34m_*^aX3 z5pXlz@Z$rmVyROl11~qXX`4$N5KLwUd&#PBg$X)Uf4}0%#tx#AQr++&Am~U6F|v#) zK!WGfkCTvN3x@8(rBPlm8yY1IH+6lCeJ^R&InQWq;VIH1=De(;ONrg+y9Rx>nz@Ot z7Q=KZP5(fYkghZu#S=?}AsRhmRv({VrVneg0AalMN*OCjDLL0DYg~Ic7k>^KlUa?9 z+?yxb-PhlwAy94cZ6!I$Ig%AY^yffr zuEVx&8jL+vSvHP&)RTw@Ak|H; zjEyX2+yqOsburr~aDjL)0Hvn^yFzk~>__pwV-u@y?S{mOxyjwLs10*+zbisw-V*x3 zpw5xv&`+g20N7QRoT*GhGK6GC9UfdV5>mZBLQ3M1d0F&65s$<|zR5Pl_jZwh8<|5B z5cFDJ8PdD4`!}&_3UZ274QQ+c?V2H}s~4jyZ!N~AcyrkiWj}#0H26!0%VgI`hscA! z#MQOzcHh$P-Sjw1joDAdC{cNvK5wijMipxUo1;jS)mNaA#ZV`oQ+KTa+vu*Bb#J=G zp^JY+B#keLv)kOfT*ya;nTCpXytgaH%<7IqHuz%3y=yaGT zd?jYCkek>Ah{s9gr_ueUekAd_t3fXmxUC#AIeGE61kvwX5Tt9d%8}`d_}l##U-W7o zc|qSPO2!qvQeRjvS6XQZrgY~Ga0gd<+sYmSsqK2ahB2O*tb^#)BrI0hFT~gjRBr<* z?O^MTXU-Go$)oe|<>c~@zvN5>%;t4|2udG#ht6=S8x*}}FwGm#=S^_3BPbd|5l!!2xg_?I-fH z?wB+FAOl3#{qbCJb;H(&=&JYNmePOE&P(y52^Jt|N>T_1Bdm80(abWgX~Gon1u#Gf z=+yMccA99G;!u&CTDDOQI@BxJt|%V62p?_*ls$4ed2tauMN_=p9#mm&^h`z2D3-*M zD-wFFh-3-h@!?~pp9q;Upi5#sWI&Z=9cB#r7Um_)V9Ws!qiCYnLLqlS7nHgaw3i02wwIvbwodj~?^SeqKyg09Pd8g*K% zX_Ba69eySPq}CG;VAsewlf)2qH@L*u&_Y^2^P0SIF7R|smCx-5#BmIeX1uaMS2Pdd z^=uVd>;_I-M2J+~XDP6qXyXE4MR@a*SE&~dTGLt+_hpDqEeX9%10vmq91sn1`^E*R z=BXlCUI)E)z6%=SD(@9z7?}JTEz{(ktz`8>*T&Nw7WcIyw)1wd4-2qz6CY(7tS(i^6?Z~8)r^mPY^0|JmtYr3! zye`UlF36~c^WJCo8l!*|k;94XSs1CW_r>|F8!lvFJ6ALMT}!0ODbXe&Cc9()heN`@ zTGoVvY*1CJ6L+Gp^B}&_CTyQzBA)VKA$&DwtRVDzK`o%Nfi!+a3R zayiXA^N5V0Adr_r*4_9&5^CH@@%^JHWdb+7Db`+SK@P$X%6>`1&Ccf8JBMyKVC=aJ zSc)Y!z{g#tE!lQdrQt=cN44lnAj5Tdg&?O?7%Yt)gUSr&xI@ls9;a|+f#xGXRH@d! zL<@IK*A9FHoF&F`0~dwcID9Zr*yC@)8`$!qvMF?-PIR*%fhg3s`Uy@mB9M8NBRkIW z(FFFS#)Hzs>N(O@6V=u|6EsR!Nf5WWh{{rB1nA)-$E-bzfdRoG-%*DZ=DT+b8YSoI z>qON>wESuQ6aYBRWd+jRtSVWMM#pit<<;o0c+fa1;Q#t_6X`gJ#LZE5L#!<}U>XBn zFMs}ZMchZvwZSYXRJ&FnaKq4wTFbzM6eS9obxX?6gOJ1^7n6)=MK0u`h$~#>{CN7q z`JPdBUXJT9t}nkPOV5Nn03JKcW*F~~56~mSDQxG2@vwsl1^mM`%h+83V8}fUtBA~KV$P*ks!%=$p;B_AY;J7 zgaq6%5o4-g_bY&XW)Z>9mYPS{sS~5|dwUP5OCY@rIx~TuEsRp6Y){M*t$i84G| z#3(^EG|jKT6@13@F`W9z+0uGxO#o45VV(b8x35t*S>k*jW7QYbl|Qygs<)(tK)?hh z5vF1{8sPgh)wxl$Iovq%1}67PlVZ_HXOZe}4T%G8$74Zi1L4z*hFtswmJEe%P zf*^U#MGm+Jtq>g0)4}e=bxcLav^cw3h7*hXhT=MYVIdZrzSqrWRH%2-Gsf9#m&qfx zXLzRJW223@Umr{UQ{Jb4CI;xVivhIpOGiiPqQ6p!o>0`WsqT5)9>49J@UFPuaT@_? zL4ejEOS82Z{uEwm=4$0ozSDO2fb`##8HmR>iGx_jz7M~R@&d)_VQBIDDGafY19?i2 z2xbdSpFkYRgB`uZcm;?cgc$zt6e< z(&>KK7kudNo!L!TnX{{bq~8vuYLLRF(hiwu)ghY>1a#4_GQr*B53KBmch^&5k9p<; z0I0jY62aqQXIy!%XJ=hn$w!wEC?1cbPfQ2u8>Blok-)~CZ0+(jXwCItB^Q-3U*jk( zuEhc39)*aiyIjyt^gyT44y0^K$aLaY8e&gEIw|HLW*j0(h)$%di21pNtrzu(=wzS; zY4QRkmU+t?5xq!B{M-dpY+Mhh$p6$=4Kp-1jgEu>^xxl5^#yVQ)_ zv21EqG&VM$*P&1xrTs4dro6^(nmXt>Kj2O_P-7R@owN@#ml+vbV^+SeczHOSY z7S9B!wa!Q>ySr_S=$5H>?2)u7r7$n6cX#)c-6@yu?(S~+HID9X3VPi`l$5e5rQO{< zyQP#`cS|X=rqp(?Uc0-y`(X@B*VeMEhth6Z!R~I_-4pBvJy~V<3HYAi^7DeOHQH<> zCex^)BX=ntRZZ?v*5)qNxl769F7@Rul|t@hVq#oeJ{cJquaiM>oQzDJQFNWep#m{^ zG-4zsk6EiWr5O!PW@~Y%8l8;yxy+OfkViFNWME=cGBcCLu4-zmjSTB%hNaOsGXL(F zLY61k9aaxH2vQ0PYAk~^3)m%;Oc)gX961H_}M%#X6DGSzQbH? zT|lO_)@p4NTmXgek$Un3iY^9o&RJ<*MIh5p6t`(8ZqqV5=@l*pC`?d>MzqY<&C*vo z1RdH@?1&0VDW#NBN-3Q}GzozSSi%?r7)?U>!iy_G074f`Tx_9*l^^&Zi=`e^;Q^I7 z=bS-kyLn*Dtkc>f7fwgvgGLON$Z9riHmRMLb=s_2TWe-5?GLbKqgL|O+0Q!r^O;*H z)mm$1VqPCL^GcYKO6S#q+GML91=4w683ZlR$R1JDE-F_$Y9He0*-lp*7XXJ;MsrJm{HyS!Wa4 zllIlgv-{GBb<+wXdFE@c0E{81u(%>-MHM=jLd6t0P?ADQ6ev;P01DU>PTb&06HF}8 z-QC?yHE(56oYzf}>vh2hLF9UOWLcdSRRk__y{|0OTxQmSD=={30Ko|#G&&G;Qd$DH z8Uym+!2<>$3p{wle4tSyvb`zf4$9rlckWZkbQi`GD7GOmS=nZMFlh2wyD|zGO33!A z(Af`Xm3}~iWIS8FskML$C@ru8uvIzIWO*6y@?qsV)K@zcS3fR#@TprUQ5?dFYHL&z zgfMcwK7ufVT(5*R*_GF_8%1$NXp-yIkt-3je zm&;r3Q^~aSQG45hHWzQ(nnWOFquvLkGj{}VR+L`JR`2d&|gfdV-vS1vWR zD4cw70Sto)K2lbibTp*^2!f#n3ZUq;YFE9{80{$Soc2xAXk^LuN*(0-Os|ZBB`Mp> zLZ0)r);cvUtCq&DSc!t$0t_ftsP%TsF<_Jc1-pS{iV1SnLX zt&`~|gjxv$2%$VN%{VjFXV1 zu+ZWMJsan(yZ~o+Ag1HNqlte{NvS=L;LKY25#93v|m-+JUaXW zoJ2^el(0b(PHKR}5lBX;XaLU7$mAwWRH_+(^D>A5_<31%1kS6Ls9>OafvO0V3sfyo zu|Q>{B0{wSx#Raa)&!kAxcvaiGoahRu){4kNGBI`GRK}JvTUdtKBC=f`1FWaFKZ6T z?r{;rMGqxO5+dquC7sOa>OY^{v7t*a@7;3yrBZPfm_~DmA|!38 zqqUXTrV%}469dO-M5|F7y$^Ep$l^&mhKnI1CM!#Mx**FaKVaenoRVn)9a^y>cNM@! zI&1<+F-g5W4hO(_d6f`2J}=p9vQU~s^kGhiGCY72Poyedka8>OsJ30v<-RI5o9GMm z{$v*CdM44kOc;G}_syR@ek@9P!}YAm__jtl@#m2uPMgSVK@Sr zBxJyhL8)}uGe3YSml4=Zb%GeBP3e+PqcPd)Br1g5NnGR~43TlNjN*eK!UR^I#bg_W5v5EM`FTX=l&hpkxO~2!e_gAb6l;0??UTmUdEo?5Ex$G}J^MDN&x24q=ohJz|2C)PpAE zk-}6Ujuc9sBb`F&Ql3`wJY}LyOIYNQI*l|-rdxz)KGvbCB+pl(T9gG4d8|gYh}Fl+ zq$1UPtVvH`N?ADNvBt(q#pYwRQkhsEYg2WqPdCV;6-tt)Rbq+qoH6IEkv-Bvj@C(@ z_DP-=mglrnd@x1E$vCI+`QS{YOye^?9~uG3Gs?&_e)IXv*lupl`h0F!QL>;xX5HrV zVcCe0gcTYn0VX6Q+I*8QmT2>u&&LL=5hK@p_4(ASPV@P!XqHltX+HD$(CElBm-&2V zWO@+GGLQLuWSHcb!+bt5Ix6A!?+(9+W-o>ol52l1IbS$PRT_i8`#ecq-|z z);b0C4ux`zu!BdC8I0JYu#uR&VHOOhx56psWEsVZDY=7T<{%US7?geLw{hmIU5!U0 zF*&=&jWPKq)10feyFAG3e<&$mF$eK{!74m%Qidt)5`<3r@-TgElU}U}VW$7leeF?q z1aA&APaw=j!c4J|n0|q$pA3D9E#84;F2!^>QAI5EYUT9OTp69r$*$QDivWG~Ihlp* z!lsx2QJ9rsj-JCmT%W^RiUwdR3H)W8*kVxRjUa%v2VBY65ZILIqd72@gepK^{iJM> zvOUVy7R{j<5`Z|FK8g;ox_eyI z7%sXygtn|r0!$J(Zw?bkzXBlNK#SZ;r%#5PeERCKUS@Y-0dM6^U9Gkdpv57yWuI9d zJ36%QK}s^aOv|2Snbhz|v)8_vy)uaxG1>^&4p5*ZGNA|dDfGx5t044MmR`T-m@qdU7Wfs>e+b7}A(a`fN1U%FVD z&c{{W!8zrwMnzlVK#>JJnSlrLs4+c2yFpeZ7X8kpsB>|yb0Yr^KC<)g{6C^obA^0m zJ8w|yB6p2dCHmUIR!HaKeCPf!O@Kg6es*-|Wza#F9KpcpcW?w~s|m%~mhXI&O*(iE z$tRpYYof18hHNzloO1VogxpQQF{@9Krwab6zxPx~{l~G0+Wr*_#=l*V3CJ2zrIpIoCgLMc+P+cpz|AV@?+!Y4kYREe***caVODMzvv(P zD7OyIe1I^timIRb#Rjp2oUEx$8nyA9dsu}{UpV)o4SQ*5p7Wc)a0l2 z@HZZYzm2zE;{rALsc{_))MQ+ub0V_{Nlc-ma~+K22wkGBzRv#|m@2X86Wt;+j2Pf( znVycD(4+7gAE{Cd1>CQJX%k(dqQ-ST(xxT9#6nHzku>2hKN&jkckV#M1DI&1KXa(E{>ZOGH~1$r{lX4qKGFK5a}mC~TeN-~t>i?8a@~8eSnA z7|D@}^VThlzBDbSVUay%OpCQ}6Yb%5KGvaFh<9*3qOI-^fQp^te5^;gxzC55`+T^K zyEUmkDPrr(`~cdITCB!stDSOxXDRn}m~y|y&AC!Mp$3|><2z&1Miamc*Bg^nUkyg` zh(n(5UcCN%hEyfm>T9vj1E98~QR%SzG8_Qy%LhYe`d=yHTq(}4hCUAcEgg1!(qg$= zV}hc^YK5(0f@X9LRhTGoC99An6eWykYB5W8m?>@@T7WDVD8;PolGY)aEmHAMj}~w| zi$`Xm!}%vDj_DO-Ykp21l4stFLdIfGDikTef;@)HcNOMK^AvBPLgusA+%YKEoPIEL zu6dT>yq*O^_ImmG(D;w0v|Tjbhj{`6YnT0u&(DX(k20l{&Y+ZrnR6~bod5FkIbnXR zFVUBf-{8Qy%-xO4&*$bpx)X9e(dLdb+q|1zPEOB{0M;(~cvSE^d|lp6jJ=rT;kl`I znHR&E^1{qGN|L7v<=Ei@uLAeZh7icpy|Xp5)WwUXu6;J|KrP_-9d)JD1xE>``fTt- zm>3H{77X(|=fNWiBTUj!9yKAJ_dA|D^CyJkjRSu|9bRvX_tar;kv(|czeGT&fXBP= zxY~h7FmpNZxb673WiQ9aRQ8N$tAV7l3M#Nv_yLXp8Xn{*pfH1w2lK!mfIq;auBMbsAk<)My@FJIn^W1+42Ifnb$PsX#L|rlh@QrA=KccNZ zk$WT~fFn#&Hqy4xbg;mddA$E6`l8|eUujnW-hWfOTzLOj`c=dG&(f|HiV!J+fmlB? zyvU1SpabAD(N=$k2Z=;55bHpTMFA3xrCs{9%*0lvch!HHeUqv38e+$IE&;tbzD);whwu13^hzlIgAHpGh;fU7CF z+R&AmhMS2U=-JQ$3oN`-$+Ykqt_@$|vS7vT#T#-po;$OT)iobvj((4;gEoZZ>F0n% zDED{=EkurAz$J4IM3}&!>wW$-SkwrGV|PZTSx-S zD%_cO-24Xm%6gb``hY>cIRNnZ737=iz~d^2eDf4=CW3tPo*dUcb$D|WuBFo9&3Uek zNuHbIxU$0=c(hCT=5y%gZLM_c=H^+Fd~+LF^37X#Tw%#K5Ag`vEBWR-JIFWJnNDip zamzQ|mszJmJn`m2F8&ORC6LRyIN;CxgXa7vTzrG_rT>Fm*3D;lkjHRYH&}-jkgmi) z1PXE_Ff^S@>39l5#&r2r&EjB_c9h$mvG}hR<;N{lst~7^tauBF1p~{RH_87)U}P zBLqZK6iDPnIhKL#&`1hlZj z5u8LA@DJJwa;2y}0ge)u0t`s+JefCe)R>Y4C3*Y_v@qc|(1PVM0m@_1EhXAUwjFP2`D6&w&N8pSsqhwK{iYzQhK^74_j4_sQFF;n7QO01(nF9Q> zj55XvPmHld4_uJ51)Rw;$`~QQJ5a)X0%Nj_BE}aryx74KK$t9}hylwv0<_68iWo3x zf*3_7Pyw#8j3S26lYm>6QI7C*1gDsNXB--}ueG;E^1OLrscdTG`LV`0<0T_&R;S@O z7!>N|Fx8>BP0MD_34*JY#K}Q*dRwfJyOa$scc~O;?out8gWRQ9 zLwsaOMeb4ocK}y_9SR9>>^hk2al3=f++ePF?8XjCH)T{6<^BjJjVhwrBzvGTy@gRJ zN*bapPsoxe7DzNrA$XxQrzmj)m`E=TCd7_5C27*p0VYB=iXuj!BvuTHK%{szg7va~ zs=T5K6)>^V%le@-ric`8FGGO+PV?$bA=X4mq*sdFre&xA03i#LNH2>AV%yhSoW0^C z_B~vz&n`%9r4j-tGGGw_nnOSmlk{-WT43e`u;x*45`j=~60^)1C2Z?nb=WJZ!c<|D zRzlz;hgnJqfs(9bOO{fUVByJ9ijpV!{jgo~m4q@$nUecFv@ARHwg9CRB~CK^VU&s1 zBW)(HWm(O#EX%TrQH92yyB z@5_>5c9^>(!|XHnhD;&LcI4~@k29z)cw6#hPhBcCnIrpmImwgVyC@lE@2-o?ksWnG z$&;PCDw!kuCZ`XSq~f%M`smBQ%$ey!0zkfGjvp<~9y6rx+2N8kJXV;;eMo31fpL7d~b+M>!8l?^j zrHqI+Iz?%SzBVGT$jHcuiN5-2$w=lfr*EX`qn*qg^iQiNu%{`<^+kHT{?xz zkrEPB%4`uI#~mdxae_ioAxe})$x@S%l`BUbs)+8>=qSku$*7-@`l$wY%;;sw%Qqu) zsnJoAQ43rkUA4z&gnYd$dHGZxl%($V6I3T9(HAu`N-|0+0x8Lep1V}boFpN+<|)$) z5tQaq(%|l#+68m@nPpybM#%D$2+{{9T_g|vIIGC=bISDL&1r?4JCLr=^#jQTQ)*(F zP0S~xD+)QKm{iCfc8u%=VCZ5^2cTx==JGVY#OAV>s8ARwtCUhoDJv)?36-8#i*iT? z$6(nZwc^p&kyb}tlqsmRa-mCxF4}zchB9*`O&<-LIq1JyHH?WokJ_bO+SK8dNtZgL z*C7Hp&Lp~|W%C736e>yS36!p*MAV25QExXrHI__Iv*ga}J|B=tzi5cw=L3EoHIaE< z`%M^<4K324Asbqxft!i8=yi_hXIzRzVKj-hST?ujQW#C5NJ!8cP$^`Om($ZH`A z4VykBt#8;&deW|W>IBm;WJo#bos`l^h7h2v0yC-t10u^Ruq0Xj%d*N7TAsj?=RE>+ zIG`5UUAIEFaZ==wYmj!0q180|Av}HzV1@@&pokQClucP)pqAOBT#ut&Gz^wK>Otam zS@zt6L>{QSx;p%9=P=MlTbE)Gy5S$KLS-TJasc+==&(K}3UCZF%`(M2%I%a}M#=4x zReJDL#2jL)a)ndwk!6)Doa8R$$^rQ7Md-GH;A-{LQ7&~@1SFC<`s25Gcr?Nz)ZWSK zq68?fX)^%FAUy9>(&3#J1CgJf_?oP=7Lly_ar2QBvnrNh=Dt(La+ZDG@lbLG>o9vq zv*hg60+F*<+j3fJGne}T7=g0Fa+d2azZ_b*VhgZf$g+H$xH@&1;hBGQx1(K`l1F}I z$;*IyI+WW0U;wh_Cu=^;*(;t{hA?NiCs!S+l;4mYW*H)CN4q4(v4u-ZIh?@yk)?g! zzG9Y!WeCF?w&p!0y7>dxSxQNQMF3P#yU58sSMUUsDo;GgvdR-oGM8nQCycVJ@&r*H z!zxb<40{1zWrd>a>cWXZr<6^@z(ES`|v(e%Y7;tduRTxlsqyArIgZ; zrq&5U>85RCVWtd_Zgo4|dT>y>(QVtdZNsxpNhOuk`tV5+I_fe1GKk;<$9J%h<*7XF zaI!p&d~usA``DkdLl58oTAW8tSmZKn!j;!7BL!K0v-NgLDMCQV^hzo6lu|elgG{fK zlIiDDL(SEqxGlRd^5!PTI45o-kDLcLnj~-xK_&#@!}G$WgZAumZrinywd_XrsAoa) zyuqzQS=)JAoV19uhWdPJm9$+rETwjHm}LlA`CUTE{bgEouO$$nLLDLt5K72FE9q8Y ztC4NA)%2S@?QcEwg~!zvBH@E<^?zV$rWoY@9Ks?<&!O(C$jFGG1Qg_`w%li2rB>q5A?{F@Q`(;u2 zdH>PeW&PkdPL&&oKsXMBB!&o4=RinQOo%&2aw9fLJxDwTa^XNk5<`Ue)BA(-8W@Q6 z!}A)ifq|?NMmGU)ix#m)S1ar-6K19~ZGKvnexX_}Yyn07JpKimfATn=%L2{Sgk9*AJ zM<0~wH4>9!FeSmv;d1Vd(@A#ucgG53m;a!vYhhzdw%9_EPcy8i+^ zvW!wiQ=ah{&IOt@;GqUhA`lXJg%estogJnP^6;dyxN+Q9ShH94|}cKU(zrE_{6Tz6JjcDVWoYV%4S?UW9~ z8!tfaF}L|>VKG&SR;3m0jT@hFu#U@)>M>WdxmwK~ja+s4y`VbG4ZsP683)y2ZsW3O z>&AZ~IF5slw2tG)N1FV!j^jsme&bS<$yrl}jWaA{fMW*BtS4~Pl7Mu)=N-j%<)YPC z4UbZzHZiNOhK@}Q9=9FvD%I*PAFZL%S*dnhRG*6C@mck$uHEmkDOD_G99c%Gf=Mot zH5y}Acfomx$J;d3(9!vKof;TO=dA;UI5sZD|20ko=QeN+e5A>b4&G?%I}Sb);_t_- z?>G+84k2PwpacBT`Bw;8i6=btn_+xl!Ts z>0mS-I*{auT;Ji~ag~W{;;?X8!WBLnq$s5XLVXxx3L$7bbRY?m5ArpaWUK#udBuXs zg?!ba&eB_wygUih2&yF*##>oRec$(a?F5Drbdc-24@j$^3oo?D^{5ZXge|2&3+lrd zQ+!cXAp6~vM5Z2ilKXW?_UJI=>*f9GgS67G7fg#@KGGd>FQLcCF`x&7k!BX69>9?% z!C*8=qfclOt+m!2FUTpBU_}jpypr%_hg{#est+oVFA78zB6t0vHmNVj^fWXrODR)S zp+FEdCE}Qf8kYO!gJG0VI^;MkxzGAu&@#o`4Kl!ao6pC_#wH99_`r!=U-JPuauh@s zR>bg1!jlfYsFHApb^+}1|NXsT6b6h(#N`sWsW<`2-do|+?QL`r}|#ME|yAx7E9YK zsVj3wWvQ$0>Qmsw_DYBCVx2my-I3&}wg`Fb4o)94*X$llwwZSCj$IWUI-@R^*`^Mw zWomn+!+IP}fMXZyVoX$)t~j-em8oEOK z?ogcOvNH#Y)3mNyrdh9As%2J+%u*-YSJuA1$J_>R&)m5xou*~eb-ivil7_Ov)txLi zYFX0dB&4W`>RP#N3+e^IL=LrCMs22jKsXS9_4AsQwbstXlX8L)gwm4|#12w|*nz&X z*}b5XIpYga&fd-GO;OTU%hWS(L#42ES@Gz}NIgew8wY|&PvS;j^V??mPtp zlo6n>pSC~mV1_^`ClZqE;X=+nkC59E5{jJVAZOWzG4SO2$$r{ZpS7!qwDLoOMO1yyAE}iqrScCIuxqwP*>*7d*|YLvFsfsB??&fZiv7GmhuAHg#+qdhq{3T zZn$=6El_jnE;yv_J$3Kd=fmN#0-3w&0;vvOAn@Sr?g$QfIRfl1JG5sJY4APgrHFd! zKd8&OYk|s=0hLi%W|Zf-Tvqp*e?y0s)#19yuLNKO@B?H{0A~L|w<~MVu;-)=;e{#Z zgv)Ja(==_{G#Zku&1f_?hdG&M>V<9`ffLJ|0K~yF3|X3Cv)7*I zoO5!YcU)zSo4Gm6%)M&-0#&JKXv^MdpSk1AGw+HN@v>dj+`hxPMShw9abCc|MQYwP zF3=Qf)M%n2&-1+R`@VM)8&QDsDdq{BO|(_(yHpccJ^J~?AW>_)u3l?i-$SjWT{Ne; z;@9x?T|{5^^=(97zl#fXaY>~{FsD-U(*XvpDf?_W6xsP-MCbRcpPaYe!az9>5>Z7o zXl(%AJCEuU_#z~GxRC2pzCrfLay`wrzr2Xe>+37dZ)o6r1`ZBR4oLEh+dHoEO%5~9 zz(sEGPlqhe0yW#*`(&`W{DjP$`;TVbnr$vi1`darbI-XzIgbF)39kTc4UxIy%rbvD z0;D-+5uqnw%p%f9a^9DslsW#X`RNM4v4xD>_eKc*oG?j;++Noy)TStB{bWb6FM-!N0d3knGxP+#gg9`KizT(=Hi; zbXY$_hxIup+|vuxykQ(PoL`W@(FJ_(jR0-c|9(3dfg{ZIqg48F18vn7s?`PAL%uNG zw2c)pr->&OA4GuTM4A%`L;@UFv(AafRS~5|t0_h3%OeBn15@-s%MFyoJ_hLP%E}6u zBneI}h{6L-C_&r-W`r+LAY}(g5J%Y*1qfb{U-lWu07Dd0FK#p6nLrbC@a9rl$DyC;lIg1Od7tI+Q#jaj5DGB9#y8Pc>!Gs}>& ziC?CVd3hfbHD56>_$50%BOgFPnsin**mkgphQYjA~xfx)9i>hf5Zve+^z*_BK^7aFrjMOh5VBFWdx%*@Qp z%*@1NEW?=2+-xbPDT~q8m7Q z9(!!A;W1?0;_*<}C0O^`v|2SOq_9FBEz+2M7D@8-V??rt%ez-Rz@Bj1I-=}oh@xsV z1VzeXzrlnQP9zRo^b`jfDPz*1&Jn;diybu*eZ|Czh;na3L|Lroqc#LY3Ls<)%k+_Y z6SAgd3TZ{iL)ao@OJ+?9CbA_nS5$X|MJb8g&3H6Q0J>x;MM;S4V+n9*MdF<j{K(NCRRz`sG zQlt4tNSkoVG(_1uO1Bv6C&Qf*ZOslwTk~RegTzk<;7Bu+yPdNs{O1X_T~!evwa;q+Rp#bZgfHI#}CO``JN} z`#srW*#V@>sPrthMM2FnL^A^b0002P6aXM75DW*!qS0V13qxg+4-^0kd#FNkTA0dX zNfN{`3L#^RA;u6wfC!1m%*?1G08R{@#$mj(9e2@0?9;T-n_td>hKfAgZ$Rz`Y^&i+ z_%)5bSL8gKG~DOOwz^%ibx|OM1#2o?g!r1}CZD9JHryf*LqS7>A8{uY47R6k>hcWd z+Ev2RKKcLQAwgb=4g5opXgwz76RHMA%3n^G1<|)Dy76a=`ny9}){O153b^6=v@|$! zFrJW26T_ls@_9&V#M?q)rJ&BPUhG=~d)a(67WSkgBCUCfIh{6A@SOE>LJzw?!m?`!gRm>)E+I%o*N3O4*ZqNU|CpTvrPZ7PSPp zJU>+e6*zpd6d?3dIo8|d-eUyasJM*xthn|XIfskw^vTJ+IKp)t1)WV6gPWB2-jsG+ z@E$cW`oZV7i_wboCAfk@Onl6@BHd(ub}8J@anZhQUr}3I547n&oq2soN$k zd4@z&=K<&-*<%Yf|25BW;JQu?g{BD?cB8Tm>j$1YbaKg)^BoeNVyxfgpchj1CgdPB zo_i$|YhJ$*LU)k`l@^AZ=G|%-q7?OU0UKWs&2^i!SOS;FRsSna&($qMxR*I~pv5ma-dj-kNJegB}pGh`2-=8ZKR;*mS_J3 zgU{?jeP#}12x@oX{V`v;yhykeV+{)8hh_{s64P=WJ1WgZ0!GhO5z(u9%|OM%=siO0 zTAUc2wHdW3T4NW5uN>GP_gMZxC9ALrTbR65N?$Z^NqG*R;C$q+N00knAL-i%$M(T6 z6eNscf`U>$V~!B58wUw_L71^QLvg*AmEwDFWLPbZ6EodWzBq!=#U)TbiYi&ne(|oR zd_=^?b#lVQ?pt~Tl|PA@+}pM3gwt*P_^E}Z{x8M;VR~`(6N<3G>U{vB3q zMdMoiMHN+`TeK}-gnMwlPz#f&K(*whP*qXtQLvlIrmC{Pgo+AB?Tt8OhCx_gS+_13y)RNrH9jt#nEQWul zUO73<0W#MG->cxddn1)|jIOp%auflOj|n%z0o*0XgD*V7a!<~X2+kVZ5H zW;noLn+C`T@ZOeAH1M+>wv914a|Kk!kq#h;4T=`dKs7fI357#_>xGB|0EtMrax)zC zD?)eOxUhgM{6El9NBc&y^yN4QNuI$c|7or!@FOdj=7FVYj}J_&c}M}v&o1Sqs8wq- z<}=?s0Jf!1VJ@j$CRO~^^S+hTc`1{TV5764DW-8_1psmnIgq#zU$`~<`Of_TMciG1`QH8=Q(kJLx;M(1EzuGGDM(}e%;&}bPvJsdw2S$jw)#+y&S%q<< zoEgk-)8 zn&X&YNC(aj@|KRZ9V~RwPr|##N{goqcVr5btE#d$k(~B}987vkoPHag#wc3uofcK4 z`;bi^Qk~n0oHOPz{w1gRxiaEn07YG=BjXM|RN`%zVdeWD8u;+By(lY+_dV6Ee9>zv zivQ@4^#^|I3Ib-B6xclp_jFje%un)drwk%qx}EgR;U26Ys&1AFIVdY;y7S^NR1B9(olyt)3old6{7($09px!Jo3`v&|@#u-$uDAL6p`Gn&q28wM^d;j3z zeT6eE@^iVRQa#N^XSlz<3H}XNxUmrvmF10~o_exWpk=tke}UC@X@vFYj$LUPYXBtd z0{q+rS1E^0CU~=QFq=F^vw<{>%Ym=mjPVo|N8Jdk{b&XeCIp%hDaM^~8ksd!A3OS*{XmK9I8kB~e}Lr`$x>;>A{;=aeZLLpnTj6V;eKcPL3@ zU<4wqk5Bayg4_?xF7Z_V;qN=|FZ`UA#T;M?o%HYe3eZ}{N2R8dO3?TGAwMRdTzHlY zMPdT0g5suqMW7tE_DLUIoUKa}Uli8(Ffb*;8m-=3 zX;V>hq@?1yQSYFjSWH4hg0=)sqDa3aa|e5$yC>%7}3nr-kqz_-_805r~dwNYUDy!(q#8l<=0F~y6wT+7QIfF zGaaI}aX(0Jf(#my>rhCDW_aZt2Ko~ z^3LZ64@rArbq>b4^F|m=hW;S3w&Bv~irU7T78!r&IqE}Z^Rp1jvW}KCCQKH`0I9x} zn>`u_MoD6D_ca$C^z)Pz4D%t*j?3U5rRaa`hd+)-sRFev;@>cKQimL=&tUdCR<=*8*r2w2n+eLQB#GJv&ok@mJ^dW6!xcFIY(U`g6m@lSirDdtl zi?gAtE{bDUh_9)mq!{al&E@JENO03P-sN(VzUnnD|5Qfd`zT>gDvNf>He2D#c9iPV z@kA=#KCS05v}L8FP!upKy9H;rLdjM|rT1xdU?Y?$yVeUR*i4eL)Z7VlW&^s=L!ze< zO$G4)-wD)$VyVV8{ukDwdCU4G{w{(4x6?Kk`xoPSLa_kJoa92B^pzzy(NO}y`@5$U z6XCdQD%^VXhU8LvtTgJ%iYn0UCM=>QUoi`D`fSov|FEqE8<*KVw|!+p4XM`kDJ0;5Zry6G zB)n^39y0q_{bF_GAWE8s8W~4|gEQgmFGzNP#$c@f>@IM1lzOk?`@{|qvD+sx!Tw4> zrn&lPuvQCmk-`$HUc*Q@OE14lS6)bs;Ggz+PpPnddbf}Tkwg)K*YlhJ89mjP;+pLc z)le|9kKoUl^-(_DxF?xR0X{3Rd{_?Q<=(@LMJ#c>1kF+DbkwhimqPl2Ls!VJSUB-g z9-!kCJn_HR3C@2?*-UX55s2TFYTvvIj)}8g7tLWC00U4iKDQ}*#*~- zm8Gy+D|KzU0j6{<64Twb<3@Mh3h1&VCrp^e1i`YrRwXlaTxxf2PzqlI2QoEXZBwQa zav@<0)Et^HNbyT?4b^noI&Vm`k<`CnEraniXnXk?*g+T|d*)C;Fp}&bz>6>^%}LXT zkD;DVn(-PLvACl%(HImEY{#Crg^zU!F3~RdPBX6>l zI3**BX9CgFj~SVAa{*pt+fzQW5|5oB%5IPGV9<;#6nH2~ z;Ock2;zAAOl+E)x;P()E{kvu^jT+csMPJd6b%=CyCVq+27Ov9CXtQzU9ozRoR0$t?MQ2KA4ZlQ{nB&Sk}XBr*#E4 zm`^y}Ku;;14-&`yS+CH#-6pll;j# z4-^>yGeFG0;6KJpeyUVJ*otn89R1y7opr$kfJU`1x9zYjOe(W0PuF^^Lh4g-B~RQu1t2(TiILO=iR+1Gz4 z{DD`Djt@Q|Ccm}kfa-h9=*i#%ZI2}!Zv;=mchPCMjQCQ`E4{!eaL;3(GT(D%+-1(@ zD3V2|a&38@TaK*Z^__C@*WfoN6{*xzlm@y{4)n^SXJ;!ISwW;6GK17REhXxW5?3%r z&$^)S;Qttkwm%}3-aVJbSm{Z&ot7wC+0sma{;4c3Qk>2bx=W)4soQ)mr*pf$Lrc_p zOdg$*s0lktP6K20dm<6U0RSfnHJ$CM;AndK1i#*zg{$uZ8;P+IX~}a4cGn;lo`ka&2ZCJkZ11L z=*Eezi%1iGZfJ$&^eY18C_<(XJPjtw0NP|Q20oX>z)Wodh!xm024JV(-hl-Nqh@TU zLIFmpoLY*VFXO@rJt9LZ9cfsMwb3q9fRas4G8vUZDC}hg<)B^;ibKLOy{>+GuW@7m zQpI_u2OvT1st-j|xzGPxMa=IoKb3w^_1R`(+fFEUbXABEmZLrpr10V0_p|CYi4*0A0tEvR5Y5i+VMXZPazt zI6X50{uei$o-W;`l6bWz4aVgbDE4_9RKu425u^=y&NSndl9lf~j3#YL%ZnFZ=Z@u% z+wZ3kd*}h}J;>nrW|?WsBluJ@ob}J)Vb^W{#Tm2`^Z{j(sa#|x=*RhAhU{bA>kMA~ z?`#%5SJIq!X}A|}B!uhM2>o&vD0N#m7}j1rS~|!_BnK&rA16A54vHFc%oY=A&U+@F zTYff~QXP9~8DhRly0FaC8Y1^kOY_lXy9iq}H4%+Z`9H2Fcj@R|7)lrRRIuDW_{5EH zI%N+h@CZfkWf?K7vMkI~t=b!+R2$4f5{ToYTEUhYRLWQ{Qu_wvw`u`J-P0C+%vgH9 zQGjkXF2rkttb=WKlftu4A&3eACvh1M10C$ezE=t6LQt(E&y%(vJ1^LME(1mvz=JZO z@Yol^#hN_2l-<^a(HMQPC5^u%ac-qXi(_e9h#>2?9SKyAQu)dufDjxN0TL}e>-82! z;9^GQH_0ii&d!hF!4pBPk8~iMg&@vndo{0=^y`3$N5|`33miCqK zE`>mJ02zG~110e;hAYho5c*qKjmG-Ix*S_-om0uQcsuy)nfv|lrHuI}7?K)+Y6*X8 zyFt46i2zR1EzH1qoI>Ip-_qf&k+gShn!!hCV(D2DN@3^BxU)sSE5VY6UZUw zWJwlPFgd$=GqxAcUGygJ6*Vn*Vy`E=c`wbnyro&(j_US@FGM5Rh^IA=Muj7-zewP@nuds?f@((Y= z7}AFmEFJ#gTI*#X_aQOI>=P#m*F-NzY;%AwbfPi83MEVf+&gc$A|n5k^Bbv#(?Ef( zmRTk;`*E)tu8(^1C+T3%In6-i^m`G0CJ3ig>Vgf%cn#*Vi$77RfgN#de>b!amSo!n zwkJf9Fttnd^%@I(&j(h^jDQ@vilFPIpijQ~8qsl#4w^D@)aH>3ix5GG&{EE>V)o;M zM8Lk=poCOohdpOu4hvXm{UhNEG{!g2)5HO_AKebR>e{A2>_TKtH_6)30rSt#VgK%x zQ#S-g;EAEjg5uaiRLlFX*1_tfoJidQ0>0ZqJ6*9DP_{A08j-pLJ!@4u_>S9Ap)qBJ6$aoyO1yp>$Yo3paMqt znCt0%=im9=*Hqw}(0Ev>fL8%L{0X#b+*BtOiX{%m)2R$$vkR_}3Sb-Fhh}~2xR{?K zOB)P#{C8e)%iaY(-^7Gx%8y?vOCbXcozVuE8fjbuk~xsF463>Q1!;WFO8(I}9_xUv z;fE&P4A$BD!kztWrpGBYjU9b7<}7R61dJ2R0pXSmU}kv|Qix>@cuPoEgU()*|5M2# z6~-3ChSsY1=*t)yZKDiw}Be0)8%1sgktKAUX{BOr&C>$3+|`L zgk16RF-EB8XQM+8wkQXCOa_^MK{_`tmBZ;q8YzQNey~BchfMUv&4h3=J%ZlW2RJoF z(M-8zC+~h5`k=ir^YF!%lZ%c%07=!YN@W25@{~39y=VOSaXxqr(o& z19mx3=4pmo0<06#<+~Q7Tw>#JoP*AuEgmtt?N0(V-cR(9X=&mO6NUD-JE=~wV9Oez zahGezFN8Ez#y~CqAm&b{@_SZ@ulI`2J^`g%p(`QrX3NH>xd>_V+Ak39@(kB?*ME`~ zoAeAQ)nwpyFp*J4nl;4cBOvyeVWHRuD2`R+XJ(#}lA%3VbaDe92|&{AclC)ifMdHQ6J|3_`%pNh$Ib(I;zTztrz2bjv zQA{Vc4`JD|sB^`g+E;(YpF-M)Zn3oJD+VBSlPUX=dyiIe`~{v*_F<+=oAY0)f(6(i z)%KlTDw|Z0YQ!`6rd;x0mw|Ks1z$w$JhVC5H?ym;0aLhi(3tRhd9?LP&x<9oXG#;L z#DK+ZMn57O4|}nTPaRY>=cE5n;9wl;7NFd~G2tj%=XRP%a~j7BJQPDS8m z0AVTh>_V@E1+-t0_^qoPCEQFJS8Ma(tawEox&i~{z5z^>wG!sU- zJT`TGc`!@7Ni!=qLnGO;n~X9eTPnB0dK6gAJ!?gkR{cV}P1mzA?5RuL9#73?>*Qcn zyPM&H4KXT&R~Z^6K6MIyBsa(f$Mgec8D`3#;Ne63lSuLCfy5aT4{2&lb2%(q6c#Zz zJj+Q&7H2K?#Hcl4p|=BrSVR;|a*W%x%7O`pSPX*rva$`3CVYm=%3I~0R z91?gu*TRlO-HNJ)x$APAOW9_tTgfF^?x#4B7h~@2%>L_s((3}0pu~HT)mSHqM8c!V zJeqzhk=!bQ9z`w8EBGsroFG^semX{_|3r%41mvhjgeZ=kRd=00n`s9)+b4-D;i*UT zU0bE&E|U}WV8Q0(et`x3;olFKtL8^0#*OuY8QhL!-RZVw$~xI@@H%>jAu?1TospWO z`R_XM^&OsaP;R8-Of<;>BAm%y%8aM<3!8*w7juHkzC*6i>Ns)59HEl6ZBAxm+41@MBm&N}lF1c2D1cp@hUE5} z=ZjH0;2fOJy2&0n98}38TTDdF$5ZM1cQfCU>2MUFg2J%bVAS-%9XjtAk zkzO*mxdXJ+ocP5fDaZEikwe;w6878 zw?$`1p}Go11(z}Jj#TVGedb0p&7biZx|~QbKHCld=LOPc!19=+d-W@0Y4aDLQ6URBpe2)uJq56a_cT&YgKj+;4L7w>Q9Lf{#Qg;e3f=IAA zTpDI|)=l>3TOZycg@XB6jtv|&jnd1@jiGc%2cd@3H_FN z%MOTNJy1(wO+hfMBmyX+#*C8aGG=K!Ay@Kw;S2Q~=SPO0MmNr@O=TSSITLlIk8AO! z@GzT3ga?62V2qpe$6%S43t6w`afd9O=41L}{mfa7O0t`HhXe~hQdl{(3&62oUG73C zq{IC=l;jkTh8rzA@hs#VE;jM9? zpqrbIkSeYysb0i^52KHy86gamd>sD1@-K1K?Sp%=CD_B#?!1Hk4N(|1ygLi+)CW(H zx}p|*KSAGb2rqFw89E1iu}{9^xZYBA2&{Y5goCa@4`FV!TbC_-1^ha7L>A6GuuDdY zb5wRRA~8q0R#zaP5&a~E@pLmWlP=68#fVd#z1bDBS~z^oF}4J^9DRfXIlmoo*^FFz zt(rf%;tZDvxnbm3FUkV=!5%7(ZbLP1sCHQn{-RXb8Nosh3;jS#dMKV_T6*wGm+-956r+8;|>`QPFNe{mf+!}YR*YG4%~Z7tZ0S*rfi#S ze?7p4Zk&p?WUH53(WKmO4iJkA*lTaGD{yiD&|{hHY^5@-^lsluRj-O!@KOwDnP!I` z+}c37pQEfLZF(p{skEK)LrrdR6M}cO&ebf{7MNRWnK9L!+@!uJJvRg4p1%bGa2BCx zIlIv=ZXVO09CtLGt!+AX>d8ncg_|No63TS2mZ<`bq&ge~8CI5a3B3i8jVzKhq2+C@ zDO;WWVQ%!EJQ)?>mrflHBfpboXXh%$Hs=)xEoEZbbPZ9+NTc1J3l`Z8k=>9lm zmPL=t{o%BElAl>`IeH;Mg@A?ZbuK)yBS1@A5uXQ8Z!5x8ayiyOD3VX#C7$U~#JqT@ zx)nP3{LQLEzi!jDCqpTTNB^W+1M5vV*lE+PfZwp;`5%&wjE+IhR|Z>Nsd^7&C|D8i zSn1aGjk-4+>~|zz&ueDP{AoB%d5_y|HxiPfAxAxy!6-pQD8)Y_dNt*AV{mbS+7i0Flg~Bc#WV+oLA=A;jRIs#nBZSvP zqwxoZkIN= z9SC3S))^|of;MVzZIqATPB_ob8b$*?53z&7)L~!XQr%91*N~pp>F|#Eq>Sn9(xv#T zQ2c{nZdW5NAJR-np?Wz4XzdP)3_&giGR&ySy#8#&<8~?{Fd~~Fc@>;Une?QXcV12oe9nh8T_)gOh!r<47UK z&U)P@;O(Mm=TM~~+D7vSk6ASBvb zighTZrA`R8IwDN`GYdXW7I~Zk`pSdcoWRn-8r9%gs^7V-Z1-gqagJ4X|1yUTyFaZb97rp8XJB7OH^OqpPxefD{K=& z0v;?u+^s9Q5Lk=(nB}c2|mR3DoRNePdz)WRfun8(H0P&B zhk9k|IHDSK8%yGS%7&Pn0yscimxLhA2+9Ph!pLr{Mcqy7upMl|NzzJ4LgF&)pveo_ z4LeN;#EcOz)65kf&vD>+ri<$1XKV+_cboK9-T zL}sz(7EeLrgrM?b@77oq#>NqSrvNAzeftzy*OdNVO zXCDIDSD0fMB#99cjjlK}@yJv*d7hBnN%J+EW*2sBjMf$=CjvP71O6JFR542wxH&?3 zzjjm)W~V3`&03W7LNbcP+77`IppN6c6_JsTgEQ)8F6nX+(`ctDWK!Oj$*`dl^!*bk zIFX6TNOUKz9Bm7+6D;m9?VBecl#6EY9k|gJ;i%hk6bLj23 z#6hfzRm6@(Iz91w1~_=cO8#=TpC?rSRaBd!V2pQV`- z$=&=#hv{4wVHl4e)(0ElGq$@%!(}^sDefcibeu%hw><88xH0?!s!QnbEICsa9}fK7l&}!}pRIqa%w!U}O;xj63gPM!M-GBXD*$E=lPg<2N? zr+C}2Ir&_*=n4!U<K)aC>-iXW;g;)@_A%Q7Dm~oFPXjC)NhIRETMSRy}xx`YO$D5J&|=gfC{M1xX5YQ&OR>7b1N& zj?tTKSjxiE0{Q82j_I;Da{Qw9)`M97lSvW-8!YOBoe7FlV&%glujWjp>M`G2176dSZ zBf<`=tVj+9s^n~_Y)bM1k4)OMW=Y%+hJL<8Mh`Mym^k26(+>Xd!d`%`v8h+4G80M^IY!rUR~u&B!#Wrh+2SeVKU z@`-#o2>Nno_^6OzDJ)oYttFKp#jmJonz`%VDTTe1Fl1NG?>~IRE^~kZReHh`{!>XM zx$57NsebYHvT);I#aBxC!QeQI0^yb%{+Fa2%sivqd>e{zI0lN*h|QoA=`)~+Cwqx= zBA79vB@OOmFz`jFm}k3x4`{WMGLBFq?w2BD?7*_IO=w9LX!Lnx8gTqWbVD?Z1ykD+ z?IoSy|3Q8ASt70X!XEj+h33&ojV&7el}9 zOVL{*6%LM;RP?s^P@LDsgEi4-`*KF__5hE}-&pOpRfa6wqp;S}EyJa*r{Xa%8)Vn8UuzvdL?PC7oL-pn&eMGq4T(CY*& z+^dq3?%D2@rF4Ub|7<(BjVd&g{_!*louwx?J1{Z)ZU>5Vvr9?=-l{c;3e>kpy(lOx z#Yw|Dj~RyhS@tt(C_~dujJy#r%wBQIbs*t#!Wio$6yfa)vOe=rd-MCMdVa+qkY^0d zDIZuac@`mQLHe2tU^jgJ5sEfOK9JlxRfmk{;JkV-0`PevJZ+%OVlm>*2%zSL3wIsA z?Loue@zN@WHG4QjLi}frU3nl-ymJ>`p&~X=>QmI>&>}J@3G`Y+o%1i`e!ietX&6Fe z;WQC1g^)JRJUMe_1CCv2QQNWM%#dBY-bE3i7lsXq{VQ%3u}mTr4F8a1XfANRO)cjW zoW&C!;|@e#I^jU1uq153pRv!}xagrm6rzV-NlhK+#1j35i$R#Ax6e!)5} z1Ukif^6HT~c+)AkR#`^(2{=9m*(wOIgb7zZEL-7wf=7P#jp!aWmsIZWI#Q6o5Fld2 z&k^{+#OD%zv_9MSrUPu0lJRh>FmCJW6J-S2f8R@SdWG!h$v zWzzii?5pZ8N!cseMMMq_taZUHiQhgfw3`@|ys$>l!^qMx1L76UN`E6b4p*vcFbf+& zir)(>-pG-Aue5{tImV7O_O_`$m9}N>24n)=LHbXQZ#Emh@SjtmaH#dyKK&BuW>^3H zn|ZX7;Znc=as2555ZkoMgVXwjAGoqdT}-DRDVow@&vewZP`>GV#!s5r2TbgPaIeF_O8g0(Lc)=+LFgNq8Ag~4#=-@L^|eLJgY)36Q-x%kz5K?Y3ReFF zJ&89lNm@s%*~ozHw&Srx~desdz+<9hN<qqZ}EP$Nhpk^7{oI~T;oK$~U$BS6wd0dXD zyE%qnD9k>Y;Z_f*@3Apb;{Fw%FhB1*qFdEA%f9R@~DH&*GBXB$07)|&rYPL#$ zf$k$p7K$48#vOm8p=9n_-@S+ckEaUM-JUAri_1YM4lTl6W-ZFaW4tLgs0i^ry0@Y) z%qGlR2@5xQ2Zy!6L?=mF3u+S2KG8=wmj$O_7Xh(^X+J1IkK~>MDPl|2>tk$cv?bW7 zbsLXG;+QFvxE9L9+uPcp;PuyM&q!Q9e+6C>o(R+z4n)h#8NHbk9w8{<_jSBh8l*s^7rY65>{T zDjSZ5aGsG0NQ}u~e7zaE09JmP9&iQ@ak-C!h!gV)H!08R3InRK-jKz@2|pEc z8tFt0j25+L{4aY+kU3Uz-$f7kG)-=bt6@7GPnt;2k6O_Mwk5h8bu}ps-Lcta&OcCES`28NE+Dm9dcBC8I*7 zPH&*qPsf-0rDzvly7o!Yn&^)w8gWf85MS!@g~J;H`j5YHa8XfhsQC?ISL4!BxPWMC zBP){I0o;s$X{Tz_dPb#PoCIvE$Uo1aDR! zL+M;2I@(nU13-&#R4yZJc;GGrKKkx$#mjr^3EguEJsPE^95MH7C5 zcu_B3g0s)9fE6(qDktuRh7DgCbmYKD5qw*xc~?11QbKV4A2^H8Lz!*W<}UN?{>ZS9 z7#dqs>&;nW@Y zKUUPeQ?=2#G%Lhdv1g*usY;DftS+q_y{!cbRvxPiBGfw!R?vb$NGrg{*zj_|~0WT}bPb}mHO{1t*`DEXp*ra$x%>?6Y3+0<(yws=b^a$F1OHf1~YAuO-PL5u(xwz3By4J6%n~$p}AhgrgMj#$sfLXv9!GCzY(8%0xZErPKY zB(oe5D#`0by8SMo-x+$Vt5i^68Ms&}Bugs>Z|c*^LmX~IAtGzeU*6i4t?3|CpB~K) zn@y6^7W5hhpqm#Eo8N|JgE=9uRf-wgLN`=yo+@-w1WTb7LhK_k^&1{k_p$Ed#_AiL z)Z_XvuNf0?H>h*fP$`^$z7i`wE>k6|8i}_69dr*RW_06oE^6nB%t{129;lT(kzVO5 z#n@dOXM*FQ-mo6sRo7D+Cn;{nAN9KqBb1-Tpc6e?(&Uj|$4&19Tmz2~Cb2}h#Uh}po}eOcFAa8y zBam>0OJJkz({Jw5cU(DAeTl^B93%+U6^!8us7lk9_^@)SYL`ymmyZrNf8 z<7||LP3mY9R3GVAno4B7JDS~?xBMvw#HeDoxcX=khGEjPm!$^Xr@H-nXq4P|a^|Tn zL%e~~6R8qh5=t@Fj1ro`;IX$^bw&usM^LPv(;rx-^q;KsQ;vJ)M`D#>LiW^Wtz`<> zOhx0M^t~#r*~f94u1SPg7=?l1eUlaPd?h}I;@SJuE$>QX<}coRqQ_5PSg)X6A>@bZ z2_~(IB+;!Id+Ax~fN>SBKQy8q|DcC^@hbs7^`0ejqcXcnE}3^QO@54np7#(|o z)=dJK5W)4FQb-~Io>Fm)io@od78l>zE3g;DRHbFK2RvAnvDxCJU{?68a;*ZWuziJo;liO8x3){p_D<;x6utfl3U7TT(?YGYJ^ zflrl54$`~;9^$jWCT-T7*05OKwIorR7*#6HY5x9U|{`F1&_O1oh1TAkg{5Gtd%_8Z@$ zZ&7F^!#@k~GoNm18rk~E-#|Ws%m?$AlM%ZlNo+HT z%*`*A*_Stsaz?AZF{^4Ll6ETt4Zl!vqr>v`<^B{nPml+Ma>q?!K*Ke>5(V)}oYrGP>m*&Ht(AO1#k$=`wTi zN}Dm8bd5C8LCI7;P04t*`9N3(SQk5u8eqi9bnvDkO%PUj!RC^O7OfLmlxwlsB7vn$ zNfc&;mmlBzT`vVXk41Lif&hVa_FLfI4UK4OwcQIdXp*tfEt^BBH7H`jpjrIOw;TrA z%`6y&aIS!h-sxfy2F#|61<3LG2eDV0;>a4VMw>;Lm)8a6c%A$(ew=#sxrb`8mm*^5 z(|I6Kr+(}nfWvQ@I(AjRg)hZ73h%8J{iC6G7i+;r9`vWS7_tWak^Z|k z@QAMK84hvz`~4_%sHlXajYLP3zkb_gt2&Z|iO#ybYy6z$zo~!^L46`*gc_k^iJcd8 zPX;$ks;wiGp>Xu(A9<4tCv1ka=?OL(mfGPSDz+eAyJfVDs!)JKaoMh-DU%@{(7@_< zl|p#yrx=>EVKKlR!!MnhFSq2-YEZg;fq5(58Wh4N?lDo|^%^x!A5gX{aDYTH+}_|U zK2zS`g%$iFMSbndaArn+lFDJAF+8#J%zqY44u4aw*Dz^y!RAgIDDbSu;N)TqA9r~?$?;&xg^U?6nQP8IDK_*A@Obl32x=_t2+yo!?QDiA(( z@quoJyoi|vdmu4Uqrr7)km_o%67_|n*wUw$rGeY{`@@JfozmU2;qcc8;AxeNO}<^H zLr5tm(Dg{yAVZFP(z8n>?joEG$zRq?%Z7D1QDJ7N#>u{xgP_4r4l&Kd z@I=y|9fG#2BtoZeQ1Ou6MGGE<#(f)K7C2BMVW0h5DWyhIcB=Z;G_GGYLIAo%qlYl! zE+2*zlctT9QmXO#Qu@V+%Jy2JIyjDLa{DU-mk#ZWq+@H%Qg~}1y*kpp%;00AgoF$6 zZx&Nl`jQ1K7Yr9kPS9>1F)d(J;e^!)DncI0tT>>kW61ZA`>htp)K`ZiKu-=H(4uhB|wBfrM0@AokFhGa{2t7OEg+mpmd-Ks1Id8dKCjG}WI%V`Z z=v;LwWrFmYzHf!FhM-4j5JZ{0oN;t-(@m(WL9}G^G7j}e)96(R*;A(F(e-NruDKk5 zYTVPKrd&iRQPt+rIChv%;gWNcAQAqPVX@b{HhlE)Jo)gf=ldFYCy7vLSy zY{J%frSunCY2#Vw`};1={95LdLu;X3krN8A!Wg+0#foLW&50~*M39?rgNqZ_y%sRT zy1@lb#*}3C#>d#Yszf0#^mR@FB~?3aP5U%o_9cQJb&~#NJ?lx4x)LO-Sni;h?%=sL*B;zEo7`zaK@YT}8LKM%)+yk&^l8fcs!7lBblU zs7~ST37iy9=ye}Tu%Pk(?K&P8#UJkN(Uiie6SU!cG}3;w=4lpC%-pEX=2HR56|4a~ z9L#(^dqPab>u{56B>i$7Fy)(uKax*5YeG3_xw&2?hFFl?JDO2t%DIn@q?%X;rq8@; zigTu}ST*pNN#emirDv(WDK6J?dy2=LvKE`}ME~=DKc~s>nW6t#*Su}V^C{YadZ~W| z!G$kS)iL80LnYJ#gh^=67FBHW)I1nANC~Smo+Y%@Al2G5p=d8(%8SV{NQK%u*$NNw zyk6G#7j%;)v1x>=jB~YtLz3jJQ+1K4WJ%fAVyjBM)DTuG22!qbwPMoGR2_>THs4kz ztRZ$eO13OME;NGbW|dYP_wnAtcLOPA1iN;!kUWvGfFZqe=6}Bnix8%oWH{`$A3QF0 z;Gr2%aTx&WxSm=D*WC(+&-4UJ2Am#$_V6|vSakuj+Qx*Ff(CqKabTAX+pd4YzJyMD z9GP=#z+#{(QH#KTl#`-uy}_7|5&TgSVInWbupA|<&gv+eY>@ z_vA;M3EsrAOJW4#m>PEfV(dW=_!9vZuB@WQ>Nsb41zVSbn}*)@iLt{L`!x~oM`qHm zb$)wBIE)Yf=Pz&zwaDOmdO|&#&E8CPKsi;p7$MqF`WVy_# zUu@N`Lpp?aKx$EH5#b-w;w_P*n z6lubVMXoqQGe|Lu1Wi9d8EkJ=!YWB9G^>?QU9D)wsof4+)Ekefxt&77 zws@Lql+$91tj;qgK=UubRnkFb%jKf+S;yYWpD#fv-3h8d>{ddRhAadmPpUQ_n9aiOqLUEl zgfVer8;XHqZX(l%|Ey^xEa&ZjS@0%SC>TiI4FhQcS796<1ceooS0Vbmd{<@JuM)rI zuECF^jI)vye!&#dtg3d#6kdQ<=jPUWOn8}@YS3>OYA z<4kBA7)nqFsEryHA}oUqxr(nopgG9{leTS->(x>yh-!XtXWyMLZDQ$wdqK>X$$tSg z{R5yMb-8#bB=dkxh)!7%0vJetC}4aY1<4he1qg*$zCXdbw_hZGjb93?=2(qwZ8#Hg z?$W))*rx=p?gP%REH*IQ?TDh@0)H;~ofCp&PW17#2T(^M`P1yre>dCnW1$5*P_=ux zJ1+uOMtGNju}6itDe|bC6kZsu<3?g1j|)2_=g;SuimoEm&{x6mao80Q`iH~jjX?M= zK~w{Tpy`}2W3bGifke+I>}6$bveNSXjrUV_$n<#;r{z8s`GgTs7KRv{oC(oHh?$!# zhn-bYJ4!&-+*x_uJ@F)wP9lmG^$Izw8&{?LJH5(1CEK$u|w8|d# zMgU3i&1$0hr8pTbU34sMZ&ujqs)j)l5P(_np4Z!Y`zKzcOG`vA*U+h1b66KwO{!Xx zl+>u=)Y#8LQzku*h&YT$NXKb|L>Gf;Yd_^KBCG0R`Y-4llX@IO!%E=-D_upbcz2zi zc^tki_hB)md(`W=O2VM8N(mqD=?<}43k_JSxP-S2%)isXLz0Xjjasi``WF`cvrcKS z6Wq<8Q62qS`(T&oy%vg}af#~~{|qkC`*zt*B738DW$s@|tvoo1ZYLa!ByF|Nog-QW8tquDUq%(QLj(k74aTDTLGb{8K6K)bE9A zhGH^w8l8I@PK96s2Vv|U1tf1+13v_eh{C;qbvPUHaAg#3YnK!H57j=LDEfP0;S&o? zd?*t`gcfMbXnu<$;LP$iBbbE)G0S!+=-I&Bg3gxh%0gK?zYfLGld!QM*k$JPjzP8e zeMo^Ut`hv}$qSUWUR>&>XQ4cr&O}~LgL*@NiDmxf-*FezREqj1#}b&PM{FC+%!AE7 zPRNBx8Hv*1DcXvsgT^CP;|@*%J3jOJXV0V=shE{z%yx_js|ILgCy2Np>H3tZ)S_Nl zq?l_6I#K5;*dGK_EHT38#*TI4Slrf|Q+xXUCpxI-Yc#Xypg=EA^V1p}Q-OMBf%Rv5vL5GMYZiM_i4or|36FOYD|2~iY1Jco zChT!gZl?WD|4{Mh2Dt=`Lbi1r#|u1)HL_f~;f&X!A+AOh*_ggH-72IM#yvJnXiwMz97oYixX73-y#KyK&f_Tr|$xc0z&zMLU*+hZ! zCOAT1wny?^feQ&bV#%G)3MNVCQ%XcWUl1=^dJ-lzC#=3vE>uWykzUw{^9p+@ zA{!SqH37^tC~qBSQ9G4;?~#4$tSsUC9U~O{JDTw4LZ+tO(^EaX%<^|m^diOKRr*Tv zdHpK&Df4)n=X!r7uR=1ArK{=S8+n0|J>bD5-eiLd+yiWr0bYEHOiWQM(wCG2D&|d` zE|8R4)_uDqS=9(700JuU8yDnG?EQ6gh(Y`MykSxe`!8frB6Q=J<<~P z4^-F;+OIH`h@gey`Uv4RD^75wvL69D^lR0zacLAoWQ*{~NDShQ(uudgc(6LB+sBm} zYg?4t#s@0eC7|3LT%e5*3kqS%sTj`}3%nlv0Br7YubxSH(L=1r-VtpoFO-!ldbzh; zd8FIwT+cDYx84(f%TcMb7d7u>9q&&+9|i-tyi7{U%EcZ51=p1F3z2^H|0tYEN$jX$ ze8mEq##N^3c33|tNY(!9Lj^imNoip_ox!o9d-X)Acseu?@8{V<-I5bukJM0%kVXwPO5FoC zAhxR{BsfkqJ#}CsLAd&tgxa$Vb%rB+R9_#VK3vR3k{IgBM~)nhfQ)f_tDd&5ModVa z`UV};X)9rz1O7*xn`1e@+ulFBg7iS%5Yk}`0%IjRm3Ra^-^WsADcO>bi}AB6B;GUW zn~42p%57{|aoDkvCjE2lBd#4+cFz#ovfXXbAtO7qVI-K~PiA+xfHEUpS;g>B4cIc` zHv@w{F#$%9a+pQVx0daaFga6dJm|Ec@*6kpWYR>69FSsGvFYLpDtAt9gt{QZSw~3; zFwfz}OaM|^XBO(j>{)@@OcywMGI+K0=}}rz)@KFTJI29)6j7_$jlj1 zI8rWAfEH|2-X4(@{d|&e@qC6$qN20LTVg1K(Zb7X1YbK`l$wautUP2-!xAz4_j+C5 z95~`)%MKV2A!-{gM1q*QX`iX{rvvXLxHH((9S34!9UNjvxJ9T#e0ax8P8<@RMu$m3 zcHmQ@RJDM8DFUvWP`F5l3zA+XqGf_#PQnj!9ivo+amfU>(^Ih@9ClqN(tBTw2r z^b`$^Pf6yWI9qrT-`#x6z!^BUFA0XjtaV7$7jy2*JZ&}V##~yCB4yJ-ai%y6uoOa$ z&H=(aAH2=*o8}!O>av2~{@WF$s3oHxlMd|-!AnD|6mb$VDjC?v$$%FQrbFre-1f4j6|Zr z_yM{LxZubE+LU5pt*t5dPOoOhaH_s~pF>@on=CvA$8%LTWKkWV_x(E`$+e~ztg!Pm z>cb(A+m2y+w)HMsj*fx(XTe856o6t$PvUd1CTqfxqD0c{;U#ksgMYQ@dc<}~d%RDe zIewX}Vx`-5HNeov-@+GkB9YA(@+54XKO5+@Hf7}q!-&_F+oOE>KQH;*Ch-l-*tio7 zaA&2*O6zKC(P+&8Z9tO0WN1@MZkpGsf*87R#|ysh8QKcPXRwtr)uQG#%i?HXD6yh$=iFQ!2eK5qE*NH ztakFSE{rt;L?1B{qO4X{`cre>L3!PVCk(|>z_O=7=$h!dN1oKI6!V#*eOj|K!sQRS zL<=2{En=jP2s4v?rk9CMlBY}<=L3Oj1Ds79jeClM;|d8W$*oL-43CLfoOJoEsjP0& zWYtQ!E{k_enyhP%q6w22=M>^0n+WvD8Mhi2<2Q@Kut`%2=q>94p`jx$pg(H*Um2}C z!WP`76#aYy}oXvuvlg=Od~bNK7|fkb)MxQ_oW$j3;on#99y| zCXU;g{t&GW&#Dd`0c;0ctUtVVZO%ziY#o)>7Qc}WWx?sm6|`zwl6VMHx!RXUu)TpF zx_`S497?qWuONEM)9$zY9$>%Ee2+`jY`b5Ar*ixIEz9sJh7E&zQrI2SxzG)!;E*Y8x;(7k1JZIVl`hy|V-n*4T9qTuK~wo%tB?=0n4$a?>4%Vlo?3 z&$}}?nV)ShoOsfT3w9y(+`&&lCp?72eSceZ0JH;pr<+AE@0$slrj`&jXA2d z45Vilpc7e1eT;#v7U;=9GG$b@_5oEi-?o;~pXh9_T(N|~R+|%JwT_Ib!s3xDF-gxh z;oG{6VO7Orh_Wf##mI(!62Lx&?8xFwQgGYFYkbZrdQvrHz*>tvJ-qG?V>fc~T_>4V!D3HibC$Pn`ZRPOqMi!$z=PDy~X(#4+P6hzWlJsWL5Dh z**>xFO_tW2O6H)6;8=C!R%7(S%?O=!mf{-6E%*E?#{v3n8mbUBgy+IJ%umLn_EQ+xCB0D9!V0&V z_4i&z`9{pY+kU@Tb;BDKcU7W|3Uq{IB_~_n3`Bzp#JDsylmi?=fJNOj3SMg3o4G?$ z@Cje)Sltflr$CaURuR>YM1?b)$|6z_;}zx8lY_(|8WBAdo4{b+F_!jDTmr|fWG2iY z&!wJ(dzlw24JT(JM&Glbk`1&UU+%iKXQ`9R&h5IIFhcX@oux@NkW--_62%L<`w zTv@cC5V^=oTHyl~^zITTMBoX-;FGn{noJtQFeDHzN~;o-@b$1;DXSRnOj>s=Wm~NA zAkm8D=;W$Y^+^Lr$23{uWGL9Tz+qj<@}=!s#$)xI*6)zWz|n@VmQlRkx}%en4%?r( zvx7c}Ra^m100<+K!nDYiI8YE#?hUbtw4y&t#1^Dye$<^C_N+uD@>w5MMt>RqYotlK zhQs3!KTPQZjS>wkun9YyZkkiInHN{39F@x9maq^{4j+V1BYC9q$($S!zNKnZx%WKU zWDngJm}rEzr2N4|$^t+a!0YvY8iQyyB6_tD?}j5y2*1`gLTD;yq3ERjwH2kI{lg3Q zCXeu5d;zU5%DJb~vJ6}F%yys>I+Aw6WS4CUbz`;(6-BRVQxy+dh8p2AMBXaU8~rKD zJSLf98M>AJoB-pkvasQ~DD${)vapwS z2Kl|k9BQIog;gsF>@yB{vKhTB(DbF=q*f2b32byrk?|xQ(~`Sv)oHLt7j$8Vd;vyf zuOJgXw>%lc1sa2_1uYisx6!O%N)hOT@iO?@a8^kNdCCJ%^hi6ylqXG@3D)9xLS)d` z*OGZH4KFy3*cgY;3@78J;w~ZDO~onQH)2}n&dzm6CFQ^x_qGppWL~LtiGi$q646mc znjmyT2cht^C z6$cNVP%VPfQ^U1<#K$yq6|HC6GRFW~qZy>8hv=_PQ#O#ryN?oPt=L#|E!S`B4NZe4 zA&jlPIJPeMej_@_!?-0Ji{-0yZyxr(Z+wGgT!dGStl*PO&(2LI& zQC!Vq;C<^42D79(GTL7i`S1l_VbFo*`K`$Vy7>NFHvZJV2uCx9TN#h(j5gHYX(QyF zT_?go2icm(iQ~ToMc(O^iP_N%+L70lJk3l*$AzTSj_4m_rfzsM_Hnk z>Au#9Pz`!Pwv^l||D>oUy*qZ8WJqJmy8Fu@=4v#bN2Q^zJX0MY(*cYY13D`zb6qe} zvYHNQXu63Y3>RYrcGu@^C0p*F7~)+f#9fej&`h;?g1Pd=)VAhE7!rD1M}0qeIu7s0 zGhRCOlHO#+n?&nNEEyHG`-ACQsO}i80ci8y;chz6v94GGGC7*@oN5b^^S7vRuD26TXh1}ZHGO+gq)@`4{g zfdMaasDcF<5W|X?5xJh22<>B_NR=Oq%%B97o0ME%)?x~(01j|iV#y3jP`S-=JuOjz z9-NR#k?Ug_@T5d&zx*CSZt#N-R^(b6Lx~dP`aL)yi=qNJz+nj@a(y39@`4{M0sWu| zk^Ktt7~vTr?AB}wwYHaBMXgPC8cY_o;1TpuHH3HU>=n5&<*ND&=(_m9zzm~}t6D8s zaD80G={-f1cA{7UDQ!`%&v8QXv=~tGv6aBJI=Nrn^Stjdvp3Rw?}GRKG%9%S@4f%` z{X+5-#WILZcYj48xf5lenHy^h`ldb=O+Z3!Hx<84X_SN|P6|*^|9iubRxfdCE^&{} zH%LhKJSVIA7d=H56icU)%L&*b{CMmEMGV74uCiZ)g0Sqdv?*(4Yu|_75Vt5f?c*<^ z(h`1{atT|)o*-d_q@!n4)AjdvrVp zeEU3b>|9wF@OO`KgI!M%_}yQz6q4_Io8DhY7E23I$@oFB?EcRCY3kAceGAE0bfo-= zGT7{mJwfzM_db;CIBeAU@V(5P=BYnVJ3W9VVa7`2REcDey{L+=xVGqx1F0FAn14@; z>3K1|9n2jbXcyT%&#O+Ja6%^Q%hP$Dl_5}HqP#DvN=ApUR9PLaTM7k38hyQJJSvePPqI9@;?b}Tm=o<`k}#vE#SI>fzD^#EzIdoW5TQk; zpwq>1=@>)(lnJQ1T(zWC!7^{eFEzJJ&L(= zU&uv#5y3piBYVuCHdnTbN00{ux9W0v&Jxd|oz=Vx@eB8Ch_b&JTiqrDk)R~3KFHw&x=P7O-6{YtS(orlzt#eE;4uS z`%@#$)4juVQm0$~7-a!q9rVrbG?~ahZ-TbCsB9(vv81=`vY{G3jv8%X5S0&`QL~A>fY< z|HFj7|CAsPg~j}b0zikbiGJwodN)d*zN;cEJzD3Uc~xfK7d^f$T&Ef(VNN_KP0ch7 zNTd>x0P5&K*g8mIjon(5B>UH=!9zHco|r&~E3B?lHS(~SZ#~-F;reTT_ubvSLrN&~ zF<(}f5ar${74$V;EF%i}i4leTP;urUtS(BntiCFdli-hkEed)vM9`BGOx4Vf8Z)NxJt|Jt8P#<=&bovzr%FMfPe~yQyUFZJ=+a_c zuX=-6i%gc0zNtnvR*xzYT~%3Cs!K*V^vb{5Wq{c69TZL|fX@^RXuu6l$JyF7997YpH_A)P_OVy4^H$A$qhx2ruXwe) z^65}jss^E|x$CrAuG6`o4p&FQoIub~s7%taCfCqaCD}erD~3*WHdXF!Uvpn;cU_Aq zDj@|;_CX*LmR&8?Euan;Z2n9ashH}bDz%In8n#_CCu|yB*`^iEfY$`M?3j-5LHytK zY*aj{=xR7jIb3vrdA{xPw9;J(@?qta0F(5w^J1>-^DtNTZFe;ol42zwvi%Tb`%X0N z;}{_y<{V?FKVt$Sa(i3Z(rh3syPChcaXP6q`w0hOY$Y1Paw^4|ru3Ste%LKjFU(c{ zyxrCiUG?KMja!b~Cz=sv*og4*4~Rq|fK}{juA)!J&ej3|=7FOG9j2h!Ux2wX1(CF~ z;w9L}Hl`pG#JFYgmb-Ack4EGCzR-Uh$94Y0T-k_YCSLzw zdXdQE3j3A-{}G}q`v4%))$HFEC0~?;DRH_gI%c~nb55|!msT?8m!6Xs7_qa_mAzvb znz~wNC$jHG+1gHr38>2sqh!q6pVVl`>0xdR%n8Ih-RinqJwyv0A9{E$*M&2=`x3 zN0RM(57U2`Ij`p7-oATa?%cQEH!bGQ9p_|~4F!wI!;P)f9T4uin!Cf$qa}B*LYTX; z%m4*D`_%;0S($BZ_ny14oFQ{g^m?^Y^EeOl#=h-gvUZq&{54tjY4i|+c_u-jK~7O& z084-VbP0a?hvEZ(ofRjYsH4+azcb$c7)k+13lON3HrEaL$mUWCPuw5+5kmz+$&QXchT2EwW9WyE5KZPIhHAS;9+N2@eSktiXUENp$!@(Oc` z%MU_;Tnj*k`sSe@+*}&^R?C%Is|@@srMHJhrCK9RyGsyWN*b}NK0ZaSGCIv7Es|L)34of zc}~laVjXLOB#Rw&H;l!W95q3by<}lKi?8>2hd=LfwYy7oUI^0Jg2=#iop;^~L5?~G zBZ6^lWI3BH({7o9V>pwH%e=NW4=3-3L-faw6+pP1k377m>pE_Tl3kBNu5uroI(vMC zaCE9&!olI8)8ivVyG@REUhdDY-A(W1>c5ZAA1utB@BJSz$%f4>hWKH<>vhZXo&{F{ z@xGk1A0rSXU`(cnq5~8vKNd;$ACzn)bLCA$&t#q81Z+MrL{OLSsN<^3f~&3xs9$Bd z>%G59Rk=#5wN{@fOQwn^D9X{inYpYS1g;3gjz3tKRB*f&D4C)^SO5ZnR98D$*L{zx ze7Y}nbVeVJh!eB`2Rf8&fv)^z5CFo0tA4Pc%$tF9S7**xc;TpJ3OsK#DWg~ZcSpFB z=lsdNFiD>`JBR$vLRvq?Ny*4EO%9FS(xms(oAjZp*Cbnh&M*6RNQf{&64{SxxMS(% zZY-OL))Q~h%C0#L^IJg^Dwi)gA(X5YVQ)pCbHd*I1NI2b|ve|jiJb0v7A&!`7nk4r+9{G)J zM0%r-Q@RnfsTZgcRZ^14Y__&h+IFcvt(Fs{vn~K-##sEKSz;I9Cb#OR&c&ufYE-II3ck_5BYH zVZRMo{(eQpb7)$AQdxb!`hG=Yecu9xw#oY5$5*cWtzh~49{h6U%3sP=-(OkyvNU(V z)hmBrzS#2TqN`dHQ}uoMB1Qgw&Kw&uSAB09%NHo}_cF`h3oU=3D}RqsFe{hLpV(;P ztD#^rI9jF2a{P@hjIeZi5+fqJyH4pq4ob54!iW|a@l(HWqKF&75w4^<#WSl&X_#Ds zBN&50PF0z%WQuCfet+*nWC?q4u6^dN{V#zg$3{u`56s=Ll z5f>v`mH=TkBMAgxLrW5p9$=U-N|MQ7Mie6rAtha$d+FecBW9a4aU1mP*qq#a-|_8^?e zGie9fCkat`ChdSFN%)dy(kq87LK%4`y^3&*5z^$D^g=?5@XIsl1qBW;!kcH(%ZeF! zCh>3u3=$Y5Fi2pKz#xG^0)qqw2@Db#Brr(kjq-$}eC_|e_wfpjZz0W=@0XK`kCU!$ z`979$B)l|A`rj96l=RW&70Nggc1J?{Wk?gbj5(0L9aERaKKDW#;9q|Q`rJ4J6Y%Ls z1CA^B3>`#31cEVs+@Id}@!nU_)qNp9LVn5={Zf^0{qml=2+JCqR}b(>SemT+R`jyX zYwqB`k8_(l_HPWGOPkjSA_z;FnCa9-Sk{1}IJ0rho%!YaVr%Z0z6O@B%`4w8MOwaZ z^Rl^5!qVLNfMAFLKM)vn$}sd88OY_W*wdP<8-BUN2=YgVu*{((!Vw8oOba!SzBgwGLMaPBvaev1y(C64 z+bq~n5qeL>3EZe{G@F?*`4EzE%l8Cstc2_>*_9+Sk3#*P_1 zFfUZsX5R9atGwl{+Z3f1C8L;87H{2d-kQ;W_yGmz0)jVu&y;l*_r2Zi?zT5%8TPSS z^{bWEc&Sva^v3fXnYt2}ouwx)RJuTr$?^xWghkv?3yne{`ho!ipO6r(i_?0~FneAc_nd3UULvi#N*;Cqd{#O}~lJd(&_7Ac}g5xK;9(gIK?-#NL9gusQ;;itc* z8>HfvX%v|z2@$2}NTx|eVPtXy+s}P<5VcQ*OE>H^3+XDULPOshNkI_#AZ2VKqBqN1Ck8@%Jf(ay$fMW&<%}V76yZrkfg$DQLQ;iDy$aO+5>~ZPH1cNM=96~ zU`9!nz+gLo6~U6gY;b@T!6wTZ0U?vYWH1>_Cd56$0?Ri}b!@fOR;pt{2B--ALAr4 zCysFGjnW$>@8xRk*4o^;U&&gdE9dI1qVDL?Cd+TO)+~5sP81<`(BlZnn+>djL>q|KI;cyd@{!sJQy zjn5B6qKNLfZ}~YicfOxG6oV$1Q~2^XTa6aQ4+L;CXSU3oZqA*_LhWvexjlCjohOg(BYf(Z#I6^aZNp0ku8B z1{*Ry05~Z*|Ao2Z**AeX_-7L{$LDKPh>}BJ6M25d>1nCfyZ+Y5h=&y`IUco^_6n&9 zq$cbY0SQW!WJ)`GUE_!i3aUUs6`3YcBwMjZ1zTh*>f{n!1xaKphLB6}Ku(T^ zv&IpxC(Dw#6De>rC(fi4P?388BTNFAKnVpMKD@3ftIFX6#3wL9T3ZqWo+U&)IZQxZ z4FJZ-yiANZ=Srng-Pi%IIFpXxB3Du8h6yKtJHX*xaff$tn1Je!5lWPR!w6Rn4zK&F z<+_@(TxYpdP0=s_J%WOyVFIG|0D1POIIHT)jo)js{JYv2`RE3vpAtlo6YK6qKoM8) z@R>oTMgf3a3LrPb1Z3;$*rTqAja3^|5E3|WNdckW1?3`i0vxmu$cZ~t06B3w zskPPuoZti|9H5C9Iv}{XxWJrVLYEfNE}1M=5EwMI{pRV4cRS8!$}Aqh5*a1|O>8jX zS{R?&Uz`#*lp6mO#jd`{%C;;q4PW)WOnZyK#Y{eWI zpMc8reH^cFd3@N~VEh42K%?4C@ePj=j&Y+P{XQR;aU?|LX_c@NuDJ@^uoYL~8?Q9; zoGDKx*%&L~&`Mb18vf~nNqS@T6@HArPhNz$_W6jBFjCXx;N`{i`0)#j%i|J!nQkr^ zjEGO-%s7kZoE|^e@*J4QEf4-l#93U0-^C#rX7v0bdJe@BbY%<@$rya$o2&4T&?KB0 ze`%F&8NcR^KYolK$0&(w6!S21Fw#$Ilrc_Xs_>VXC}UegN`gM7IEMBl8)u9&ev2Jr z&`1U@Ln~LS4#gSbzMYe0{J2}jkx<4LWU}z9ya-EG#u$H%tMCL`P|Y17{5?*x;H%ZF zslnMtA5UeBAE!8w@t3Lc#eTJUlMHe(mbKWz&L76#EnTt@CGUtYC4Kk`KmNuPUE!ZU z@t609tMJ#rpQ5A+bA^Li@;3@i7Cw0qesABy_~#8gy1>b}C5&Yp31QmgE=NL|T-HoU zYGOc&u1pMgx>|w0k28dHWmoX$#u;2iSJnrKP$&gg*+)qU``ebX)Y^24ayezwi4=26 zwWXkkCYPv~6G}9Y>C>3-Op9q|rqeOPQvU3m-upPlI{<0O*az0e zf%SWTAIrNVe_!grnKz%`e!7P}QT4b@J^a0Q@m=-3s$D{v?BA1|fkao|yXyNECPL5U z=kI4MF~`W?e?J3>k}o$Ocqbb2_xPTygf^OZ$>OW;ztfN?`8yGbB7ZOANN95m_2xM* zx9TeI-}CpfxdW3;qYW8mBIBPEKgk$>dBU@d--c`ki%Ht=PcKT=|NaD-+001Ku z001Bm42guI;czgH^H5R`6aWlyl1gw~G?NA+F^;1!3St-r5o8P?1^{A=F^ZX*GC=_7 zJvxb{C5np8=US*r-T1iNHXA6XA+?{X^aSFp_X@*4=C6@%S*f#xJ7isQ(_)uTo?z&Z z=*|rSN;VP;{M23S5@EQWRu>{qu*r1n8)A371%)MTcRF)QjIKn%H(~af%6o2g!o{#l zbO!c1GUQ~{*qUyEDx=NpGt5TFVRr;7&H&mgmz$_T90A%mK~XaYmfs@oM{K=d8whYv z8@4tZ^^WT)Qbl{;`KQ+G%s;hY-|U_yCue0)#esdb&uuyIECASJy+x_eOcEp&BOWuE2juX7PzPSy!_~TqkBDYpQ^Vz)L>(HW=|dtZmtu1d)!> zfg=?n%p#2gq_&PHp*%~{x!}SQipfdm_rs<(PmPa^dAe&#>aMODq;j>E+orLi{7p%nB7$!M z-~(}=Z_#V=zcHs^@+mRdtyplx!tA#~p!fhsm;ws^pEXR251x1V0x6DL z*y_}^Gbaz0_?x^mIgx0uz%Oc*NTU!y1H*|CkD>4}GV*^Mx3fipN~N4AISNgNScRi- z&u;NxQ=fc4X~YnIVk&3ScAZ;lO6e*gKK=&H?YR$e5p*vk2Er4G*M*FfFRcEQx)d@> zGvWeI*54<79Ybl%80UEj@A~TSx)k7l9mWPmAmD(xG7$h=Gl3~Zl$GLBVQ??5bP2SIwb8K)=8cZegQCxBWj?Yf4{kF@*9j!0{t=vZ83al?-Oe10lo!kJl+8E ztlk}S*ZNZ%s0X-WCU`Ic{ZaBrqQD0V(EbPAk=~uh6)sA9cpxycNn~fAW&WHbfZ&YL zN{R$u^3_KJf=7|uK2Bg1oeu7uL5C{H)|546X3-tsbzOEwQ3amk8&>~Ad)P;RG-&s% z@F0tT;xm@D#5A7bmhFr;1kRwbX&?Wux$m2aplp<5O0UbsAJ`#XJW<0xoR$QHCKLLz z$SmU&Snkjj%st;{0|>ITnrY1Si)7S=zR z3amVs2E+^%NHsS|iS3ymu(ze6t#E8F0L8Xpwm_QJX1%YK;(2>{_c87gH>~^fdQn*{ zFx~2%=X2A)JPgFa(4Mp$Uu9;Lk5AyaS7~d;K`;?hWBNfI7^3`sWw=xq#i8a$f64gj z;`)wAMR{SmhKqhSLklA2dS{P$8+HwQ^hvTsa|Zb(&D5l3@VPM>?*19K=G{2*z$dJR zn!W=&+MoF73zY>Sy;HbNzRtptotn}9faf&yBlkKXig|+uI+c$I5h_*tpYvYMt1>~qdgS0`mT4qg$qd_=mD!zGX!RoR2xUU zrI==VL7^);uYN%$q?J?bBhQwn83I6$r%)R0L_Qb*rihRt!a5ORt^dp>*!W&4@+|G6 z0QZm?taSFgmeOcag2|OWgaJgoanl1XYCGSF0uh^6CpR%Nm--Mk{2j)F9QkhXHzBV` zqm%6_G8qUD+jvSqFX=lCit!D=8(#$OpXKslI^$-1U|i?q&PmwBEp%siS3m2IAJ z=-bt_-7$63$;svj7$$&pW(7~aOrUYjC&@#KHK4H#XhS67O6JgI^O%#77n9bUBfR-G z#H?u0^nFlq7Yd=^7I#!xL|$N6(pVlhC+gH+N2?=z+6w7bHV05-7*t|YNwW1pC^oXZ z83QXjgAzJBR~S?|yHwl15q8+3u3X}68GQ>0cGqZ#kY2&-m24|JS}{5wvzLB}ceL>m zq}6CsVX7(mOBBM?JbFN-h1!w=0$zMS>{QzoV|qe`*uPuQHo2H6T_L9RGe zfxIpoM!TB4?8{yRODovw|9j3MQ@swsvtcDSpN#8hn|wDHjmxb~oTT&7Ht7$OyU0?b zH!kC)_?UTyGsTQns z4ud?K-N2AsG`lDZo0xM{z@eoU=>{EF|-9 zw_3hE7MKMjcyx~2Yq^J)s6D4H9De;a)j8Z-?T)9>x4WJM69_Di_?>@WIUtPpHGl7;!x(FTz z%nkAN70G+fFScuC*m0@>_|52US3}nWJ*J#OpZUd9{mSGd9S1ec$CbrQz>FD5uzrNJ z8ePaO>n;ZKI5~++j@AVc@b}Yd8aXWlb-U%LpBok!T;r#qKu%sKe!_`9o_lN%s2WqJ z%#DKP7RfpSSSN6xR?6i96%)|i%t4(X!L#`?B}W`U6w@t9KldmyAqpdgVuS-bSU9wg zTjp^GEHF64ftQh8p_lDbs|IV`!#JzU1F{3%W_sp33FXXU)`3)?m8#(B^9=N|-80WH zZU{yRhTVC#g~62P+WC%mX7_0h_69baWnMa2v(g8iD!X}J8;b`4Gv_aiVwpUAen_VG zuzAv`85bBRU-XkH${ceY2Gg|4?}6IDV?(@SK-XmXh1y8iQXYL&aqV!mI@)0)@)d2Zu-%?g;Mf-leh;k1!qj-tMlh!_`tifHw4mM2vF=+ekV{b{ zC8mr8b)rS-!vsBTA;LpofyFLcu;VG%TZ!fR2B{|DN`D!EmQ%2%hA@_5DH zrC<#JlDkLIL!Ff^NwWJT17Qa1x;5h-ESjZWg%C4yprDQ|C;sn}vYF!_${FUM}5# z!_!GzN!*`$9gnq6_yD3s_mW$)LLYP*0a&M7nNpEJP}aE-(Xn5;Xec#nZ1=Z5f@fEt z@+30B{xII+=d^SF`ezSnt3Ms~#g>76sWQ}bTV6DIZ1w7q0gaGd^DGtaZSWW9|5*Cr zK}Mk6pwL&84N~(}F4l|3+`(RFuI;;l3IMrOIV>4#lPRNG58=KGX7*1DVp7>Qq1w#;dX{CO68ue6HSTdZ|=F7-4f;# zzm?iPcVZpq$v81WH{?{i9n2M~iM%yu)jzZUuQ68I4cKAiUQ9J}Y^_5uSn}-H6K(ET zCz*8#OO*S`S#mME42yDDkS6O5OrO>`2SCw8t8?Yb1q}&vuJHlja2Z{e;{*iuFTw&wG$DzZ*L_BWpgwM5;W|L3F zfY4EOL;1t7v>TDKP#G&}VDpPh*K|(PTg&SigzCnQb_s7Z{@6EA4k$O$}GbsgZ) zG0Cu;Ew`x>VQ?)Uk?hI*tkOgeLK2k4{Ajw~ zyi)%shHE$_F2n6*2D6s88|iU4T@Iz-Rhly}UbUdoRg;PhfVKkwRH-msR_XUJYUI@4 ze4%7SbhGyjRbE-D6z!~CL-XcD&UKs0jQ)nd;zVO*(|)?Y=^Ek0n!(=;_hs z3c9Ax6iT*tO{+T%I5=>4$Q+Z1o6_Jnp^R2`YM-SjOPovo!OL<|DA`+8(K{K5wA0s5 zAhPMes$A@_zkWEcRU@$y7%Fkh$NZtf=5H+t)2`utW!^c{@!xlW_p+8w9=bso)dEWV z>pkWujXJS&NGlGGJwK{^VgD^TouE0CO3}vwYfd2M6zG#o&>gj+r1d`En8H?cmq(HY zQ2`6Bas=sv;5CXr@kZ|LpaY81HFa=}*?3yR!MCr}fd;%RJ&1ElAUReovzI8M0s$4* zQWmzZSy@swbVo1L+2cRSCfuSt04UKN(^g#nX!Vg_p{22|qiJOYOAd&+;==U+;IV@7 zZpokgV(|79RRUt-$%Biz$4Y|MWBt`*UYa09oBZ&#Z99Gl$3xl)IA{glvOO1CSDhlz zYF7!^EonyjJpkz=wBe$_$S4O|K6U|lFeelc@3mEkx**!J6+aeUm=*6iEnANB5e3H% z1dt8cr{jf9;~0IrGEX}z!G@$mpRjU0$phJjo<(nf>U?jEb9! zjZLWjHRhZ7Gi7JtPwt`)3)b%dWHjk4RG_hOK@8$gwmB~xVixmM7I|ccrlA(^|CTag z{_k^Cxyg^2&AVC^LoCmwrT$Yfc7#s>gkVMQ*dgK!cy9wRG_sL40EZd$dnvxh|CA6|Z{8K;V4rH0|Xm9zXkD42ORXwBgWI$ZME(4xbu-;8H`W_?rRK)C zr7I3CK$g4J8z?m77zzw4gX{vJ5J8L`TUS0rT+|i;y5}j_!X_mw$mO7x3MLsRTbepX zJJVD|-O(0n4=8Y8H`zmbQdDvsw{hycJ(cV=HF$*t=Ek|*o8+kLP4Qdrn{<;>Zv@nk zDxxmF{FSpZ2Ic|A)qo?C?GRzV#-&oqhdQS%oJ|^iYbR*LW_67rV-$!(#a3`unPr_u zGE5w{qa^|t0s{&x(PkAxKrz(AEQsag8&|Edu)^n7o48Al0OdUnG#A9NR!BZkq5Xwh3P^~3OLIE}k9!g03%sE=1~Bv6NEHMLUwO8D ztQ}RSp%0m2$nI!i_>`${?^=(1%Bb@A-wR%A^v?wjK;sKedW*@NWF z(?Cnrfl{$oqbrwg0@vtMbGdETcT&98XBMcU&{#yfGAD9C?@>fAme>l#K*+OzT)yLM zWZf+IMSd9jm*%6G2Afb;6h!_t@nV%YKE#yx8qM#3CMB z^nmy(-yGZtfFyXpEaO1JZ@k0cS4D(7pilOItV$PIGpIjahRu?v`6m?aDeYEM7nX*( z<9;X1>Q?T4EC9J^uQh}1lHA~zAeNW zR|Q_1-G-mt2WIlPn>!v3?OcpSX`5(=6|pTth!ngfqVS3KroXH{k~|Jp{|d%k#j5FS zqW^E0BYM7#OEc6$c7`-10aya3=5kc=V=sM|q1K5FQc#`A+)Y|8KvIZQS7|G*kD!Tm z8zl}#nT7my1nxVk%;k#IoMM}kdqu*6)Is; z8z3(PY{o;>iz{|%3w*dMj-&8Fks|pEsHr)T72<46(%zkeI-EMxuL^nL&^zNsZwD< zwQr(n!^_x6#2BlG5jnWNEXhhSSMvE;gZ4VL_CGE@`ZHIVm6qDo`^l0pa;?;9S0j zC&{SSB<371oIYtkVXa+{E&xI4NJHMi+EZ6qL9*PT8ETyvb8)Iq%{Z;2WUmPf6woa- z^`#?rILQmSiL5%4rzM&8;C|2*X*vx}6b6l5YLzWJX=qc{{Jogm!);7Yu#ELh`_$}p z@QeNygCFX;ccXI1a?SAcIml{Y&#d{~giV~KEAOv}VFRi_5loDGAYD9F&v9BKi_Vmz{+>B7$!crs2Fa`+g?v~&sdRFn-IyR)ozW|&S%RZ~i z+r==NVXVsHICo{qUmVdUhLzb+B&7yyoOoW%s36W{aczw~om?ViJg zvW+Svg`|^mS}HmSo4hX~@3E_5D(Bl97-W9+8IRx`eTL$>M51pG)rlm3x_bu`*AL z3qWk_gH*;}WhiJoMYW%oL>=2@m7e6Lm%g2>G)wYWm-cQXCQQ9qzDL_1Z9RT0s92%_ zb>l@hqXZ;TjI0cjp?U3Reic9BUhiQ4@@$5m!dA&4Uv&IbAOHwJm@4cT^=$RocIa-8 ziAy}OAEP(*!cyxC-ilr^5Pj`%p8je@CDOf)uAC{_;4wb?%M|d{kzp_>vmQ{oI1j=F z1qZ&7D8ChJK4O$uog3eO7mo2tKA|P>!B~npnp#5I%muI#44`?x!P|yDI z;C9~~6pz|OZnPZ5XM7`~eM8DPy7kE(-jqs{_=gl_w-2P3ywd=_wF+W( zrUMQ(5r{T%`2vGq)u>fH}p1$iA8-toww(z9#F&1;Hn60|3}w_@aiAQZACh zgv*$lf`lkzNT3^hhj$jnYJ2^h9~M%Jb>E26Bh4>|$b08^E^5di6|#k2K_BJ|X0-Y- zsVJh+vjK`gjBJ6!wjrq*QfACZO3D-(Mmh`UX*Msbk4FYuMIV!(%IoTmz%uB#YQ^np zi4JYwxEGe+prt6+n>iGNLUxTVkX#50<2V?8J|GT9}%H zh&wm2YuY`&Hzx`1J~=O0dR#MDUbz_{;|L!=`g_2F{aQG9a5!P$M(nyKBs{|8(iC1J zPG9{{pv8u`p{T;NrM?*Wl(R8CiPm+Q#dSfh6+N%HAeyIayV^s9m5!q;WJ_CE;L8m!+6yiKoB4!&Uyhl( z!7mY$CU|Qz(}X73Qfb9F-4gLxop~?TAZ_8QezT12BG-Gf6QIVC4;EP^Cla?n3qr-& z*C+E}*Tfz#*uCI*cpz7cV^2en6tm@cj7N3FL3?0TmHDu~M}GP##9>A2Ln`z)%v3Az zNyiVofV+)x*QnV4KkJ$#tlq6m08e~>Kt8#sotLRK3<>TYiXn2f3bO;Sz)=d2KLdA@ zF+B#RIfrC#b-W&mK)%pASn_g+0LeJ7RVhn$xcf;?{SQ15QMNlaaPJ!oyp*H*`h~>d zo8ZDah#%=}uY$W=#L21ZqNW`C1)5}v|H`_YNXLV&rL-lu^1lFZ?oQ0=X}2OsiJkCJ z#~<^9GM1sQ7s7oF%5)DqXxeCzZp#dKF%F(Iq1rUWm(ysQfgFgLhDzw4EnaaTQkQpy z=}nM_71T_I+Tb|oKEsE8o=xy0i#6owrjPE#njj9_?*_(eVC+SSbJtMlUc+k2Qq@mK zgXBJ&sFiJv$ofA%mlghqVA2LrQSQJduZvj9kzR|b--DReDJh9f;8X6tj4l#+4VKHy z$=H8hVV=Y-C%lW}utpQv6jO$&Zt~%srm+Pbh<6{6Rdw9yVl~GemJAeTTtiTzGBLWU zWh+8)!3i8Xs}r=A2NCML-0@a>@rmf6Eyeb(Ta4_$zotf8nWm#^Rr5?9bfc^(GW_tHV)xm<3(m((oJ?VDaM^ul;A*7u4{dIJ9pH-UC9tumLp8{Z}5 zmt2K$)%S>hu{#YDscksFDX1Ul61R*BhQnu#rI(Uwpy@(~Kl)W>=R( zuRZM(=lz&w4DGi;Tno_KpuG5E&D?>uA?~^R#Nd+R(|H^{y(Q?z1FzS6J2=X=vM0U58W;!*Jx}YW41Gp)4~U=x5V6ml&eJM^BY|hGSmB%PDp6Qj zb(ep(m&1Tynp{exldxa}nxkMl%Vv5@81xjdf~*zR7(;KP+AjRIB8P1uSy1n>%+~{@ z?zp-0+g;L=%IQFH8>z$(6}3ksI?kAxerNLsm9$THnI4AurpLq?6K3DWG9(S zq3t&=2&to#6zz7OAcjR2A_awh0TqH-{FBR7RiXhNhVqyYo6xx6BIR~y(A|Y7Nl`u< z9k>TOtk<=6trP;0z@1LV{Wlk4V8b1c8*aL$ds8VMyB;*<-RN+!hv;t#^8lB|_=SB| z4~w=%yGWj!p`--NbJ}7B6(bwa(EDpUf_cc0rtW(A=qs4`D~-W9{Vq#zo?@n`r*@8ACwgsbX74B}^hL z?}7R>RZtlS8B6GN9U0s9D4Sd+O}s!zR1f(}l-T7WL3wXP4oy$=mUUBwP~3$HaoLaW zYY{qTDp%GeM~76HC8bFN)FZ8ps(pVmTGi4h6YvloT$>cA zayEwvUtA+BCSK`R#!N)%-JHNpdY3G2Gi>*Rf=dq+A5KqAmW?)fM>nu-O!yh&JDSWe98^w?JS| zwx8{uY_r4AMgy?v1W-d8Ki?6XbAlfJ#yXECb-&c>U+-8GjRPGr#L>p3Tgs6FCJZBc zlHbc!pRn6+jlg0x!~UzD|8F)p<>OuHIfxRCO=So%&y zli@Wy zb>omb1D#t;!USB`>i%%3OXjsY4`eB3CIn3(3WRhJP479RR13?P`5CC{ z4q$2X0v*_zSfbAM=~~Xdq>ps})albX%DCYr31HAhDtVb@`(Y&Yr@8f?)^LoKD5pJrp-gCea71g7nAw6y#wBypc%xVIpD!k;(H7 zMDQ;_z)~Rr&rmcrHOXjHQ$CFc`lJ|Ds;#CCmtyS?jBFD;$UF+}+RWKD5BTvw+Z|_r z9}xVaN3sJRYLjN@rgRS4xSZf3ed_245G(mTplp4|DS@SzbaoGAP&O#Lg*Nn5zx{8n z7b-x9Ps>x0Q%qc?2$8`Oc<-Zd z6I+PhP-Mqtj`=V+u~ zCYAY5$=p560x~&rRn+N@M$0WV$cZ+hRSLy?G_Jq6JhgGderT`@chP5WHha$+O6QdX zaT2_kVwl+T2MYwxHTLo=n-LKF!3K~I3`(2Zdh==}LE~}U|9sYru_LlW= z%(Vnrtlol!=L{S<;O`jz*1hWs@{5O(uQFUNDW|FNFfU{ZE-N3KBzB~(~WkluwBN~ib zKe&%98E{$aeKg$1!Q-}i6gum8YEL5#`|>(=|ia=7OqVO{bLEQF@m4v`!@ z;N&0R-3^ir)0`Z4Rx_LE_iD$89gTuG$X=C}ME3bS(-kl_Kao+3dE=sT8C|4kF?hJx zZt*)GTyb75L~&}8(5*^Lz*H-t$TN)JM<%-}tw5ijMhi9+T>f1EI={xgC!^07n*V>O zPD9m+T3I`)tcje-b4;31Tj@j40X%CanRW9%S1c+*X!F3?T8E6^e`PN;xIXk+UHqM{ z#(sQboMLG_=`wF|V58*#-@HYz#YL;dC6GpE5#e~~Y9^!8ow60$0d_|-dyT~adUnR$bJZPRHopHt^ z6hC}~l76@V$GLHLTVQ-r-veeaftOE5pfV=wa2nFt~{mK|$j`m;u zv#Vr&l(tqs=1Am?2eo_QjhwXiYeR{DX9#A4r&^dYI^2l7kxaOE1t|Mza#bn27ULx7v9Mqn+Efipx^!X+jI`yfE(m3 zv5mxirS{9|cR4k0)nE!(?M_Ay$mDW$xEh~t4hTp@aA$3H0}J$lS<_w871#s|OsoYW zP;d5dvXKehAio$w|7Xj`-&dpFID@Sht}F7*~jYs`oOkYHgiRmvEbh-;sg zfujJIPpNzPdRf>=+Bq~hl>T!e@ue@%wig?KdiNj#dz)~1EM_}Ik?G^9v#Z(xGAR;H_9v--9HXB zw!@a(!ooBM_A}fw69AX5pcWf)4bV)5Kq_GHgVZ9dQhMeH>&PdNxsw^Rofv!I zen4`+jHpMw|Nmb$@ni=p8pUOM03oX$5BQ%i z!{_m3m#k-4U2XXUf5Hx^1%xoA$#$!B^K^z_^Xke849lV117YbAQf; z%C%RehKRYi#LB*8d^rVR4aN+yIv#cdvY#PGH_=6x4l1%Bl`ttQW9ne7OQmDKr-DP}^{7UQ=vC<^vbm&LBf|jq5r7rA@?D={kWgzitEG zNdVz63r|A3a6#-nv)8ieNq9ZIvE2gsIR?)X^_%;5yT~N-293(`z)275F|sN43vOY2 z_0~2y>T_c zf`geqd#}O?rEjI=esUL&f*q$Sf1bwDAtj`N6xk-F^qS>ZWhJW2 z&QO++8cbm=^8qXEUSKO`033;{y~cBMkKjWtJ-x&fM)$b~Ccs%zJDjJka5w9@R%0hW z&1@M9=oQrCcv{PBL$F86QON2NEN-;Xh3T=D!3|Sb#xxo{5vkaq(Nd4g%6F?hO2k&5 z6*O_8t8u4=lP!#Ji-hj+Nz<_+j^1Q#;K#i#tlxhB){eah?_%uD;~5S67t}2a zy_oUGT;leHCCbNi7SV{cw$V+OyT*~kY}nqAqfsDan~~4ttfQ{Rc`8PEDh55S7y~2e z7&$+Dbj^gqOoCFw&?01Zor^7K1;H$;KUte7qbT9eRKA*ZA=!@BO+`POaXe@n@bk+Q zcs*!@$v6CSy<@^uD59lzTVt2A?krfvTZd1jS8j)BlVW?&2FimOe$6pw3F~}&)+tc{ zPf$b#pjc8ElUPO6_tISllmfa}AQv7W6S6WVs-i|74ii~M7p+HJQ7*Djw#q@011+;y zq86&Qc~-cuk0slQHgxpQuKpxoxe5*^0u1zlXugd`I#oM&JLHsqX$grQ1C85w{G}90 z^{~%jNFhm#iMWfR{@Gu0U1@t)&l7~jiPbNoSX(oHsXHwhdllP_FQzH#GlN=O1RKV7 z3uwAi@vIRMMydF3mklb96uS1#xlW%Sd*M%0iKunW0Rn1`Qg8Nwap?QwVnZ)8iFP9_ zU=_POPiM!(V}Ff`z!~#UI7T1|7njAmw`8Cy#b+kKMtf-rRVP{+`};E^8G_M0GhE+@ z+f@$d@beUwq(GYSh-XXSU~!`HEE?-yM)--Z3&|K5VYYn>DqLfLKOBvR08m>FI_1k% zgoo8ss>z51CM%O^ilM+$h0RPc;o2l*AVFz{U(5d9OV?-u8b;_5w3nhX+M=am+K{$j zL*e1%5sT}Uh<;u`%n%u|3_9ej+QWo|)e);oP{N%(dOX?~OqnIz4P$&wJ0^=K;$VN2 z-d4nwoP*`oBr3EJ8mP9i{=AxNodF)B;UkE0LwL}_An1kJW_6M0NleNRw3t{nUh*Dm znT{X}d~Cw0A7m%o5+=|hav8&7KNwKx<)KH12~yW&0nUg#Ry%TY34dqGOjUk+PG(m` z)YHbi7%gW=SY*x$+^du;=(IoeBFz%9~lwWYNdQfljOLsz=*G zKq?N&d)8|dGlc^oOAgC_H*Z_@|BY+iXL zK5#kL0c(l`Tl3a?-nGLBBo;V?I*3u1WU{zyX91XEQ;@A^EF9tcwryc{rYXEGd>|d! zFY-Ja6lUrGP#0ukf7oqUhG4nen6_kE4AI(&%tS5Yifo7X8rEl&GP>NTwh^Fi&79Ev zt($gp{ED@y5(A39SaCNKry;4iUOY6%xt7mZ90TJ52}(U$sN*~ef~$1qb$6jE0H)%8T@5V zaE^(IvaPXqHksA&w7G1H?nHpMNnEq&8&Dss?@eaNjj~X#r>Mz1J7=u(gbtt}fFAES zRm6>RFbuGJFz_a56l+*y2)sE->o4uGLQoApcs7ZQhLraQ#06P)6Yu(jD7Zf$m?`^e z&SxDw18?6xOH3A5k%obeY3wYhl+>ey;PQSDJU2!eTmknLI6+#%ySy2228C9hdo;L8 zAQHNjL7xxvDYZgs5c|8+jI9H(aL3oG?{Q=0Pj+u~{%b};2{7U!;P(J1YG9-ccF9&@ z=J~={(a~jwe*f|kjhCd8MZe<(WiHuH7VLc~JNGR5s&?-oN~ z)H6rFL}QjbXhx-=x@8k8q^G2)z1{NiO69R1KD+!Nz~in=4VQ+SC^ukrDltU=q~;kaVZ5;H5DWgFfLa3S|! zv)}Hfn212Va-YXXL?hr^|Em3dd5 zCUMh^4UN=WV%`ksJp4ULMTu0dH*NLd7cyFE*LEdbw?L?X9M)PTV{eYCprM3)og6Ow zi`=5xq3SorADFH$YIH;s-JFRuEBff>;dpSA?$A8SZfx+;$w^OS#TYmOvaNa$Yuz^A z*AVr^IcQPqgW=d1cLZs(3S8V&43P)9N19VfO>j zfLEVU@s5t~co#mtPx=QUrC6Ut+?Pa5SX)rEzR*xAl|*y@mW;CX*2@n{bkJJN{Ovh% zS0v9{L8ZMj*LtQ0ZR#JxUz`X3%MNKy^VnOlzE=r^1JMEU!W;!g%kP^y_tAQ<89e#3A_B z-_Uh-zA7|xyxE@f*F!hy7`j@?-*b>I-#CMtz8l;AQw!+eZ+_=X#all1_Iy-gINV^B zVt<^GG=%-b#1p96wD-?pCXibW`bcPoYg62n*|6pQi#+wp1<-mzpG>C_B!%s;L8Be0 zZ0x9$>2FOuLtoG(;?VNecZ3wI|3jTeX5bsg7R^wrG%7PxU$@wDYzy{2lN_iJ3RlQ7 z?>sOn+}-u0NRr~~joStFpxK&Rd;3|c!Mr9GGa7&Xj&!|h$WFzOWaa&z>=o}M=1yyd~#6lkl*1A8YnbHCS z99|+6RyZz%ddX&zJ$1B-oK|xs-a-*m$6+Pj6JRD-+lQx)&5q5r#&3~ry|KW<$tgg& zX7;ws4L7nzM9UFg12f`qc#ep;3gU1)Si=4Rqn0)zZ)UcJ8dwUu4MUk7*25+BeDys> z@|${J5u4jQF%mg+W*?H?m{LbBfPSMAo%-Q;W`w&SsT076egKr5eLqX!3AHsz&*|MW z>SMN;wo%}2?R}xuQlZ+qkdbS5V~7czFfFjjcW%UWF%;vo4iV`zGD=n_Fw&f4ZNCFA z*52=(EyDqC7Qyl8!K~ofZab+PXv4#*=+TPG2|6mjo(Pc%}#h#Gva#ly_4b>>n^dpmE}u0qb{5C%5y`9(#| z?Z{`Lu@M8^?&HS90<00&25|ri=Q?MonZbYx=4)}TGojdr2Fd{MfLotrBqEA$qXNQ- z->_VOj98AEzLA<9HDDq;=l@#9Lhy5j%sD<#$qmLH4au+P`h(#!WG0jL!B$kOFO7>x zy-5mqz=<0(%Nq{^vb=S4Je{Arz1^_;2lA23Pox1wju~qpHLp8;XU#mE9byAQ zqa|&^^~S~rCdSCP5F<_(c(44JqabGI#W2Zi1?y{T^w9mCStx$>blQgn`dllc$pRF} zA}cHpfbjJR>^-=rKTreKcg>~~Rn{Qg8tf|)t^VVG5p3FCj;HS$9=89Vsz zpRf8k3aUKLk@J|48pci{=tEt&5yrB3*L=>o?=;Tq;`GssyB3rjm!*@Y#G$f1;?&Si z(M`1SR`GO@*_bE??zP{0&v0kr|pp%DQM-$=e8DAWRI@k(tFqq&i;m7ipitrp{{8g^tSiXqj=ux+_ z76Bfix&)gt;>_H8la3Ko+cP%q60JUZ*+{WM@!Wn~fscD5{W@e4o6k_-vo1dFqXC$o zF%l_QJY6AZ)UTr*dn)xW5n<#72+LtRHdZ9TK$n-<>T z7akMLGKCL7!X<(099mJl9z@0AiXzZQnPe|wo`(uqN65bp8`r2qO;|I%cbN!Hi>cz} z%UaZD!Hxa11VPY!gbbU(R8CH*1I+&a3=PnlxMav-$1b3It{gddtv{kqR^Bmx}lpK+3@aN&lMsovQJE5)Q{33e7fF56>xa zTr4`(5Wf0JL*i*l;VG@K2!}F}9L)@rqsYXpG{)p=$K)8OBjv3rhiH74yQ`IqvPe+n z6K$DyTigd0?9Yp~0P(~MDe9yZ5aTUZ}V?@+lm4E^xDvEjd*W9;DU5mRe2IdYt?{D z(WfyXs{upD<0+W9{)oI0wlR!Q9!RUj+ybvN0#&J%=yxR9m<_0A%7ZXX&9M-R0cP?0 zqfIRcjmrIg*^;d2VX>?Q4f@{qtSW)WJ{8{Y6r$tjJgTC5U%-D-qzszeIA8+9=7dgM zsBd@HkgjbZJ}-i&^CtWP4<4D4d=BT8??eJ@0jQ&?7W`oY$>gaXJLs{M!|LPVh$=pw{mk~m_0B>*ph zI~P&{y2I+7cY{*AfU=O8{MS~WP}Lq271E@3#e*w8JeD5Y3!@`jn6`BzJ|R>a9jKZX zA&^1nQ3U;*+{BY8=(e=R4l`e*Kke!v3d3br?l@{TDY~ZJ=!5`EkdCNbnE=!Ylc z@2qV5rKto!i@Onv2*1sazBv$3&$qR2mqhzOZGg5}x0lx7?EG=a2I2hbI&*+MM))^H zMV_&tmwMt(XT>a1#(Jmtov_&w_ahu9I;v?8@)sBYmy>A~w0x4zsDc6#7mXBa z;k106UR?(e4sLv8tjHDmFSlV8isuN+XI%R7QwdkjC~WLVsT`0%ksi~)ayE-0&D z1M72L!vfFX4bxG90uYJ_hP9U-Oz%ucfV-w=bDBmA8eripaW$tjJg`JShNMLoqPg(S z_OYkAwjPtPhd(=DIZ6OKR=eZ45CIfzvA`ca>%=ha+A3%K6|~`(SJ>9?-@s{i;32Nl zHh*m?S&ou;Wmn~hUwD(T2-;wj+Ay%$YdF@xn7#@hy-zK7$8N7=P6{2l&q$aG0kt~w zgU8KsM7Ddvx{(Qs3UpZF&2las^?e$B2F1}74)~X{1l{dkL0PIl%v5)mt&rBNg%L}q zRh=E81D*P8pY3e_0^T9AZ5Z(0NBP;g>k%;abxp!S2<;$6VoT^*2zHUsCSrLDtCkZQ zp=dDZnZMt>i(_&lm?(O$i7k^5i8tJdXv+_i)Sf7)>lf)#(Ny%i<2M9VtdS45BZOE0 z5g&blv#*8h=r8_WUhaycwzi~QRueaR5G73`kUTOEcDS`Tbkb>)w_ zBksh6JmM3vj1VAbSD|~E#+CJz9NLr&6}YMMnM~mzEgfO?ARn(`ve%n1Qo5*qE@_IQ zS>Nko8@FlQKsWEd2JG7W>E|`;OvZ})OaO}M1!~u1%R&RRfUJ=|?t*}itZQr%mZrTr zEd+KAscF+ZBug!H%AdqKqp-t_~oO^(3n`pf3BJ<6gYh*NVuz zKvs7BtJB~xfa@W@I6Si%Fql8Z!Qg4P4mR;HWRXz@okwm(JK1+O6ms6@Nu?LPWP3NU zW;Bz*&boSF2+xfsjsQWk2A#E{LQCS`op%X7OB@wl-yAGy z=PTE&f|RZ25r@^f{Z>5e@Yoip2tG5;&z=TE!&ivj z8`=>AGNQcAZVQLWQ;gU38I%P}kR*(imb~S|Xo?Li_1O6Rx_xlc4awY+!xWz?v!fQ% z7)SP@&e2_cSr=^mN`4eE={b2hWC5a>w@8)fRlSW6BL-LCyHyO8UVX(`TamoGc5YXy z70l&$QSIM(0~OwUcN_*PfKA>JEBSkNAv6n#UfnwhuxO_5zGws%qT7xO_0UnZpnV}B zctj`zL@2s7=(Ef#SkxKXz^*Q(f*gB1c$}g>lT!Fh;XDR98%2s1H*4xOU_&DlIWEVf zpBwlYaXis}Q%EU@yL^)t4($&+8NomMVGLn+Ikm-MYo}YunE6ZgftQ$JiUp`ZC)qYe zY(*aTg(s8@Y?Y%G>KCEG?+crtU#2{fqJ(`Ro(r+~(=ZRcY*CYemXb^tklxg);}4sy zJaCYwbWDa>|LQ;Pd!Bg6Ibd~;ncf-IS7ydVkIOCa*S-_US(RRQkc1hW92m9l3eLX0 z*bExAG*kK#b|E2kslz;eVLwG)_`nwIN&~7`3VK=~RI-{5m977m4|FOW;h;dqCg8ck z)G?6pF+AeiPZ-^ASNj4FM|iKvi*6l zPSb40V8kVD?{0fbDN~Y3266{g2fqgtTy2}>!mV4slDWG(_|x6JQc7hwu4=8dS?<14 z0_3NwmH4mYSK{c@ZQPy8?q024hjqb^CqJHS+h)5Z!8w_V7P`B;yP27pnYoQCDrz9E zrBwv&zR{i@SGUyG4qdXSIL_IF&ZvwQDs3Z~3e~;M;^-46lS2!f8F zxWFobgvIQSfYgDc4jdsw0*VN*KuNMA1|ZB2LLxxb4VFBK@=AcHE03PQU<}a4l}ArX zpu-4HIKaaQ5WMo}iZntSfT}BxuDH^41#R{+tSf}>_%*-DfBVBfRQTa|&AU&1YOYh? zj<<8%)&XHE9c4Mx1i{T6lldB!ChvD@ZF}DirBz{) zO0tWlF?IXY+I?D07Rwu!E;+VPQ|(FGw|zU@$x|ryn%|ldSRF~|f&grpboowop7Yiu z7DkEGLgQTi`SW_+lp#6Oyi6YArpUx&D}-h~2twV~+LdmWoBzpExOsB(X28U|BVnhC zPs43Mh7nNCAORFZaKenD(~(z;z(mSYY={XWco|c;IN}B`sVk3)q_`M-UHR=5Z0em07n`jo z%)r!@M^!{2x&ZX9JgVZ3FPAb^fy8#@Q573Nq8po17X8`XU=RO%&ga%GNz2l)lu}L> z$CfKaDWzC>O?!7J3d>t=A1T2Zq4i&S??9e21)mvlhv)5 zp84~UAn9f}&Kv3gf%C5hz&Ym>eWWXbvWI_qI8x4OI6FU451ZxVG2YGk zoX^_h&m4|^NAJsGOb?GUBp1mI`RV|H{8s}Yb9m+cFfX%c!{NL(t`LlbP8&)(IbR;_ z?q*75>KHr<`Ql-K+;a+6sorl3c0Vu-t#v(62J| zYej1H?soT84M#a+<{no3c(QuJm6^M;bO7d{0mu(zvLqjY{4QzFjdA3U-Q7KzhQ6qz ztYPKlh4s7wH#Ta{LaDmAOwN%mc{GK}{bAmk$&x>($8A%?dXTp2ELy2uuJ^Z?vXf+#x&D=&2|`Xec+XIk)urM{u*DkLw}5 z4Zdtt=5cH-DwK;L6dS5gwJ*S5nS#0i za9jwo1J1YOHgKo5I8CVw_rwjrlTE?ugH;2!Fm&KfR`l9b2N}klPn)AB?%VNsxv(v} z4ilWXDQnjRDclnmx^rx$4QK9&d*R#h?tX!j*XItL5R8-nY}h?<4s)Lxg4EbRV}rZX zd^-$wMR01k<|ER8NoRCczylkG!Hm~T0JyDZCWqHd0o-OX(O6x>qCM@Yy|POYc))6S z)YJ^1XGaXoJATyc5IZ7XtvkLQY5;F4nRwvA`e5Y09S6eGVCxPy`~YlT2M3$5)RN7G04?g?=gT^#6goisAkuDx^5+MIq zE09S6(lv`fbHGuxs{6%Vemga04yghVL48Dy^ejMAH^BDX>);w;n)xmRbc$0Sks~nu zMwt3R1E2_S#87wp*RFV1YCXsD<4w2b#A6(gqag~n&U9@$;|k+A8IoqcTXCr#qHw#r zH_mI^%xivSvan3n8I#pSEv+8<@H1*xW@~;{)LexgB7%uJb$6$$)ryHGlWjShyHj7S zR!lURZ2OV3(H~shx>zh`JC9N@7PBrkHkJCJRcwn`kdr84F*9OKT(Qpk_{43t{`m0) zab^{@u~-wYF=pl~Ds?1W8t!1~#ADvXg?cO~wnZ$+Rt}mhCmZMPlv0$hRx2i&OtuYa z>h%-A%ZZg>CZ{ z?1xMyljQ^fLSw7gDz-%|$Vn8m2@uAiNyua|Sxgp_i6F=j5n}Yml`A`(Zp|?obe+U# zEEbdDcwQY$#Hb8)8R|0BW3iY_`xeUDG{!_sN*Bk~q!7dgj~+H~YOq>0UM~Rf@$v(v znsKRE@WS{}sS64;mD;URySZGaq3e}_7HUh)CuCm#E(J~&`vgJfZAzQM=f20(2dFk@f?ObU{=E~Efl^ zGjJCyMJgp-{sh2Dw~em+h%l7f^lKW{JrLOnPazk|$QJ(=;*c$V8@@h#O1fRjTjD2o;;>B8%s+9=y|c))rOE35W}X1$?V*1|O#$-v{HYc$EO6zO z+i$4v0rjb`se9+Wf9K!R_EIQO0({5*k851T1R#Ikr@o!9SqNn2AR$qaQW_p4Bf?K$KslU19nx&6zJ z%w*$xu<@#w4dw3n%cC}`vazYcar>9&`x3&S1a4pB`MvFVn}NmApagyoK0o&jHB8EwNC{;B??Ex7 zfZz7*fHEMtAK&fUzS}->&T=eT=B}5J>GNAN;nDseBbwd-}imr_kCYYO-+sS?P7>0VAXH}b9nM1nxO^`R937!rK zWcAz(t~g}c+%(5GI!L$86b06>|y@oAapf=VhA$sN!eu0*UKma0V=`Q z>BpB<4oNe0%XE&T!3ULKq5f04j>62Z@@vi z<`?;f$m=l7R}WGK#_AL^WveIb z_K&bTKd0x_A!nL~s_+FllS2bl6WkJ$rWxC!pUTP}Mr&YIk-wybF-wtSpZodyFKz}sA&QqyxM`nh_gX4l= zON)z3cel0O*0$~MS*LPQwSX$CQmIroP_pOi;6fF1LBju?~1Hb)KIP!0w6vh23kF;0;l_i%iUnMZITzTc~n&m{f5;O6x4q@w67lD_ZQFcvn``a!=lw_lI3jt$<^IHl zI5hx!==YxUh;;9Xr}s`_r~}CNB+4F}%f0vQaNmOu^|`mtiAPhM+#6ROO_ALWq?SQ}bg5;J8}hc$pnM7^goWr{}~N?oXW9!+#P-?)gU^c^y#SJ_G7oe)(-4fA&+N zCtdtsh+>+5p`u9>F0Aa@?>vgxvQMw9f!S#8W2EixfDrI&iRO#Q7R^^1VZMguOD?5x zrRds9#kHS;gxR2O$s2!bTR?#=fo$1F1&uY=+MsJ~3T&jy)~v7ulsaS0O4cyy_U#RX z6ZPR$-)+(4Jxv4zX~;M$iDp=TZJaeZc$8Fk=e3uN6-4S{ca0u zeXv^%R@TirDdQkj$1)3}C-jQjwUlAN z-Tw-~NPIe#${wK98N12efFr6Fkg!eGt*$?^ZgL=bUJhLq9krV zXEa~kHw0?a#3V1pJz?^uz`?yq)+2 zj}D&CncPXNN+zo%M^uy4pULXyx-TGG(g+XmOi{vwZ>RD&101=2j;LYGB~6ecnjFz> zj>_$BSp&IsldX8d6@Ij!V3duzy->u}0e+x{* zd?tWmyUTdpO@+vWA|lxdbDkjbC#5{0z1`h?$6Lp@)fxKxWf`M$! z2b*NmomfU$J6*AHS!|-xH;KBiz!2c*G#1EwAz3R+#YqDK$Tjtdfuqx!yq4j#-g@9P zDo&emp+KY2$jGSR-3?xu6;?=Lg&!abFBYqXlQ@eeC(flC93U>ZTsmF%XZ)av4D?NP z93U1_&BRbEaaS2ZV+m)1reP_WsK1y1kB9N{>;qm%sntTC(ccrMUx0<2Nc3XX%q~j zG46bt1J??`(QDq!%yQ>6lV)o^1?o-+&k%2F>T$Vbpxn>dWX+eFhpFqdsW5SUJ>%2Z z3`9giW{Bb2ad-C_dKS?DPNGf#KHU4mHco6>!#1&#x*9rZzWTeF+}qvVRrq#12c#*R zuW7L~L53E#3n3<=&?z-59mrw3^J#6+cDP-dLVaD=btgZ;3w$7kkZx*X$O@fOvjRi_ z&qMFx`1XO6C7UbYNQvB1FNkUp5$*1tEhlO-Bt%G2L;w$`2yo?1#odN)#|!ZJ$gWoi zBN#L>#r0p|6LLff4h&&LgcLSotD~lk4B*fMdR95dh2pw;nVBM@rNxqC_kn zJb3Wf5kyfHGMu>nGM|tjmLy@q23Ed^QiAJ$V;Y?>iR`67;@2}i1qyZO(4oVG3JkF% z3e)w^@d=>-6dB+F60Uz|0M8|1lt|u?FiIPN+{wb7Ph%iqv#51vcqh;mDU>@uM-2k# zS4NRC>k&k04Vy)iD2dj1Y+o5=%F@_KJ$_}f=6ekbk1awY`N);Sd_SaX0#L9R1BvTz z;}ZgeQ4lZ?i-7`AWPk@*f>@G-i5eV{f&)W9>EYp+usP?7h|(s}NRfIrUrR6br%np6 zpvnifBJK#jlu-m3Xd%W3$Y=o?N2onvr?A!tNuXXJuvZUqa5fZ~G|I1%z9v|!pE z!IC59c4d?$7}!9~oV7BlSOV zjsW9!S4P=@3xK+QDMKlx^gHAlJRRAsX=&g{Y4-~WlawZJ=ueS~5rgY((j{vZgAhVT z_6cY~USQz`41_RSXU;H&#Tuqg^G3#x50?NYdE-M0;kx_Jj^~`>s%DeXkN}R7$p{ZS z$W-9&&zeDe1eLf~cXxMp>!*`MTC8NU?5kn`eqxM{C&o-MriS|dIMjEM{*g|M`IETPv2Vma;h!_@`!tNc zWh^~69n5ZJ4$?nst3GQ6nP2}KCY!r$Ha$Q9H9*S0!laK|-vRPQ30vS+u0SriQBQa; zKOCmckZ#rQ(8k9|?UGO(FkkiS|4_ev5Ibh;cp!Jaj@Uw5h;rF z*FWNKMI7pHzllfss~E$g&-UEuyBcHi9>%cflcYZ7!W^4!&C!M>MH!oMTQ%5n3*y-+ zkTNMXAkqoK!$6wp2=PMF45HX2q|AyHO*-;u3JnD5bgtxqn$88jII8K)u%?MlS81h{ z!@|lDKsqywL4uADlNpMxiMm%yZKV!^rjD`aO)|a+ft4bdDN{y5YO2mW(^J-OnQqpM z4CA!ujSuPKapz0vnn>i#8Z@`~!D*wl?pjxG@+{M{$eFJGK&oRNfc=wa_vh#5Cj&ZC zN?47AbT$eWVKz)+C%0#%VEz zxFurTej83MD1PFS+do~e9rX2p*T>LTDek=mp|hrWon^LopaG5@)J}N5zk_BF9+4yJmQZs@lZBC+^^okM+h3zerkGgDSLJ!<`7E9U zXNjh6_1owG962H`N#1ZAN4wpf$n!j6H$BP0CS#iZk;B2Q&)FIM8Tt|>GRE;CBuzIF zNy2XOpUFCj|E`2zd`_o%>gAGZ7=eoN#X4l_6nk*9Sggs0gu~-kiieZ>OKvD^hw= zr2=5az0ysF!nRT89vlE|h-iI!E@`&)C%6Tecyi9v&FV1kF*1h zFPpDTc8!|V+}yOS$%NT1EEu<6&TI}ko`zXZa(mlklhw99;Dt2ONWx~{#Zg9xiyP8r zG+8Vn&DiK|(O0yd2Sdx#V~nT3$Gw$oF%!$x)fFnD6J98WzL%bG7+OeLr_)zDoF>;T!e+ zT$cH|@%^WhlGBp;T7CZss9{6C{}eklnJ<{{KLs_6=lf4W^A*Ku=tRYd=u|XWhY2-Q zFH&ycQgq-_eBe^bI9bl!-`W#5zPzZcyX2rDl(W@>BP0?|Rt#aPgc(9PQ8&Wb`c^b5 zF!PM2?kCBeoy-Y!BHjKSob%5Q|Hw3CKT`Gr)6eU`@&l%tem0xs$76hWKFQP>@WC(l0Az_b)vjo^M5Q&>L z%tbqsIkWk*?@T)W>R*{}azvcW21TCWK(-`!Ysj>tftf{=lp!fZQe;w)Qog;cdX>@I z5%F-A06C)RvZANV^f3c)tt16jNF-MFy%N9&-4+~ z-xE$9_PQRgCzLwd$+}ym7*r)FRY{Ag)Wycu>5z~ol%Z$yo?QNqAC6>3%Pi7l83EcYw#DQP{r+FAbX1lzd_rmzx{3WcUALGuP25vRl<%Dj3{jo`I%j{54xB4wm#Ui_1e};r^H{E_1 zBf!zlX8l#RE8rQcER+aoM&pDi6WYWHje=4k!_wbRl~ACeq@~+GsoZ{AVh zF_bst%Qr_%$hU-0-Wz;jLV0b3^417h70T-(FDP$EB$PVdwU%NhlP)5F4U^kt0en0z zcZ%IKSCSx{eiLKSXZnZeona>Q=-Xz3JCZ8?lJnwF8}H+Rdrmq!>ZA zJA=Flm$8S31d~RFp>G8!OvGe|pkNevIc-4Pu+xS%L{%8cTfz7oUVamKbovi|C*sa?$niIloBpslOL_VoAdH2OYr zGG@9t^1y5jNF`v_s`P2cdiDffp8s3=SC#i-yO6Vl=T^h%1Tiy7>xiBs<_KP?k0c%^ zk@5ppMA`J$$5v$Q?5fap8V+L}3OFx6bl|KU$@OgNhYoejrD`)tFSy)e%r=4px)UFa zM~L$^lw&=}$Lm1?H2bP-z@5c@pxc*R#GOvO5+mqPNv>0~kE*4*6NQChDFp1^Bv*P7 zSM6f8A9tE0)7lA*R>TC%C&xZAd;ubbw<^AUURV5Q+s33G>@?m$?vRJN*@t)@Nw33-K| z~>0tGY+AbD-(S8TL%?rkPo{hfZIl48y`^6@-1lUhh#BBhX)!0O;md@Mu}z$cFOv zP%yOBzY8x`k`Ne&qSrhcs-Adn!qxl10;Y0*x#GHE0#yQ`tnRiC<@GZYzBG6#3yUtZ zSA07CtO_>UOln<`KA_i|rn*I`&w<2~_DPW~4LG1jFRlNDLEGB$A?RfXu2flQ3&X{r z++sMU^vRL%!nVWXh|!F%_&zT9nShBDHZF+GV_0B;6?)Zogl6P(-MlAgRDF@bi0!Lp zzg07bQX>>9w3u2$fSyB@38Aepbe=u@3tN04BtTU78==f2&(Hp+3oA0Z>{DpLKRWlg zun9HN<16&=4KfD!vAR^{H7mv{V7wc1efJAcN< z3?Ar{Px})IDg4;!W1`6ZLC5crf*_b$|4xy3ZS?(2&hUCU^bjA6QjBiugLf)ZP=X#zI)PUunRO$jY{<@r%Yt`NoJ-c%!#ST* zYkkAcx+agl!mOmW%-RCPf+^c;iQ!duhY;FlE``ho4U1@(=3~bX z+)ed*4Efn#0}h&xz{zqfha;^Jv1$B_W=6~y5(xZ(&CSA^1Q0oNqXAKf%K+UND1l%k z93#I?@-B4@8uSW!^PYVr9X)>}K;!WHVvvKFHNUPQpYk{YbbggHcpbdw4V>kUMS;BU zy%}KK*P+pj+Xb&?-iIKpXy201XTn?jl}GTi(`5zaicSVZRo6}nkGuk51*y#qn=N)M z4P|A7CL$aCIIyBXw@OQPgt+>QC9iv$B$@-Mc#P*ph4SwPl1(#%?gaB`p_<@$RBNCv z!9Ng;#-+L6XXA)rSyu#h3TFiy>YuD(JNvtr5imL!kl)NUag+|nmZ4I!O z@IYT36O4kf!kt_Di5lzE=!qG#U*7eU!5-28z=y~_3UtelPcAlHUvSvaIl3tZ zsSFCxuWOo@<6u^-tbCs8lFlXN06*!a$)5 zbKW^XGYMbzmNl&qyJ#vqikEVfeMi}R7928fi(VK3l?Q6z#Ax!{7$zup<7cZV01t~GXfj_R9WaA}vemGO3)pKKg z$75NyO`4Giyy&9J>#j-uxCvq8hSG)edoE5#+9hv!djz>iK}7l|GD0j{6DWD-Zy){T z@blWQ&5rl=+6$aG#8;&_w)z#~XwovUCaSG{&YzG4ArpoI+Q}=i@%{_#?F706>s>2U zgA*Zi==E60n)6zIRg|}}7o45csAqx;c8M(cEfv^dypR_65tMx=UZg3tQVUF&1F_D{ zG*3>^oKHj=TqwA<{1bd{MAqQd0}Rc^)=KTNXi?h4e44DHPxFK$OK^%~sv4o3b5>Jq z5Zw5l4kg<7gKj^^)GSpPf38#EA!VpyEU6uI1Vr7O96vh{^z<;U2pKQNE;@P|&d1`m zxGXi~X%eLQ&`aT^!dvc!Eo7#9h=@k=#>_$=V%2-GuBoLuW{lIFTxDZM6}&*To`9+y z-}u`Fb0z>{Uxhtp3pN;TDUf`(8xjqpeUR5!0Qu3wsg@JTaq2{38_2U?>2W_p{6=v! zM1(nA_J7!iSw{W2d{CIB!6omj4%~u?_lVORDKMYm5S zgaEGRAQcB17^k@M&GWC|X15u9KuH_Irh~M1bTxqX1*VN3m{{;B<&9^q$p#QXe8wJaBH-M z%fnPft8Eo`t|O8H(NSiss-d^JWnM6WwNI_KkAFeY$WcF+4rnspi7LonV2XS*WM()cb$GcdDm3?~{xhr#OZ@i~N@D)n! z?2h~oPhJ4$#|i651&MtKyQbE%PiM%ao&d8fqzo8kR4kx5#abH}IyyjL0ET{Kv!Pcuo*viEqd+fWz0iXp z=8T6X?s}~Pu7Udk$_t0l%T=;>?url$c<}QrX(zTF0O!f7`wf7((hl6ffRwK(LV@GJ zuWZPyIbmw9xE+ffx=B!Se}QY}oU!<-Vj8 zz{`Q-U`Lm2n7INa0MxBfv4p2IZALjAf&MIAmH|nFIlMZ=z6`YI5uYY0g3dx8Z=Jfl zvP8sx=M%ICjF^Jyjac4Utqj2hizBl1T?HJNkf@`;{T*?4Q*q`4@|!{EbU{U)_>zXC zDzo@~=sAC1X9n@}LhFseL5f}wI{J@|x%k<2pzOaPhVkFm{>e`U>eSg90f6S3VMCQV zb^HhM6@Xkr*h2A=qU(mXdF;WMgrSEyYsg|92O1!u8Dgvw$x5FE^iNf`2XyHplWGcQ ztf(Dpd;D&fDUT>LAgS9019rA5E8(7kH2Jh$rw24x-VF>rXmP3nL)vaj*m%Y~K3{By zg?$nG6drUJO5ym!xK4jh9LKk>u;V z2}_H6a7qW9p$cO9GVWn>q8r)L%gcoJQ^Xv?C%yv+>6da!asC6v%l>VY(AK}-(6QF! zHUv>&qmWHMJnnYG{hXE(y??HZA#*rdaI(kvs zL{RHZZ6D4gLu+L|IjN7u>uhDd3`*B%3iYgc+~~$W1$5OM8kB;!UZ?F>O+jt+X5<943)pWe)3-Gmwb_zdwyIPcbP!%|YY&XDGo?5?Li=&Mu?GVG!={8L4N}U^YLNsH; zd?7AW`;!p~>fckWPFMqp=<6Bt8%YiJs z5cX%S-`jc`m9{FE;1*ZAX^b!JkkIY}a#|KGAh7-lLOVz2T~;Uod%M3`5tkJY-?QvF z@9o_@EE{-&*$!nA>BYzS*Q{v3JDccG`c{=F7lN|8Y5u zgwiXzx1_JSIW~PrDNHq8fDZLmO(BuzVjx_>AQG(CD1&b64hGQ_M1rCfHoB?$%l6}y zY?t;_$}stPzy}#ZqsOM_JoXWTJn;Ntw140f7$Hu#4P*tl`|;2g7%G-3r78Vfs~_t=cdn@0LzZv zGaH`O{n>7{&OX*#B07c`JkdNx+G7_(nCzZC89^oO%d1SA@(*ORR=M)PL5n2sQV`1l zl7Zzlh_iQ2>B@4PdPg7oQUBkVgk00(dmNGqz%ZK+bRg3qEB2X-FA0?@87CLd;%z{tl3rpZh3M47QW1Do zS6Pug6DW_TO13b{B8N>L3#4|qmrZMLgx9hq6Nm|Ez*SlD=&WtHa1$*nW}r>CzoW;; zbZ!+S&X(CA*+mSz58-5tB(aUVrHzUNS%~{ed4PW(=$A+5uA3SM) zPm@c*_tF@B|eLy^rhOSB%I0LJZug`uY%EvDO8 zqsqHXSBra!CM2T_pk-czs3OQ)SL{e8Vtte<8z!S*6k+2xvjAz#i88cCUuFA%@su&d zCAs^nGLid`48LCJ3(Ah@G}~D6aGZpOqz7S(yk{ zr8xSgS?{W*P{IOUg?*`TjfQ5B z!T=g6{?hN%;AG!NSp#2(cOYZ=G<$$F1)zs(Wp;@pF$P$anb-`bw?ZJ?iwvSR$A}*} zSjm8Rnc?|f$1@CBIf9L_k$4X{iHy)p*mNW}cCxWs# zj3z8*PetS@hw!oX)H70nq7SrBD8`!1G5DV}L73+=QN&fcNLO&U@O_y?ub9VB zcQT2)G&+AWr{QbB1a%2o$2990(LPnYjG}!3S8JM^GU1!ze&dspG?SW*9=huCdS@u+`2H}pv-b;mkxx&PvrxuZtl(Rq))?i#! zj|dTyIngvG{UBUv2_)P{!Z`>M^m(?2e6wM0BNu6VC~C(kl@icbK4~$vqrOpaOQugd zWqh@OUiqBN7wsg(Cs1!PT*d`Z>PAN(P}o8VQfA*FG{2X+Bc&T5-G&H5F9bVa0Bbeq zEf}@l&{!|iKQtQRf38!o5aI$)KXr`Oi7E%uiXc4I7 z9b>f@C2hYtLDP}S_hjd&YQ0NQd2E*;_|pP#MuW#CP7#L=;pWI#4D@~GM))H3(kK?J za2GeFpAE!G%CC$hKyxF}i4iL{@|$msgGyKf83$HSAYSt6N5XiNRHiE?t%$1G4{6CZ z5%9IkDjq1choDRphxK3XyCugurfTTq5D`iE<^;3C4{DHJI-Q)3VoCloh!hfGzt>zB zn9Rcax|1ww6Qm-98dzYMV zXPlF>l^SCMk*Ii!(E;?P95-^`pO;A#lo+jip41-|_FRUg<#T&f?5XJ5(vxu6pYKS6 zBXpYy8BJ8&RN=*Q$ zu7GpRBrn zY%!?T9}M{(_T?OwVN};b6ki6!3LDfpm9Dh(D7XTFN7{8SDOWY6eYK>W{dgZcU)5(vhXUA@sO8bQO>*&IDj1L@!tO z!li!d9a}ddnPZF!y_^_va1%JTKh74;$rXv{lv5`r499~t^LL?UUwIi&%TM{6PJ0Av z2gGC3>PLSrDiMhgLEMw12g!NTI$m`seP4OplaICe34y{_YTmli%qu9|Zd`fRGT-!B z@cjBHLm;^F)V>Ra+S7o1vnJeS_1q|*IsHq(opipbS*G?@;J?uI(q-U21|4O^ka8JS z+QfN<2?HG>Ve^U#jbNbBMFKC%cn%1Y;SFEANr|6je^A^)%MBBoWgcm#1QIXB!9c!n z37zIwpEmu=Y&#+EikYY{?mM*oJf$G|YYkjg z&bnx(icb-JRFy_H#!-U#cQ42RkaMGs{H&5&oDtrvU>o!G^dK+5u2NfDRFwNYBYwf= z6mZf`Y+P1&D!Q`Dr49d=ymRB9R(2em#DzUmi|K|ik7k|Yj8Rwf?gLq;9+EzX2Qr1} zbOLHrdPv~55NbCFth6_T7jaO*(lq1NWk^YqSwo#g`yM;z$~5#3k-;6}K*u!0l)oQd zq3b{@40jR?uh6GF%fJz6WnM*baZp{MtQ;kj!WmMsnuzki5X96Xx}8t2(f35s zSzV}*A>%kFr@}rx^XyH(ZBVySL8l|eY=JtDX2z*5nd1iBdoFaUNyLdrd_5_$|2YH~ z6{Kk!5;E}TuA=}T0(-jxgQqhM8q?V!J?0Gv^$vozNA1IXRir_Pw`|?=!0&1pl^>;X zaiva=Qe$|QN*NZJACfR`Yhcm`W+$_3QOFiyfJZ23 zd=AE=-!{7>{k6L|I``%w-nmA3@9zxYzpU2|vtCKFUcxj5mDNR~y_PMyC~({OPhDXiW8wm%J^;%3qJZk#vPm z$#s+gO`yU?AX!lVzrxFU8g-qAJnARVfF|*PrNq-zA}#KQh}<;aU#Pl`cYCMgs>t$ zX2=ql!l7`d5a!i7yMw`XScwQk0^?gIB<^(o?==13U~BSROJKv^*lQKU_Sq0KR{iHq zqFM3UQ2)!sc?M;~e=DMzAEt%c&>0QGy6Yr{h5RqtTN`YXQs@x45sorucyIqNqmg|`%lQsh~8A;cwI~cvHKxN}1AZNoGV)k%j{k}In zuORJ-VohZ5S?}tnuYEhWs1*-Wx**#@A&{_Cg_V@rN7=P*x+E_1E5us@+yY(( z!8b1Q*mJAOIEV_xBWr4sAQmZGgke7<(ll*gW|w^+UXDh1?^w;8ktWvX8kLOC&B<5= z{78%2cy?ctY1eQ4FxuUjY@vTCmz(~~%#JyuB}TBI_AB^fHD%aRy#)vuGfM}nd~|;R z-!24TfK=?WC43uZ+}zv@%SJLAoZ}okGka0M#m5inubndPDpyYzes7kF@%V-+=$^4Fw2z~kiv|rj09)*F2$hLP*Ique~93;0Bqih4(kTjN>dZ!eG{jlmh zabEhSTsD{doYOvyooRBh^;?zYw!o3Sfk5^@CeKmg=1oO2jQVIo(E#^Gb$U8bhj*T0 zNXXlEX!h6#9Akuoy@TG7y#u*W_WJxrOISI)6Sm%V=21JrV>AMZ-&8=sdX75-kmxSq zGoU$Wf3PukbQ`(YcqLeR9ercv@CIkq7JM_EV(>e3H)Bi#Wrm0m|AX&6MRJX6q%vdM z&bZ}3weh^oZN-|fwDFxx2Q9^qo?Q{hnb3CC{$54S>Pq=Q$$1z~-3-iAu|Y$%Ms{00 z)2sT)$1~5J)Jh@HM5X=^#P1A{6o^k*meQH*ZVC^G+rL6FNbylMe<&=90-V5o(TLf}P8VwIXoz<)2PlK~&8L z!aF2xB7EP=YtcT;RD|VcFnX1z4}1C%-0>$ycE`UPExUmrI$%DGBO4z?hXWe?6-Z$n zAHJ|}3ma18`W4)*M!Fqd0-tup__+7KGJ57{^f%?6*{k)MU4(e018#PgLPbHW{DDxP zb*h{BzT1~`HpcZI>INDFKKdX-4iwp}YR?mNEZ{cD zf1)*EHDom|Il83&u*6|{r=?G*z?eK^j@{))ny2D6C*oU9R!g(x$?>G@x6CIH!|)}& zhQe0OgwDxrY;#zr7%*&<7>p|419T)z&fGY8JUAM8prm6R6c3o8CxYLF88Ds-yS05P zzm!5DqQv0~$y!dVJFGgw-kIm>RFcfjKJ}A<%mu=;>b*kvD(Shg23#c$?CIqrKqjLs z(~z`cE{=z-yH4#wdyc0j>^ssxoh1rq7p>;ZzpW3ryy&AOcx3(Iy0OD>R3yOD@r|#x zYmW80WhTNO{}u*L!(DYk2bF?b=wouJ?589f7vsLj&AwSp)sh1P>WX!sMSBG$d;vw- z?3$C+)B!}|ew-(!lX>6HrhVB4CN~+iNNy8?r$_iD(_PmAT6Z{0XcwrL@QcaAjpMx* zVAuyhh_3z&%8}0~5!5C1Tfp4@_M^2<;p6n07&<`_(R-h^OnU%bPr>E3G_(VH+*Qo3 zXLL>kU0l$cdBa`w3fw$$`c1u|Q-x;qvMO?=9?c3MXhf>dS^fk~^B`NriPlrA!Sw*) zl0JT%Kd=;WDtpv7VHg0r14OB#CJpM-V@?;;Lmz|`)rh*YGrhj90=;zeiENV0t{HKc z!sX7J#kf@GgbLtXov=l}1j zDJCtDu)4N$R5n6GgIfFIC85Ogo0pPIEEHY6b~FD&!=@6l2|}J%#sBZJnY-4A(lTflC7X7Niom z;fh(92E_~0(ps_pgW&d^;keCt<&}+u8LFPw6!g&qN6EeaaO*U2=Kx|3jK48Q7dH=ZZ=)#8K#4ka3sLyz zbYkJYnz84S=u1OA+}k3!p#FkFu=|h8-pO8FN`)wg5a$X&% zqfk2KH0MRnZ&$)?;p#pDo6A)W!a9M;Nr zZvk5&RTg$Bo~5=wspl=0>st(NiagVblJ#J}jCtnlOydD8E~2_VqMCOi$wq-jzi|OC zrBl__c5&{I+>m_A%ePbVo==S6SQ@1`JRSm-Q~wa&80ZDBTZ>h;hzZHsoj7XFZN~P! zC$U7-y=Pfz!;TazU*&@RtrQIkEtK&A6u8nG^$V!>;3E_Jp4nuXG}0DQ_1r@uiO_ z7xvvlGHuFVN#aDC*?U39XplV}C5T+*QGfa@4zHdiEKc0QRgj>Py)dIjRZuY}NUn5$2{ zoCJ4pg~C(CVrCq(wWokH>&qv&DT%&;pFrnF5+<8Wxh(Gaa!mpX(L2n?=e$cKI`jo_ zfFfRC6(r5xq}~32+BNiuM7<0=_4~Usiqt)KeaG5+;Oh+}=VMu~R^f@WduTPhgG$1}MC*JP!DOXDYTsZ>qjB9{$iN=)-3+|_J=Xj%0&eR6qTKSwI zQ(=0u`>Y;>$A%T(vw$%=525(batp^Z9k;mcy97X?;7l9&16s@3yPwa^jy+Bh{hUB)F$phSyTlEGCPP$&Jzz_L}J zU0tKQ-#)UrlaMNjp)!Vb?#sW%OAr}`O$*w4gI8d?|x7UweHTr<=2EA^qbwdQ| zHRFul+7pfVrvj24JKi@b_GLCE+aV6)is&N*t5=af@m8iyzT4tUAig*8BYCOE>PpNi zyte{B11+jyopf`p&int^k>dOX1L0vK=i^J2HkV|8zUhEc*n^FV08Bz1z)r5CQlYl_# zhdx+G*LG)rigJ$L;z%%UGulNiOno1CikyD9)4}rtvQ&}TjDAYY$0Z%pl?U3LeE`OTr zA~l{c7{X%>WwUuZTJ&eJA%WdqpK3YXl|}CyI~evK*qwXlh4VDZrml1wZZ)hYJ&RkW z-$nAfA)0k9i8#8j^JABc_I7c3&hMYv@?g|wnWzN8tDEZ;)hehinkrhEi6EMN-3QJK z*E>q2=UW0{W<~xDn1065DSPLYpJJDrwNYK%@%Ag7&W%{dmk{3+$-Dm%1NVBNvHj9{ zmCq0u1jmJXn8~6N1wFkhMs;`2a5ZUPWerLyrZLY%AWT)LmI7PeHm0e!4(osV%VlFH zaIvygCj#!@q83iQJn-*GvBy=_QIkL%mHPoO+^n;?Mg#0pSg?81xrRu{Sl7+SZhI+0 z$a8efk|VL2MFcl2iUfj_2^Onx0GE6gkQg3LG#yM@8qc({1M<@<-gRjW)LroAF0lei z;ajDX@oOq@nsQ5j=BVguLj4R-LgvctOs2$ImV`CWKbRgLb~%$a3?LbV$hXx)?H~-gOlR@8FChkOq7TW@e3wm{p^xBqkB68M z8KpCf-u=DnKNH>LQh;pG2)xq|S5;G+JoRd6j_mCcWfdZnmwxUwUBQ7C_W@Z6uW^!C z7~{Aqy8dzw zhCN1Kf*lG%c=(PG>ePAccps}8Qnqe#NT8(HKv3`E-uPP-ZdjoXu^*Wnn$tclSL|+` zMM@aq%xx&}XZVE-H0Gkm63#2CLz8O~?g7yQ=zy6IMH^+2k{N}$d|aWg0y23ZEIwS2 z+>HmpRBHhx{{^;KUoHto(J#a3jIxYk@i2&j8p?rF$==zYba3*U`u4wh)^R1l!Z*C@ z#Oj3a$+1vX0vEb`U&O$9Ti$hB4s3=s9*sWNh^z84bXbTB_FH-+vL$7*xukf zPa3uRR4laj)TNKh=6TG3B0NNC=@m#AScZ-gpcV`>JItJS4+uysfHa@`xHmvSu!)Zr zF(3#&!}AuA48C8`NB~$+6DS^SGiZ^8GQM{92F$cqT_#0KXN1_wR8qC;+h|--+>i_i zXskn&+?dCI4!g(D$l?7~EEjIscAPY6bfVY_)T3iCl8WnvW{_@|B1kWJOM`=q4z>5e zJ5G*TPUiDEINt;x#*#t?o2HGwae2E(lr*3)^0Q~IISzwjDoAXZs2T#n)Xn)lIKO%I zXs|B=k*n=qWaSyB5{%8bZ7u^fxY9)pJ9wpogr8G!7;wW|3AbCf+n7^6+nr_6c(DW+ znFa*52#A>{Uho+*eV9snV;$=(;7%S{^z)_`%~8vOgwcW35A26>lR&9LH{_ba*pXix zg1@xg(|Rl=&&JkR{Vj(xy;q*5jSZ?={bEr5tg%{btm5!ed_a>cuV-~pA`XlAb-s1R zUetv>(XK#uX|H%|GRJI)nSDx@<_rKa#5j)PDNKGCRX8yAYgiBe9XqmMH6*I~6UVnT z?xB#^0@U<2Jct+i1O>zY~cQWC|TGNR0b5pE1dq3ZaC z%Jt%8v0wyxcjVq-Rq&JuUz_v3#ITqkU4x0ft#0;#WjEOIKG?{UjMoZlS|YJ-YnQkF>vD?EMkt!vOKiqv z;NwOiP%Z(6S}zzgcOx=z*v3qp+1y$kBm=WVvNtmd;yTDT`i~HBnS8)dTa-c8tBAga zYIM*~S?p(D=VE`djHh4Slt1aN%8b&*N2t|^ap)V|AuU^Vb~)IumQhX4BrSNfM?ac0 zv(M`YPiA$RJG|S!to#)I#?J^7x>T10)rRAwAm&Yg#(Ja}J~`Reklqa?{j?pSSg~bt zb>9StJ|2-a=hu)`ZG2tctjYs9SW94s|03p`QTmwY5&IWyaHnB9F_iM4#|Uz?e~J?( zMJ^at!MHHwM8_QvGg8QBqi{lQ?_2TEI1640g_HDFOc&iylH#bM zsW!u;M3cGXQR^S9>Vq?beZZqJ*|_6>djQV%*yd7lYq_lGDc4c%-9J;O*FWvP7tsAy7vCFaC>M2z7;UJLH_&#g&Rcoq0q|1 zja)4QpGi?8(lnhTYaFk@zJQrhQOS5_3M{%WdaJ`p8t437u#T}-%#5y)ewDo~AS@V= z2=Ml%=GX7$Fn1Y*Yu3d4=5W!%a#2)qhc%(sLfZjC<4EC7oEaw&@_4m3kmjMAEOo@Z z&7O8QD5Lr`9^}-<&akwN;mL7agMfyf!jK*h9!v(1IJNdgwPA4Ack*rh3v1(qStv{d zxY>k*AMJ?-We8L4K;N<4e^7pBQ z&R3erJtfAku#w_J%A^hLc`d-Q)x%4d-qk>@Ks24LxXLL*JOHUcR=;fTB?rfY--$C| z7gy2-wy8$&d=m;Y8I%RU>Z1k)HF$beugW)XtS0(K9GbH@RZ#mb-+>@t! z=bR;hisiKK+4*|msHLM+QZ+eRUcKg;@I|V6;OkK+@{#P z<(EQ;Z6jsaINvf>qZ+4IC6Yz~LX-MvZikRcbhEeN?$l2dMz*TD-Kg<}bq#ec7aV zEJv4m4`-xr76LywAKeztwQ8yqS3`~>lHPb?07p_E-LBoQR+Uhv(M!;G1O-c*R}=;$ zC4w)Z15X;yu{7ZWE0{D}C+0&}Kjb*5qeSa&-#h;;R~zM*{B={{c8L9Om{K_{LzX!Y z&rsPg0!iM6lE_yV2%Pez@Pepm+1= z%%HMX9qto){Ii5f1USeR+L%)$Vw!-lgd5iA@!8amfIVVQ{uDrUWw;jGtn*<&h{(ka zSW`&-0qDP1G8QkM#~r*(6VR|%%3BC?r^XP;m={iy?mr0FKx-@3KvJp(kWi$w4;yV4 z)Qkl;03pg);`3~1nZZ?z!9B>xe`riSqs-uAv2%P)8&l}JI;1?ctP>;_eWkI1DxO_n zg_)OY{)&NAHNFxDP&ffp1zn5kDPCIFmp-9)D87*_uZ0Up+=Ue*ghNyK2ICC+@rIUL zXS{btQ82D_!^fNM$bF-lcUO`mI$%sQmwtfe5z!&% z>gVIX#@e3$6Ck+WnM<{Am5^6+Hlkmv`oHj*B5r*-i)IB~=#J!UJ+6n|nV%;9HJp6L zgct1_*QDJckiwcN`Vbm^wCTJXJFw|Q7l3|!qUoSY)SAVVJ(R980Xf}Ny^?vU0A=Tb zArRm6LvqS)TgS3hg-wW=q-K6y@bQf$Mp2V_}Qjs^q9&`U^V0Q9@lAFOE znFF)09k#|Oi1~BFJ zC@`C~U|whzP9910CK1zS{#T#aKLbry9nsMBBXP&criWtDwD^@cx+Er$<^$w4TZuqs zG(g}^D5bE_6?j08*WOF4!1Ete8Sxwj$U8_(g`^#*8+_^`9f~%3Niy(`Cf-1`*pVFo z?Q6@8m*0@Nl$tN>V0g9x#MfU6M;UY=FqRpU+j@0R@Ou%XW06Kjn|L+e8geun!v|o9 z#4f5c-2IOF%29Ja$|1urj+U?65A~kMia!5&2*>2r@|M14g$K>>aB~!_xq3HiO=97H zGtF-0lbkO&^x1q$L-kTe9qS<@*We0gmE`I zvp~Q|0PsFbtsKaqyUJJoW#gu(BdERlV!=Mc_SHq)JmyhdrFLgmRw`(tHtt4bJz!ce+Ryj zHK7*T5{~RA-5)(+@%Ky3U9K6Dnq9%=&=nN|rCBAt%{m8aA5tXL#w|c$1v7!p?Md(P zWU*~pgtR0FEZ2SQP!4^G(_PJ_pz27DK=*NA^?E9J{0Ie0POY3uCU2Ys16W#-Q86x8 z;Z;}^?V^ibQ&5>5tD1O(A}9{&w!oACHw(<;7jDi}Rm6fzNUB1$sim&>2Ea<Uv%^sx(@sOTov>OJT=mq6e+S}Vy)Ap{%82;YeckAy5 z>uBAL4g-%xUgAh&Kc-T++L#e-^t$Fk1x{eoBuviaGR@YBDWn{1|7Gb ziUbk=H$h0pg>NoSM8%isn^|N*+eRw*`^h~76B(PLYq+dT-i6%!s<*Q@EOS49V>jIZ zn$|iLJ3lQNi%#k5W^mDipPuSYKFmp(WxhVSHFX6?xq8rxV zx&No9(rh|((JNtIbnIaC8oI+RWAsX5o*e<;#)lk`4eV|*htXX74{R3mt)WD>J9jCp zR?DN<$6#bFW@O(%1~kKUP7n|kv`4_RQVx0wo-av<+B-i1U^dingGuZOf9#5vSRmdj z3_i(iJPcv3%i_x^o<_Usy;m+2dr)mMdiDF@>@Yk)ZEsDD4Gur}flJ$Ohs}i{dIXAA zD@1GhI>nV#3x*i1HjFP#4rMUW;D4QK06?0ao8NvxmA;69=7)j#Pb02w^6YfEDS@np z1cx@y@;3_&CXsj{T^hVlWlU6E_8|JyUgTU1*126YVC7%;J@cLB@|#%Qd@HJla8|8G zDjddTf{ghq`w!=DgN2JRzxA?*H-+#XOCf%MfK4mncpW)k)(XF4=j~LOh8M-4U&~pu z${9ZR=JMMgAb?l{k>w+~!SEZTn395ZVQUHTiQlO34E#@Ro@Xm4+QHxO@Nx7mKN8@I zp2<%QYQp&=+@UFS??<)#m&2xM+?i)Q`*4Fl_GIn#t1LKw`#yLoh}dsg=0x5rO$@O; zkKvtP;%lPP#`MC;Jx|w}gcMeWIo)zsm#id77A0jPpM|Iv&gVacfE;sPP8_OT71KO( zv|ccGQ1i!7vQA+ADIWTcp`kL~ukvF%XeZt&xby62S%*8ncQU);ZfqxeJpm^kKFs~A zu3!fb%l`&dS_N)qsm8S0`j-I({k!@ZvOv8VUow9%v<8IrluKjcHz!1Mt_iFx_@0r{ ztGV)ERSf(D( zvdk+RWF-_6u>F+xqu_Hq3;NtgGgYGdxG2q8qxF(r1tUSriui}10htqHnH53fjhX|X z>WyKZ%~8fi_LjO<`=VXaeKZAP`pV!7T*zbi+aI(;0VERGA=VLm&%O8y?>@cQ=i@1d z6;8qRL&x9`AVrYtU-`;9xyi>;Co9oB97y$ACE<1}%Lf%GYTo9+35r0?L$x`dD)t=# zCzysQpBh~+)I^ONtYSN(>)9`nr<|pfw>9Xg3eUDa8`o^ZDk9P<)Jfx^rQjJ+Ouirl zBg2fNOYbMrb#l!LH*U*NVjdFWgc(igz_OLso7F6(PV^T5OFx}1#)f>-;1!xu=mPZF2ZX*P_5z4IsV>U}) zxHHZ)mYRJYC3CJ~_Q8(EZ)zBxzqJq>>@kh67UzRMNUE+fca2WQ)@ zt{)Uf|`rR+zOH-4kf@I@rw}J$>xk&k0I3q#oh>Z7nu9K?}&LU1g&GP>C#+Ugp zf_Td^s9WMij?Ywc=t9uDJfiarcXGFFSPQ~x?JKP#19&A2@VmyN{kvZHUa>W@7HN=MZ4#4UluEqiCa6{|@4g0=#ybtJ3()p4dK+b_eDGs?% zB<~Sug|k|2XKZqIriNI}s=cU%yivE`qJUCwQlO!DtS*0F%~TD()}Y=0#kVbPNWh8& zN|vSTR8BTp>0X>nb|!%x-8~`sQR1X5+EmA{o~i@Lop|&I)j{i-r4i@^xk;zs@~JSI=4GHNq=cjpLE~q`5{0T zdqvCpEBlGRom&HwGu&WM!p2k*K4t>=z$Zlth74;angBt^HGr6bz=T3*0!j!J7oyMv z5PIhDlTz6RG2-=J=O?XzwX3Y#32K-oONxahG&vA58gHT|8=MoCHGgkuPIMk?z=$SA ziW_7Jkq8nJmem-93ORwzgol_a@)wQ82&j}vA;bPxhN(AY9-;it(QMDtefwDR zb|s5>`Eo}zIF#&@kL5~C+NM-owGq0b(_9{d|L6YMYqhGb(NJiR3(yHmMkIm&fwDwR zPLjM9o77|zXExBhnlxG``Fl^vMb!qPV!)jo(x&6LOje9jV&0@gcgCwUSZ0v3D zd@D@3yiQXNzHI3a-EB1$9R9*~>>2r5GUJ$g%jS4a7NXxY-j9a1GXve*%FlllL~1*2 zRti;PlcHk$uG5uG|2SW&Hu|Tbc4E;d#1VkgNl5G%;dzw2c?jV{82obO?ar-iO6l)75?YL3~BRbVs7;M<%^r9v9bdUlw+o>8Q2d#{w@^qd(4TN?EmeI75qd z59;{9y%bb1)+XY0yUoH50Nj0neJE7N5{cFD;E>{pD|%50x=0-1pIKI=D%DztbWm)3 z@Swzzu6~I%jnV#er(!HqF-WP^dO@6M8D9e>oc3=xuKaUbJ0eD92S%vKxfGwIfx>3X zNL#uTPMtN}kmGtJkw;K?^#>50`vy)&m6C{-6?Ky4{rO^{bOA`c7+IqAQ1nd9GD}l8 zw(oCem4}=%z(&-(@?3S3l|DXZ23(v23fUHrS|FNPNjfQPZq4E8HMAn8I2-n0Q1}Ht z>!2u8s_uMFS3erG>9MQ6saw!0ARdB1K!EPh%2-mOpNqizz!M@aA7mV}TDE@O#H;AI ziocE7wvk2%A!L&+x7-242ucZ{2tAw*^ViE!f1M6<)ezKQt^@PaUyi!Y%TcJqoDPHH zU_vCJcMBl7^`Xplxl7lzocnm#-tunyLX2zqD#vl0%cI9x6%M9z2Vy$s!f~8Swc*CK zeBL+jrmq6rg%i|$$P#xUH@(7s`g~w2?ecQgMzVNNshI`sjE#$tmV=4SV{^_q=R7?& z=a#Y7&GWoAGwt&?HF%$@)KrgG|lVAi;U_g-Wf>oXj(msMsJ$bM$`Pct4_zJ=i1jIf|qY z@;>~aUHTtVH!I234|3H<ywKencK1!TyWA zbJr=oQw`znU5AUk(&=9E?3M)#nxFzp<|<_#0=8$iNDeHjk#0qeNW{@H3^*W2w<@zW zTxxH=P%&#`cSx{*A_5J8(2b8TdG7sj_SMI38(|Fzbbg3Y#L;17PFZ_3K^yt`*rE>6 zPM>6ZhE*X=BbVZR@oR5DQ6ZUea~Imhg)5YFlsq6w~por5KJGUU>bQPS7ota=} z87OhFDHnU>Rt~&lC!_j;lH`$uZr#PPLxh@v!g&AM5}LR(wbT7}e-% zD{=sY(Gfg6uIPfYg{n&rBlch>T!YY@gZX?%#EGvou}6P?CW4Vg z4|IbQf@aO_=%>;oh&|qtRM9u7^+p~jQ3b=!HL1ritOh(rMxdr?n#~RZNLF|gLZi>o=cr&3FFr5)S@My%n_Pu1mzFldoxK1lW% zTe3?Vwp{M)^MSi)!yT@ScLPQMA=Ejw8?>9*RPzy;t6j|URI!b>M5PMRL4xzADn&;; zB&d9rJu&))Q=&BN3z_3POY`H=0}M5j;=zMCu{mYtjOSPx_O4>aIo2BmV zo+#9*xx`}!GRCaL%uHi~%Abtt)=E5xVvI4yxM@wm=2&H2 z)xq?{LC+#kDDTHSDu$S;Z80}Padv*kX|o8JEhb7#OcJ{3;^JZj5<6-YUF5h-Lxd*8 zOAv0TWmPm;xxjpJB{{p}0-y#<5P=St7%X}@h(W>=nip~AP`ei|UJL<4%Z#naimaZA ztPE$KAEyQb2}qEkRxbx0P^gMZc|WkHejo!1h7wM|1LG#vsXmM(P+>=m64sP^$33)1 z9Wgh)^u3666~Apt5}JrX(=^XBKz8k(mjeXkv^BG{M3=-+LKd*9qH42(iW@7axM6p@ zjoVCKs^yogdHXX-y7sDts39Nm(NDyoPlccjhv0@Z@X?j1_jA~GHUw{Y&W1L3^=S)` z!!gT9h^%fx1iSl8Me`AEpQSKS6wFm#rieJFCSs3Gi4rGdVhlwbBz$II-!tClCPoAi zdu%@%XdCaDca8VC!8eZgIf-Q5c%OSBPWL4$2ziK`fr!Js|ASpG_H=#|awYr?+vX09SX)Zs6 z;c^fl%-^1DLP=~vTabq2*>2;wP3u|8ba;@@02{?-bKEkM6C4hNGo$W7zUV4_2Kefi zxp1&ruUg)H9R7e^?k(SfHo66xghgc{BAO-R$&zF|G)o7??K5XR5rZqmI2OZC6cw{Omk+z zP;)*ri8$B*9>ybFz5-&8jS1Jp9vcwXwCmvvm!E-%qvQM^BrC`HJxJE-{3DVDo^M35 zaI|zdwVa<5ac-P1M6ztKW@^|L4yG;UVar7YUJfx_jh_4V@j%bLqup^`*Abz|0N?Ey z_i3lvJJ!H%5s6m7ZZVI|10;z3RqDUI&zGvGGAArfRj4m0uX*pUtLSs)z322xkDiL! zA@kmK<~MZqsadcsISjSNGEU z4d_bN`=I1>HvVK(+p4tpOP5wPq+hy9vpM~ejlFtzRgQf3?BhYxvW(-nc$3*sI|lgD zQ*fqKMNLU?{)9#4hcy#Hj9+wdUv%~AS}aM=0GPzKN2>x7FUCi5<&o6guxr|snANH{ zVNvC!Ms)cPj z!#+Vsi9!Sc@k0&hN>*3l@`V6m?WbFs0G?1k5NY^Y2VxCB)MA3DkxB@rxS4` z1i?`h$zmzpEJaV#dY0T!3(|&=(4$0?ayd$jlDQf0NxDSoxJli*IMW4|+arIHBon#hN*>vgPgiOvu{2Lo{JJO7bUs}eeV}_H zPPFmGMJEb95{$p0?CEYL66~HUDbm+P(2Y~N__;MVPWb}TjouBv@#88!?h8j&JP_mi zJ(q?Xr*MJgcHNPS;*Kf^A_-QwF@hoAcm!ocg7OHG2E;`Y5?>)%v3oQgE~Io17G;l> zN+c-%BB{!UvgfB;k_13T1hqg2iJ>Hjnkb^eLv%y_k&z0|(B&srHjzE8BWlPzKNrW1 zQ?jt&c3jGUxZvsH$}GzkIuKj3hj}7SyxgLVJ>6o70*fSlY?LlhUe)raoBH(lC|SZp z$|#Z*B`d}$TP(Sf=m;or$`(!BP)2cO5Ux=2k7P-f{DJ}c_8?dB(Gp+?H74D7pch2g zk*jY6HeJ4R^7s;7(_ zBTQVyX=NscePT8x!BFEEDGA00WhmIB&675k^^8Gd1}8=;g4j!+%xAzzgFVYu z3z#!7Y{&q^`+>z78>t)H4OZ$#>je%ChYT;6nVGeY+a_b+j<~|IGmi^^9Bx0R;tG4m zZF7P+VwjnknVFfHnLDhxO_NbLN=&T5QbtxVoOCcV_ngek%*@QpG}d5LMi84Dpts*N z+@672jx>@3^xIK)^rV%BtAl3i+%#3vrj3I&BpYx+13``rtFs#4d zNtqeLFpPF~(=v)_Fc?i~#}Y7vd3^+h92Oe&=0(k&nhPAa=Hf-ErwZ4{iBZIXyT03q! zuBWt48W;Pp6=pjcaL{0;;pG4U0GyxEsAechFo_&08*E>RYgRF~BpP7Qpd%$iiUu73 z@NU?WCdJV)V-FiBxq`RJj{!hCX6SDg(Wy*Kqb(uwva>)m@V|IV7wo#gU*)e zxKm_lQ#OJ1N()JV;iQEc=s?NIZCXa>oO7cDcu#l9Ms8D?nlfs1{sOEc%3RP100LAdjy;m+?_AaSv8 z$8GU`bld?GKyZ16+a3;Dzd21~W|}N!c6c|OXyiK>q8EH%14@xmY)%+TQ@j9!8Rp-< z;r-|dgBDL(iznUPlaT;GizXzgz{((r1VSYBBwc}vnIu<8LL%xdBF+xU>i!Pt{pk6{ z8#88n+>ME?n7GHY2TPKKslWswh^`<41$@*!WF%%RrZB>XZz!2~HEt+#y~h|_&-1QO z!u7C7qEve4{U}u;+z@rUuFCDYD%jw5SA^hpSGYQaDO4E2vnxe6`=!UcA9Mym=3+B7 z7sFnsFvZ25YQYqwET&8W24E-?g%p%Xp-L2r?r|r?Q=%{wnHh-@Cy=5BON!ux5=UIn zq9_cZl7&SMc$s(B1IawryJWbx{N*SL#UxHMXcH8l0zUP}m*#018DQf(=3ute6R+mTsI< zgesf`b-Qs&5xh{t2~+UgaD|>JRv`KeIB%R{1t~9lZd0L%!|%rkMI4;lr#6T!`t!tf z62(VR~=F(w`maZs8?;e+7)Uxgqn&pF|$%bDs-DB5xEHp#S0l=C!@MCe<^UA z8fInYC3BW#^I3N6J|q#z$}DS~Wj3Uj@90NFemO$4m?y##!&>ZO9}?u(AVEHzLS-Ts zDv~mV3hNPOg$;&%vp-}u^wQ(bAYdPQh&c0NuK*LAdjcN8jaqo%YPXRrA8vebFhBi; z`paK1Kb?gFCUrlNNfBp;+gj>ik~OuhB`bw2 zl|u7IvjJ}?g`#L8z@9IJ(b~SnmQ3nZ9}4zuv$;I*wQo1@wQKYp{Y+PUm{Owrkw5ZB z{%{ZNcDHJM;lF&SFLwPhm)GmKyuSX`cR^V`vhfFY)ppcoRYU4su2b)VI?P?{3rY^k z#_q%X6lwsXslZ{$yjXP=9&I zJ&gM5QO~K_F`MIZ82esj?@pfzdj@*dnDrqC^_M3gx_a0#(yK<|dKj_XKFVT`NT-ho z5NdRBu6mcg9BKH7&E5W^gPOryzQF+T2{I`=5jT6*nbopy9}k>;TMpc@1L15K$@L+% zZ=ZJlG)sp*(@oMY_C=N=c__N3s3N1llEg?dDbn;yGywZ3C6#|N@}!E%Wacvmv8JLz zQ-ZP?n?f8($$iol{iO}tDffBjK9_IbrjqmAb^6=({)_wk_Nn9$j@veRGOFAkJq$bn zvj>>s;D|Id1}hNa(nl`ArIu1^I#=$13lCEl5^xZg0tqqV^7*JAksf+Q@6jVIs+6aE z9G6m1$(7)c?ei+_UH3Lom1c9c&u_N$?K++J=<5FBZo1BP&%V5GH`(nkQ;GgYg4FcG zQ5W<0s6m1^mu@&B4%Twx$zlT%baTtvr6(K(N1;$)@);L3&0``|5S8x^lpJ~fj_Esm zX~AAi?_;BR?&B&xKKhDoiJ7l>Je7qcIKNqbB0*G7?S~ws*|5sY&HzEXa0Ln=oY0I? zN-3rE+A|^``j;k>wViGmrSz#Qb)%GOmqKxAze$pfexsXaE2T#PAvC#f&@F=yak9^p zd@_AhkwV}e+Gi0c1&kttu1q3ZM7jr}o?l``$(@oXNz*t~_u0|x5NV7^u(Qk-k>E|J z1CcnzZSHfq(Ys;Z?UPj^&Aj$WA#lxn_Q{(9yCt9e%+E&wy7Q=46Y0(q>6T0)SMxK8 zd*+uYu`;nFXhN}Fr0Il6Tlr)8AmzELfsbT-yIw2yA_``xo=Ydl%-B6KG<=WHUu z7a$4FzXVBe{-wza&`Zz@(ELl2Y|c5KLaNzA4&opp7ovz0r`&nT(=Gm$$W%mzB61dY zG8XRSDBQ_b+&Os&cb?@<58axHt8Ue}>Q5WSB3{y2yW_TI!_@6Lb&!3d$4w&5eD=BA zId4gcN^M2)R4F7yW4`_39IY_UVg)%0LZr3s&XTldBzC%$Yc$5q3l`%?WMXudq*VkdGAt%8u68n^3 zmStUnBPaZ1-54)P;^E=xKoh38lB1{sDNZ^1adJaGTH=O$Ma5=^NtULGR78SteqN|; zwOM^oAcGVYJ3ZI6)+wagNOe*!l9r=*Qt7!L?b?rw1m%f~s$Em%fIWL=nVX};Of}MA z@1En?oSR9`gz}26MS|L63 zs-q3rbFAuf0@#6ETFF;#%O zxO8)6(KY9cNmBL`BJLr3ZhZILA*pnM2pkoOIP%g4f{RNj?O<3zJz=48hdBbGJ7-lH z5Zqy`D$BkzciM-?YV2-*ESwB_wm&~e$ z)W6u*%WM7Xgo1fF)e_7XUG*)`zU+3uI!qoX&G%ymON02 z@!jVk62-iF9F#i+zV9lEq2bCj%Ik z7UjjuX% zaV7>5HPkLvcVraPic%?NawRj7JT3J8)KqWxFoQbJk4LGa9o?pTnN*~?i8$K(G{jZ}Dhwx;Z+LTWu+$4Y0!3=L-B??c1i20) z7E+}narJF%8qmG;9Pgb?*@)SQWuOgq3Kr?se#pEMR3bJ9237tC*-FVG-74KIkqsu1 z?>;UPU75wKlkTZhN;?9(Rge83K_OHV7b5NjU5u@!HaByg(w59zCkLdIS2}*C%d*K^ zN-6m-=g-KBtQJADGoPwt<5QJNB^^hS<2s&`<2vjP6dK>L&q2fH>>!!30fOM_ zGj`|u>N|g|@tGZa8%So3#Kv=Q+{XDfZhXe>>>$Z;Bs0&k@tN~y><$#RIWx~;cXp60 zag>3dpP!$fpP?v1L`6|ZqKK13#BouAd%VEBV@{)plVnsQW&k+uU|aI!&t-wv!ss%gSbcczLWv8I2y1L z%-ZA@Vtmo1eSEp+MWzWwnm+UFprnZlq$xZ|QIMD*At6ms0Z$ZM08w#*i5sStP*RH7 zJy)f4sAFd4QzEuhijF9iM!8Lg?hutCS()eBT+D(SZkJ_C5S4km4_WGwEFS7rV?(a! z<-kTNe!M9OHmU+KvxsS;(n-UeN78XAVy8Fs#jH)FiKjQtG+*JwlIEV>-OVA78}i^m zg$XGyAflTU01_{E@7+L5_(ug1=L@&FCVbR8T+^s`Ot(@=EW}oBc>JIq+q7IW{fF6( z`cy-Hn5#@y=Z8`0#5n3Pjyij$n`~&}Lgg=haYv}N1%6b3FOYa=q>*0f$IGYp#cL$N zA{12FBa@tWnNP)5=ATuatZImi+v|L<@!fuZy||1=SBx5uuK)HrFKhP~=J_NueZsqq&U?$p1K)ecE$`A>tSX1nO$So4QG(UBv^=}X`?R-w z+F61|Bq+VoXA@~8OKAp@%tV4lOvFKbw8K5vh*;BCL8R#{w_T|(x?X(I74t>c7G0<> zx+swx33eMvpBE%9@>Bz)C?~p-NJ$()`iJ8o z88)oBd>I?osB8=yf-r2#hJRthR6SX%m7G+QCF0qf6V&c@SFXIa0zdFG*IC`h>NBgq ze(=%t867sB!-l>6j0Lac8=s1AaM<{w%Vy?_ zF3Om#rJ?v5pZ&D^eTFnO!Bc^lV39moJ_8CSlBkG{>gy5G%NJeD6KSLlsuP#b&q>c+ zF3*5usd7-^kWrx`%SCeOrRmD-a!Bc@t2UL6>8G21x_l2hrOOK;(yf+DxqXwUB5KG# zSYUoWRdyTiQ)SkN9PcnsKy-ngMdEsNnY;;8y6IuP5)1dxf?3<;`3ua#JisgtK+j#? zLn*|Smmpvpyh|6Vo?cu&?=vFAh)5&PeVhWWVFJ|T$GnguBP-H~cB2PGMjH9HC?%DX zU6ZZJ=|&t}k-^M`Od!_q5NWz~BqA9JF>*wLec3@xA`+01*0h=uvP9*GW4heCi2G~1 z_E&fAR(Ns+aN`s#u(<58_U$jOwQtwq-fh>evt859Rj#s+o6p7u1b+y(>fxhG_BTD>IXp^n;ReA5pX6VaZey2fppqpQXT>t0s<(B8?OpvNB5c8Bo;H4?kg{c+| z%sr=(y&u)|C(q^1lvi9)`Rfm+O{U(joY>TXj2;f_gNoiphr-d1#^+*vr{ai}x%WOV zl3C7&x|4`oR8to}Hni<;F9M}dz(QXrG8qU!nJKcIa=(z#_6-;7bnhTuDj;M?7SqZL zRx}Z~Urom3S#7=HJF!3c7f*;N6puE~S3I`&HnCu3%}gCAJ{_#Q4Gyncawy0!N)jd` zTOO;?4n_4P1AcgDg)}D_eCx?Z7p)Bz5)_q_1uaIM|N>UY)ei#1o zPdvDKIF1Y&+wTX4jNLq_0}p4>4qXw-O2s48NC+p}$bwa}I*fLxnSE@_lxjq;lu07V z^V_(!GH%3_*lAx1a^(!S-uOUyvTjVXotLKsO$I&WAPb929(sZM2;onb>M6QOpQKqC z2WrPUHLV6Nuu#dJD`d%GZWlc8P!5|{Kd((lq4jy~8DXGRFO@1xyN=f!oXlHpUI};E z$xJEre7EO=rdVRxoYV?b(W26hRxfIJvgVlmGPKv}t2iUHu$(p2;8$(K;a+~lAEA9I zoK?yh6Lm19F86Jr)MVy8%xa~kHdU1ptB`0z`b|Fdtzo0<`~nS5Iy>4k$QOzluA4s225@tYl z06r3F!x?tVUuf?}#xy0+ z9Lbd8txM=2^?Y*CE)Fj5#2GZVqNx*(c<(0|{>Vu%w1!#K5MxAEO3!=9P(->_iX2na zu3<&KJwHmKU&|2+)H~Ykx9}0yO+fFp{3QGDbq1{fy=FaOAh~1Ux-f?OUdLc_zaT&p ziP^HxcQy~8cUiN(BD1UIPvs-sj{-+tPu@84y7LAriY%yJ7?ggwb2GNh zqc0GY2S}*)8K!>xaW0(|eBg({bwfm{L;E=%egpCu)oZTDjRAiJO-o2ByA#Mh&UZhq+z0Ovwu8iKm z5HxsaFA%^t9T@i7lj2CBmysbLNFqsk!#rw?$cQy~fplwLd89< zZq?3+FjR-|$c1ijyk%GhjEGwH2!mik3g_`s#+*IL@an|#kqSX4hO`!T^J&1j%0xhKbO;r?g}57(7HG=DsNJvVtrtfQ z4!ww{m;pdXlv$|{GA$48JAoNw-479ZxYpOb{>MgKt1y&@@3H2hM#N=>hcVhLux-wD- z2T6%C?#Q=wSaGeM z$7HbQ^-aeX`(%zvot`Do_&ui5*K{6Wr)`pcXyjvL`5)tm1tGRENb6(U`JKG%V;3k= zBABlqmF~lMlqGO~@k4CH+HwBl!$YTIeHrxE2nt^`VVG=2S`d z%nK2C7*p=YsR}`@5-dVvj2TKN0FO7 zu(TMqQvsDKJC5P0vmk;ZF7;bNUYyzb2h~-MXrNz#;FfyW6jc;5|y{6u^T4{W(GytC0mkQEda22bLG<1ceslXgH z!?LS|8=DkBW|vz5B%zX(`l-i0R8guK0HLAkOil48LyIDL@oERQ!?AX{3e2F^7*5jUJ~qzB`w!w>W{e~O+ydW%qg`N-rkFe8Esf9a&R+qe`-%?1?#%&151F3v;#f4 z#AB6s9SB_O7};HHJvU#vq+0QNdsypu7)f&$x;Uw?-a7I+bEs|F3~IBn5Uqr9wTSHN z3{5U^>EWiCEfI>P9F`c*{(rvCiQUZ%5vr?Xh;WRhimcg|JSGEf(%V~cNooy*q@)(H ziI(Er!%?XbS8RM@r-!sqKlKIUW%zIVPbP*>tt9z`#uk!=ws`%aET5H8$#uBGPng6=vRwk!X*^P*l%(2PwiW34H*ALJ z5(V*5OJK#4ba0DBIB|!J%(DRLUsL2gdG0P~&|*g|cQ8wMqiEEo7yAay*z{%4MjqCj zSfHE=ssqy_iHCec_T;-LD|NJKd#|U<~rsIOKT%w1ukF6nUQYAAB?Pr zjP!Z80tygO(v)%57-lKlVZu)=h_z!~H{*tHUKSr|i z{AUv2f3pClJdRuEB8BpZf!bZlwxHx{D1VhX!qXXUMrlMvpWRRwBnSA-wgN?7#@j`k zrHF6Iq;mYaL~#`@|Km(dL$gT?0*`4iTH|x;n*|aryzfZDxL{gi)kMH+kW%crHR8eK z$8>%*fG{~iLdQ6s6aVgSr{-4akg<4ncg`KJw=Xv1uwx?l#4k-p|J~G*_^(F#;Dp*f zrzQ24oGi*wj9dz>1(ZW1(;pJ|8IE>#h$DJWdHb^Z)beAZzMsj3I&YlxBGWl2RzY>9 zmhkZ+GLS(p*Lgm8=6S_Y4h9o`=gS|kEs`&qAisq-(gZ4LfqIeH(8hOptmudXggFB8 z`B`jRcCcyi(M92hD>1ghUiv2k4P^@9Q zOCSYHWlu}2si(kv-r3EdAx?AjsY2UR%-@8K3S5vnD%UFo26J$O z1QIo~R7cb&dV7!K>k0FKLR6pOY*IHfn7t={RoLGUe`__sABvWNiKLhMF)TtXIq$j; z)Q`Nb+aDPg`3`Q+o7AZKRymKwvN_7q@E&X8cK3)W5Fn@4PWGn>*-nQ`FV@pNGD){2Zw=}E>(v_(Uv$zK zo*ZFAWA?28v-&iwe%GJ%66vE2SHtr}H0`-W2BtAvmyXKPg4uos9PO1kC-#7f4l876 zS~<6Qk{xCqSQpKS_M%caCoDml!#?-9rs=eA_>Fk)JA@chj*PX4Yh{Pi_${#*4wqSN z#GPs`fD@^K9M~U3v^PJ`X+_S~@F*K09PlK^-OLnw{r9G-sVxw`W7I+!1#_iDh;2nZ zYqCvqas~oO2U42Dl-5^g4aBuIS?ecalQ#hBWn_!)xUDsTY3P=|jA(_+zUU4it>qR5 zKQo_a9a+i#Oh5i~u;G8mt}(+oX|+@r)2zEv8!R@`fL>!=DW?Ce4GMVTf~+D&rwoV5 z)H4FWk~L1m`PIegsgV$^F%dD-AkNpSZ70+oLha0ps7QGn(oGF1q9F^4A>)%6o^uF9A{x-;~&oBMpkdrm4Z5uj6qBhkt=POhWTfcxs8eYNdF-= z$w~M(`)?!9a{Ioo+mRJQeNx_x=9h}(y&c^}g2Cb7ug9Fis*$KV!q;)pcxgB!IX;$04p7Iu+=~Q_hO!h2}9iik=|V>~kD`+x}U2SbI7UhfU$VExJ(|3frfg+L2@{yEc~Rx#PMDa_81(Iqj)#alX!Aso{js63wMmZm zluJq$a>_VACW^@TlTl!Y;D3iLKclMrqw8eq4GaE{QG|Be@oCZE7N|u}66|AD1^uvq z-l!W0xq{7p^EN}N7&_!n*m!q8JGhA8*?LF}+A8QYqU=Y)aHw5A?FK%W4f)h);~B#U z>ytkBshO%;wPY1rY@dD8t#B4L=mh!FmAGw`{HR_aTLqe?FsYs3WH`vsw8mQ@l-Uv& zpc2nyp&0tx64)QPcR`)9rdVK96z{b+PRo5%bR_BoKr=Sc@2WzF6-x`A=DT3)@W;>w zF~qp!E>VSgw8>i!*;ZM{K~usu9|N&2kkHDz69~rr%*|^{=oMJ=3K{YT9ouYhg}$&( z<(ya@S?Wiz67$nS-sW|}oQ6ay#ybpmOXd_eb2@|edicKwYl)#m$Y_aT<4*nBRDf#n zAo?@q6LXz?CJPGu#eQRW#+7I0k%fqC%D6{+f(A6o%+f<@)jK+FnsAKoJQz>IG~)u! zL)n@!ygcZe#9q1hPLo@VUot(HbjQXFy<{5Sxzdx*ZlplXR5aBa?dF%dj&8d`6bP_? zQ2VL`W=Zs>R`gEi*ftBn#+$`E{AUq}7*P1IY_V)0>Lmi_T6AVphmdj0R)GE?qBG9l z0-K^U8Uy7uq|d~N><#MZu!Y9XpE)*yxLYpVo}b9p`p}p=94(yBfSXxjIvmDisM#zF zAlhUJISpP z)`e629DgZfY3L@ve*7A$O@#_VX`QrNDtQ*JQW*XrU9zSBz*E>03T?j8Tu*cM#0Ea| zSrZ}+c)t{hZfotR9eZ%lf+L;7N4N7QzfWf zJ&GlE{y`PeHB*o{11zm3;;Fzp9r8-uwD5ZG)4+ihFXp&7oFyfk2SVb_bX9@RF;FV? ze~s4n@s5^Ny~R0JW1}X$qgeL{F~ZQCQjl3L7Q-O$Rj@a)M~e-hEp-Uux78ENv>g~y zJ}YCBX}$X1R*irrSU7I(84%}GbO`UhU3p0h*F)ymfYu&m?x8hKmZ>tfw@%Z>)5`I- z@lutb0Fq@lQO_x*o^_=XgwPK+*`LKGlgmr#>Cy7-fRuMJ0?faS*Ki zfh!DHhjlF+F@hD|s+J_Ds+xqp2sqImex zFga0dxM}6~uwzK&Y~{#e0|kk_6xr_PttA$wDv0WO*5u`^!~NTdbIept#83d-4n-b2 zm&jD6Lk~A60OTtwPh_40oc~l$)#LG&F_>M|uCz~@huhh^Y4VQ^T4s%SlY{S@`>p5| zjJt{$ZiY=YCuefCGmC`4pmemI#v}%6bjLUPRYHD_8~(g1A`?1Y#ItfOn)Ig5Z+-zL zf;IL7aT_x5?|;*ir2djY_*pEy!(k`{fl&}-VNn`4%q4b%WmCL>84FXl5Q-pv_HG6> zsvwGs&3qYZ(R#3av(5hzelY8ae_j@4mBoKyywSANmA28WnV6Vd(r<8Jc41qB$fQ;P z2w4GmLEKTX@$%=P#Cnr8+lM-m+5@So>j?d7LbhG}MC`df`(2rKq{OsJ?zbZb*4Lk& zSnpQ)kkE;{F-ff390`PdVGp*dq%szeut2X-7g-$W(vC|vf%&!7UhcM218x^pR9=1- z>>H}NN`iqS3P^!jyU& z*po~`TCDrnCcUmJy1*cMaRa2r@yl? zO~wo)Pg_EVF~LbtSo2ckD=31WNZO*Vh-HcARHuprOG-@IMD83AAhS^imlp(C0z<n1&IXX$I8Px0y(GN zQ7Bw2LCDAG8KMYP7b0acI4Koy6dseIw3$_!m2|2ZFc}c|Fz(!|tV@AB32sL4Fc5_7 zVxVSG<5JZKeUIg*AipXd1P@_-Fk$wTri7vFrQ?;&*pv1%kTh&%B=gX@Uw$U+AZ^H4 zLhzhJ58{vy%7L3;iH}gFfHyu^D{+~@+}?tf?@_FU1%%){daU?vLGXqRvaqqqW^^ac zaIXco+>!c0EDlH?FGP65wu5uX@T*(+7o|vIZYP~YR)a(LuxU>pLzuw?32W+xFgr(K zhxGxRQsC|=)~pFJH-G4Pw`ZR84>p$zXFy8<1`DD*92u|#)2 z{wPB&3hI~3w6zRO$@F?zSc&oGR{6PKg+aXRUQ|GcpSebOSfJOb3+TOEoIpeH{iRT5 zbf=aVX@Z)tpXu}^!cV#bU#l+}ybt4{BdL*>3(#br z5!rKdo+y%N#eON34S*Ib_8Z!UfelDx)~*H4(&tkNv3+f^kbI=&H(gku{INT*ltI_D z4pu0TK&~X#P9y;|M|I$RW{_432cfsfqbN976%Mhbvpo4z3fUMSIsmZl>7AHBx8{o~ zgO`y*vS+J}hq8IYe>ZV9mmKj-dHhxZ*2iNDssSzn<^;D$D+y-bB@=IC%8z@+jDJ(8 z>G5~rdYPILZOOCnJl1syURoKWqTb$kH{d~K1DQrWksnk0^A{qIdP~tWCz)5^EY1>Sdg z!G(KMe2Ck$ov%A6%@ddA%U0xeR6jWTzp+*)+>hKreFWYk_R*a_Lsx4czmxi3(tMTH zAdgY?t(`I7aqHCJo_v&#xU7@?a1q)`F4uwg*}f$Ri(ZmLxuW11n+ zp~!{;C~L7FUQ|jhvR)P5@94`$h7)VVuC45RI|6F)K|Ch8?Cm*?shebv<}U@cZT|6l z5^=%J5a2D4{HY`fsFOj8VMIZiH32lAAmIou#iUEOPl00R4ZF1;ba_G$A8S`Rul%d3OzL{qO6R@pe>q z*%f|xcITjqN(ecAmJ_8-Wdw8u@W!1ILem|RYmORJ#<*YQ4c1dHWGSZ!A@~E!V2_MD z%B2y67yO(Fv)t(sKu@%G{8?WCFVGFzc4~y7*T7=l@&(%>@Nqvsh;B?Hq>kRdI8zd9 z1Q|*?SlEyboFnzUFZPX~BVbSYg}bXGa=9+96bmyTc{5z z9Qr7Oj+4_(xoR6|^-659>&b%pb+WK{7)6(zP~tU&a?<0|aE{|}px!D@Ig8d9r5-tV zqBa>Ch^f#fpsJ>}WP2B@x%F(1Ud|f9@C=(y_`)1dFG5i}s88cd!=1;7zb@P(G5B~W z>Myt?4KXL3gCDm021DgyWCI{ZW3wj&{ktQ)dK}1{zaefi{9tU%Af&6HJFC*+XuTX6 zG{JYyDWxfmSk;Gu5D>^O(5^+$zBwZh7b(AY<5Gjf*~scCy|+cNv5j}wslh_Wt8@5Q zurLYJ#k2Hfzbg8_go+CFYhzz(j+8(QG>OpBDhi}3O187B;RD;X%CLs(-HNcZdPjN8 z`7s%n2-a{2uweoz?KWP>p%O1`+?m;`bRC9=gHRQu$IqRQq%Hsrcy5lzy88u(ETIXQ zQ;6^xiIr~e&-)W?QKT7Y%nj=8Gg%~ZTs*HeLg1#v2i=|y<#m^NCA9JO ztJO=V1sQckDsn;OE7)^IdY|ZZ7oLl?-x0-HvGqd#OiH%J4@iug$_$8%K46^2Da@Ez z5O6?;W@Zp%a(%x|uwxMrZX0KW%fY5&wbuzs5ynTSr!heG{^fA6{YH&OC<9V}7;bCG zH>XG<m^0-}fFYXuF~vOv;U?R97NhmN1GO={py7k7hYjcl*@d`HfX zu)69%S6uaRnALu4aSY8e&3!z49sU{y9le!#JkZ@f#@8eW78D#{leO%VTwPfeRmJ?0 zsNl$zGfB=6V)p>OBhg5@dyC$={~>eN!vQ66Fb7NT8f4yHX1X}6)oyxpC#cb)d(~uP zbIRshfFj0@@Yx%UG`>^Va({uH&5Bj2wr+3k;c5K7-mL7` z6qq!EF?QDW1}mbo`0Pc&<(y6{w7Ya}I`+bXP}1ZmZPUm2g41mf`QB|ClnTe>t4^4s zIly}js|btwvo*@huQiQ|;h=OIqb7emQvwx-{6z}Iu<2X&CZXpLSkwP1+nRH{!PKI* z#W?@4`oOQ4QC6?+CqDAwdt>xk(?d%Y$_(SEQdkx4^G$`0-m(Yf3$H2Iba~DCM1LS#;=s)9;Y9ke217kA8A$y@#?7J+wmsM zxw%jZ@?Gz3!I^L-bT6%CeKPFTui>Yjf%0T8LfLyApdMCy;TRI%eLetiPkt7h&=$x_J94w36& z_dWs9-l5Sr!U2*UIs|1Y(c8R*CTYIUVp zA7noliwSLxU22}h>&cZ;a$TG*%snqNivw!#B7NvikqC{;e0S>wAaDLJ$JltPVRepR z{^Ko2>b(AzY{?2aO~_w~1esA&{2 zX~LSOUz;pV*a{?J@iTwq5IwjM5(|HD?myC$M7N4WV)Gk|t#o7yzV<8E)!J?S3btM< zs9l4d;26%t6jx|kLhV}h*n>Ew%a^jZ=MK`MHHpawoJvz>ZMcs7nZY%&!_swh1w}%J7PBo==++1r{Ne_ z6VT3%kYQlMBcKPB@EbLp%u-wB346^L0Et}QI=g2^eiDRMVU!;l5>ptPuAz3KHel5b z4LlV&&|-(tp(|R6+9a&v$Q+mun=Cn;PB^@x_!voD0QV9AVbG+#n3`p_lm?ziwK+T| zh$4Qk>^l&n!wI;(qo%VjT_~>xUcVmn2wv=rzB~JZ`%P43aJuK2D)6@nLbdP&x)46< zfvv{@>$X?Nk;PoTGUFf>+t2aDtx}hK?v1r@TjyP-gA{N3+9=XDChpiq+>Fg1m}9^D zR{n9CN`c$khR1OvsKMK-8~+wFWo~0|U0M(ycZdTcSw>$65c zJ5D82fC^KJUkeT<_ssasJ4ODICzuR1q7zT+WWUdWinr9O4&cWKXzJIc{;G-&6DC+` zZICAV^Pf{#N)_y9bp~-Q7LpJ}v?zMac_f((+bTV}lR z)lC$VfQZnd*D%eBt))9;u;GY;FevOmJ0i7oL~l{WjJDk>2fD`U!&4XBBpw&doT!@* z2pWee=eh=#VK=GJL5tbKqobk!lPXgVVe!=>^{0u!DY(WIUP}A=Y9j5xNIPRV=zUsW zL^`aVJ?{`l#rMa-r>)=lY3m3@E3u7el2V-vzSbP8RLRaim>UDiK6P85s`9v51ms}p zSu;bNAk(*P$KGt`XUXzvu6d_IdR6F@39i(?4nM8OlH>Er{VO=Tv9`%5N4vdUdrvrW zf!`?zb`oG?+7}DxrlWK6e%D!7uX@#=kXU-9(-K+g-DBgQ&8gBy)3}`uq-}9+?PgCv z{mxK)Btzg)t0BjQ$#UiNrq+|kCSmQzcg+qB5?Pr)~vX$z@LGCzk$_fQ9>ij)V31M z$~#XG@y9bZ3_zffD@8CX#i&EN%SetD>=bRgZ0J#;I~HR5sj3+<*J(WCPS7E7ETE%W zGMvs%prO5ZQl(FN?ZGq73Z=3gp?UT^VnLhWMPkW3Ru?lRo`vy}@-MD?qL=WbbE2Zj zd9MB5Wbf+#J|GT!*Q*;+qf)1QOz}Gu(1UqZdNImdk=1i;)SD>c8oK-u5$H7e5jn>0@h33oRz0jQA zCF^IB7Jz$$v8Am7*OO8&!<*G!J*Usi)Qi2^U>@iJJ2Xk%T_Fb)=E#)}dvmm3O@5S* zL<7!Qc-J)M8+)Z_#uh{-y4yTqGUUV7wn&hAb)_a|u%w`XCB9_F;=#YIbnpFWb>4gy zd>zzHhDymOXLzcMo+K-bvhFnZvw=^{_W_Z;oOBQePoZbgt??v>oPv@8w}7_ zW3c%7J?LeegJjxLs~d8sD67QtL*Bpz99Fr9uwC&H8YO@Ph>ga67p`pSkT?S+1;9YEpD1=ljEV{jD zxO4Td)8N=y-btMp^^`zFgY$Tq`UoS`@n_H~^|NQlzBva%>$>%P$2bKX-^`nXc=_U# zxj4%JEd2c9vjmu zcnhkeM45GwS&^9o?{YyRjzTVc;c%bzXsc>`u#IR8c&^6w8<~*H^CslvG>pcRRsKBD zpNYB(C8VO;N*l%%WB@M)Q{ftgM$YfIgUlxRv!~FvO*2MsoCA4r4%qjM`2UcCAeNUl zwHP(*Fl{1=^98WRAbF}(tfyw$528^ z-J#E%V9}HSVGt7?G^C9AKt5_5u*U9Q#A2%*AacuU);5N7m!x~Xt85^CiA}_@>45_> zqNlB0O$CyE89-p)1xo**l2Dyy8m0Uja!oZ+qY{+YVg(~g@ccwPA}aLPld8+L^^Xso zmoq_pg$39rgf|2L`xbyP7E!2vhO)>tL`Qs(QRZT;iekmwxvz`74C{ionYoodV#r}X z<8(zQ@l9yho!XUseLNXcqQGG-bVJB^D=qARDXfq!U?I??p|&rC6eD}^E}=C~VeVH* zzoiX}N;}CGfds&~R#AJ&Sw3(V3n+tgTz#dr5#J&K{h%83jG!Q&)q zAWeFpaUM`fb1NCrcPyH?wIDm2h6HI{@B1}N01t_VWF^x#S?NBkFWR(fDLgfF#IbZA z^ywP>I9^}Tn0ffhf9eP>YnAJ;6QT3q0Y>m6edc+h?Zi+fpM*buEY&JLa!Xvx2=@hW zlt}%bZH3&O#1Yg;5znfjy!H@#;v(4QD3Sfk%~!m8a7tW?vLkBiS1rORqWB*+T0(|T z;7geeursS43J(`=0R#BR$TCmilt(^ROkKVV^tAAJuruy&k_!mpt2X6WC$teuXcwYR z3yQSqOwt^jD)_!_LKh|yGfVtM8SnpgTwb?=8LS7=5YhT<#5^p;xHhX(5wZCd-BKu$q4wkl!r*;vvHx^ibh9@iM!IZt3S{lI!AH-nEkrN zIjRpYM1x+-e*Fwza<`>KV*zY~YRyX_^4nDQvQpR0KZ;qZ% z7nq^85Z1(C9ACCJYObnZ%0?tyE$*srXB7Oh)GvlCnjwiGvJwebofz!)hvr^n6T()| z(l*lYi~-ZX^>?kS@BpAB8;c>MtNg`|38qeM9?=on5(^?OM}H8ZOOE6pNJ; z{OaLs-fW7-A*D`SBVqxQOkuMMY9qVMyGE5puCFZwX0DqxEQ2q#d-rIyJkuaq(ikn* znpog*Xpy#s#(NO*;ibh1{<9##Hr1DeS=P@Gg?+0PK#!&w)adD&^$Uwoyf2;M`E z;U>jCDo?Y+Qj0pf2f|=QJiJIf(7Xw=C}`mu6Uv(iv4SyAi#yAUu2Yl3vL`S418i9)%m}<`O!%oMCZ?&N4ReF`$Ow@+?qMfq4K81 zoBnzR+7Mk~piyRNwnSIzXwY+!tE`M5syZ02!i@tqra_+|^;p=(L?+lVWMkX3cdiK~ zBB1^O5onH+IBRfB8ZP0@((%Vi${7?!Yd3S{Q#F1l1lG_XP^>Q# zF8yZe-YyO`;v>tds=f-5mI2(dZ$JeJZFV;urZnh;Oc=$`XQ- zmu;ERdh92grgfC9emRPq#;(pLXf2pX3GfUA9SUDAl7eOZW$14cL?DE`I06x}V~eb9 zr9!SMBsqOx^Yba=M6x#2@zghHQ4t42`y}ffZT-yRE|lGksJse+vTOBb)~mLkZ(ACl zpxCJ%Z{CyU+vvN8P2JUNJMuXW7O#HrttSVQoJv zUZ|2yM#c>y7F}I=JjmNz7;$Vn{ZgGueeuerexDp__s|hki1@j};1|u&y+Kxq*y3lM zsp@apYA1un7bJXOO>4+dM)X*PM$%h!eD&p}``9`?*KLx%w`U@n?*&N{4}V=Wjcz5{ zG)Zr080O<%xvFka6=bCmbK>u)txU2r5t;d{L1HX<`$&cPN${jUh@v}Zgd?o8=JrA!68p<77e)V9uJ(jAa{>z6= zQpcD;K+2?W@zQYPK`{oO#j?H>D;|S@5`g#Q%pfMN%p;=6(2b)y8ZcHYSZ&1^bDvqh zl<1eNQAX&~SF%e>R6e~y3aK?sBe!U8H1yPPbL;IBg@vM)`#Zk;6n=1>@!?BSdH`lQ z8zVFFrdro26(DhUz-BU=E~d?YI)#|8!Ah{}Q2%3cUt$YZ#qssz;7Zx&297=)!)H%am%UPIbw(09*zZ9JpnD!WDW#sxt1mZBb*yFPh;O?jzyk|Ea@1 z(v|_%yf(_&=qY>Z;juI*7fu8j+&VQSY=*oR4iT_-=THumW58{!{jbUN#83{Lu4_WO zh#`n`vst#$*jbz_^0tFv1YMON=4Jq?ge$;M4d2lJw#ulT_Ad0W{BGz|iPDHDRCKYc zI_d0|GgacrYIHQ_NzsQ(C?}0$=Vd3jVQd-RP;|~JD#ACIs>}d6mv93oBv!cJgiJo# zo<*}{ijIj2WIcD?elol`|~HkJ*t+KmY%ZZNGilooc}K?-qMeG;aa zxYD#MT!wFCDhhVhECDg$3;@<(s$H;RO%mqfo!a~?T_OD!HqED{L^%jIeM|WJ0;rtk z!2Lrao4Gte;GhOryTYS~KSE>Qb|BWxU@b^fO%OM^`pi^Jd^7{9Aoe7;o0*-^#`<|+ zooGKq?{$^J(_{*srh@<+u-W?F+2JUjTcu7Lbe;?a-M!Hm_#ligLqo`C6h7xK&8Z9g zI*_2lddYa(Vq}f$Lkge&l zlNUBKJEY0K^`UG56l?MiOdO3$g^On@i=DI1AfRTmrfOxh-Aj~KG4>an8L_!(Pwm0} z>H13J8^u#WBmdnD1Cz*6Hwb3 zhD4T{$opw2?j-ck88u0Ni4dgid(hFD?lI{qyvFJ{NMzXPkCXbFPg`-n$flgg0)qQB z{y?h+co`Y_iv@-2U0_xT4HfimP<;)!LkH(Jz#E`j7HvL{ueL{UJrvdp$ZMSecxX4# z_K}^o{ZPsr{l-$#%6ov|Yqkg|10d$NQSI`0)WLPHoJ7OmL zoz^riNt)(jY~2VZ85)K;hef02A=#}`*C-++#}p*5{Pd_fD)|F;M)P06n8*uSu|##~ zZm0qMVhb75->?yC%=F_y#da`c<}WQQg`7G%&FEkZh%YLXC92Ckk5t=pUnAafbuT8C z#8*w;D_C(fG!Ce^2nL~#!QjJoLv8C-Rtk%r))xWh2HwZoYO@%NLAC>%B%OpJ7X_;m zq>^4ElFl8h1d*(c8oy||Nk{`tLiobmKR=GFLH-z3#A>Isc>9wLaqRfYca;Me4VZ29Mv#RmVM|Qtv<-WyeP%3+kFpe`ya6>2k{-0+uMBB~+OMs4M zc>|5pNCfk-P2}MTbn(C)T=qg3bP4Iuqvilj6C)>pCJEfFYkN+Pn3W4KIkIYmB2fLf zUPox17Jo8wKUDK0E0@H3rE3(am_wx%=gFs#=RhqiD5Zl}x3=7c{+CZ82PZ(TBi5s6 z>iic>VpwAr{+K_v!Lo=^rCr>Qm`|EMWqB$fnc!X%ujBYrebyS1Q_PK*r{e8jaX=_x zpl3Gkv2`u^HIp*2i-LWWxMIMb9U>`Z=ZePuEB{@VFAO{IRRaL~Nl7gIL`5j{lX@v9 zwnQ6|e%^@YQ$vjZ=z71=qxMsKOolTDSR_W1l7f*%MF9-VCbUx?x9g>Kk$ruX`!)&K z%a0-S#k)bnzNy625iTs}@Stn*K6Z!Go5q4PRFZvxfhoTb>vDv^%2$R{l~>Z0OG}z& z*^)62(wkQLsLV6UFG`MU zi^uU1BCD;h4Pk3^&sF0Wb!5PQBfzax_8L&fxMYgFFT#&KvT^d9t(-7IajH;RW9bhzm<$BFa3(qN?#^T52aPg`^Byu7+N12sYt3E}xBObX@Vb5%hY8#wUx9dGUo z3G~1}pL93@S~`7@?vVJ9w#c-`r}>Lb14I1)2*)dngF>Gmn->H*LCt(pFhbLE918jb z9eqO@mXDY-=Ft&>sl&(bHa;O{oFb-*#N7d9WP&ZcA|N)+WTM`Kl!@sTF`S+=-TQ$x zF+V~FzOSBX^Vusca$vhQ3C$;IqIbJ(K>6$iS?Cw)+_pGjFgv3}X0+@eUtpsQ>`5*t zjWb$dz1O9R*k7F^E22*Z?9~I7?*PuYX|21SNxn#$hmGT+Zh_2sDe^>rU=ehP3u&?2 z_bOR$(!VG6|t(@Hs45SQDiqau@`aW1skBx@8IB2O=wy|GgtL;7HnG zx!4riCvkLx?wJF+f}CEnf8q&eLUye>`AXvz)&2Jhvk&)v)eI#-afw^sL{1Er?}59@ zq|+0b3>_(fC~5s$mnZyd0JiZiQ<(q-4N_H1cy5UwI}sa_L`L|%@wB$}>^=N?oJdvg zlbi}aJPf3a0;(=$qPT!O_flV4rm1MpK$?Sjpc0TDS%L5jXpiQa6}M$9BnB@9wvo33YQ{qxy7oz+U_Ym@Ei z`3XC8WR7KE!yOs(e)Ok%6hGbKVN02EFqfn4wSJzIBOO%a5v_Sqggdt`%iMN~m%uSo z*K;&&=l2`I4loV4m<-`8uf(RSnQrsT8&Rwanx&|~HXZ3$cuG3LRC$}&-XMV#K?dJ6 zOZG)URqBib!)PGf!Vu&*i<-LIbq~z6ilTf=3z8>t3=STGIj!-BF*P6nyesK*b10Yq zO2SvGR?g4X60?fyouJ-D497Rrlsn#LkL1Q%--@#tuPtP3`5%6dnM>=;V6yo6#|6~d zxNhF9sOkA|4N%kKq-Cb{NJGv3cwQ7T8j#_=Xu*NF zC#hmvJc5Q|uwo02oizVb2>U8U3OqBzxE z?kDPl3$&spAyi}pG|at<6%%?&!hy;BcJgR6>_tnt(e%SB8=M%Shy8h*7RwvHe%~N{ zqpiF+7|V`-Pwg~)R9q@n@di(h04AsD_XWQq>XZh|c>`JYMgpu`U*Fo<=sy>OR1}P- zb^zi&UZg)VEsfKt^6Ir}wf&UXKEISGs2fcj-3e2v+~jRXxfyet!Q_Y6eOAwoz=b04 zgX&!SfVcV2&yJ}_>StsUI^|qMsNnE725+fblrl{U_JR;}$CpB&ac#PXJes;c+VMV! zqMNzZh}+q$0EGNv2%tgF5)mn#jkR={Aup<@%DYqO-X{n2j_opKAU>7WQTo%bQeK~} zfRWyK@FOh&xaF2{+NLxldInG^qD}T$BMnx^r3g()W zDxrTev1FNQWyS1E;~|C6>ZXkFFm@N&JP?*VIhqM5y;~Dx5fWe-N5d1ie5pDh?>%@rpp;*u0gO5`#YfhatBKccCYXgKx zo30Jz?>-$$c=8g;#M7Bw=mBbKnsWxn!WJ94? z{Y_$@Jp=3S1r)&{^$&`h3XtF&)Jnz;!Y^M5T4Af<_r2s_YoC0F&r_ct;mD&XXg4@8 zS3~SMy;tD`_V2jQj2^Q@z6lVrWdU{gHk}vK*&M7`q6BvI)meX=0HPkl!yR_3h-$x@ zHQ1mcpY|FFn6!<@UsglpNe)a zZ^NCL`?*PPrAj8`L6`JfE$}C*t9Q$Nxu6pxfdxiF7yg+CX9=2R)&1&9QgpK}5A5(< zF@89&=#Z$pptBS|Dp9PGjbUVCYsA{!v#lO-0h~NE@}Z2sytt@xmdcE)JrdhwBi-9% zETb=&5nxA7bS}2M-RuwD`{{?H=4(<4+T>t*jAM3%cNW;g8Y*a+1W#BseqR2V$9SuwUE96poZ#19fUqVLJ)&?;e5gy$>%oOAM3MM)rmx8 z8hK{NI%y(mJv8X9xE3SH*n^guY=7T!7Ae%2U4=giPVr=KO(`=mC+e8RRC!tI*eSz=d4 zQC)47*HYJ|=~h+UCUngR&5%^n&1?*zF<*7NrCn2=BgpzPw#L##)p|k$E#Jx6q8acK zp%5cMsRKgqS_7it+gE|eN|_vqt;~=hP8#_hddQ|Q2=UoHx_%8EsH1WFv8)^5pz0az zs*2i`DyTg|l0sSw!t%3FD{a+^yp`9s!Ya~|9V%U3!CH<*VDp$vi>{19UYGfp4E8%P zM*O)Eu&RoP9M4Vm!)Zfgi$aNNMIr>gK(H>ln#Jph0NcyHmJ;D=ACi!Y%w`HsD^?^VkYBV} zmT?3a%a-kr`CEdj20(H1Ll8tC&S8ndGf6|U9l+Ove>-VJuM<1V(WwF~-2AfUyREju z_{4t_Fr5|j%p5uiNcE2DPn}}jsq1qK%P1-`44<15Vg+INfud}d*G%y;ZSNOulTM0&xZq>2@Z@dJ`l3=) zQLpSy(vB~hRfuZpi>jBm_Z`b!$(-=TBFsstFsOlYG5R6t!_=U%Ob)8mMvH0@p0+fe+&K}#p#oTB$HRCb2|gg|@00UXloqr7$^cHU5vec?F! zv0gJp*;`19Uv+vb9MHjgFzp%7vB-8vw~vIO2Ia{>+d%TKVKnU5>`N<$s51Q{JY#($ zo=6`ePRqQAWFQ`u+hB%N%RUlA0X)H*%ieBh&f?gDKWv+lB7b}v06HXmmmHD~j0*Hg z(c~Y1br9J6f9FfAlR#SEKpcjtZy-gOfQs^Tcz01@jLM6I8otDR-}os=>}~Yp~3rRyLO=GM-9wSg8&@ ziKDv)7EteDHLU3*uMmWKkwF;tu-iow;8C-fqQ4iOFl zS6)Mtw$M?7W)e40QCg{CETJK13$A1*PxT!&R(HeBx zc~bcfoAg2MyBmNK@8%+?$gU7mYYT(#0xFACS-VZ7X{uX9c!|=nY5wAnfEQenshSRG zWj-{utMY=UhcB5OhIZ3;q)F5@zjW0uY< zJyX*6Q>M<`&v8aKZ=27+1?;VwfP^PvRI@3QX;SWKIZ10$0_~{Mux>G!^%Z%tCfj0T z&2R2-N{E^v)>!U{MFM?QnuEjjn#PDwb_|_JpO$u@%th)<6Qq%L^jZMOgixWJ13cLe zppxhmboxD9y*;ws!+dgM-i@FTg{!u+ju}s~8)9f1U0B1iZS)+&O)y1l1ap1;*@-=K z01!eCYj;_P1T^ErE$Kl8CWCCpZInCj5V#K??zyI6;~8#KO=I-y==e1s`K%vJ38hMb zL;r2jMc~jlb)#AXh0HdrN2*KmwxI&0xg?#6d=W+Rn_Jp&JI~P_4+MWDS7Exft8V$@ z$wHXEIwlNZUg$)LN;y7GB=K!(h`XMvs|<5MG-_5M1U;0y*#6e)8H=M zLZ}GRy(<)sME3;v$;wpiJ~Fjf=T`bHf^CaIr?a`28^KeFPJMz@yiI(1PluEf!(Hrw zK(&xnhIF*#Ovpe7B+isuYs9!AYrgrZv8W5h0ob#s*l7Sr zq?wfl%*cWJW0wZ5Zp0YPt3Xc_czt>sEuE{;B=T z{^2>aM+C1G}Q9=w_A5%A$pw!<%a`e-z9ItacSp3N zp5*~@ahI-`;}#}p3Aq&UF%eumAdXV37DtP40G}*R0)vw4vFbB=lt>vYo|{s%D;(iV z&d(#ax2@e&ZUduTxI$~Pw4$nK4u_?K2FMoGQ!L{hy5CQ|(#WE?>4ewx5yh;()*%@=ws zCJH*%{+lyZxE_6i@8MF;x*!Zgo3fRs?Yp&5J@J6mI6-mnI~e7V0Q&B>o#=3QzGX1M z1}kawB--+d2nchGnZ;YYpbD?XozZIDy2P{s8pnlQTrf~VP6xG$izsfQq{*{38FeZt zzhU=azA|rtsOkUdoEdRqH7vh{2o~%F42C%ADZyjH6Jz(p3y9E1U&whVING$rGb^qU z)HA|+WfjPAp0zL7$nLh~-crhxQp^RM1+oRM)3ceDFdq|I$fGkU|^b3Z3q{-OgV~j#K=D3so(~qDp#V=Ca-o!dwJy9;h&ec zg>&2&bx{+=IwohwT!)Cqj*cyLQ5!XFE-cl63oSu>NkWMj5=N;=22RQ)mYeLlR2Ozz zn!xrwy64`7jK~lJQ<)=#@KS>js;IkL zwp~T3!qlp@R?2PkHKWDj(o1jxq8emercE(oiVu|5h3lt;g|%8Z-+H}XuNKa?yf+*N zI>K5Zx+BkIyucdl2+pD^Sx9$xDW&w@Xt&EM>{u@lG$~!$VC7fWah?$|`mmtE%akS$ z1ZDkhV0o^{A_Ex`f=DPLfdnd1ART>FEPt&a2u2#=B3nu+Wp{UXclQ^vJcSmNuC6j; zuvCSHAEJz*Tx79%l+v#2XzjR-b{$_yxs6ik)7`x$Rj*R!j=v-ZB&00apiNmqL<}n= zw5(QkRf9`kVxkKsB1&{d9UYw>;foBb8c4ZODSLJf6QVTH0xzU&+*aqDbXIOoTDeXB z$U|?l&g^cpY>_oZzLZAA=#JnLTbp7Yz_(im?qMi+tDke^xG~F-OEXz=!H5zX5MI#GNL0Rv(g33_Op*{IrMyg2nxY0> zn7%ITziipydvKXng$7w#pi4k7>&z~{gQVnSO$J$OZ3lG-1Pf{yPzRw<)KRFFqobLm zb53jRv~$imSxW5qjc?m$G$t%nR9-M`K_Z4l3MH7f9DzlNTJ4(Pt@%9k!^i7RZVCbK zXkh3AAaE&;GC-b3J2>cu3BJSQE;&Q)oPPcVUS9fb@VsWc4C#SPR$lhY+{4W|hx+}4 zbbtCF-cr?UkRYe;K8SyR%Ue=M2XuOW9sMo>L6w=pG`o^TEcSDnFl68Z3sQ{S^f4iX zy`+ohr$hd^0QWe{6enJwh4ZRWA!A8oM@eKyvLxL@aE`29Ei<2h>Z{APZJXI`b6Ji3 z4*lp=#3m)(sB~aQXIlNLrR>0t&U9O{_e`~_W^F#kt7;a;gFm{g$c=DIzKmgG=9x*b z`P6$pj^Oq)Nt(@N?vihRw35laQ!Rm^*L-FZdXdX_Bc3a9j;s-#X(k+<$>=s*3Fb;J zqr4|^bShVV7s|$Ydx>-8(}2Qd2nfQq5S!RTylTAr!o;*C#M?D*WF6sob7$QilDc)-+rY;k}IKt%561^gXO;Gn!4Zji9tZ!SDqTofr3sS z>ia;5S^tqIM-&+Bk!#}8)-Nd>&!uod* z7L>wP@4ZtBbr}m&Q&P>c>h}xzVbuwwHa7Jp_blAYxQuzL!}@cQEpQI)L zIKdW2pzJ0sxg!(>wAF%Oy4C#@j1?Y}-|KJv_IFISFBMnb0xz}OMo~B?8SIoRDSQi= zydgo~Xpj0_7X+|A04=R!wL&7>bCzwZtSQ7W>^&)vdt zE8%r%J%y|jyzjj4{`=GEzdt<}exZ=>x&K5UJa8h=_b3s__dsye&ub67E)_=@r6>1L z5U}2AkwwMloF?}Di?#PS{yE%dTrgAYiuB8-Oc@0Hlya0IQ|QJUZ*=2Ld~wbdPpTwI zO9D%uxDLw!e(AFyu(7wIa8E1YfqSUfHN2;wN9ZL@qv!`uav)~h%}HSnk~{swwU#}d zJtGFCDoV7U2!c~QwQl!8at92UAi2XoOH56%8}g3_${qh8>2k>~LVp+XNLSB#w)xhA zM*;uoeue$p1FPHPd(?Yg&FZ31s2?q}OZ6Uv%r2YfkMS_V9{e%h zV-QA+5QG5(1`Q~V{37TJL@4f%t$5A2wfUd)dJ?eAadnxd^_2mP& zX`J52<@Z22p!+W5`fJOtm74~yxN9S9ihN$kGcLTx;X#IcR)6>2vvhRtefRb1sDJwU zClIW#^}FYOv^=hJ)9@L7Kz{MX9WFV1?Di8e*!*VwI5e){if5WT#g&F9JSV(&?Ti=?07@%{Tj?!+qP&pGF`SE}&kBAht!!w#HGxxzCW@`eP|1R?w)s{{~C zDULjs#S~gs$Q|M@(3>PyK7UJQDSc)+c>3Is%q*phB6DKF75A@l=zvXah%roJxM-O* zX{1)tu`)k6hr=)!Af6g8`*qhTnXu`>_KO57A2`60A+>OZ_Gcz+UiAj+G+Rp%3*gOGZ@=ehcM;2^~%S~Js1o{s7I6oIjrIc=0@`oEV zDMbNA%J=Eh=SV62ryQk}!Ahh`vu-}0IV>R zWg#krvlA7CpdUYcH2tWx)*n8GnudJ*81mslC^Y$C0`kLkMi#SUhL|)GVkS2#W!t>& zGnvU*lBOv}rYKeEA&3~lSTSNq7b;QgXX{c7OPoZKJDm6>RsWKXs;uMXob`G)AsNiTa{Y z@8c2`wj`rqMD;l#u~;lt0h*%lRq56=GLgoJrs(#6G)dB{6^%r8=Mt^;2vq#IG>!T5 zw-#`Z6h9<5XWky6#%75{L9y~xM_dthv|A0Axz+CM#G0ZzWr&)=`m2h(HMfn@T5GL! zOku@|DkE=Am5hiTRYmvXa_6gx1l*vivk#SpJ(VEdNZC6@d%OuY$qyS6?sg@%|*W znH4O_9r-;yMT2GO;I`+wAe6lc=l^bEeJO4~Inl|Wf++V=WC2MaLVh~Yo208>%CNAn z2GdK;)J;t$_R|dp>5kQzl3eCXa^_^L3f4s?N@hvQV7@dz80>dT#zEmR&Un*u{9bTd zbom>Y9zlv!66d#Rc!&BuSU|2sclf#^}0%5`H&OxaTHG?tE8lG~k^N27L3RNBF=r z4gc}0-4Jno{AxEzAgEHc_|=|R`Qwdjc1Msa!j7Qqx=O}mRY$5MHb>UKH<{eozNV;1 zCObMpLVEHfDQQzuB6G(N%n9>n6Kl9gm!rUrH!4}}I;RTl3^%n-7DJNP9LI4SCw+?Y zUtTGVz(I@IKeK`-a;J){)7KaB^SzLt?nD+)hZ^D@zb&6|(-8MaBw3R#EbNfGySrq` zQc5{vms7z?agKFSZ!y3J zOaB2mMA(fbEcbJ6G;Eo|>iXxPHIxn>GxNL1ER%##DJ4pEdrB(9(PnZA;7~Y3tHQ=E zDc0$O=a(iw+K?Lx;O_2|UPfJh9&Ii^%Wm#r8WD|%>5iTPy1QFG4o#QAu+ruCBL?#U z5g!m?y9%Nz1~`3P_qC4X*8RLwN94lmwAISdCqm%ll;2imN-7!#(?b>PcA3V)m$5D} zagyL!2Zaj@MD)-#5uQ>PL1imKscV2SF4I_e!otxMlZJEVoSeg)C5Rgt673?(5)e$O z#w#cYs1{_cwLw6z8Vo212GpDiSSAkW7XmH~<*cM@FIScTxY3 zA))>qJeVj+KahTu^@eWuHJry=ZGoEDu4lf6d}-dR&z&gbtq$^5jbfI1k0$&(6aK9? zWm73st@)YIekw$XpU7et#IAnkpA$^~=Q?Bck(FqMrh@Ep;kdfv>#l4((#la<@VmQr z&1F}!KF+aBV`#p#jirW1Gy^JFSk=MPoOSbu?6~TI;ITm_fjmnG`3& zOx@%Zp++ht!dK(UR;RT(3HV%}PKWw@h7?|V3iU6pQfX&iJa=;6d(SpZ>n3OIp_SWC zJY4NiKPBZXDiwx1Fi`^(chG?b4JZykhb=7{7LE=!d_dy?jtd5`)>;B^T^powmwD01Ti)0I+L*DzstO{O+`^I8gwf44L)>i95rbYj03E#E%OD@MMNd z!volGP7zM5To@y_od)npF8o_Vrs+_{rC|t{rasTip@{^{44{=m4hWcGwVG^UfD{2h z8DEIgveT|yNaTP(YeEB!Ip@SNE2Xo?Wg>$Gd>^DxB9j~xfP;stRMH0lhbwA$AWTui zyIm+8JVQuYbLQI~!Cnu6=0qt0A#|R9FlKi0R-lvM{d`;LoZIv!=R7SR*halFJY1*! z=kJ(G-LFpJ=Pvo6lW=6B~oTg#t4fLM#3biExDld14pA#A`|a?+YJK? zc7Op6mK@On6)hw|yBgT>b+?ojtUDi7O=zOTYzG{afq?}@R%$hgj&*U}`Cj$A&CR!M z+awS(l0^z6Bv`!QXDdRZ!U7%IuU8G8jedv1LBA7xq0zv?onI|Cr;R&fu~=;Ob4TuS z=bRbfL5vYroaDd?FDQ{IP}Cyei>rO+P&jCh_qO58Xd-v4VS}}>5qD%SVeZCac+A~4 zE(3sjm3X;hH-W*{QttLVwh(uFKDyg)UoH486V!0G=kdt_lL5-zK1k>VcY7W~V(#`o zVz?q^MG=#`(PVIfWOO&$(bC;$Gg!GB?F2(|s6sY53ln#~1i>Dv_zMNN^Es);Ao8^P z`8w)TF$n!iMOOb7gw-PJ1p3_Tn7@fZwx7?5L3jY-x(n^*?&bB}km{yL@_P7c6-Os4 zGgcfSK?T#77*jNjK~Yg89VC5^MT8qB)H#FfCJn~J92{Cs1oFD5%hoqH>{tfz0l`QACLjVRC^o9XYYJ0h#Ry&IUWEPjEygSKGXp(t4Y8EwQM7 z{Z6bOL_YUI-S>%mANQ7oeq13%$67C+5T-&CbFawi@3)YDC=cnHO8 z-h2n7Zsij(J<1({*rQ&*?|Muq0vA6S*HA1S4OzjTMPF`t;XlYibj3P<<#PycNj zS8J7={C+!~wv)W_V|8C|M`%36oSk$ZVdzIY_%x*FXkws7d{#Y3M`N`JUcqe9ax z#uA1vV6Ol66g2_AT?fQ<{7M+Ip&vxj1+p$z&YBC3$l#8RbfpVqE|A}CRKkG8=1NDE zkbvvs->v)ZnR~$bs4%2qe+~UNAM|=ieaQPwAs~P+zWCz0e{B_o$2i{n@T)BPe)-N# z=2<|<&-{MRBjdXL_6hfdaQgta#czmhHTAw{OCFMlw8RXO+?mCwgw1#*tzA$HWiJ z|A7?o(PaG7OrgEtaulYL!7_N#8$(u5u6QVQl!!UK=dOFqUWXJDKvQei6j`;&?dI-= zSV`pDoZ>L}*($-dy%2rAI`zo*e{ANS%VWV?rqa;&i1q>1&2_V2+GcpAQb}EHU)p8F zq|=ev>xT7Tx2StJ+ndnF%jw-BJyjo{*_DXp?XRYiL|uRe&hpzhMate`oM|YE7%|tQ zs8E|A(~~@@FD@r=)yBC0@-{w9nUgEN)9cg@xjjhFfu%UHp;=ED%>u;=g!*4#JyeP3 zFR^*faOIoPvA!R;pyUWHz_YbuhBMLA5jlm`ruAaY8j>7v zg}J&m5!r60wYd9mBuv9&(1D+7x@;|~vyR1%_X+qYZ6vUnyEWYN?xxg05CFj42lL0P zY#bc4VPQziBA5i|-%ByElb~vX$-cAF;}xKU)tkP^!wE2SkbNlZ{2Y<*DVZ8K^DGMp#bOGSd%RQDFNK6`MmPaItaP@bsWvvQRd}Y#SlK~MIY+J=TQS};3lB;CxQvEy5PvQBa@*b<3wgk$^RtWx+v``w zIO!h?S3pNUpDGZ;;4z{3nif(Lz-D4MgNTok)Cj$cYRhFqylGELFbIAx_+6g8Sgr){ zy7fxCMA#RqlWkJ(F#0m2b9eAd%8B5|H$p^4>Ox$P6D=Y6ervB~??=2rj7x(tQ;~-U zBKx>G6o9H&qN203We3K#HP7xZ+L8EPxN71rD zo3X*CS)8PmAD}^MXz@^rO5a|p6QCmg^+O+OE8AUFRM16}NDxsj1tQGQ3stm=6uS)3 zPJhOPqa%W+Ay*K#fw9HHUkfc$*LkZDgI3(qmZLP<2SHo8!slgzE2 zC@<%ybFt5x#nKd7w%Svysr9zAb}c0N(f0Wsd$`M4JQj4+f)d|%m{t7F0-xsEG!IfytMK*EVB@=w!lGqJL`RW66#bA4JH0iY zr6ir11>>If_JWw+S=wtU!Ze@qfrO4WOWjWlK}t)`dKs%y*!J1Z(2gw%!LF8Z)v{t1 z=JVb(tdSXUA0*%SptD#tNS5-|s(Z_#Q|?*{)Euk>LHJfL*3XTjpYV9rG%^x`i6vqC# zuQYdH@jkm-iFz5LPt^$avV-j(@%n4Q%C>*#l=7@~yOUO2X;RK(PK5wbKTD628{z1! z4ND4Z5*WS;FXqR&>xI;eS3+(&C(soFS7h>g$MrX1-(_Hj|SJWXS!;PdI~9K00iCWwEP55PGl0s&V6 z)@8&=8=hq!+G7Rz8LOmql$^Vns5!Q^;DUZF)6ywA0(_QWz0B{2yT8TA1L)nic3d(w zP&xMe8uP$uma^t4of5AOlS?S3kJJ;+MA}=vTz|1Y3t@^S%xfho9enX5&^`Nnl)DCf zF|SbC*68$IQo=P;=Q)V;KW6Y++iP`CUh%og?-lK)t|<=uj>978BvAZ=)_xqP%CspG|KJeFsTea(Os8cj=`;KF z4%w#`8x1`rR1#=Q35Kks1c>+6j)wzN#6vQA;L^!!LlU5IR^K)Qg#p6L9^WcQ6b%&wEEfGjS$`zhI?#DKJ_LgHy)y>39MH z){RJ;jvgpvk@eDQ!^fhH;5BW6rmQj z$yuVyRNIh53+s5;p0J4np!GJ}U-cc#gamW=9?i!ej_MTl97%^3t+bk~oU~{)mf}DJF_P(>tdN|6}*JkVL32mlpqYc+~4zYj>mbe*-#J!L_q+D$x z0;|&q?ckRUa{J-IK87euzH&2a>Y^L6e67KZjbFR(+leS}ejr_P$*$@cCn@Mt5bLkUj2+B}w(6K&gi} zH~;?Ba_>Zu^-PBu5?gJ;Au(MIpo3wi?9gZp)eHeB9s|rP(loKgiF@zB3KgwTNYnZ% zW$uQum^>x$@O4~j_?@l*S$`s!WL*)&wZg$K43v$$YU-bTb6o8{wMFqaC8A|B(YDt6 z15*@$O|i=-RC!YbX$$XVurw9pVScvst5I!))Emg zDIp*+Xwz;4nl*7dW%(p^sdTS?)*esojB=TetT@(^EEoq53ca8j+z19^tucsbIgN|$ zn+vSY`#r>Ct;ata@DYwCy#o*}(h^SfLegYB~a_CkP&rSUj{F*KwuS;6dWsj?tLwE=Z@4K&Zu7&7w`p zN!*;{kks{x#ai#W)Dq;1*6eOyTfMUoD}SJq1hXNQuWj#m?JXm;N0v&?5gS)1-t9O5tud0*R~)2st5f z#odSA=2Q`}sPZ6nT#X$ToxJY(jK<-h>-13z{cv#ahofK{K+3l+e>s`LxcYKlsbWuFXtn(a?ULRub>GjGMvBK@>r;y*Fz+U6TLe;rU+ z;fA9%Y$uJR#6<@ix)dWkj#7|lJ2LDJeCgVP44m03zw(C)@un1= z$&R+9u{5Y%IcXhi035~*qq|Xgc|}x?_EO?bZ9?K1Rc-MncS6FpY4;JNH0p<{toyMV z8*XCYc<~V@7~QyJ*U$`pA@rFD8>69r5<_#?VL~z)GYfRpw7v>QJl`7Id(c*D?d%Q4 zyGO`!r{V5)nZ8$N90ytA3pxB*=VUtdovC_0e;mOa(>o7%lGHO&)P6f&Apw0e5 z+6=5v4sr@;5jL;C^l91yZW{Bnwuzs<Z1CS)f&DxF$beAGdqxXC8 zPI*+kM3@J(Ri^JCM~2y^NPW4>zEVn#td_U-BU>o}T3grRtTC?xTFzA815lVGg*3S0 zFgV!;&vBz=|2S@Xc16DUQv;y4OQ*fHw7NcDm+i^U(TK-1jYQ9j{m$~WV*7Ut@wLSM zpvVJ4KZ7U@Ai6DOASp|=Eo}!wG?+8JH0bTF zq{ml5d@wEM#jy3OguljU*EXkk13aVy2LaPu(bX1(dampo?7JyUl`N7?d_4b0p(zIA zp4Y>cR;z&;pu-LkQl=mMIQ_V4&_(0dbR9GYkmg*V5=u?$D1&lPlH z0b7l7NH3!5kg_UF@?9S}@t>8Bdr|DF5}Y^>i+E>!h*wAnCf_;bDSOq*>M3_Eti{#t z12gpF6lTL(SIuGYR;_^B7TE)E;Vauk65%b$8LJ5%p^(bfzIViM&UXFiDL;X;MM+R{ z?$^eS+xde%ehBR(AyhmPYAbBcVF2@1$3LP7t#`mN-bZpo^ujazVEtgWSpH3M9u#=C zWFUNqmBX!2Rs&OPB2pg7KqXmP4d{g+zNGc))Ke&Y+{{2Wn=JVQ0mEKEn^Fl#~(Uc40mY_q~&_d-pNa;$ZablD6#Ya!% zHM%6Z$`&-Zb?Z%($XhiLHL@pYH4$kL(!3h0Cx_AIx{F||XP6#d<*gMvx9tjXb zCZz;KW*mdBC_Sq}%xM*3B`}-!XG>LA*;kSF5WDc0N?<(E1|(y7 z&mMU=*WTlEH%C48>CFEASZye`xxT*p2JuzSc+rNrS^2l^c6;? zTGPWy#bddxSu~=bqX~MF##c5oxJEsxjUm!W#cpYXT$<@s0CN!z`UxreD*l>u3yZU2 zsrC;Sq`Aa!L)mcG46ZR#b}cd(*C~?dAR7Xqkug|wxd=Er0?f5TST2gA@B|M4;jsS0 zcRWxJakopFzkGrg;pe*tw#`ih$PVJhJ;qTxPYW?laJpy_#}I>I;3Y5SaE*{qavmNc zi`A|^a|`x`M=|Do%zVr|yt9zG4`T}pcc|$-`9VTk$b&-H2kOjB%JK*7S()+b8lTTN zSdUwCLeI!T%irKF<_Hi|I}w3$62YR+;uyFMOcp91JR=2YF1DiYgzi7KetDDw8ryD% zmwKVKiTf=58CiGVTaj)blJK#44ntHL)IF+()M3&+73?G_{SKZjU2C!uf>168->oYd zV7*B*tYiRVSTAOsEdll!&3t0hHU|A879^KT z7PpZni$@1mQ#AKBG{;O| z?p-WOJ$`U16^%0k(IQRLrbrZH7`Q4@eqnmP$$Gd()D^+XhR1D4sob7LhL+PIl75cX zQKD(I;*U_}IWLlQg~}@^0L+sbdRvZID;Q z?f159m={%>D0fy$C%+zj2bJbnM3~dsul}wpG1NF6cckxaJ4BS@4vj+eiwY($4;$_P z5x0*YS&{M%mvazjpO1OaEO1VA4CKP~CG$$#Mm$12KWUBTinJIJ5NS|bQtXNZUNp5h z2cC1A)p6c8{vr~bn+>aJmmCa?Mz~NnmtyXpI~PNWM;tkeQ*&W3kyas_w5;M8d{cH- z-vRT@)zUzPUlKEcAdQC-z?N}G9Puc*0t@cBa5c&5&7esyz6yB)e;BekiN#ndYLfna zCLg4+L!_9E=FXjft5P^MUnOC>?t=rb#G?`K;J}Ezj90-GwRFz9JleH`^x8sS1PYF6 zi><%*222BWiqHpiD1D30+{Jrlh>XcC#~w$GRj|u7M4+U}k6=$9^TblVLKhK%>LI>7 zK*BbMCzPUB4@jB(!! zUCJO5=~K(UgY!yW;SLL%(zb(|cT(fY%7_-A6%0Db`!=vJH9;9C+{9sv%n@QA(O0#YRud-7{gj!|kc7HZ)-iO0)g-dmf zX#t(#bL8;Z-~==gG>P${?D>HQ)$lqV0}_i)lqjFq1}t~!i3XzQECTbz859DrMtDm@ z%m)>m0XOR+6jR&{-Yiix;`Y&&SCVhRe?cLT$W$YgwJ*(J`mmrrVA{!en5W4k&4=N|JC#=sL?oG} zGKY$;g~4rBgVL8dAi3gC-`!KIaO65yrdJ+l*X_h}D6 zq^ny&y#TkV|KE=XM2s^FZ}srw(W3kWHlwaNGm6U;n9AHz89rt+E3s-ba(cQfxz{LM zU3}M4C8-#HNVMiS0IW~%J;=0^U)W9z)C|6M2AW7D={B-3)zt18bNJ~lDHg=!us#+G zTP<_E|FPkT2xvv%Q&q!b^immT=<}SDh9~U&D$$(jZ>v8Pqv3Nee;t{v1x%(UHFJSf z<_6JF#*ho-ALVjLSA6Wx`8{Ly6x$@>K78j7!V9p!578OAzgcZ7v5akZFh~1tCbA){ zpk{J^?%F+dFvJ-isEJT^bSbpUQiWti&98=p{=lgX(v8+v-6m(J84KXg&^tI3gf=4m zf#l=xQBxj#X)Ig)0drQ3&vqs27ErnnQBaHSqI?#=0M1|neD~P^9kB`(XoX0B@T#fC z7Y_nYmCryvj+sd_I3;}GLLX8i_94Pr>d-Y*EpX+_V@H@l*o+TewW=A0Fz&0z$!}8c zk`;@gw#P?%)8Yb(+LV8Q$B#Btx+tQXSwFPGuy*G-t5MBroWgf@Gz&E|q@L-*Qs2Py zZ_SC>Tk49^;<7Py31Eb!1?~b1{X z-;?RU)?RrY>DLoybcLB3uX~8ozBtSb< zus1W$K{5{Wr$=_>*~r>QH7UH%TQnDRXc{*b$)5DKT({-06=U9Bp=kRj|s7Y=WA5|6|mFnC)IBQwzFvP??5JWn`jMK2%ts69UM!7)`9%tSny${iAeBS)J!q{>u(j&Is&QT`= zd5t5n?A0NBRy`y2DThXJY>7jl$B=l^a6!KG!l=GCUb@5O(CNob(b>-2u~v^N>$UOA zz;H9#QANoKT%UOcb`iy5xQ*whDHdODc4^k}2;2SxtqOej)Z!J}u8Vhks7HO=*;Ry3 z1xToU>V#8BRX~ukS8LpWLKndYG*jlZIhV-O&dRhL`M3lX>>=V5F~t4chw$Ku{j5_2 zGzOqI{Qv;c@sRh6M+LUCnP6}#p?et|W9*LcoQ1s~rOL{(8B{ho%T4~RYf=c)3h+?7 z8%04%tQF`366QFDPx%S7g(}(KF5MZj+VMz-vM?i?x|g#}|9-64m>DJ;$hpKf{@P4G zM*4}RP0cdO%SV(@D4$`PBPavS)}CTkG)-bpn_(^5mZ z5U5nVedh)+;>g&lOzf-&*?Yc$j^G-fLr}qaH+ks*+qXgN7mCKkG0@kaR58jtK&k5w z8gVdb`Ny}CcQCr-Egu(B_HNx0+R?cuV+H543GjS0s05?V0dQO#Urzte-2KnYZOYFs zUb)0$p`g2ls-*OIbabmXI9_d%XDBbtfv%=AQ-y|K|qRl$BYJE>63TZc7>r^aa>)C~-l-XIxWvBem zI^V|zo1QK~JdV&Uy-K1PdmD*;+W;A;H)2sM7z9W_Cn{$AC;=hz5yN%UMbAPfSWS84 zSx1}Z%GZMyge{{Gw~YsL1s-ans~T(y3bLdI%Mox>P<$^&kNZb}uL-{v5Eqh+hLF>- zTFIWj=$S+~(kvn^cpaD<0KDA7^jxkNY|0*nm6o5!?tVJKq76*Thv(U{&8C0<4V3rQ zAR7os+z|9Xh9=>2Qk~K@z(;^dS8Ex><p+W8)gOGMQ&D|JTUxtDM zfj>8{e$V2}-f>YJmKD3G-GP z`+6~ypQv>TTCcfNE|pOd$HMu(&gcu?X7fXTg$PoD zx+i5wFikc7t%`a+24U{*v4Dl}w$4ftOSU74ovrrYGU`IV%1N>$V?0ZoL4C(KHBiR< zs4w*rA7l3-E2@=6^BGAWrs*c`iM`%6cmdIMe7C=%Zfc@GFWBYtN95a1nkfBGD@a~D zuY$Hf62zvq`jc;e>Y*QdWb35&3V9$~B#cQ^BwPEyO3NZ$WH5KcOeZr$CyFZX1RNvj z5|CVpU>FTwr&OXaU1+{Q-M}LsPS{=2L1-z@og`Fa)bz`bgJDg~zXeSVWibm80L#X* zrFT%ed?6%<%nb9_O8=fg&r+3E8f_7j7g9^cFi?F;iqW#*bfwTjf|SM~ zAkeXDd%?i#YO;!~!^@ClhoJXn;sLkSk{bZL=>|9gp|@D5 zelOfu?SfxI(rRb5OAwRB0AWC$zan@sP6lZ_0pioJH*8k9aXsiX-qjH|OftuG&KzJM z16G`TJC90U(8vG=UfLDu^V^OkG&uiB7ZCe>m*+vbDgf||hdz%q?M=~aOgqkP5xeTI zk;*LNJAsAT%{^^1!<143A2~G3Af`eA>)x+5KZwFtP{7;Z@z!K~vTfvHd>0{7D`XoC z!+tjhVD?Q%#Wc;m#13UOq|xuPEm$C0)|%Rp%R|EFBTAi*k7hdPH`^sug$z~*L2q=& z?5cldT6PhirHi|l`vjlA*tHH24>*P{^4frHKsm`4KYJ}#w6M+#*hy;^CUabyx^|Vy ziSYQSwP`tU_&HOghs;#=7nw9OR69?qUr45#lLL_%hbQ`Gk#*W4t~oE>)`?c7~a*NZXaP73IITn>>TtE9Y>#rVHJ$|MXHXbWqy+vd>Wp< zvM(aazi#UlMY47!xxxPBy?M%i6X|Qu8bE=j2e_a3AAHpgZReN}rU&}ZPrdLVI^zp_ zS95Zx-st=;b^u3U>aIQGK9XabA^+Nhy|7L-91Wna{=;)t_tvq&dTQN_u+B(;{0Avn zd}7jQ5{^&rOV*aG{Ir~rh_!j!9ckyrpk2qM9GdhTi0=C5XKpK)dDGf zeQWThY1S0|nznJNA2yyL`~=by!7Q{dA|c8G@046~NRQEjL>sqdBtGD-9CYRwZVZCg zDfXhcX8QbZF+pz*MquL&x1fnV#* z*mc~NpxSiuLf{XOk+^17tB-lD2rNe(Q$}KQXK#W_D@)q_6UCqE@G7Oj)Y56Zer&j6 zg7sahhVyt)QXjqKW@`1`3V>Hve%bTWqr)s+l~1Ff6Q-+3F&5IMy(3mZ0J*@Cp#{4R zddbzaGmh<9)#5xgn7KAv=li)O)VCMg3Mdv3#lwHyUU7Hpx2*VG%yJ$2%WAgG$J`a? zG`-R=EX#Gu6CWsxinti_%T8-Pt4w^{?n3kJCWh-eX?nT41~>k$=N;E!dp`591j9fu zO7GxE;7_h zJ20S;bC6-pX}5~Qg6=b6=>d)yB)b`=BzbEjsa^xf%y<) z4R#Xwn7ICQVpbI}uuCcdGIh%W1U(V+KA#%Y2grb{4x%l9u@C#u#v257GBGg+tyZTs zgj$v6#MHZMHcl zN@?qan2*`Vw_m!51}<>W)ls2y$&|%*Q$VXRIwdIrlU_M%kmlWjS?VuXHXd*px-mX#~tYzez`<02$K+1 zNuvnlC)27+k7F@=cTmA_bk{Y*1vqf+RwsIFL&kQdKE#vFh+&qKh>&iO^geI<&EFlV zK8X6f>OmX$tqhXMvhtgc9Ed_ArowXYh@hIGL#BYHLa?8@b6_gOR{tsY)`drs#I|+m?o}U;Z zJj8YLMq|Y`M{XXqTTc{i?@c{x_z({Zw#0B)MQM_VPG`{znkwqrJa^vj5|OQj{gmL- zZ@2nwKbXyQe+x+x`X5~CLGYPJLaN_35Z9G>?kHMSkgQ@5?7jt$LQsHXWVMP*tZNBA z%JG*finF>4Vg^CoNo49!)r_g86*TdKHgopAePnGXqZ{P#>lOQH!(#L zA72^IW#GMjlPZ1n1Rk+k9hfX2Guiv+Kn|knQ3z5o6R86#7LCqITNxfxpuRE=(#@2~ z!$Mr?Y1q#3F^FGvJ_nFj3PkV?-~YM9=YrrfDJ7OfV{03zduM&bJ;lq>^Ex3-mO%({v*9KV)GyIxU8!v}<`OLvh{0L0Oc3a{HP>sE8?Pg2BqQnGHcA zDMH@xU>QgE-q;>qvPdxFYra6M?we3Mj-aTA8YS%Aa0Ky-3c>*Dis)aEHEqk*qj;<6eh zP{}8%1!jQ)@hfpu{%^CPsQy;Q_;w=caisJlBA2mvvA|7p|6!TVd+?7Cq8vfF8$w}? zxS}e1@WHF<=2^!D+po2|43487Z5Z+~-=CA}M8-*4?}~NmdusLq$1`?(rmhV*l3Wq! z__5nnn(V}SMTr5eU@5v~z;T3eJiWb-i@hyn@fEdP1%s zn$YM4s<_Eznwtbc-#?pD=KN0|+zK82>tX{Om!sN$K@O&hD^4tss&N;8ceIVpO~ST0ua&QX#DEZ93zMXQ|1bqla=xlWDficrPLEOTmmD`a#0RhzgTTkv zc1msnij)JD2SY^oZ=_b56tVb(goWOb(63l6cpw%1ekrC7p=vYdo0V5L-|OvpA4R!; zNeP`b3V@%m!Ed&k`x~E?*TOh=VsE>v9i+JwcVa~!de%y3 zZeDxS1?!gZ!eG_qTmmB&%Z9rY+HRKP6mO7r!hsE9785Z?i#zV=Ec( z1UxI=qtBp~BI2f%ZaM-kGJ7J_p#f~1X%5oLlc{2=*^*1#1e*b5wd73;kq{2^`8Bz1 zJ}o$)!~Z~&x>?h2+il+D;&cNUhvd_(5H2C4&4LAnU>kc%<;TzGX7bTQtGfhUv{1hY zMam7eX7wPpN*i`f#?hZJwtQ!kY+uNEm;LG1)3?!dz^zIennKjHSuAJ(UY$N-9XccvJY;&m}fF%f`jaJ~-&3d#fe*F(@+S^g92dqSRT1W?p z6*6`3e)_4mzdB9#jcvdCGYUw{JI|$7y|H0{!JFfb^F??;qh%u3bOFTV`^=X>)$6@g zEXp(|XwO|0Ixjd3t*56MmO|Dn9(<1U37;*pS^opE4q5C!4bTfOr;eBeu!i!-UPb9m z&F9}@M6v5@>f%*@duP|SlS)JfWRhFF8=TbzBYujS+lR~p!RU%+U#p{8Vsr22mPpw5 z4i9=CMtV^?#onAJRo9)ugg(JY`fE3*t@R)=WXsLm_{fU4ux*7NAcj9ZfvmCb%f^(D z@tArQdxW86rm+*=$jHMfY5W@hhW9bXKI9F4lq$;q?C$j-I;f;ZD{pREsDF>0D&GOQ zLp>n0t5}b2*)cW3!9Q=}ie-Zlb{m9a5OyXvI5)@t^qXnMKb_w4lz~WSBJ6&(dbP0t z&)>p<3}x+Xxm(Sz(4Q|tXs|q9L}W+0+RiaX@@+A!^~$6FIj}qs0Co(l8P?cf`DxdU zkThazB(f$Eob}?-9ce3B4@xV??znd*&9d#TNSgWw_PY`5<6QDnvtZK0 zDpUTyt)L!gPK&uJ6Y(MEI@>vf9}5#>qpSCHMV$F6Tb4R-lsQXiZCroOQSXvM^8br@ zg3hzNS-(g`Ajv)=MR5a>70#HCoT*Y*-r#r*CK2h^pXq&D9htP^69MBVyeB`U(_6LF zsd%W?AWpi%y5c7;@ZLW@rNUzgbFmX7Y8`y)Ug3mgjHs5`IU2GI<_0zGa&y;qq3l5| zf|_aunlSM0p$HZ+VUK$djTG44Rs(*B%p~%O8FX+q(*Ba9hKXbH80O+zz1x4CP%N5} z-2OXOoi zyw$>qjSyPzMVqe43nVxW@Q389^v_&OMLgg~8r=L=GYR5*Op~^7|AXP$FzeJ~tpLO# zxRE%i`sKH9v8roZKB0xSiM(+1FtU1eX#Y=8Ze3!b3J6l%=5N5=jWA#Om{RU0!)yOa zf(LMOkr+Rz%23%~chNM5WwaT!TI)?0Ql2~Mu%wqeuWZ#@VCjD~7t5ayaDdBvkZ;CM zLjr_}YY!%JE4LER_i9hH<<6A|i%zS7TQhJ0=3GkeIMe>i9CYWP53~j&7x;bZ1;1nT zIMn{nat6!WP<}4dH{$nB6S7jhbG1wc!BIDEijs|337`Rv#cE}}fKF9^;h8$i0LCVC z`vRl`en5{O8@;iJ!jd{b(l2ajv}6r;O7uEeK&o*Yr2lPR`C%2xsZz4y)qnL@Vy_DE z8hu>~#ZJYK*}O50DHyaT{Uy2r*GV1LV>U07@_pLdup!VxJTjdM)lI%8Od)K+F*una zPInc_L)c*%wlmmWfWKj*P$3GAtwE8#E3hzFd|_viV;v7aEEGPPMQNV(=|I$fr6dl| zcFok#%3$<~3xktbE26K*MQ^xR_E<44BQ$h@d4IW^x1eN|G`us!9*>?G^|dm=UAFT@ zPbuZNN&n-_V6KvwptpRum);b`2Y0;U(i^l$?oycO+4JZ}hM4s_z69~;w0D;PUQan+ z0Ew#k2{5|4SP@|(bnjdALc?R(aMn6qk+$u=-^O>a^BFR%RLbVUB`*+0+IoeX+*9TB zkQ#D>rnF7c69FN*eDW)eD$_r=TZV^yJb_GZYS9Cyw-?7xH}fq;H5Jc6A#Y`PqURuc zCQP{7&AaCWW?#+^iZ2K(pv%lo@j_ENcuQHIX7SVLx29RBdzG^}`(>YN4U0@HEl|Jb zc@}1+_`c|Z+j?xU1>TY{tds)K>ntmVZFT5S4NAnGG-!zKudQ?5Ccn^shF4)c{jw}Z zJkyXfTl;izLFa8IGtP*cq-lH$e-Nosv`OixJy}FniQ9%OHlJPqJ8)?K@OsBs82Wdf z+@x}78iD6DEIQf`4eh?ug(E4Qp(jlGUY<`5DxvYryv#|@G{23fdo~g(3v-1Q5f+1E z&QZZK!r7P%D-9ErpQ~un-Q;_Dr0ypCTxLf*08tzXnA zn_ElL9-#s-03R$8NAa99&Uk&rM)o)QYJDP!%JUW3+4s$YpmEf7enAps1hl~G{Q1CE zHsZ0R*G;;S3?ImVS&idRU0V1p7ht!J>br8h_N5m*@>=}z>1dHKP(P2Hs5nnLtrj@O zYvJ2>0uO@}crHS^hD6FaI=7+F?zyGsxF#Z596L)(=lA0K(N!d`dc>;m8ag3nmcje- z98nuWsS>t3C!t`nz=4JFGFAK~{IWTq0~6T?r*W6irZfL*puo%YauB(UfGn>TOrWV% z^2ZE#!_C!KLpo9!K`ZVOd9Au6j!-_SUqTT8fm~584-5J@LGTK>G<0>s2W6=fkL?c% zYy#i03<4Ym2zvHMvuF}az-000&P3oQRZ2II%(n_f$lV{p9un!&%0=&XdanuWHPnG@ zx9>{jO{uu!t$DygPmd*TiQMf1;_bZXdbm);puzJ)AJNLk%?ulymlgq$$$zgsDln*Ns}eP>@+iUG<*Cpl9GY$3FjD;4hjs2k-g)S#d#M z=pbo=&Ky@p-gn0u7U1vJ-npC6tT17k#L$q0)_H7=&b&K- z4o&XgSoFmuRalDBDANd0OOD+ zb^RD*z^ zTd`~Aoko}2K7A=`sR{L{o)*q;v=o>&p>1mSg6jvbD6Y!MccYw&8-3Vzdzd|7rLQXo za^}Eg2Lj>|$G*hN{v;*mz4W!ul(SeNC|0A1N}tIw8P*?t#!WSkM#}Xl-GbfdW=Su0 zHpGcla-w{9lKkMaidv3`YI*535NZ+q!YR7wvRm^qgiKX^Yl>MVR#_zuhv46F0!ZpF z8}}MJwf97|gS~+ch-sq%yebF!WE{aH=!+e9=`b1{Tgi>m)=vfhQZ2+ai95}X?Mo9c zVD2!nKD!2hzyaey#WfTzYLN3ET)%!d1e^nisFDPwb zanmCxZl1*B;IIOqcYDr2l*kug$ORAOL#WkuS4{r>&%tU*Pjc>eEkBqva-9$hMul5e z8^^*Ae@}48nD%_fG)?g)vKmTs7=d!@-Q!e6WlVM*A(O|k=dg79F8K?D|FT)b25{ncLoG>u@H+DOZp0y^Q5RR~qhH zT&=CAm)56F;)+XnEN|1>!%PGrS=bOFlc~Nj$MeFR97g-sDw|pyUfyQXH48lf!0h${ zS_L+4TQCYzn+{b2sceIK&ALT;M6Is11|7LR@2%C=AgZw* z?TZu$1ZjyWkkz2Q)p@ug+@`YCRFk_}jjOga+*)H>5VWsJ9Nr(b7}KI@-^9P)#-?_I zr7fQpG*8{WW)0i6H+)dx8mGcmRpg9s>@u9J_y19neCl+%90C;$kL`Xp^eq0!YK)D@d*9(shMDNdjmg-Dasq^ZXjF|kG((T-H)aZ@eQBVB{s z$ZA?u)T3Mta;@u;3l8|yBcU2J`s^hNQRx4di0_O#c~_R)uJA+$YiFe3;{QU z%H%Z&J<`=7ud7EI)F9Vyo-S06HmE_ai|P>#mw*QKsDlmakq0%X9(_=QYK&VWn(c4S zsP3R1RTf&POHLGs$(A0}ql%;+B{`A;1#%B*_R>Nt0#ewfKpl8ck4pHU9(jNUxvn{W zao}vHUQA}1Ml{Pbb7oei3gz3lq#QG?L+|R6TTq#rnvB45sL#4Y(@zWGuLfz_Lz4+l z?`Cz0|2PdwfdV=C57Uv8?3<$TEm^8dUv;T2iSWe%A@Yf5HjGTwME7n6O~V6kV;gRtlaU(8)5W)=IG|vSo`ZE#MYa$m}Hc zEz4@dzGV+l&#uxd7`ANMvqc}G&19sG8VS)NO2Z}40W}hHhO&-r2o2S$+5y-Uh)O_z zu6|JgJ@WAztCc5m$`thH>Rguf#%SdgWi?u3`o>JsmJ}RO04zI`wgkcw%DEugwLD`2 z(tg>D-=djA+A_CqNw26p?fj7n-0O)Rr^<;ZDpq& z!Rc(nWhXu-S2lFQ#a2n;3h_UbBkBhhHdkW!ag~}xnb~le;&4YHfUpsjWL8G76BaNT zCpdnTvcu~?3_uVmIQE(2jThPMY1Ff7^QrdKc+`Hg<9=WxQep#aq2b#XIzeSNf{plT>%h@yCL;g`A- z`Hf=28E&etqL@$si!@qmAOHVTp|{v(?TOo&W{0rV)uIp++F3y(phM&Yw32iky^0dz z(km!ToBGhTr1l(H;ymX{^3~K{jCW}6M!;eMlDuMkyi(i;`!$)Vjppv9xvQg^Y^t%2 z`s^=j1pCXE$*8gh*ln%MaT7dsKh)|$0ojb>K5bC6*c^V=T1<0bg5~EUDGP}-RzxyB z+C-q$6@w@y3@r#E4hl8!xZ(oh_W1F`lKCOz=0uD_viC{TTtx{P?^RTe4F~7oih$PK zlPcQ>1WzoR@ku(JHo?h6(QKf6X2|#{0vuFWp~RCQrJ5%_ig=Pk6Ui8kNhFJJBv>JX zZZw(<{!p^n!SrQZLst&BBIxCuDf6p}nJ6VWw&|4C~!a=(51_U$`(W3il^N^4qwk!zhU_e42L9}Hrop=paSy1U!<>F@43IkoIg zb9YMVzyH6C9BZtKICOV+&~e&Yd+oc2pu4+=;Juf6rS5)WmV=^{)>^BRHEce6wB#kP zY=?pb*r1CIw%A~i?q`o7S%-r^9v4~E#@w>SjvTO5Kn#1?!Ug4h0A9D?^P z4#6vgGlOb4GlE=g=Vl)kHJOaBwMiEHVhk+ez{Z%;*ww*B_Di6h0U(nBmOVSfWd)ns z4@a5~1+pRj|F^al6+L|x1E58a6M)T8Fq5FjVsgy6MhM=RIR3Qw|NrVgBnvMy*=<3B zA+{}qMjQL_VzcM}|NmNRtv^aL8i>OgjW(<0w-!NqVca7im@?;EQ1>Yii+?}fdw#t6BG{P@9GW*wgmtE&;S4b|NsB{erdmN|I?3a z|JMEo&|L)swWGUgzkW$h7d`m@LL1cKzty4ZJV&kRaq@RrO8@^q1TiRr;QzmfL;wH( z2mk;7Qfti{+n%}izec*T51rLr0rUbR-PpHpj{wSk%Zx&(zdZsuvzz?dAcT8_92q$q z0o>Ingo?C5xL{Z9NJu*)(f$ALU14Eq(r9UM;Sv?KqK8Mt4ggZ%P~1+~baHB$Hj|NK zOsplyLI{$y=3`e)XJPoY1CAY%XpZjl z!>}EY>b+ZdOQzd(m_Y{{Zutwifw9(fX%sPaYE&y|L@kps!?D0>$etL}Ad6!oY}eJl z1Z6Y)_m}Zegw0EVtaUOuyuHfuv29s^?e5|0kw&J8gEATJCB4F;VcU`jG%W?X*5AH^ zKxhqNH_P0K8dZEC8*IbeW7$rUjGM#=^9)#iu6R0LyBj$sVNgCN!w#57En@XLdL!NolDP=yC$ zX#=lK9G%3{xw|1hgp(viuPyfuM&NMR}>%+!!F zST{;b81EjTYP9r_;sH;PbjhLw4=Ns>qzRSe6Sv2__b}B#&5<`~W)MP03{K3*RJ@=- zy%*HzwS;Jys%alCK38``NtP;EWU!)yktnx`mMSo~H&LK1zPD!3v?~hAO%*O&Ck%no z0>hoaibG*FY`oSeLE(}m2b0*9j}DBQ2)qf?h02v2f(Us*3lSYo4ImST2^Oq;W}L1I zT9kGi$zDdF;fJU)JnRTFb(h5PagR(Dq2%Nwiw{4XI)HO(*0zt$b$c^Zf=vNF5o{^FpG; zLL6BZ)T`;WVR9#*jv`B7p`av44>V6cfIc&Tz8*SQqtxaID@c4_H%Tu`3KIaUK}rb| zaCpPRU7?r4j#dYnl0+#XQl+E@Nl(ZLUUTfAa-za9gzE*T9xrBfonT%QSGpvjB?%zJ z9O>Z*U0}JOMxYrD9(hwH3lB1DQc&Ry&F=&(kS}CzzLHo^To&yw~2?)rX;%tPefxpR;}&=7AvQ(?oPE*nnMpOB1?Ag ztk~QXuwXH&M{Zm(0|W;Znk`^E9IY@TV{NrMhU`_r)`!BOjVn!3IPxV02p+e{ z4z;lDnu1^y$Zu>WS8s54*R&CW-8I3d{~@#U(C0*0JLbxe1)H?+G!;Wuks@O*5v?6y zMY<7%hY+b5n7WEIFJk0DoDV2X2vsF`UW zF8R##cCnTSBrFt&U?M7uw!mtkA?sAB)d@~P6cOY}Y7G?K;pztxw=XQ%))(gp8CC$I z!VoDt8)RGSeuScEA`KB#+LQ^?#9iVMh6W+x^pcS3!TP9-rp zc>}}<09uI2+M#?_<7|~)7Z_C!h!Q(~SP9}HtD)O*u5(BF15jp zy|@j6VE&(4_y6PnsdluZW4T!4P*-iK#!qQTsSZv0KHjE=?TgJeYHVNBXH1`<4%sRD z9trm)DTmGQ89{&Ot~zHcN_6u|I#HgCKmBD^ry%Ivfx zKW*1ks%g7sG33lr+jZtT^Vg0(vzH2e=3l5i)H$r_8!tryYMN#g`u0;{?u6zJ0*QThTAlY>T8E!lV~*G|5%aAWKCz^6VaCb$90%B z`|?H2zMhC@_BH#OeTh6AjB-b*=HjO znijt7^Tzub*Ar#m|G2K{lZIl(wNYdrZJ#$@t)|CX8G_yC?dR?_JtOa$d4^!u^vh(_ z%vyQgytd!EJm)BC+IP)7ZEO_g?Z<`^kc=+vhp2lEW>kB{Qg^sHo7K&KJ)L`MmLBHSL1; zx@>um>xp>GGwT%^$HnzoD_40>&9UXG8&9)f%IA%Tqdz%1w{vn#>O39oyeIOfC!3M% zBy->b?HqLUc!X!)ob%S5w+>)s>9wbP0zs^sVBl; z*vm`DtYwam6K4k{M~~nP%ScVVel+XWE}ZChtkBwPg^AsGk4gPUC(M()j&#gyCuTZ6 z%ONSFdGLdf>;W`TJ%l)zXhbR2O7Y8cqMNVm73R5{LsCZb;D->L@v+9o#(L;#u}Z`e zwLB;Ka>!me30rBO(E^;d#Y=u$NKGi9C|%`gUT@f`8cuUBj@SO20~?G7n#X5$-{DX$UK_v zY`ePSaj-BavgUpxw(B>sPSviCx{%b*^IQePV4_Hd$?% zK8ZXZqFG$PmUMVlmn7~xMf*MnA!I?-u54>RIc(|#>&3z%UDD+ zz*Lz5W(&=|zCP~kdm;=bB4J@KEcv7@d1WRadfF1L$%iO*gTX{35GUXRIBX4Z#Lhl2 z?6qBEFZ_j#z+sO9X~!wRWc;GCB(cXtFlNhUI8v3W zh=LmTD+ZU3i~7*S*or|z46YblMZjp*hPsQ|E>LSK`&xsjw&ibIH8seZ)^k_iFP*Gb z*V1*>?%{T?dRro3Hz3hIEJb}w?AknQ=r1X~A;47B){5g;gRr(G)!5$3!`fSw%JW_j z!hJ1R(tW#b@KQzldzKAfSzKLWmb}F1SlW4Am3HN_X$?9n&+fAZ8G`*v`xN2zSsPG! z)S$3*4VG7rUs95Us`OMg1Mja&F+ME+HI;$&EB%?(KBQxO3@1zNIjTV(s?rut#TLn< z9#N%jOBP`+y5uv5rACZ_{00gp8H11ExdrGKR1+0x6ffkHVr_tdYu~nRJY}?HbaZ*z zQ6CPgo(dUuJ6tnNDdO8vE)-CJ+U;0P$v~~}+tD&Os(9_Z+_7ez+U;=dd>n-?C#c={ z94p_0| zswAJ!VA=2+VoC=jqITic+M%s_LN?i_3ne6sITFN|lx0Ol79|XAn`TAX5MEst3n*;6X_gB?e!Oc6 zT&${bU1HV4N)sg>T|AaN5_ch=p;DyH(+XI6IJsK-0+vbf#R{#=m#SD;MAYgn5tU#i zab@4DaXO$)vz)5zylEB^o{H;KDdGAhhXKm(|q|QJY@*P_@Twdex=G&RHp%^(IXRaQh?y z2?=S7fTJMIndk4TV>o!ty{itH$S2-sY*M>Qx%Z%|&+WUlZj;JdQg!cJI$K#t`JL_n zLlTXzI~$BPMtx&ftD9s8Tas#ERZCTlOa^wFBjLu5dd=c%Dfppzd@V0W$%k&0jD}2) z=FSGAzOnOi15(dS8+A#$)$ZiEr>{_TiT6LXE|InDxtXTvkyesWR;2%_+QruoC3hXZ zUlc4S$%k&$uATu2PejvIkFyDWKDMfn5=Jf4v$6z|#;9ekuXgS3S_VSJ^~tPGMP%1j z#4V7Nezjtu$x`y#MATQci0_vVSvP%7O_p>wo_L3YQ3I$cq}{0LZp4?g`hunizwf=* zhN$gL|3h~+9PMm?szEeo$MCDmlm2!GS-w7SYkuGX5xF{653lXs!3VV_YD7Z=D<(|1 z$mJ?jmHMBmE0)fa4wR0RPEW_DgT++?t6pERDp>XHde*>dVAQDYs@)W-J!M^WRoa7= zk#`1EA-L>VC?7g&U}Mvh-Sw-sdcV|z);=p1iPVD+`>bf}J6H}<4$p^98&p{3C(P)M5OMKP^>ipEWL)g|P)=3x*a9EEr{AY{A&-y}l&us_(5z)!J%r==x1s zUDxugyuUieU(=e{)_bk}_gdXvSqiFw3Te|TA$s_$Ai}PKP_oBLQcdHDZoU{i_;%F` z@FDvo_!kdIY^m|Fi|p*XhN1JJ+GbY`qaLl<7tB6|#vroZa@>inC7;_X2{6}B8hK2>bjZe8e9WZRYA zwk3U&PpvJE%BR*k%N8xVmR_lsG(1=Lz1K^732Ita>NNRY$J1NG6giP)#B$QqeD8(`pQ?w$}dWkgeXmM*4-J zZ!3Wm5*Vj#byf1A-?nFUFLrpTES0rCr@r>*+N~$v%$cLSsL@UP3jO2SU$-8R zr+wCL*|(zH$vx#xHg_DLb&uwt)GN#qR_Idqn58bEr^;l6BF~$scyxx{aX^pOnu8v# zO%7J*az&Y?jyQAEt?6ln*1Ciq-Sk8ytkBw|ZT*jz+fvVVc7-vu(Hs&ZNclP@|bTU4f?}y*2`T>=}Z8&6TwKUm}n!;U_)q@z- zU6e+N0Jt$4cHDg<=)-M3-ZSmw!Yh8O)N;>)4iqU;RDV}0V#VxOOcA7 zs5n@dBWFBfsVZI#E*U>Z!=BQ+sl=KwTs5wp#l{X-mb+gN^{oetYEuJ^`364c$S$-5BnJbbI66{C_!IUN?PE?b^gIM=+^@D{O zG#_AR-TPjza-qhasCAi;LF6`xU>!BTYQkcFM9qJQpmI*d9pp$*qD0j0AmGtE|BViZ zJH;s|zjl0GDE`{v#*4P*rR}`g1vPMJ(*HP$C^F zNE^~3LMp$osvbnHB@HLI{XXGa=CR}TD1VWml=(vHmSN(TxtTb`=;@->&H<-(BAXjY z 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%0A$r~(s>Z9y#QRkjUC5{># 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 z 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 z zT@84IjEx|GB+Ga~O^Tuewt@@NW`NHFON$Q+WY!rCx>pcX7yJT96p1`dKL79i1ZMsI z4}^&#OtRU~kxVt0N=Xq0O61i~Pgp$wY7yA7W@HX+CmZ-mR7UIb|20vNHx(b3m@)xpS_n8 zj&rc-=doP5Nw!TqG^+EVi5~AK9O@tSF_;h2sd0|c(VDH zx@Q8Oqsay?R<|>DSP!z%{p`fJ0=`${M#&7zZ5cMcTt`ph0JD(}AmayO1b{A{R)MQJ z-f->p;O<~KZALu0QfHvY2?^0s6q$t0rp7qTm#jgr+%6Hxyc-_d4#@!25=8AQ6x!X} zh%U8yh+_7wiZ)@simBqHa56VjfyQ~7?qWYv>p5YO2u8LUE>B~dHkkv>SfNpV^0&>) zjK8}NjIn<5s>MN3GLY7t#+be+2uF?z=tlZJvfN&xXTr^DybR2InB*{Sj<(kLtMd zZ^ma{-u}10Gn{dtIIjfsUHlYa_Zj_IR(kUfUHc9u;+*3o)1fofT<~6>qwVZT6!qTs zLK6Pu5E+#)Q>0Dra1YQ|)=)~fLLNBS-8NI9ui^>z?aPyQ$b%z8F;hyvPvlV_mhPvRC+HGUP$`Ke$Y zs$3W6G+yXQhnjUO`qGo)JN}-S+Y|VXRfbUXfqysRr6YLfVcss>fbSBkqo{>Rs$uK{ zaf@Q|tWCFZO?hiP`89rhOq0_x3@h~%EK|{o^QL?D2=zYS&JDQhT?j`?4h$1!) zkeA6B-Sca$WZs)_loewCiPV$mycC1yW!dew!V{pF;RLxX)k|DnE)Yv6A0E*L=s3d< zdE2^&a4<2QAndA%J#f}%)94;ZVT*0m;A_;x_G-B*mGzq5AMu7+ZG5t<>4Q}f3QhUF zQOnl$&QxQUR_&ZV#y%4z;+51{oHizwa6J=bLFtw1k5_`LWTcXflIK>j5jt4|&o^-1 z6CW}A!V>RBM$6G%Nw|Nyo8A56W#BxDpHL{hz_a&nw_Y8pHJAttC9dGsq+Y0SRT=7k zHDu@67RI=G%RgH{6$;~GDxDm*Hz@i{>XfvXloaNrhQji5E?TX(TLD__TnJaY##~m7 zxwP9Uvvs{UFM2cSVYzWod0V3Mze{Q2x$B*?JsR2-XcpW?0_&=h8j~f8ol*-5W}K32 zsC8V=g?ws`59~tGtlppjip?-whIog>nZm?7-si#^t?6q`}^8BOhW< zPk*edJo)z=R~@OS3nGEOT5@+kq;O|!Ime82QP?uU=l+VFhoie~xy_6oDctqB=r(`% zmJ=X%M&Ekjv61a32Uh-K)p(Q=zMwm%njTNR4Ux`58$xmq);>ub`##l+6$C_zo&QLq z_Q90$r@CauZ&5Srh_ew^I&5W`f=<=L)Yg?qu(TZa#uZ|E$36$wcoT<;4jrb*!6N59 za6-Yl^prVAkddH+WBb|$2*lNx?5;9}3uP{;UrL#Dd$ZfrOfm=Q!Z#B;iRbK$teJEh zN;B*_Xg1imJ7{Mi-$2LFQE#Z@bCj!>HLSfd#E8!tCdP`UF;;`CAobdK9KV*q1m(Cm z>&}OZ8k&f_q?R`w~)}k?CSOV zWyhd9yIQ@F7s#u<@!kH^4$=oLn~eHE_8qarJ1lr$(A7n4#rOn7o{A>L@&eK->_x7oVnF7M>az&w<+f^hVyCf+o0pNu$z2-5djwjZQypbh#`VQiu4y zS}OY_ueG&z{o^FXD=7Z6@9dZ=v_5`#`w(8J)Tb_yV9gBQ>rR*M6+lf}zoZJze@a5a+!5u#?lwTNZk5{yw{?r+7@^Z+ehI1ShvAN(ptl-9?uHHZW4q7M|Cr zwKDjr5BD&Z(ITgPrh9ZFxuPW4QOOe5SxyI2k8P?OQ2zM06G)>mDgN+|R{Q_QW_n<9@e3`12En-Zw(e&wN`{Pisk|=b_Oe z2VS-;s(&l^xNw$7Kn@ogq@86<&EX%)BpLE~8=neZU)61=MV67zFMda>`l7?>EsX%` zgf-Gl=PwIko;-_hZL6X^sb}Ln8Q>-kn0)ySQ&D8zz(Hr4eb#rtI zMEusv*IT($^$9Nn#m13?z;LT1LY|75&(L_ZqG)3|DQHAU_F14Odpjif9r}zTNuUVN zK}O<`QIq~Qoj_cansxxL@b;u<1h-M`l}^I8TlRv-z<#pAx6gA1KByhkfTC3aK+}+C zFEGs0j6{da_Q^(0HhQv4g=jg#g zGN5o}46)!}tiJO}c%*8gQ^+}h5?(QhiBsQ7OgR1N;TGGmD8MTrXaub`(RM762nCHK z?jC!6At8es*iPusx1;2xwWI!kG`zx&nPPgjEbbu!YURylb_*oK7}J8QumEtUB|8ea zk=t3v(?&L%D|qT4FB@CZ!*JMYn;94BLgJ&xY_N_Qpz2|M#)lRF0Tw#CWh%)uu^}Pu zBlg{yjwPb1uOjUFlIyi`(gK+trn$|T?-d3>(2#z$-E%n!AjxUix&7K;n)ocHQ&H@>KIa zS_K{)U$d)(wV|lHYEfe0Gia*-RbfwFw8XzMRt^cCA7H-kSBZ`Lg`whJI^y)WS_`e{ zhO~%*l2{M7vCKawG5>Z*DL43+Jno1gmkIRl=v^5nt_13*ioLWPgODJ-Fv|Am!Wcr# z{RAU`+R@^x8C8{-C8x0!r=PpLD^ZGMun?@RXWN2uX+4XS~ZyTvDvIYd~((C;0o}GZPJ;t6RECX8DX9hHbR=w*%dE ziGIMOEWDn_T>9RA^{eTYK5zl@gL+~3JKS3swq51iNEvYf63egae-Vg!jxs#aoU(i2 zk1V#k^^td}nGmrSukMX%_)f_#S?;xI;nJpRm-+2Rfj+YrOkqW0J6Qi*%qwiqAUqG}TrBVJ9xGE6{TUVe ziO`;Udi7)Z5!?|!z<+y}_t`cSp+|jMWc#6!e@0-KrdROGCLK^vh`$@ap0NrA7u_?A zmaN&@mcPmd9rTjnLzo*355o-~cSFAOBQJR-AiK~++Dy@Gnnw|w-_8!DOw-A#_{0h; zJR@lLo>TKQ0(Et3@|qdnb=R&MEJP_5uMmqpa<`jnzYk|c&w~Y|#?Dwxv=7ACP5Y43 zOPZu;Z`j?mhd#lvu%>uf{@zPvc2dD1hq3-N!2$A!UzH%e4R&~Q89_S4BBQahn588e z2lK}>Oh;v6F&pT8%ZSq<7N3vs049pu``sJY0f-r{e242c$osR1dg<_zmLrA2Dzu)H zX9(wRA;$o>{^JS8btJHRfUM^U&kz&N2|>^MStZ1V=_-bob(bwFnb-2YxE}vV&!Sw2 z>9riezKZVO-=;=T@N!U``_$3w5HB{EHw;6rgn%6 zWBc|ljiFc!F?D^TA@D*J+{L6fwhlwAL=7^e)rdaxs<4HaSc3}mI7RQJpK?=VvkNV) z>aQHQcP@NR4u|H&UTXnB2}cOq)Y0sMQL86^O||-Jdgv};ole?b0dDF)^_njdA2l4Z z{WJ7_(1^lsw@Tv-hOzVpUgeFkg9uH!qBFIT#_s9?5VtZ4D65DDS_XD)0t^{W1SYwZ zKF<$lm-ASP%j#zKP6}{p5k95Lw1i{c>rq(@E(gZ-0XE+mAy`l34dAb>w%7zjE+_3Zcwms;x? z9Jl|!XDJ^rUm-K^(@lHvDmogRVNOEDks1w?5_SMn(@r%)P=!d7XkqK5q}umrlPz+FmQ9zCX_U-j={5OR{b5Bf%57Hpl(-6h zPx+*yQ=PqI3PbPFs@z8z@OaX_n>UJXPUCC4+})@(s35(;TUfwYo>yV#z~FP1o$y>H zX#&KRDpv#I%|IO+l}$YZ9Dc$i4TlHEPvw#rGNJ|9W(^VEP~<2N+QNO9RI;%}M@j!V z@_qMPM-GpXU(j;C0`76eXDxh=fyiG8xUvI*@mL6vA0{!X3sD$7&e zrZw(`K_fHHbD?dP`&XdX;%orp0^8OCt!?(tM3ADMer2U2D_xIAh{1~4s8`e)b$*9v z4C5%!5DWFz5BzoZ{hRC<64tw%d% zghYr+Sq1tNHGO$Dr*Pqiq4-sNmR@qr1!$+3ZErwOOIUwFuFsS~Lo3pESrgn|eU#E9 zWVARK-z0@x|5ZIOnSLUGaUH`-<3h}FfO0>YOwk(g-1kt>Fk6Gh`gmUhmO&25oNR{# zaK!En0{|i@?T^!(6yt?7XYxgTuhF+x!cyP7sA_xLvuDDZ<2xyOR&a}owDfvip==$% zwWV1k>3IO8aKXw<^RDZCu?L;d!?f-@ACe@iG(mEv_!Q7<6HxzJPFFsb7}8g9@MF?X zr`zZEd#~1Y}kQ4JHk98YFj(IoCN(rWlM4wXhYeCS2(U~ z{;aQBbiyZ;la$ z6da#m1i-7wv|CF4{wp%K!LL?peK3Q>XA}7qu7qOnpFlt&Ko9z<&RVA4)rerK^-B!m zalY#?w~SusBiE`K6Fr)w8guJ&70r5Z0MKbjX{Z45k|rkvtP~H7otSc_$t!Ul_L-`w zYYXVjgY1^ROX~g9Gy)rUrOo*FJL0vSvS{W1@mV3=+Zh?6FvpML6z@|f!!1>lOC&+rBFiw z%)5K_2OfYmFbmZMD)kd$nWqSIJk8?{0OUObvl8*#UssotAlR1pkd6OW%*``vfhuw^ za`Gtvo^(tFcIr_>?D=mz#Vs$grP}PpIR_c|;2^};{G>fLA8Dtglip4_n!yD65O`$! z{tUCk?)6G0%5P*2UYduEAod~reE{n(e4SIg802tR!w|Pzs5$rsLdo}K^a3o151btU zfgy%ReGs)08_m_V8L4t@AW>SUN#>P+o5+<)jwmmZ#=4If9&p6tM@K&~gkxNhnAz8a zu{|4&*N<60;>i`0)^Wvp|3%rQWl7>a@L}! zIBC?n@fS=|QsX|XcvvBASXWE0?CKSC`5hRk4gSA$oJI;fhxwV~!Wzh?!N*O=gLvoekkd4Fj;E1w%? zBd_snAyIhHj575YhD8Dm20AqIj0ZSdB~88{Me8|ZKoZD5Xr`NOTv2)1QtDGa-@1DF zpw^giVLH@gxpuy=LWbyqs+?4i{#7tZF{<+(ykATx10pER$;NcO9R_R)W01FSFJmAp za4?rHW{EtdofgO}sW&}U`g};aGZW4~&@4CcxM*-sEeU|*@<2r~uRpN4>`@PUhJdBJ zKpI`tlOH={vO3;!AlDFQgA~U$!H2cZOrP0c7TBto_0R|!74dP(`AnM={do~vqW{A` zWdb=>4FP27GzuuiRK*Pl`LLy0Xuag)LYseCI7)uDSuFp-*K_MIatI5?`iV|>XYuOg z?@)vAs7=*?^Ff#A)i< zw@K2E-n1XF^bjXwz7N@H^p=W}5Kd~6pXFMzbOvj^@J8JnA`-FOaprC6MEK((IV*kBkq%_t;J7BXDzZJ3M+Q=wc1mI-0M!A zHVK07Jf#wfjP8Yel2EI@h8FVe$9U#}U?ivm*9Af4z;x>txsuzgO1fHii*@(|o=pLJ z>(H-%fZM}2mb?}=o$m?omc`YMwpa@{52e<7_@*FDaYXmeoAZ?wu~6Qlrb?SA2F|b% zHf1iHbl1##4`P1hPo_DcD_slaMzw=@R!M@jY#b$_?V^_*n83y?(Q1al?-(bp!zi7M zpg01-^?t7n-Mjg8P&y2nnJ(T8Oyx%WWasX%nU#&6X1(R0A0#={vqMOskdf^B+|Hbl zh(*|&HbK`gv`c@EuZmg?$LRH~s>Bd9ZcPTPB!F|M2#by`3vE^;O>^zl%qD)}f3=g! zYZGb>hPXv?M?~NrJbl$xX^Lqwe$VN)(&eaBiPI>e>ycadFnB^&-lIDpYEntFfau z^dNtNX_KD@790xBEFQ6){%2eZ$G~hs3z}ou;<$l|?x3_znc3QPSRrb{s9PGS5*2iy znI-m&cr;~Cto?-Xs{l(pph;(l(M|=GChBJ%D6a4MsY1#2`q91h?MusTU?nx#;0om@ zV0S|5PTa{eu+Pv?p6GPN40fVH?f+l}-vSl8ca8X-ox{EdH{oCOczE5)pjpXgg#6}v zLf+3Isrv{nKfxqPo0&(a0TA=Di7WE{+xVVY>1T+I1dbqL*@0CMz{?WRFPUsRTw+gl z?YW7&TV>P-1iJx{QHN4~56+mjdkuN;^~^>GFL!Hs|MY?7U;^KBhug~g2xO$l_)_eP z>!gn=flFh)1Qy6@TWaU%@hPa}FE@)02573TfDnQ)DWt(7(9B+lz?PDzaTr#EsY`I8 zOQV=!Z_hZ{Wa?Z*fNs&lABid|Ij-qa=hC2!3@<`IwyaawK@*H-WN1{@O=-Ofp$eyb z^k0wRU%B>lV>S=*&HM~rg{=8;5F47c=CJJ`CTDe?u7l=m)N%de;Nw(~IA501Ay9H= z72M)XPRq=tY*ns-iDkF59X?BofUrpWXfyH$$r#4g>0MCyvPsKT9yOhOPynP64{ThA zLA0g93U&*pGmZc(-i;u^$YH14sepu0^*{5y+wUh4m))wLKb#yH6Bsw=r)5_)(BTB_ z#2ZCuKfv;*Cxb~Mh%qB_!I;n{l#?ydHr zzu_o|AX5?+A3+13g^}MbnjFH{y2GieHfdx_?`?0^*?`*<4Z9oCgy!jThewwKOyO30EcxG1^))gdx)8P=C-+5Kf9P>Bn zj-@@*!b-Q@PKER*fwP(~Qy3KlJ+z!cu{OI8609F@R7yPJn|;rZljny_?hl!Xm32*^ zLy{pP>S!BDFK%j4uOS^AP068GR!<-#;Prsf1T#;nQm#`14IYR*1hry#8Fg8#6-9XK zt#cQ3Hmzi%^Mmu&bt zE38MRwVh`-^g2kBr>0{2Jra8=QAe}fVnRe2I7YD7Re;kD4@T7TSSqy6TLnU+4*3A7 zF6gwJDo)0VieHzij(5vA8&0sB%uZy>UsZ<>=AA8Cukto`{{=T_;N|kWg!deq`W##mez&Mm^1LZ-XI-rtlYs+`SJ z2`jR%b&06{lYsBTPcVrAA~Q4iLVds7Lid@jY^Obupc_Vuzs;3e2~!4?i_k#^xUHT!I$;n^7SGX$+qn@?1|v0Oy$~<*dbVKWu=*U=mTZ;M z7L_PNRnfbZb}>7YhX+pq(2+u;GSK=0cydw%lOgz3>zIU{6o_lk7b}BM;aVqK0qSz5 z?Bf^HvpX-*zw4~?lkmYzAJr^aFk3PbnCe@y0MX&pnooIZ<7Ehj2HV^#lkI;j_>(+cEf%mb>J3A{Gd=DVztG%9TYb4Lr3flWEsx{ zTE2n05=o%{N=GsO_U5ykf_p5Vi`!I`x7&ORhlfZr$uQ#wH$%@~xkr++qhQh%J!XOE z;A^21Fi_xW@ZIE2mpPq!`^pmPE-f0{dLM=L`*Swb4eX+|hizf;4hl}GO+ItKz;^c0 z2PLMrp}oLDGj1qY98|{PE)<)lvowwf?vg^HTN8I@)I~A334&!W2j`0Vc$RfjjAzux zb zHyjDmHthqYZ^yWFv6ixm=`gxqy~NnIe++q|?5Eknjp6EeY*H2ttmt($B!>d)_$1FB zQ3xT4QPZP@!HJp#F5q>qw~&+)u0ykcT#XM%fnx3`et{lg#)Y4wvUUX1DUvtRe&3)} zYYM`!yp^=<+FLhF=uEiO5|>0@%L>Q8A6KS6_pIYNf93DO5Y}|n+rN&Pu!W@!ubE&} zh*rJ$L1SnBl^|Zy9g-813ewP4>4{Gjsuj}zofo>s$FPunD-nwSVCybI)TywXSJ$rn zPw)uZ-TA&{CA3~I6+P>Td+KHG8E#KK4^2Vq#UUfd9B)TvlBO58o<)uI9&BRg5Uq{W zCU`x+M<5FCLwtPHh>xM0gW@#ibH((7E!=BlUWr;k_;lnA!FMV`xWd)>M(QLvZhgS; z;JP4(EcuiI129?AhdHk_0q*9lb6B6@4*Axk%v5VFRPx#3VgY5_uAsjlJ3!NX3w~o) zYk*sMLLucw6|6$vv00-Hzj9!86n8R7$jNoqm-9zeZM#S-5$32B)8f@ysjC<_^gdR# zIenFXrRZnN;ajzo8$yb{Pw#UZk$f znZJ?EldwSw5I6C#7K$ect53nyxJiQLZ(Cf6C-};%f_k0T9#iI0b*zYE z!nP|UitP@R0Uz^J8I|T{bC1WGZ`AlK3fqz-8JV;jX(#NXf#Vm>(zF8q{pP8O8?$DJK=GqwSaQ zupdT>q=g`!oa-h3DvL!v*pNa;t9kwmN6e^BC|L1#f)pep%PUs!EHBAO{qf;Wvhp6y zo%NpFIA(#QCF(*ykYgKpUk(M!(9oEz_9lM?dt?QJq>so(=!4x&ydJ2n?I@V(?zB@? z7_te}pDbSqTlXQ$cfm8=bn~_2d4vfZ90{X#&ua`fVNUc*I*<#I_$qycmP9xkrLxb` z!3omQZzYHmr)v!WvGUM|J5F|k_#)wK3w3}lH?5(zCYJ}1jhG!3?&x)q7>BxYI4zR$ zT{;+_tG4s3;h}oH;gKMWYOx{7nSP!gsAsD&DCy`pzF?)Gi$IYs$Y*RY={U%fGhB=_mwCX=6q*_ z)4di=;T#n~&oas%2`3}&9OhKeC`vUxosp4hahk{y!1(d+zEJK|nBry6tP>eCIh#+( z?j?Fi@M!D&0fuc+Tw<$3wLfQ1q|ctLdxp7GWUH9(L2)mrBA`TbXkg*fgnNdE6VVwA zMcCMU=GK6?5SB;=Di{eNTZ=Gn0VEqmKz~2!AN4X5?#rYr$;OTC zo=a0b{?n1T5HO9gu>P65rZ@4u=tfOAuWY2_qG(TPmRwXvw5p5Z(*W(pe99g}`SRA+ z^ZjE!NxcQ*y04J$$N?c}0oe@&Y(=j&1Xr(ey}y8jr93TvIjNZn96w38-;TsXP#py1 zXJQe!^ei}!tC?tiv|n@eQ$0i#t+X}Q*u<8-zsE$y>HLs-48FTkffUO2Ld7P-rxsd# zBoI}P{kXcgsbfuQqffyVdWKocATK^2;>X+uq1gNt>I88VffrXr$RZqoH3UBz?kaZf zxmh+FgnF&iD*o~ce5C|B*vq=Or6uFaWFn`Z8uJxiFO-pb#l)>^Ur!2Sah5S1jH5qf zKx7bg70YAHIUG$qhtT18x#-H!bCQhvV7;XdRvpIUEwn0%=6`UWW9tkH)a!0Uju{O5 z=loz=6`Hn9#=qYjw=t`Iah1fP=w?tDbQGs92P)^V#6dn$7x`wIezhK@c6p&`c;OaI zwkqyXdmy`W6Gg>na*%=GrF#psgy(nRd21ykAUdMJ1So!b9((~xLlDNZvCnyMr4%x!Yph|SVomeWGlV;_$gV+vSLKI zp?z78?b$wiIWNz4o93&=O@ObO3LlZ1bfaY z2pec6NVfe1G9Z8_J)-f{NLx1z%8%#h)Nk-1aFp=Zk+mK29486yjrK{Wpyjjz6x~sX zdGsRsxf3uns=%HhC>s6gT)Y$mVRa`Ar(kRWQiG*h-!(%`*`k5jlgHN%u7x?`r#T2g z$1dtEr7j)ghnu#9gC$kgwprI`-8y zT&fQ^P6C^02|I%fgk*LnfiBBxtcHGem7VyHFV)>R!wGSxZDYeZ;yHtRaZ2L(R0PC) z!$fpycrQMqJ+A<&Mwzf99!SYD;YKc)!nC0cUeNS^ky|ZWW5gC9QYq%*sRC44J`=d% z&Sxf8LaeC?s?6lfl3KXjXH{h8fKC&v)`z~ZKuwQ`WC7rF$mKEvT`y5mxT4I?oiM^< z%DF3fX>P7M(RVX-OhL4*sCt&gPEioCI(C1wGo?32-O(E-$Lp1`y-!3x&D3|H3ftq; z-TW6^aLEOR?&M1Zfoh!R&~&nhkI(?E+#c$+AA@y*%&;9z-^(e+s282So{eO&8enuqd8m@vdux7f#aKbYZ!)zI3Fef9_X>wZ zJtFm9ZH;nVuuXIJ8iks7LcBotH9p@O8it|DwUZ`x@Z*oGrXEsD^0y zG($e5JTbw3s^!~NG$bJ`d*=`EKS|`b(r9x-A9WrzTzii)6FTVzFsODSD&^m(2x!S? zfkqD0Fn440Imf3_7uEMZ3Q=QGCkyF58J$#@wZ;i2b#o4l;$^~Hr8kvUWVObmD@~ul zo!+a@QX)(6^l{O5eniaSV}n`)zev)(kGD{D@cQCJ0L@y2Hb44FVy2Hsc`s|pLJ#HJ zBIQcTa?|iZ?%SnB;n^@f-@~iWQTQO$^&c}uZ=W^@aUq1+CT1ABdl{oJYTk9G2=>1o zV?s9^!d^FranYikg$_9Zefb1;okxy?GpD6oHQKANSgl3yR-wWg3tU@q`# zbcA2Qp`-&>uyDk~%KSW2fU9Nulz1lo0#Qp-q}(X}c5oAU9Zc5thj3=qHhIiy%VX)y&@$h$HtU7er$SOR}5CS9Fu4%VDIJ@LR%_*;c2=K~S)c%llT~8QWl- z&MMDlfi1Z+j*v#m-2wG2qwN;jut7m^eh8&5VK%A-@|X6nk&7ho9!w=lDXg@Pk;>(J z8fzK*3MJ{J!*QR{yLs{FBn8L| zl}p?_P-AIn(x|(LmQHo(3Wf%3+k0FblOaoTl%tnHB&MPZ|A-rtbb`2)hB;!TR*NdP zSOV);&Vto4O`P%agKr+OVgvR;H`mGN30y?BuqepYN?;S~T5vmoXH-r#ES7>!XfMSd z!Kp13_6~RFptq&5MwD2wiaD$OZ$Zf=gPNnQ&6F@flAw}ThS0w{si4l7R!m1_wt`JI zY4=Du9A6H}x_#&hEieR%BFzYwIh8c`?EQXjBGiKD6;Qc7IDajHvC7n}oaI>DdgVM3 zX@$^T5%wQGS0Rb?+YUD3D2!{YHJ_sZ9gWt5YM&hnu zVc-COXJ-duY#NH4<gC{a_mybI~F zzVh?C6Ryuzj49U*V{98p7?$V+@`wVf%_P?Smn(c4qHj1=snd^Isv%DUjl$N66`Y9o z4#Ba$=uE9e7z?lu4!(0teIv1qUJ`dgvHXP=SLUs=<#2d7>nW%tbdq~JeD@kGjWw2UfIn7N!9OtU(jkbE zBZOX&jG37^GIK}Bx`E`7IkD^ne(c>KFU#=*IUg`$`7_{y$Yo&+!V}9kugpDOjYrSP zGDgWU^JE)rqgvLo{B*O)n7~gY+IW=gXq074Y~+uoZ5!!{3@T}*DD>oWf!}GfahY>s z*qj(PF$(jQHtiDvKP;;n)}>(GMa_pPn@z?8KPh9FLFQvQ>p`I+3gr;hC{`g|A}c04 zy{m)GXnv1sr+0m@^D|er^|m=lzSf$PQa#+xcRRfs;K$#hZM=!LZQHiy8l>w1D*(G< zr*|b_rB_#MgCXh35coUnfF2MYq=nCxJ#Ilp(_(*Q-B4!-elb}$gb>0AzgD8PkMXyU zTW}82Q&NxZk-O+OP19T?@-AFixMMHm@qtH3aDw*nBP7U)FS$h1TpPKCqSrJ!(nccM zP^3MDGFvtpb#1qdYA^cH=(EiRkH2Uss{N%zF`xiQFoA+Jg0~Zaox=}N_ox$f_1kBV zZ$ck%mit!mX3WT8NCd+l;Htf_-Gtsk)ucw>{<+<FL-XDnUBVH@ykbpGQn z-ts0iI(K=g^tY7qw`4D8Q+}gDVhqI=#29;JyRNMK-E3uHVPSzO2D0Mg5I08)M6f%ikCjp9J7d@1BJzT%hu7raYzY`^EZj_vQf%h{ICz!$&t2igAjE_K1Xl>y*g zj>l&pi(mSGY<~^!(iV@EIzAIy(PjH-$oPUgNNhhhv@)dPUC!k~>2N9E+m4g}Df(~_ zx?IP1?B!VYa{jWHiz|D%C?us3gs8&$cNA(P2=U_rH85_qPT3oc>S#nU$2#~fBsTmg zBqpGYGRhD&WP(c6T^bk{uEplKE4H8SjO{N9_Ka?8iCs`LZiTVEvT3BQ)+c?bBx+0I z9C9N}{;2a8snGQ4NEIk}xG~^#q>3U+O;@c6u`aQvG*UWi{JjgJNte!9Fp)(KEc~ch z&Vq?7mblFYS;E_{aU>npR(mm@)l!c2||Mj zXGsibFySnL0c!{<8l!wwS;dtnCs`X1um?>B(EdX-N} z`MKFZ#G=~rhVpKl=?zQ&-msT{qFB+dbTKCy5p_CDhi$-*;RrS5N3YV=mP%KGIw~FM zwY5s8v5-oa*%*#c>#KAl8^aN5e?~>5R1a!VPc4cA7WFEf$j<0k)?`th!&WCIwY!p|T>hd+Ug?E-p>pEYwcyGvW%Itzc!i5j1g zQ90GL5p38!5JJuR=QBI3R;$&hQQi4~pJPqrvz~KCcX$4lOqAHHHRqhDmt)16sM0hD zo4R}tyY7KA+)8Y3^kMfJ6iwLqkeZDT_(kpMk2>FMMxt)0H4)n|3i>rZ>TdXf{l}iq z@RLB;jA4?fKEv>aMokS>_iIkY<>4D4`PR?(UC05!>Bq-HoCrVqq6V zvmy^h(KNywQE#=e#t6lGJbyw_=kw2>&z31*Cxj4ocCv_VKoQK(*hNoTjE-XYE5b9> zU*T85|67cu1=JiX~%Q;^7q?EGd-i{66YeA>ASe*W^8`5ag43)B2L z%NfR0=$=F4*N#k04hM9ALGEBpg_#z(|!LHtHQnb>p z!jHvvcee(=_|oI^3yU7Gpa({vC~>W|`*a$0{nP1mI-PuQmmQf#^>jMbda9>WJ)KUc z)9G~Dc*u|cr}sadPN&mHdpey?r_-sPPN!3?r_2x}sPN&o9vlzS5_jan4bn1F~(^v1FzMkH6swXcx+Y~V}cJZi5jIpi(?%erf zE@j6D;B<|FiO^%Lwzrnjyp_iGN-p zV;Lz(;l#RFZb`wiQt)8&rDrl%u*??~h>*704rrNe)Sy!@r7}B?eQl6c5v!oP0)X;9yQ?lsG2`p0Wl z4C)!0JIJZ9(B0ix`~u&5b0Dw=pJm}s`I&5~Hol;&GLu^mRvPIW9nijm923K0J+O~7 zD|weAb-l#M=-r6*&qP`kq?A>*e3t#i?JzX2Sq6Bb-VW*@cb5!Fmq-n4RB?$&K?M?pw2ei+HocIxrLR9VxS-z8`kUUr)U|Da-z%Y-{&E~l5jDbgkCG&rz^}gLtQ)ZPFny`?rc{kAn=>v4LM=}+IA z15R&3oo-0=c(JC3VO#Qih)ZAUq!(->2*w1pB}I;9Tly^1V65GRw!RNJQ;7xZsuBlh zSVt*{U;Im@&tz|<_aVsy%9x(x3d)?`|0|+S;j%)YP4$R2<)cmUE(omYuY^eaW&2b2 zqsyw+ve~o~TXF)wl6Ql&kTrdq{`94;RJzcb-iI7p^1+BLnKIymyKI{>&=0>4e(r^jV?(0`qTIq|{Y5h9a&|_} z9TQ4{C?#|YIXx~RKygIR5ILwp3wlP710E<;kb@#X@q--9Al;3>^bhfw-tm`yB$USo z!qh+6Iwd_B}s)xWRb;>R3e2G@RB1W!O;;r4+$N;1um4Z zqa$|G1WD+i*1GpZ33^yMVh62IqNB+G+F}TZi>3ib2-nd>dv#R=2ovYHQB45KxcBgD zmsASsWtVhMi!~6oI8o_e{>fS8_~+lMmE3sOJyP-}Niy4OSv}1X)Zk__DwR5gijRt) z;xYVE9)(Idb*AUdPaP5Krc#eBJ)_{qwZQKw{639{Dt!VtJh2cm{mH%;_ze7%O9y{# z2EzwXa&+(yq`-tA9X)UuNYH|i4j(cmIv5(@YR++JiX|@{K6GCo$7Ut!(|IJif&JrR zTgVDR^s7hTXKrqMMhJX?9L2(E#6lx>utL?~w=<`hqK}+Ih+8P_-E^Ntu!v+Lu`b~T z0Sy`vB}x>P9ZPAQH0}qEuyYD@^n}H{(d8yiv~zw8@^-8jaN_K^HxdG)PMnMdVT2Jz z4IpX&Q3Hrx!Kfk)#AJ7OY^B5`_VHV|rplXgvA0`j;0I-BAum9vK};Nj7>0d}4^h^= z+fQ&CKc&Gh#Y40}Q195s7-fvIV~b&oc|1frS9nnGXTKLt$ff(sS!RdmT@1wN-5qQW zLpxR*q7&HB(WG{`#eM?tgU@v|z>m^Y6{=_hjstxWyxi4tvX&Kfmj;aptL?bUm(Oq& zkih|dE%z|@>GD}#?spgXwbeQeCsl>&54Ro8vN@fOgEZol2O9?e=mt+ET`bnM)ahw;&X!gAOs#3r0?P+G zbmWzOQ%&S?-MY_bG){&`=NN{uchj%6F6%xhieJRuJIr&+@`;RX>cw^@axeL zb>z_*I`zgH2Liw4?1)XD@TCW&-=P>Wy3092rF!&zB9?D-;4F~QKm1^Sol8rX-r@4O z$ip7*ClXzGkO-Pf9eGFax!RBW?BaWKZuPy%DH?b;Aj^a*VODi1JUwO!)}0x_2<9SyN`){ zcWR^TdF$~m5=Hn?@*u54Fqp;Pbl&_005YwDt10q znKSI1-tCxesC3*fSH(5}0zd%UUy`x?r0UuBF825Djh(OA(5H?0kkx8613P!fk2=uU z=>bWBvIowBJk<0R%Ama47WFDCF09m8Nv*J~JoCyQfM;2Lyc>jtEJ}kyZHwYTeUwt3CFN5oU&DozSMge0{TZ8Y*MQ8XEHPV|q6{N(I$TU*o98x!f9}@QbFZ zQBo6(pow0|NB%b8k$KWk*H5P z>CdNLs)s-Q+ZKq^&E`f6YJWC*`fz(J^X`+n`tXCdceDqD2Pt~ZL!lstwQxAqz1w0t zbIJD?VzJqRg_|85{5s5Y7^1=Nez0MGKl0IN^w~&?sEpA|F#zjrM)@&L>7iDts4@%L z!`AxUeQ=KXEmjfBVgvMlbT4SZ)k=jrSu_Kv)%sQ|AeyYe3o%$M*6WBTOK=Dg1SC)3 z$ccGERYebQ9HBY_jw3h5P$>ZmDld@0aROD3N{ARNaG-z;6%{y)n8Hqs2yiT+g`pTO zur0W6l@DMFT;+nDBiQ6(6OQ~;sRCn%*4f1mlbXh$_)*c&m@VXpR5ciJH!PRpC^8gf z2j`$&4s#1QlK_6{zhXX#VZ~=CfB;;`QhvO$m>p<1RIrnygtf}iiEN{j{I>~_R8m;2 zIEVAh#F^y3k{Db3_{_@zTwUWY{Zm=My{YE}v_or3%oyCGRIHvEF<&sLnZY|XR5U6v zHCVy10xkv&mMgfY5k^Xtpp+!9V9%D?KA)jLqkJDh71i24H+65QYopIhgvj4LqkJD zh71i24H+7WsiIyUYO$KQg60edg+MtUl7$*sGeo^SWMK=+Tsp*YzRIwIr!|BoR3HHb z)eFZ;r2`s{`?xuM7=bxSz1%{Qr00qo2l!|xR^c#0)0*@1@e+d(xXHyt;eKdndXloh z5roeVpOLn6X(D!dd`7-_j1@~dSiz4b}7tcw`A6lq*>SdSeN4Ib; zu9K;jQiNWfplbCKpp-s-Jb*-ztL8dNklkcp_5T|7eg+0irjjII_MpLzJwU*Su?5*YvS1AafC z%k}JHDXNl|OXC^B5)1zZ%H+VUATY5nz!ng4EOeouZ#}9Yx(TTI@m@6$F-T~pF`~kX zL=nSA95PU0@kGdp7#4ssj=lUjL&Gfo`RU3*vfv3vRUr`JNTS|exnizxIcN(gGcy-x zICNI7*Gi=_Qg5$FtJO-bR;txXI#F-0dgXd;B`jwEG>GXUhDTEc5%D@C4iiMtGq_C5 zq&tzhBSe+q`bIl6fuV{4lOLEKIHMAPB}!}$!5A7i$CAQSJgAp{9zF~<;thIyrV=P~ z`3IJB=%`_8Qe}f3D06wqk%)wINEtiWHztl4U{jz$)XP6TA`DaA#1vo%-(x>Tz5FwM zVw^h;M<)>-wN$!@fdbFV#__}bJkC(~(*OPJfvO_zuF8>g-pt5@dTA`2IX*LW?2e@A z8Qe3$zd0y#6zZj!OQ6jCKBu8keU#)gVG$adhDpKqsbC8iWAv700>`~`F(w8ys$L+O zs1XL?u#bAPq~4w{C?l!A{QUf2H_dZ{^Hcc;^BSi+x(W(4$huI9)uMuly;_TkC6-%M z^jQ9AxkZHy?8$PAiWV$jYLTR4fT(k4LT9m9v8IMq!(u_HmsvW`;yAM}YBw{-7-Kth z_h#?9ySp=cJ2Ourn7#mm72voqp>AZj0EQSYGkB7M8ijxI!W1fI87K*t5n4b$D@(W+ zDj+Hcn>Zl?4~&|X@k&${%Ro&)0fr*#e7VE`2~AwFgCv;nLKG^c;;*P8DPYi|l6YKX z00S**$udwADEOj@Agrh>mVuH`0R}158J2;PB*CYOECVHJQ6!RpQE@$pFYX7X4aFER zWKlEAKv7U3i%PN#6vfL0D%6u@pekhWfFxL+<(3sMpd@sFz;$C#20$2shBbksA%TSD zYFKXlWMQjipdGB_7AgpT@C>6OQm)N}lDGvD_Nc}h!{!sh$hK;LBftPTfdlz$vJB(| z41k;fqECDiEQBjs#LLo@O6_W6Rr>aqR{$-5vW1PSdIusmNy$BR0wRyM=S%awg6f&u|2&tz{_Bq zQvv~DgymKlOsqd=xm89F+iv&~VK#B_>j=O07c6=#Mz_GPX$6DF)5C=YUg6^tVsHPU{4qZm864H$^=O(F_0p0046o001Zq3I@bNv4B9L37V`u6aWo{ zj6ir?nhCQc$x#?a8AA*r1^@y801yC>nE_e@INZmO2aKzHz0-v;VpumN7B~ECFvJ*u z&M6}_T^X^6O+l}Sn6i)>RC~_;VINr%QWi`(^7^YvPLv1^L8odjk+Ar8;tkYkb5-I; zn4d`RtGY3oiL|ay8kJ*Y$tmcm_(ny&73hh;x11~Ot=>Z4PEoIk(2D@3@0{DI_Rz1i zPB-A_m16zRq4V5LihECyUN~+PbPs~kBlMQgy}_k-aNN9+Su|!Q3Mxqu7IL8gbU(Fa;{`6+ehboR`2-^Lrpt~V(3{x$_V?LDTi@iK_uVzb& z5;ASGIXmS^z@6~o1k>e;AE*DU|P~E?DM{>D1#fin@WGdv&mBI!Y@PVq}$0V-u1c4RU}C2hp$pwK=(jtZ?7t+yXHBOk=-sVD zRgGdQQ_V3w*zfiOG$WZF`y8({sB1oBF_0mK!REJOzX1w#Tx4)q>1>;^d?ZhKe0|Tb zf#?T^SqsFQE1}ZB_LuYMd6p=(%2D=kU({G>563bW!VnQ}sW%#R6tIgtQ zmiuGv0KqiKN%qMPYMH=+_dgOG8ESdzF2o|D1)4`xCRWGaA7}pou>_E{7byD9=B$^R z_=!6d5%X^Klg``X!}S1-q#1>-v01N%2iT#R3H^`pD>ZqA>Hzh}E=QTo z>aGr!8gC+E%p5|a*-0c0>9M?R(KU5kBmTrbeytF=QQdQf?+;aEn~B%?o5$%tKvxJ! zE(xNLw(u6xVirHYs6tkcfQajIx`b3^kt%8#ccD;UrwT+3%L&7A6el|XrONyPty0a@ z9*y>?g3!hlF4bIMtM&Hp-+6MXRFDR8#Zmb5*b)gitp8C96DHF!7r1Ie6#>C z&Y|6@)d+~u1YFEeld44rIZ57VS93F|S%W)?4@}3|160fv(vk$Ry{PmSQxqyvBrPo#E|+bUrQ#KhXJ*QiSwBV!v&MN#1mlQBQ`s_F41 z0Iv`WZAuUfEY^gukSt?y*7wEuvW|BU|7H?jNUg+y!V9<3b=Kk*IdGm`<$w=7FfeKu zUUybFsJ<89lG;$p7c+hPJ2MJBFpG?uFFSmPRi6u zDvu>2O;syEh!OCYC7fGTN(Ap_2Nk#l`Lka?^#Czb?fbjlu#8-TVZu^lg( zLD!q0BvPn>Y9`z^)}y^|(h2J|7>fghQ<>=2j)ZReJJ$n%Y;e+}e&0oR9{9F63WoY70RDK3lxz?Pf4 z+2_D$t0_F$c`xg-lN)f>6e_E+Qu-l<1 zPoIrQqu02ep{YjhJWOGaoo}S}b6m}?csHC&SB|3RluJ&6G*C}J%JCxmo z=6}l`hYp@svh?T>TP4KEL@YWos(?ajT{w3;_p%Dk?U-{=Xeu76yj!nErnXRUD)NOi zfDcHY=FISkLcKcyolG(jlj>k^*5m>reJBi-MV=AJWjCBk?Ljv1b^}akZsT}n2;%Wy zL0Uj$GCQ`$xFHuiHGp2tmT=mCb6$2bs!1=f$G-naRdH`vj`fxh-9c>D=R-@8h1t=2 zhW5@|at5TzR**)-;*yc`U&@%o-*s@c&9ksh-`Y5qE)hQv*jAV(qUzB8s&$=k+Suys zw;J*0Aiu&Heai0jHgOxc#x9qBO}UidS^Bu<9%6`gb3vd{7AvSpINU+l1Qe|+U!$uZ zPu{yO=;V)r-PD>g!X`6=N-#z$8{CPbxW&9F4C!itd|4e@*LU1ELCJ?^!B4w{$Pu6m z+}PI$MB^`Tue^rl2&DWn@wM#!o|D56N>V^tv2(Ga=H*s1o^Z_nH0#a$DHlcsxC)LS z?5VS9IqQwNQClha$FDdM*O-Y>{Fv#98lVABb}aO?BaYB_1hUPj325JO^Se#YnQVku z4D?&aj^xWB5HQ8z&r~8qO8izXLcM@qPU%yIVo|WX9^Pazv@nWJb4CSVOyx!0T8jEz zILxMlJ&&wL$}El?4-=DBqc!?vcjI!80!tD&Nk@`8?9`?J2osa;A$PxWLa(cy;eJ1o z-oDxagX$Bo3?d9ICWrF^H?Od`>c5@*jZ{RSHP4m#aeC}YUL*9~VesNbh-|l84p0Z+ zZR#rJLZyQ)50dl*g1*F+5)&w<#TE=yiM|1Rp7s`<3(UA;QTk<;aw8wC)Mt1GAq{LB zf)rv^SJL6y#wQ&ym4=8#>h!Q3ZgQlI+(3G@ySM}*wP66*cybu(lI=>&9qkfOY`>6+ zxj}+ntzq`%e~WV@fdU71v)4FH-qc^x0F@e}D0+cRZ&LprdcslES|V-)KEUNeH5zJ+ ze{m%(7~C_tU|xdsrHCk=lp531_Uy@?WOdv%lg}21`^edtiy`ipAkx0e~H z?kCy5Dv<($eBAzaat);C8-TOp2{fRVdYKe!^TFhjmdt>ymUlE?Yp+Lztu(I`2RIe_ zm_tlko;3;3f?5hDN=<-<)+(s!;&R*sE}C#utlya}{R|1PNA2xL)4}DqL9DAUAM$*^+Rk<3DuhBMfrE z9;&J4=t>Ml$b8vdfG6vhMjoEClbwy^G0<%)X=>0ATJ7@> zvH>FKX)7VDs|r}56~^s(Gpw_ll3q?FQt&_z2sWDQ?gfLi42}XkFXh3^#mEeexNR%1zGT}ww_j+6i>&tC$^ULty zZJ1Z!k*0*bbAeW4PzJq8GDdgK)0Gy4kmVwAuG_-g(O`EZlmwYXo$JGUz%+(~MNRJU zafil2gegTBW`HHRXYLS`@fh}vN<0X5h=>7k;83~!n*3i`9GP0+hcYyOTG`M;%%4%? zghisKO$qXqKs$1$JT83u5-RRHsAoaAisAwYbJ-&kCGjQ)>LkP5ADI7>AT$V}ULwpJ z@khCe+JlUE@L2sm;l`-71u0Erl0b0a)Q>aJJHH@p|FQ-`cx>G>DSV40gk!_{|J)Hc z1mf)pa zmZS9|i+N)xr?DW|+k^)2w z*AF<7fK)hVSH5AADCunxc{Qp#c~Mw(j{T1~un1XhfghX_u(k&`9f!X2RV6_?p2*r- zLKeXTcoi~i$oCsrt+dY!O90Z}Cd4sDTqcJ}`=h(8BfrN&MGfSB!q}SN3^(0*2dD$356F3j8tpCTFu`z}i#Niz7<$*xSsDvp zIn{D8%F?o}_kF~Ax4A1QP^Do{!Lv}d5<}f`ph0l!^EL>q;SrE(sL1Z+wpz;^G^!AQEAW8s*I}KVHF84s z`{llDM>;h<^dp03Uo3?WJ*NZuA;DyVf7SGnThNZu-TW9NAkVubeUZpevULR?2L2Xq z@R&&{v9VhGU=zFiny&P9^?v?FjZ#tI=Oz})5%s`*Q!Q~ju0!?jcrm8<4~o62zyN`=SQxG%EZ)P zbND(=FrWVjno&!k27r5?Ld%;I%SJS|ClNz9l%WY@M&ysaA9=( zRxgrRK@|%kG2(A=2<>9(Qx1EsU#OYnzDEmD)f|S zr_Y80x=k4f=+@C<@r?%K+jVlS*qg{+BVZh9hCNNF!Qg#py5b>ahsZzGhx@+yUu~K8 zk%_&4{ff9OYbbtW>ovhXLoz2}(<6aV*<(4H7BUc)>g}n~0LVN6b7o&XNt|5_zD7F!%{Futf}$s9q~fnbTxP zUoAL`XDSPDe?=aIHLJ3z6_HmMNG!@Z9UB=%m9AUzXc*WzOeVYf3CXl5&twnZng&kD zim!f!+i=l3Ld4&(`0>YiFxENOI#@6r_hZ`s|1(T83l5!pKdSdclm7bdPhLr2>bE;e z;T~Nx{)4Vhvu@awe)4T?amA!)ur@=`JGiG-LC*|TWVQofd55<=A527e$3~zWS63V%5wh3*~_j?YmxG{~@SU-3}%exbgAM`lq>I;8;u@u`p*}xvr6X zkcxJSLBK*Q(DvqZXAlN)mZ-sC#QFXpZ1~H$Jt{K4xjQ!75XE*+IuR>>ESHz{LAjzpr73&rAl9|P}{@7sRg;JQ4`f*yA(E?kV_T6$a@1p#hsKN82!bZ(pI`lJ` zfrgpNA)BuIg5Swf`cLf{LRM&wCiG7(qcF1o6F<*CThxzib%_}SqYBE_70r}5UX?*^ zjJkUo;-_vks_*I%#>_$NU`kwOl`l!FS@FSn>R@7*PQmbt-oN)VmAH#Y@w~CY81w7Gsx8YahvZasQabS4Om1U$M z)OTY-T0EI!fxkEp`a(Rl=s+V~QUED7C$qqd5zXm_MGR-I_6e0m7!+Bd@paspfZmJp zy~Z~Ow79jwheT*dEm{*k{`tC7XHBb~E5?+o?^)Fvmjz>BdsD6X6ZcM{+ND+eEawiP z>_N_DX$LHZ{pp-H8V-NB;9m6%?x;+j4dXe`ZB*IuF9w3Z1Ene6adtGpWr@IZks1j- z-yD~?D5G`+rBPYfVr}3RBBE;uz&=fZ#CQ1Ow73Wi2G8ZL;8)@nTk8nwLU^?`9~K|$f!b1AT6qGI_HIE%7`#>r=WuDwC>(&` zH3?n6sT2;IBWUb&XZu8^J#v{R0hO;l#9^MxJD}vC?Quz(o>!pm7$Un+#S_3ga##@a z&T*`#vQ0tNX0!!qKoBm=dQ^J0Ko%ibwXoQl`XD#O%?sVHpQDNAnrtW|9{nTU=F^eR zvWhOd(wne?E=*HrEHy^^@f|XP)m*1bIOambt0O&7U$(EQ=qSkegI}?O3-zO-El1qI zkFthLTu>pi1x8NOjZcT!`OP#sm`9Dq)+|V9i|HtjjixZE{fd57^(d_&?rA=UxEiL3 zyk!Mh-{~1#&($W;8+V%?fE~l!+~vq<5wbLGtQoN&lRwLAju(U*6BrM>*9UhWWIw@X z4y^v<5>30>zwO9iTIY{BLJ(h)L3P@l>kp4z?@3dHQcBK~^e`R%%pGv}uhpHPuyjW~ z>0yh$EkcH0_va+&E5jN<_x2i_M8erbwaDfBJ6@+;S9*>R#}J0$VjDNdF|A-JU@W

w+Y3B)5g(U(C!e*&}r79d(>k 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

$7IDb2!7Cx=^9e0mDbI?Hm1$ZzSe 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�&h@tybT+NG{dN3U~Qn+@J=>4 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 z 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 z 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

l~&WVh8)Fc(jjWf8aaPrbYsXtjHZ>Z?q{T} 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