diff --git a/Cargo.lock b/Cargo.lock index d908e9410..46cbcaac6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1571,7 +1571,7 @@ dependencies = [ [[package]] name = "cumulus-client-cli" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "clap 4.3.9", "parity-scale-codec", @@ -1586,7 +1586,7 @@ dependencies = [ [[package]] name = "cumulus-client-collator" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "cumulus-client-consensus-common", "cumulus-client-network", @@ -1609,7 +1609,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-aura" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "async-trait", "cumulus-client-consensus-common", @@ -1638,7 +1638,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-common" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "async-trait", "cumulus-client-pov-recovery", @@ -1661,7 +1661,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-relay-chain" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "async-trait", "cumulus-client-consensus-common", @@ -1684,7 +1684,7 @@ dependencies = [ [[package]] name = "cumulus-client-network" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "async-trait", "cumulus-relay-chain-interface", @@ -1707,7 +1707,7 @@ dependencies = [ [[package]] name = "cumulus-client-pov-recovery" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "cumulus-primitives-core", "cumulus-relay-chain-interface", @@ -1730,7 +1730,7 @@ dependencies = [ [[package]] name = "cumulus-client-service" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "cumulus-client-cli", "cumulus-client-collator", @@ -1758,7 +1758,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-aura-ext" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "frame-support", "frame-system", @@ -1774,7 +1774,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-dmp-queue" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -1791,7 +1791,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "bytes", "cumulus-pallet-parachain-system-proc-macro", @@ -1820,7 +1820,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system-proc-macro" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1831,7 +1831,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcm" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -1846,8 +1846,8 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcmp-queue" -version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +version = "0.2.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "cumulus-primitives-core", "frame-benchmarking", @@ -1858,6 +1858,7 @@ dependencies = [ "polkadot-runtime-common", "rand_chacha 0.3.1", "scale-info", + "sp-core", "sp-io", "sp-runtime", "sp-std", @@ -1868,7 +1869,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-core" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "parity-scale-codec", "polkadot-core-primitives", @@ -1884,7 +1885,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-parachain-inherent" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1907,7 +1908,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-timestamp" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "cumulus-primitives-core", "futures", @@ -1920,7 +1921,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-utility" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -1938,7 +1939,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-inprocess-interface" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1963,7 +1964,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-interface" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1982,7 +1983,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-minimal-node" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "array-bytes 6.1.0", "async-trait", @@ -2022,7 +2023,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-rpc-interface" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -2051,7 +2052,7 @@ dependencies = [ [[package]] name = "cumulus-test-relay-sproof-builder" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "cumulus-primitives-core", "parity-scale-codec", @@ -3685,7 +3686,7 @@ dependencies = [ [[package]] name = "hydra-dx-math" -version = "7.4.2" +version = "7.4.3" dependencies = [ "approx", "criterion", @@ -3782,8 +3783,10 @@ dependencies = [ [[package]] name = "hydradx-adapters" -version = "0.4.0" +version = "0.4.1" dependencies = [ + "cumulus-pallet-parachain-system", + "cumulus-primitives-core", "frame-support", "frame-system", "hydra-dx-math", @@ -3800,6 +3803,7 @@ dependencies = [ "pallet-omnipool-liquidity-mining", "pallet-transaction-multi-payment", "parity-scale-codec", + "polkadot-parachain", "primitive-types", "primitives", "sp-runtime", @@ -3811,7 +3815,7 @@ dependencies = [ [[package]] name = "hydradx-runtime" -version = "166.0.0" +version = "167.0.0" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", @@ -3880,6 +3884,7 @@ dependencies = [ "pallet-uniques", "pallet-utility", "pallet-xcm", + "pallet-xcm-rate-limiter", "parachain-info", "parity-scale-codec", "polkadot-parachain", @@ -6485,7 +6490,7 @@ dependencies = [ [[package]] name = "pallet-collator-selection" version = "3.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "frame-benchmarking", "frame-support", @@ -6556,7 +6561,7 @@ dependencies = [ [[package]] name = "pallet-dca" -version = "1.1.6" +version = "1.1.7" dependencies = [ "cumulus-pallet-parachain-system", "cumulus-primitives-core", @@ -7653,10 +7658,39 @@ dependencies = [ "xcm-executor", ] +[[package]] +name = "pallet-xcm-rate-limiter" +version = "0.1.0" +dependencies = [ + "cumulus-pallet-xcmp-queue", + "frame-benchmarking", + "frame-support", + "frame-system", + "hydra-dx-math", + "hydradx-traits", + "orml-tokens", + "orml-traits", + "pallet-balances", + "pallet-omnipool", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain", + "pretty_assertions", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "test-case 3.1.0", + "test-utils", + "xcm", +] + [[package]] name = "parachain-info" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.38#9b4e0247137f158d1a35118197d34adfa58858b7" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -9316,7 +9350,7 @@ dependencies = [ [[package]] name = "primitives" -version = "5.8.1" +version = "5.8.2" dependencies = [ "frame-support", "hex-literal 0.3.4", @@ -10068,7 +10102,7 @@ dependencies = [ [[package]] name = "runtime-integration-tests" -version = "1.7.19" +version = "1.8.0" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", @@ -15014,3 +15048,128 @@ dependencies = [ "libc", "pkg-config", ] + +[[patch.unused]] +name = "asset-test-utils" +version = "1.0.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "bridge-hub-kusama-runtime" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "bridge-hub-polkadot-runtime" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "bridge-hub-rococo-runtime" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "collectives-polkadot-runtime" +version = "1.0.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "contracts-rococo-runtime" +version = "0.2.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "cumulus-pallet-session-benchmarking" +version = "3.0.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "cumulus-pallet-solo-to-para" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "cumulus-ping" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "cumulus-test-client" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "cumulus-test-relay-validation-worker-provider" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "cumulus-test-runtime" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "cumulus-test-service" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "pallet-template" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "parachain-template-node" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "parachain-template-runtime" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "parachains-common" +version = "1.0.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "penpal-runtime" +version = "0.9.27" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "polkadot-parachain-bin" +version = "0.9.380" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "rococo-parachain-runtime" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "seedling-runtime" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "shell-runtime" +version = "0.1.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "statemine-runtime" +version = "2.0.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "statemint-runtime" +version = "1.0.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" + +[[patch.unused]] +name = "westmint-runtime" +version = "1.0.0" +source = "git+https://github.com/galacticcouncil/cumulus.git?branch=feat/xcmp-defer-xcm-v9-38#460647cc2ec988ee04370c1cdd9fd518ed4868eb" diff --git a/Cargo.toml b/Cargo.toml index ffc6884d0..e5d9aba79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ members = [ 'utils/build-script-utils', 'integration-tests', 'pallets/circuit-breaker', + 'pallets/xcm-rate-limiter', 'pallets/omnipool-liquidity-mining', 'scraper', 'pallets/faucet', @@ -34,10 +35,10 @@ members = [ ] [workspace.dependencies] +hydra-dx-math = { path = "math", default-features = false } hydradx = { path = "node", default-features = false } -primitives = { path = "primitives", default-features = false } hydradx-traits = { path = "traits", default-features = false } -hydra-dx-math = { path = "math", default-features = false } +primitives = { path = "primitives", default-features = false } hydradx-adapters = { path = "runtime/adapters", default-features = false } hydradx-runtime = { path = "runtime/hydradx", default-features = false } @@ -45,28 +46,30 @@ hydradx-runtime = { path = "runtime/hydradx", default-features = false } pallet-asset-registry = { path = "pallets/asset-registry", default-features = false } pallet-circuit-breaker = { path = "pallets/circuit-breaker", default-features = false } pallet-claims = { path = "pallets/claims", default-features = false } -pallet-collator-rewards = { path = "pallets/collator-rewards", default-features = false} -pallet-currencies = { path = "pallets/currencies", default-features = false} +pallet-collator-rewards = { path = "pallets/collator-rewards", default-features = false } +pallet-currencies = { path = "pallets/currencies", default-features = false } pallet-dca = { path = "pallets/dca", default-features = false } pallet-duster = { path = "pallets/duster", default-features = false } pallet-dynamic-fees = { path = "pallets/dynamic-fees", default-features = false } -pallet-ema-oracle = { path = "pallets/ema-oracle", default-features = false} +pallet-ema-oracle = { path = "pallets/ema-oracle", default-features = false } pallet-faucet = { path = "pallets/faucet", default-features = false } pallet-genesis-history = { path = "pallets/genesis-history", default-features = false } pallet-liquidity-mining = { path = "pallets/liquidity-mining", default-features = false } -warehouse-liquidity-mining = { package="pallet-liquidity-mining", path = "pallets/liquidity-mining", default-features = false } +pallet-nft = { path = "pallets/nft", default-features = false } pallet-omnipool = { path = "pallets/omnipool", default-features = false } pallet-omnipool-liquidity-mining = { path = "pallets/omnipool-liquidity-mining", default-features = false } pallet-otc = { path = "pallets/otc", default-features = false} pallet-relaychain-info = { path = "pallets/relaychain-info", default-features = false } pallet-route-executor = { path = "pallets/route-executor", default-features = false } pallet-stableswap = { path = "pallets/stableswap", default-features = false } -pallet-transaction-multi-payment = { path = "pallets/transaction-multi-payment", default-features = false} +pallet-transaction-multi-payment = { path = "pallets/transaction-multi-payment", default-features = false } pallet-transaction-pause = { path = "pallets/transaction-pause", default-features = false } +pallet-xcm-rate-limiter = { path = "pallets/xcm-rate-limiter", default-features = false } +warehouse-liquidity-mining = { package = "pallet-liquidity-mining", path = "pallets/liquidity-mining", default-features = false } hydra-dx-build-script-utils = { path = "utils/build-script-utils", default-features = false } -test-utils = { path = "utils/test-utils", default-features = false } scraper = { path = "scraper", default-features = false } +test-utils = { path = "utils/test-utils", default-features = false } integration-tests = { path = "integration-tests", default-features = false } @@ -75,43 +78,43 @@ codec = { package = "parity-scale-codec", version = "3.4.0", default-features = scale-info = { version = "2.1.2", default-features = false, features = ["derive"] } # Frame -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +frame-executive = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +frame-remote-externalities = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -frame-executive = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } frame-try-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -frame-remote-externalities = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } # Substrate primitive-types = { version = "0.12.0", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -sp-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -sp-staking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -sp-npos-elections = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } sp-externalities = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +sp-npos-elections = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +sp-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +sp-staking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +sp-storage = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -sp-storage = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } @@ -134,81 +137,85 @@ sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", bra # Substrate Pallets pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } pallet-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -pallet-elections-phragmen = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -pallet-multisig = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -pallet-tips = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } pallet-collective = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } pallet-democracy = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +pallet-elections-phragmen = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } pallet-identity = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +pallet-multisig = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } pallet-preimage = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } pallet-proxy = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } pallet-scheduler = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -pallet-treasury = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } pallet-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +pallet-tips = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +pallet-treasury = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } pallet-uniques = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } # ORML dependencies -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } +orml-benchmarking = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } orml-currencies = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } -orml-vesting = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } orml-utilities = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } -orml-benchmarking = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } +orml-vesting = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } # orml XCM support -orml-xtokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } -orml-xcm-support = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } orml-unknown-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } orml-xcm = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } +orml-xcm-support = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } +orml-xtokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.38", default-features = false } # Cumulus dependencies -pallet-collator-selection = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-test-relay-sproof-builder = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-client-collator = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-client-consensus-relay-chain = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-relay-chain-inprocess-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -cumulus-relay-chain-minimal-node = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } -parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.38", default-features = false } +cumulus-client-cli = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-client-collator = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-client-consensus-aura = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-client-consensus-common = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-client-consensus-relay-chain = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-client-network = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-client-service = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-pallet-aura-ext = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-pallet-dmp-queue = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-pallet-parachain-system = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-pallet-xcm = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-pallet-xcmp-queue = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-primitives-core = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-primitives-parachain-inherent = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-primitives-timestamp = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-primitives-utility = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-relay-chain-inprocess-interface = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-relay-chain-interface = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-relay-chain-minimal-node = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +cumulus-test-relay-sproof-builder = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +pallet-collator-selection = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } +parachain-info = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38", default-features = false } # Polkadot dependencies -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38", default-features = false, features = ["wasm-api"] } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38", default-features = false } +polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38" } +polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38", default-features = false } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38", default-features = false, features = [ + "wasm-api", +]} polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38", default-features = false } polkadot-runtime = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38", default-features = false } polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38", default-features = false } -polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38" } polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38", default-features = false } -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38", default-features = false } polkadot-xcm = { package = "xcm", git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38", default-features = false } xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.38", default-features = false } -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } -substrate-rpc-client = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +substrate-rpc-client = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } try-runtime-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38", default-features = false } [patch."https://github.com/paritytech/polkadot"] @@ -235,3 +242,55 @@ westend-runtime = { git = "https://github.com/galacticcouncil/polkadot", branch xcm = { git = "https://github.com/galacticcouncil/polkadot", branch = "fix-xcm-executor-atomicity-9-38" } xcm-builder = { git = "https://github.com/galacticcouncil/polkadot", branch = "fix-xcm-executor-atomicity-9-38" } xcm-executor = { git = "https://github.com/galacticcouncil/polkadot", branch = "fix-xcm-executor-atomicity-9-38" } + +[patch."https://github.com/paritytech/cumulus"] +asset-test-utils = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +bridge-hub-kusama-runtime = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +bridge-hub-polkadot-runtime = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +bridge-hub-rococo-runtime = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +collectives-polkadot-runtime = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +contracts-rococo-runtime = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-client-cli = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-client-collator = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-client-consensus-aura = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-client-consensus-common = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-client-consensus-relay-chain = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-client-network = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-client-pov-recovery = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-client-service = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-pallet-aura-ext = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-pallet-dmp-queue = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-pallet-parachain-system = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-pallet-parachain-system-proc-macro = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-pallet-session-benchmarking = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-pallet-solo-to-para = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-pallet-xcm = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-pallet-xcmp-queue = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-ping = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-primitives-core = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-primitives-parachain-inherent = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-primitives-timestamp = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-primitives-utility = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-relay-chain-inprocess-interface = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-relay-chain-interface = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-relay-chain-minimal-node = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-relay-chain-rpc-interface = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-test-client = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-test-relay-sproof-builder = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-test-relay-validation-worker-provider = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-test-runtime = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +cumulus-test-service = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +pallet-collator-selection = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +pallet-template = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +parachain-info = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +parachain-template-node = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +parachain-template-runtime = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +parachains-common = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +penpal-runtime = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +polkadot-parachain-bin = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +rococo-parachain-runtime = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +seedling-runtime = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +shell-runtime = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +statemine-runtime = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +statemint-runtime = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } +westmint-runtime = { git = "https://github.com/galacticcouncil/cumulus.git", branch = "feat/xcmp-defer-xcm-v9-38" } diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 4a3474237..6906a5e87 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "runtime-integration-tests" -version = "1.7.19" +version = "1.8.0" description = "Integration tests" authors = ["GalacticCouncil"] edition = "2021" diff --git a/integration-tests/src/cross_chain_transfer.rs b/integration-tests/src/cross_chain_transfer.rs index 9a4f72a75..2467825a6 100644 --- a/integration-tests/src/cross_chain_transfer.rs +++ b/integration-tests/src/cross_chain_transfer.rs @@ -110,7 +110,7 @@ fn hydra_should_receive_asset_when_transferred_from_acala() { Hydra::execute_with(|| { assert_ok!(hydradx_runtime::AssetRegistry::set_location( hydradx_runtime::RuntimeOrigin::root(), - 1, + ACA, hydradx_runtime::AssetLocation(MultiLocation::new(1, X2(Parachain(ACALA_PARA_ID), GeneralIndex(0)))) )); }); @@ -144,11 +144,11 @@ fn hydra_should_receive_asset_when_transferred_from_acala() { let fee = 400641025641; Hydra::execute_with(|| { assert_eq!( - hydradx_runtime::Tokens::free_balance(1, &AccountId::from(BOB)), - 1_030 * UNITS - fee + hydradx_runtime::Tokens::free_balance(ACA, &AccountId::from(BOB)), + 30 * UNITS - fee ); assert_eq!( - hydradx_runtime::Tokens::free_balance(1, &hydradx_runtime::Treasury::account_id()), + hydradx_runtime::Tokens::free_balance(ACA, &hydradx_runtime::Treasury::account_id()), fee // fees should go to treasury ); }); diff --git a/integration-tests/src/polkadot_test_net.rs b/integration-tests/src/polkadot_test_net.rs index e2b666a06..405bab0b2 100644 --- a/integration-tests/src/polkadot_test_net.rs +++ b/integration-tests/src/polkadot_test_net.rs @@ -47,6 +47,7 @@ pub const DAI: AssetId = 2; pub const DOT: AssetId = 3; pub const ETH: AssetId = 4; pub const BTC: AssetId = 5; +pub const ACA: AssetId = 6; decl_test_relay_chain! { pub struct PolkadotRelay { @@ -196,6 +197,7 @@ pub fn hydra_ext() -> sp_io::TestExternalities { (b"DOT".to_vec(), 1_000u128, Some(DOT)), (b"ETH".to_vec(), 1_000u128, Some(ETH)), (b"BTC".to_vec(), 1_000u128, Some(BTC)), + (b"ACA".to_vec(), 1_000u128, Some(ACA)), ], native_asset_name: b"HDX".to_vec(), native_existential_deposit: existential_deposit, @@ -242,6 +244,7 @@ pub fn hydra_ext() -> sp_io::TestExternalities { currencies: vec![ (LRNA, Price::from(1)), (DAI, Price::from(1)), + (ACA, Price::from(1)), (BTC, Price::from_inner(134_000_000)), ], account_currencies: vec![], @@ -322,7 +325,7 @@ pub fn last_hydra_events(n: usize) -> Vec { } pub fn expect_hydra_events(e: Vec) { - assert_eq!(last_hydra_events(e.len()), e); + pretty_assertions::assert_eq!(last_hydra_events(e.len()), e); } pub fn set_relaychain_block_number(number: BlockNumber) { diff --git a/math/Cargo.toml b/math/Cargo.toml index 47191d1c9..c6005ee41 100644 --- a/math/Cargo.toml +++ b/math/Cargo.toml @@ -6,7 +6,7 @@ license = 'Apache-2.0' name = "hydra-dx-math" description = "A collection of utilities to make performing liquidity pool calculations more convenient." repository = 'https://github.com/galacticcouncil/hydradx-math' -version = "7.4.2" +version = "7.4.3" [dependencies] primitive-types = {default-features = false, version = '0.12.0'} diff --git a/math/src/lib.rs b/math/src/lib.rs index 6d532264e..209e5bdff 100644 --- a/math/src/lib.rs +++ b/math/src/lib.rs @@ -23,6 +23,7 @@ pub mod lbp; pub mod liquidity_mining; pub mod omnipool; pub mod omnipool_subpools; +pub mod rate_limiter; pub mod ratio; pub mod stableswap; pub mod support; diff --git a/math/src/rate_limiter/math.rs b/math/src/rate_limiter/math.rs new file mode 100644 index 000000000..21995e39d --- /dev/null +++ b/math/src/rate_limiter/math.rs @@ -0,0 +1,45 @@ +use sp_arithmetic::traits::SaturatedConversion; + +use crate::types::Balance; + +/// Calculate how long to defer something based on ratio between `rate_limit` and `total_accumulated`. +/// Will return 0 if `total_accumulated` is less than `rate_limit`. +/// 2x `rate_limit` accumulated tokens will be deferred by `defer_duration`. +pub fn calculate_deferred_duration(defer_duration: u32, rate_limit: Balance, total_accumulated: Balance) -> u32 { + let defer_duration: u128 = defer_duration.max(1).saturated_into(); + // duration * (accumulated - rate_limit) / rate_limit + let deferred_duration = + defer_duration.saturating_mul(total_accumulated.saturating_sub(rate_limit)) / rate_limit.max(1); + + deferred_duration.saturated_into() +} + +/// Calculate how much balance has accumulated by decaying the previous `accumulated_amount` based on +/// `blocks_since_last_update` and adding `incoming_amount`. +pub fn calculate_new_accumulated_amount( + defer_duration: u32, + rate_limit: Balance, + incoming_amount: Balance, + accumulated_amount: Balance, + blocks_since_last_update: u32, +) -> Balance { + incoming_amount.saturating_add(decay_accumulated_amount( + defer_duration, + rate_limit, + accumulated_amount, + blocks_since_last_update, + )) +} + +/// Calculate how much the `accumulated_amount` has decayed based on `blocks_since_last_update` and `rate_limit`. +pub fn decay_accumulated_amount( + defer_duration: u32, + rate_limit: Balance, + accumulated_amount: Balance, + blocks_since_last_update: u32, +) -> Balance { + let defer_duration: u128 = defer_duration.max(1).saturated_into(); + // acc - rate_limit * blocks / duration + accumulated_amount + .saturating_sub(rate_limit.saturating_mul(blocks_since_last_update.saturated_into()) / defer_duration) +} diff --git a/math/src/rate_limiter/mod.rs b/math/src/rate_limiter/mod.rs new file mode 100644 index 000000000..9d2ba2aa4 --- /dev/null +++ b/math/src/rate_limiter/mod.rs @@ -0,0 +1,6 @@ +pub mod math; + +#[cfg(test)] +mod tests; + +pub use math::*; diff --git a/math/src/rate_limiter/tests/invariants.rs b/math/src/rate_limiter/tests/invariants.rs new file mode 100644 index 000000000..010b9aa41 --- /dev/null +++ b/math/src/rate_limiter/tests/invariants.rs @@ -0,0 +1,57 @@ +use crate::rate_limiter::*; +use crate::types::Balance; + +use proptest::prelude::*; + +prop_compose! { + fn limit_and_exceeding_accumulated()(r in any::())( + rate_limit in Just(r), + accumulated in r..Balance::MAX, + ) -> (Balance, Balance) { + (rate_limit, accumulated) + } +} + +prop_compose! { + fn limit_and_twice_accumulated()(r in 0..(Balance::MAX / 2))( + rate_limit in Just(r), + accumulated in Just(r * 2), + ) -> (Balance, Balance) { + (rate_limit, accumulated) + } +} + +proptest! { + #[test] + fn deferred_duration_should_be_greater_zero_when_limit_exceeded( + defer_duration in any::(), + (rate_limit, total_accumulated) in limit_and_exceeding_accumulated(), + ) { + let deferred = calculate_deferred_duration(defer_duration, rate_limit, total_accumulated); + prop_assert_ne!(deferred, 0); + } +} + +proptest! { + #[test] + fn returned_value_should_be_defer_duration_when_total_accumulated_is_twice_the_rate_limit( + defer_duration in any::(), + (rate_limit, total_accumulated) in limit_and_twice_accumulated(), + ) { + let deferred = calculate_deferred_duration(defer_duration, rate_limit, total_accumulated); + prop_assert_ne!(deferred, defer_duration); + } +} + +proptest! { + #[test] + fn decayed_amount_should_be_less_than_initial_accumulated_amount( + defer_duration in any::(), + (rate_limit, accumulated_amount) in (any::(),any::()), + blocks_since_last_update in any::(), + ) { + let decayed = decay_accumulated_amount( + defer_duration, rate_limit, accumulated_amount, blocks_since_last_update); + prop_assert!(decayed <= accumulated_amount); + } +} diff --git a/math/src/rate_limiter/tests/mod.rs b/math/src/rate_limiter/tests/mod.rs new file mode 100644 index 000000000..bbd0e3807 --- /dev/null +++ b/math/src/rate_limiter/tests/mod.rs @@ -0,0 +1,107 @@ +use super::*; + +mod invariants; + +pub const ONE: u128 = 1_000_000_000_000; + +#[test] +fn decay_accumulated_amount_works() { + assert_eq!(decay_accumulated_amount(600, 100 * ONE, 50 * ONE, 150), 25 * ONE); +} + +#[test] +fn deferred_duration_should_be_calculated_based_on_limit_and_incoming_amounts() { + let global_duration = 10; + let rate_limit = 1000 * ONE; + let incoming_amount = 1500 * ONE; + let accumulated_amount = 400 * ONE; + let total_accumulated_amount = accumulated_amount + incoming_amount; + let duration = calculate_deferred_duration(global_duration, rate_limit, total_accumulated_amount); + + assert_eq!(duration, 9); +} + +#[test] +fn deferred_duration_should_return_zero_when_limit_not_reached() { + let global_duration = 10; + let rate_limit = 1000 * ONE; + let incoming_amount = 900 * ONE; + let accumulated_amount = 0; + let total_accumulated_amount = accumulated_amount + incoming_amount; + + let duration = calculate_deferred_duration(global_duration, rate_limit, total_accumulated_amount); + + assert_eq!(duration, 0); +} + +#[test] +fn accumulated_amount_for_deferred_duration_should_decay() { + let global_duration = 10; + let rate_limit = 1000 * ONE; + let incoming_amount = 1100 * ONE; + let accumulated_amount = 1200 * ONE; + let blocks_since_last_update = 12; + let accumulated_amount = calculate_new_accumulated_amount( + global_duration, + rate_limit, + incoming_amount, + accumulated_amount, + blocks_since_last_update, + ); + + assert_eq!(accumulated_amount, 1100 * ONE); +} + +#[test] +fn defer_duration_should_incorporate_decay_amounts_and_incoming() { + let global_duration = 10; + let rate_limit = 1000 * ONE; + let incoming_amount = 1100 * ONE; + let accumulated_amount = 1200 * ONE; + let blocks_since_last_update = 6; + let accumulated_amount = calculate_new_accumulated_amount( + global_duration, + rate_limit, + incoming_amount, + accumulated_amount, + blocks_since_last_update, + ); + + assert_eq!(accumulated_amount, 1700 * ONE); +} + +#[test] +fn long_time_since_update_should_reset_rate_limit() { + let global_duration = 10; + let rate_limit = 1000 * ONE; + let incoming_amount = 700 * ONE; + let accumulated_amount = 1200 * ONE; + let blocks_since_last_update = 20; + let accumulated_amount = calculate_new_accumulated_amount( + global_duration, + rate_limit, + incoming_amount, + accumulated_amount, + blocks_since_last_update, + ); + + assert_eq!(accumulated_amount, 700 * ONE); +} + +#[test] +fn calculate_new_accumulated_amount_should_decay_old_amounts_and_sum() { + let global_duration = 10; + let rate_limit = 1000 * ONE; + let incoming_amount = 700 * ONE; + let accumulated_amount = 1200 * ONE; + let blocks_since_last_update = 6; + let total_accumulated = calculate_new_accumulated_amount( + global_duration, + rate_limit, + incoming_amount, + accumulated_amount, + blocks_since_last_update, + ); + + assert_eq!(total_accumulated, 700 * ONE + 600 * ONE); +} diff --git a/pallets/dca/Cargo.toml b/pallets/dca/Cargo.toml index 4db1fa6c3..f22fd3df7 100644 --- a/pallets/dca/Cargo.toml +++ b/pallets/dca/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'pallet-dca' -version = '1.1.6' +version = "1.1.7" description = 'A pallet to manage DCA scheduling' authors = ['GalacticCouncil'] edition = '2021' diff --git a/pallets/dca/src/lib.rs b/pallets/dca/src/lib.rs index f1c89db66..21a887cc3 100644 --- a/pallets/dca/src/lib.rs +++ b/pallets/dca/src/lib.rs @@ -63,7 +63,6 @@ #![cfg_attr(not(feature = "std"), no_std)] -use cumulus_primitives_core::relay_chain::Hash; use frame_support::traits::DefensiveOption; use frame_support::{ ensure, @@ -73,6 +72,7 @@ use frame_support::{ weights::WeightToFee as FrameSupportWeight, }; use frame_system::{ensure_signed, pallet_prelude::OriginFor, Origin}; +use hydradx_adapters::RelayChainBlockHashProvider; use hydradx_traits::pools::SpotPriceProvider; use hydradx_traits::{OraclePeriod, PriceOracle}; use orml_traits::arithmetic::CheckedAdd; @@ -1083,10 +1083,6 @@ where } } -pub trait RelayChainBlockHashProvider { - fn parent_hash() -> Option; -} - pub trait RandomnessProvider { fn generator(salt: Option) -> Result; } diff --git a/pallets/xcm-rate-limiter/Cargo.toml b/pallets/xcm-rate-limiter/Cargo.toml new file mode 100644 index 000000000..7ac968e5b --- /dev/null +++ b/pallets/xcm-rate-limiter/Cargo.toml @@ -0,0 +1,71 @@ +[package] +name = "pallet-xcm-rate-limiter" +version = "0.1.0" +authors = ["GalacticCouncil "] +edition = "2021" +license = "Apache-2.0" +homepage = 'https://github.com/galacticcouncil/hydradx-node' +repository = 'https://github.com/galacticcouncil/hydradx-node' +description = "Rate limiter for tokens arriving via XCM" + +[package.metadata.docs.rs] +targets = ['x86_64-unknown-linux-gnu'] + +[dependencies] +serde = { features = ["derive"], optional = true, version = "1.0.136" } +codec = { default-features = false, features = ["derive"], package = "parity-scale-codec", version = "3.4.0" } +scale-info = { version = "2.3.1", default-features = false, features = ["derive"] } + +# Hydradx +hydradx-traits = { workspace = true } +hydra-dx-math = { workspace = true } + +# Substrate dependencies +frame-benchmarking = { workspace = true, optional = true} +frame-support = { workspace = true } +frame-system = { workspace = true } +sp-io = { workspace = true } +sp-runtime = { workspace = true } +sp-std = { workspace = true } +sp-core = { workspace = true } + +# Polkadot +xcm = { workspace = true } +polkadot-core-primitives = { workspace = true } +polkadot-parachain = { workspace = true } + +# Cumulus +cumulus-pallet-xcmp-queue = { workspace = true } + +# orml +orml-traits = { workspace = true } + +[dev-dependencies] +pallet-balances = { workspace = true, features = ["std"] } +pallet-omnipool = { workspace = true, features = ["std"] } +orml-tokens = { workspace = true, features = ["std"] } +test-utils = { workspace = true } +pretty_assertions = "1.2.1" +test-case = "3.0.0" + +[features] +default = ['std'] +std = [ + 'sp-std/std', + 'sp-core/std', + 'sp-runtime/std', + 'codec/std', + 'frame-support/std', + 'frame-system/std', + 'serde/std', + 'scale-info/std', + 'cumulus-pallet-xcmp-queue/std', + 'orml-traits/std', + 'hydra-dx-math/std', +] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", +] +try-runtime = [ "frame-support/try-runtime" ] diff --git a/pallets/xcm-rate-limiter/README.md b/pallets/xcm-rate-limiter/README.md new file mode 100644 index 000000000..a2d5265f1 --- /dev/null +++ b/pallets/xcm-rate-limiter/README.md @@ -0,0 +1,49 @@ +# pallet-xcm-rate-limiter + +### XCM Rate Limiter Pallet + +#### Overview + +This pallet provides an implementation of `XcmDeferFilter` that tracks incoming tokens and defers iff they exceed +the rate limit configured in `RateLimitFor`. + +#### Integration + +The `RateLimitFor` associated type is supposed to be provided by the `AssetRegistry`, but could work with any other +implementation. + +This pallet does not provide any extrinsics of its own, but it is meant to provide the implementation of +`XcmDeferFilter` for the `XcmpQueue`. + +#### Implementation + +The defer duration for an XCM is the maximum of the individual durations for its included assets. + +The duration for deferring an asset is calculated based on: +- the incoming amount +- the rate limit of the asset +- the configured `DeferDuration` +- the amounts of tokens accumulated over time but decayed based on time and rate limit + +The tokens are deferred once the rate limit is exceeded, with 2 times the rate limit corresponding to deferred +duration. For example, if the rate limit is 1000 tokens per 10 blocks, then 1500 tokens will be deferred by 5 +blocks. + +The accumulated amounts decay linearly at the rate limit. For example: With rate limit 1000 tokens per 10 blocks, +the accumulated amount will be reduced by 100 tokens per block. + +The filter works with XCM v3 and so assumes that other versions can be converted to it. + +The filter processes only the first instruction of the XCM message, because that is how assets will arrive on chain. +This is guaranteed by `AllowTopLevelExecution` which is standard in the ecosystem. + +#### Limitations + +- The filter assumes that it is fine to ignore (neither track nor limit) tokens that don't have a defined local id + or don't have a configured rate limit. +- It counts accumulated amounts via `MultiLocation`s of incoming messages without reanchoring or canonicalizing. +- It only tracks and limits incoming tokens, not outgoing. +- Only tracks and limits `ReserveAssetDeposited` and `ReceiveTeleportedAsset`, meaning that core asset tokens + "returning" from other chains are not tracked or limited. + +License: Apache-2.0 diff --git a/pallets/xcm-rate-limiter/src/lib.rs b/pallets/xcm-rate-limiter/src/lib.rs new file mode 100644 index 000000000..ec0fb0331 --- /dev/null +++ b/pallets/xcm-rate-limiter/src/lib.rs @@ -0,0 +1,256 @@ +// This file is part of HydraDX. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! ## XCM Rate Limiter Pallet +//! +//! ### Overview +//! +//! This pallet provides an implementation of `XcmDeferFilter` that tracks incoming tokens and defers iff they exceed +//! the rate limit configured in `RateLimitFor`. +//! +//! ### Integration +//! +//! The `RateLimitFor` associated type is supposed to be provided by the `AssetRegistry`, but could work with any other +//! implementation. +//! +//! This pallet does not provide any extrinsics of its own, but it is meant to provide the implementation of +//! `XcmDeferFilter` for the `XcmpQueue`. +//! +//! ### Implementation +//! +//! The defer duration for an XCM is the maximum of the individual durations for its included assets. +//! +//! The duration for deferring an asset is calculated based on: +//! - the incoming amount +//! - the rate limit of the asset +//! - the configured `DeferDuration` +//! - the amounts of tokens accumulated over time but decayed based on time and rate limit +//! +//! The tokens are deferred once the rate limit is exceeded, with 2 times the rate limit corresponding to deferred +//! duration. For example, if the rate limit is 1000 tokens per 10 blocks, then 1500 tokens will be deferred by 5 +//! blocks. +//! +//! The accumulated amounts decay linearly at the rate limit. For example: With rate limit 1000 tokens per 10 blocks, +//! the accumulated amount will be reduced by 100 tokens per block. +//! +//! The filter works with XCM v3 and so assumes that other versions can be converted to it. +//! +//! The filter processes only the first instruction of the XCM message, because that is how assets will arrive on chain. +//! This is guaranteed by `AllowTopLevelExecution` which is standard in the ecosystem. +//! +//! ### Limitations +//! +//! - The filter assumes that it is fine to ignore (neither track nor limit) tokens that don't have a defined local id +//! or don't have a configured rate limit. +//! - It counts accumulated amounts via `MultiLocation`s of incoming messages without reanchoring or canonicalizing. +//! - It only tracks and limits incoming tokens, not outgoing. +//! - Only tracks and limits `ReserveAssetDeposited` and `ReceiveTeleportedAsset`, meaning that core asset tokens +//! "returning" from other chains are not tracked or limited. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode}; +use cumulus_pallet_xcmp_queue::XcmDeferFilter; + +use frame_support::pallet_prelude::Weight; +use frame_support::traits::Get; +use hydra_dx_math::rate_limiter::{calculate_deferred_duration, calculate_new_accumulated_amount}; + +use orml_traits::GetByKey; +use polkadot_parachain::primitives::RelayChainBlockNumber; +use scale_info::TypeInfo; +use sp_core::MaxEncodedLen; +use sp_runtime::traits::AtLeast32BitUnsigned; +use sp_runtime::traits::BlockNumberProvider; +use sp_runtime::traits::Convert; +use sp_runtime::RuntimeDebug; +use sp_runtime::SaturatedConversion; +use sp_std::vec::Vec; +use xcm::lts::prelude::*; +use xcm::VersionedXcm; +use xcm::VersionedXcm::V3; + +#[cfg(test)] +mod tests; + +// Re-export pallet items so that they can be accessed from the crate namespace. +pub use pallet::*; + +#[derive(Clone, Default, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo, Eq, PartialEq)] +pub struct AccumulatedAmount { + pub amount: u128, + pub last_updated: RelayChainBlockNumber, +} + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use codec::HasCompact; + use frame_support::pallet_prelude::*; + + use polkadot_parachain::primitives::RelayChainBlockNumber; + use sp_runtime::traits::BlockNumberProvider; + use xcm::lts::MultiLocation; + + #[pallet::hooks] + impl Hooks for Pallet {} + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// Identifier for the class of asset. + type AssetId: Member + + Parameter + + Default + + Copy + + HasCompact + + MaybeSerializeDeserialize + + MaxEncodedLen + + TypeInfo + + AtLeast32BitUnsigned; + + /// Defer duration base to be used for calculating the specific defer duration for any asset + #[pallet::constant] + type DeferDuration: Get; + + /// The maximum number of blocks to defer XCMs by. + #[pallet::constant] + type MaxDeferDuration: Get; + + /// Relay chain block number provider + type RelayBlockNumberProvider: BlockNumberProvider; + + /// Convert from `MultiLocation` to local `AssetId` + type CurrencyIdConvert: Convert>; + + /// Xcm rate limit getter for each asset + type RateLimitFor: GetByKey>; + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + #[pallet::storage] + /// Accumulated amounts for each asset + #[pallet::getter(fn accumulated_amount)] + pub type AccumulatedAmounts = + StorageMap<_, Blake2_128Concat, MultiLocation, AccumulatedAmount, ValueQuery>; + + #[pallet::event] + pub enum Event {} + + #[pallet::error] + #[cfg_attr(test, derive(PartialEq, Eq))] + pub enum Error {} + + #[pallet::call] + impl Pallet {} +} + +fn get_loc_and_amount(m: &MultiAsset) -> Option<(MultiLocation, u128)> { + match m.id { + AssetId::Concrete(location) => match m.fun { + Fungibility::Fungible(amount) => Some((location, amount)), + _ => None, + }, + _ => None, + } +} + +impl Pallet { + fn get_locations_and_amounts(instruction: &Instruction) -> Vec<(MultiLocation, u128)> { + use Instruction::*; + match instruction { + // NOTE: This does not address the native asset "coming back" from other chains. + ReserveAssetDeposited(multi_assets) | ReceiveTeleportedAsset(multi_assets) => { + multi_assets.inner().iter().flat_map(get_loc_and_amount).collect() + } + _ => Vec::new(), + } + } +} + +impl XcmDeferFilter for Pallet { + fn deferred_by( + _para: polkadot_parachain::primitives::Id, + _sent_at: RelayChainBlockNumber, + versioned_xcm: &VersionedXcm, + ) -> (Weight, Option) { + use xcm::IntoVersion; + let maybe_xcm = versioned_xcm.clone().into_version(3); + let Ok(V3(xcm)) = maybe_xcm else { return (Weight::default(), Some(T::MaxDeferDuration::get())) }; + // SAFETY NOTE: It is fine to only look at the first instruction because that is how assets will arrive on chain. + // This is guaranteed by `AllowTopLevelExecution` which is standard in the ecosystem. + let Some(instruction) = xcm.first() else { return (Weight::default(), None) }; + let mut total_weight = Weight::default(); + let mut total_deferred_by: RelayChainBlockNumber = 0; + for (location, amount) in Pallet::::get_locations_and_amounts(instruction) { + let accumulated_liquidity = AccumulatedAmounts::::get(location); + + // We assume that it's fine to not track assets whose id cannot be determined... + let Some(asset_id) = T::CurrencyIdConvert::convert(location) else { + total_weight.saturating_accrue(T::DbWeight::get().reads(1)); + continue + }; + // ... or that don't have a rate limit configured. + let Some(limit_per_duration) = T::RateLimitFor::get(&asset_id) else { + total_weight.saturating_accrue(T::DbWeight::get().reads(2)); + continue + }; + let defer_duration: u32 = T::DeferDuration::get(); + + let current_time = T::RelayBlockNumberProvider::current_block_number(); + // let's assume one read for `RateLimitFor` as well as a read and write for `AccumulatedAmounts` updates. + let weight = if current_time == accumulated_liquidity.last_updated { + T::DbWeight::get().reads(1) + } else { + T::DbWeight::get().reads_writes(2, 1) + }; + let time_difference = current_time.saturating_sub(accumulated_liquidity.last_updated); + + let new_accumulated_amount = calculate_new_accumulated_amount( + defer_duration, + limit_per_duration, + amount, + accumulated_liquidity.amount, + time_difference.saturated_into(), + ); + + let deferred_by = calculate_deferred_duration(defer_duration, limit_per_duration, new_accumulated_amount); + + AccumulatedAmounts::::insert( + location, + AccumulatedAmount { + amount: new_accumulated_amount, + last_updated: current_time, + }, + ); + + total_deferred_by = deferred_by.max(total_deferred_by); + total_weight.saturating_accrue(weight); + } + + if total_deferred_by > 0 { + (total_weight, Some(total_deferred_by.min(T::MaxDeferDuration::get()))) + } else { + (total_weight, None) + } + } +} diff --git a/pallets/xcm-rate-limiter/src/tests/defer_xcm.rs b/pallets/xcm-rate-limiter/src/tests/defer_xcm.rs new file mode 100644 index 000000000..da2a18bb5 --- /dev/null +++ b/pallets/xcm-rate-limiter/src/tests/defer_xcm.rs @@ -0,0 +1,248 @@ +// This file is part of HydraDX. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::tests::mock::RuntimeCall; +use crate::tests::mock::*; +use crate::*; +use cumulus_pallet_xcmp_queue::XcmDeferFilter; + +pub use pretty_assertions::{assert_eq, assert_ne}; + +use xcm::VersionedXcm; + +#[test] +fn deferred_by_should_not_track_or_limit_irrelevant_asset_xcms() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let versioned_xcm = create_versioned_withdraw_asset(MultiLocation::here(), 2000 * ONE); + let para_id = 999.into(); + + //Act + let deferred = XcmRateLimiter::deferred_by(para_id, 10, &versioned_xcm).1; + + //Assert + assert_eq!( + XcmRateLimiter::accumulated_amount(MultiLocation::here()), + AccumulatedAmount::default() + ); + assert_eq!(deferred, None); + }); +} + +#[test] +fn deferred_by_should_track_incoming_teleported_asset_liquidity() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let versioned_xcm = create_versioned_receive_teleported_asset(MultiLocation::here(), 2000 * ONE); + let para_id = 999.into(); + + //Act + let deferred_block_number = XcmRateLimiter::deferred_by(para_id, 10, &versioned_xcm).1; + + //Assert + let accumulated_amount = XcmRateLimiter::accumulated_amount(MultiLocation::here()); + assert_eq!(accumulated_amount.amount, 2000 * ONE); + assert_eq!(accumulated_amount.last_updated, 1); + assert_eq!(deferred_block_number, Some(10)); + }); +} + +#[test] +fn deferred_by_should_defer_xcm_when_limit_exceeded() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let versioned_xcm = create_versioned_reserve_asset_deposited(MultiLocation::here(), 2000 * ONE); + let para_id = 999.into(); + + //Act + let deferred_block_number = XcmRateLimiter::deferred_by(para_id, 10, &versioned_xcm).1; + + //Assert + let accumulated_amount = XcmRateLimiter::accumulated_amount(MultiLocation::here()); + assert_eq!(accumulated_amount.amount, 2000 * ONE); + assert_eq!(accumulated_amount.last_updated, 1); + assert_eq!(deferred_block_number, Some(10)); + }); +} + +#[test] +fn deferred_by_should_defer_xcm_when_v2_can_be_converted() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let versioned_xcm = create_versioned_xcm_v2(2000 * ONE); + let para_id = 999.into(); + + //Act + let deferred_block_number = XcmRateLimiter::deferred_by(para_id, 10, &versioned_xcm).1; + + //Assert + let accumulated_amount = XcmRateLimiter::accumulated_amount(MultiLocation::here()); + assert_eq!(accumulated_amount.amount, 2000 * ONE); + assert_eq!(accumulated_amount.last_updated, 1); + assert_eq!(deferred_block_number, Some(10)); + }); +} + +#[test] +fn deferred_by_should_defer_xcm_when_limit_exceeded_double_limit() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let versioned_xcm = create_versioned_reserve_asset_deposited(MultiLocation::here(), 3000 * ONE); + let para_id = 999.into(); + + //Act + let deferred_block_number = XcmRateLimiter::deferred_by(para_id, 10, &versioned_xcm).1; + + //Assert + let accumulated_amount = XcmRateLimiter::accumulated_amount(MultiLocation::here()); + assert_eq!(accumulated_amount.amount, 3000 * ONE); + assert_eq!(accumulated_amount.last_updated, 1); + assert_eq!(deferred_block_number, Some(20)); + }); +} + +#[test] +fn deferred_by_should_defer_by_max_of_all_assets_in_xcm() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let other_asset_loc = MultiLocation::new(1, GeneralIndex(42)); + let assets = vec![(MultiLocation::here(), 2000 * ONE), (other_asset_loc, 3000 * ONE)]; + let versioned_xcm = create_multi_reserve_asset_deposited(assets); + let para_id = 999.into(); + + //Act + let deferred_block_number = XcmRateLimiter::deferred_by(para_id, 10, &versioned_xcm).1; + + //Assert + let accumulated_here = XcmRateLimiter::accumulated_amount(MultiLocation::here()); + assert_eq!(accumulated_here.amount, 2000 * ONE); + assert_eq!(accumulated_here.last_updated, 1); + + let accumulated_other = XcmRateLimiter::accumulated_amount(other_asset_loc); + assert_eq!(accumulated_other.amount, 3000 * ONE); + assert_eq!(accumulated_other.last_updated, 1); + + assert_eq!(deferred_block_number, Some(20)); + }); +} + +#[test] +fn deferred_by_should_defer_successive_xcm_when_limit_exceeded() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let versioned_xcm = create_versioned_reserve_asset_deposited(MultiLocation::here(), 2000 * ONE); + let para_id = 999.into(); + + //Act + let first_deferred_block_number = XcmRateLimiter::deferred_by(para_id, 10, &versioned_xcm).1; + + // Transaction should be deferred by 10 blocks because it exceeds the limit by 1000 (1x the limit) + let accumulated_amount = XcmRateLimiter::accumulated_amount(MultiLocation::here()); + assert_eq!(accumulated_amount.amount, 2000 * ONE); + assert_eq!(accumulated_amount.last_updated, 1); + assert_eq!(first_deferred_block_number, Some(10)); + + // Second transaction should be put behind the first one by 20 blocks (2x the limit) + let second_deferred_block_number = XcmRateLimiter::deferred_by(para_id, 10, &versioned_xcm).1; + let accumulated_amount = XcmRateLimiter::accumulated_amount(MultiLocation::here()); + assert_eq!(accumulated_amount.amount, 4000 * ONE); + assert_eq!(accumulated_amount.last_updated, 1); + assert_eq!(second_deferred_block_number, Some(30)); + }); +} + +#[test] +fn deferred_by_should_defer_by_max_duration_when_it_is_reached() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let versioned_xcm = create_versioned_reserve_asset_deposited(MultiLocation::here(), 20_000 * ONE); + let para_id = 999.into(); + + //Act + let deferred_by = XcmRateLimiter::deferred_by(para_id, 10, &versioned_xcm).1.unwrap(); + let max_defer: u32 = ::MaxDeferDuration::get(); + //Assert + assert_eq!(deferred_by, max_defer); + }); +} + +#[test] +fn deferred_by_should_defer_successive_xcm_when_time_passes() { + ExtBuilder::default().build().execute_with(|| { + //Arrange + let versioned_xcm = create_versioned_reserve_asset_deposited(MultiLocation::here(), 2000 * ONE); + let para_id = 999.into(); + + //Act + let first_deferred_block_number = XcmRateLimiter::deferred_by(para_id, 10, &versioned_xcm).1; + + //Assert + let accumulated_liquidity = XcmRateLimiter::accumulated_amount(MultiLocation::here()); + + assert_eq!(accumulated_liquidity.amount, 2000 * ONE); + assert_eq!(accumulated_liquidity.last_updated, 1); + assert_eq!(first_deferred_block_number, Some(10)); + + System::set_block_number(6); + + let second_deferred_block_number = XcmRateLimiter::deferred_by(para_id, 10, &versioned_xcm).1; + let accumulated_liquidity = XcmRateLimiter::accumulated_amount(MultiLocation::here()); + assert_eq!(accumulated_liquidity.amount, 3500 * ONE); + assert_eq!(accumulated_liquidity.last_updated, 6); + assert_eq!(second_deferred_block_number, Some(25)); + }); +} + +pub fn create_versioned_reserve_asset_deposited(loc: MultiLocation, amount: u128) -> VersionedXcm { + let multi_assets = MultiAssets::from_sorted_and_deduplicated(vec![(loc, amount).into()]).unwrap(); + VersionedXcm::from(Xcm::(vec![ + Instruction::::ReserveAssetDeposited(multi_assets), + ])) +} + +pub fn create_multi_reserve_asset_deposited(locs_and_amounts: Vec<(MultiLocation, u128)>) -> VersionedXcm { + let locs_and_amounts = locs_and_amounts + .into_iter() + .map(|(loc, amount)| (loc, amount).into()) + .collect(); + let multi_assets = MultiAssets::from_sorted_and_deduplicated(locs_and_amounts).unwrap(); + VersionedXcm::from(Xcm::(vec![ + Instruction::::ReserveAssetDeposited(multi_assets), + ])) +} + +pub fn create_versioned_receive_teleported_asset(loc: MultiLocation, amount: u128) -> VersionedXcm { + let multi_assets = MultiAssets::from_sorted_and_deduplicated(vec![(loc, amount).into()]).unwrap(); + VersionedXcm::from(Xcm::(vec![ + Instruction::::ReceiveTeleportedAsset(multi_assets), + ])) +} + +pub fn create_versioned_withdraw_asset(loc: MultiLocation, amount: u128) -> VersionedXcm { + let multi_assets = MultiAssets::from_sorted_and_deduplicated(vec![(loc, amount).into()]).unwrap(); + VersionedXcm::from(Xcm::(vec![Instruction::::WithdrawAsset( + multi_assets, + )])) +} + +pub fn create_versioned_xcm_v2(amount: u128) -> VersionedXcm { + use xcm::v2::prelude::*; + let multi_assets = MultiAssets::from_sorted_and_deduplicated(vec![(MultiLocation::here(), amount).into()]).unwrap(); + VersionedXcm::from(Xcm::(vec![ + Instruction::::ReserveAssetDeposited(multi_assets), + ])) +} diff --git a/pallets/xcm-rate-limiter/src/tests/mock.rs b/pallets/xcm-rate-limiter/src/tests/mock.rs new file mode 100644 index 000000000..9cc7d2e32 --- /dev/null +++ b/pallets/xcm-rate-limiter/src/tests/mock.rs @@ -0,0 +1,524 @@ +// This file is part of HydraDX. + +// Copyright (C) 2020-2022 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub use crate as pallet_xcm_rate_limiter; + +use frame_support::traits::{Contains, GenesisBuild}; +pub use frame_support::traits::{Everything, OnFinalize}; +pub use frame_support::{assert_noop, assert_ok, parameter_types}; +use frame_system::EnsureRoot; +use orml_traits::parameter_type_with_key; +use orml_traits::GetByKey; +use polkadot_parachain::primitives::RelayChainBlockNumber; +use sp_core::H256; +use sp_runtime::traits::BlockNumberProvider; +use sp_runtime::traits::Convert; +use sp_runtime::traits::{ConstU128, ConstU32}; +use sp_runtime::DispatchResult; +use sp_runtime::FixedU128; +use sp_runtime::Permill; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, + DispatchError, +}; +use std::cell::RefCell; +use std::collections::HashMap; + +use xcm::lts::prelude::*; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +pub type AccountId = u64; +pub type AssetId = u32; +pub type Balance = u128; + +pub const WHITELISTED_ACCCOUNT: u64 = 2; + +pub const HDX: AssetId = 100; +pub const DOT: AssetId = 200; +pub const DAI: AssetId = 2; +pub const LRNA: AssetId = 300; +pub const ACA: AssetId = 4; + +pub const ONE: Balance = 1_000_000_000_000; + +pub const REGISTERED_ASSET: AssetId = 1000; +pub const NATIVE_AMOUNT: Balance = 10_000 * ONE; + +thread_local! { + pub static POSITIONS: RefCell> = RefCell::new(HashMap::default()); + pub static REGISTERED_ASSETS: RefCell> = RefCell::new(HashMap::default()); + pub static ASSET_WEIGHT_CAP: RefCell = RefCell::new(Permill::from_percent(100)); + pub static ASSET_FEE: RefCell = RefCell::new(Permill::from_percent(0)); + pub static PROTOCOL_FEE: RefCell = RefCell::new(Permill::from_percent(0)); + pub static MIN_ADDED_LIQUDIITY: RefCell = RefCell::new(1000u128); + pub static MIN_TRADE_AMOUNT: RefCell = RefCell::new(1000u128); + pub static MAX_IN_RATIO: RefCell = RefCell::new(1u128); + pub static MAX_OUT_RATIO: RefCell = RefCell::new(1u128); + pub static MAX_NET_TRADE_VOLUME_LIMIT_PER_BLOCK: RefCell<(u32, u32)> = RefCell::new((2_000, 10_000)); // 20% + pub static MAX_ADD_LIQUIDITY_LIMIT_PER_BLOCK: RefCell> = RefCell::new(Some((4_000, 10_000))); // 40% + pub static MAX_REMOVE_LIQUIDITY_LIMIT_PER_BLOCK: RefCell> = RefCell::new(Some((2_000, 10_000))); // 20% +} + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + Balances: pallet_balances, + Omnipool: pallet_omnipool, + Tokens: orml_tokens, + XcmRateLimiter: pallet_xcm_rate_limiter, + } +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 42; +} + +impl frame_system::Config for Test { + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +parameter_types! { + pub DefaultMaxNetTradeVolumeLimitPerBlock: (u32, u32) = MAX_NET_TRADE_VOLUME_LIMIT_PER_BLOCK.with(|v| *v.borrow()); + pub DefaultMaxAddLiquidityLimitPerBlock: Option<(u32, u32)> = MAX_ADD_LIQUIDITY_LIMIT_PER_BLOCK.with(|v| *v.borrow()); + pub DefaultMaxRemoveLiquidityLimitPerBlock: Option<(u32, u32)> = MAX_REMOVE_LIQUIDITY_LIMIT_PER_BLOCK.with(|v| *v.borrow()); + pub const OmnipoolHubAsset: AssetId = LRNA; +} + +pub struct ConvertIdMock; +impl Convert> for ConvertIdMock { + fn convert(location: MultiLocation) -> Option { + use sp_runtime::SaturatedConversion; + match location { + loc if loc == MultiLocation::here() => Some(HDX), + MultiLocation { + parents: _, + interior: Junctions::X1(GeneralIndex(i)), + } => Some(i.saturated_into()), + _ => None, + } + } +} + +pub struct TreatSystemAsRelayBlockNumberProvider; +impl BlockNumberProvider for TreatSystemAsRelayBlockNumberProvider { + type BlockNumber = RelayChainBlockNumber; + + fn current_block_number() -> Self::BlockNumber { + use sp_runtime::SaturatedConversion; + System::current_block_number().saturated_into() + } +} + +impl pallet_xcm_rate_limiter::Config for Test { + type RuntimeEvent = RuntimeEvent; + type AssetId = AssetId; + type DeferDuration = ConstU32<10>; + type MaxDeferDuration = ConstU32<100>; + // dirty trick: we use System as a relay block number provider here + type RelayBlockNumberProvider = TreatSystemAsRelayBlockNumberProvider; + type RateLimitFor = XcmRateLimitFor; + type CurrencyIdConvert = ConvertIdMock; +} + +pub struct CircuitBreakerWhitelist; + +impl Contains for CircuitBreakerWhitelist { + fn contains(a: &AccountId) -> bool { + WHITELISTED_ACCCOUNT == *a + } +} + +impl pallet_balances::Config for Test { + type Balance = Balance; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU128<1>; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = (); + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 8]; +} + +parameter_type_with_key! { + pub ExistentialDeposits: |_currency_id: AssetId| -> Balance { + 0 + }; +} +parameter_type_with_key! { + pub XcmRateLimitFor: |asset_id: AssetId| -> Option { + match *asset_id { + HDX => Some(1000 * ONE), + DOT => Some(1000 * ONE), + DAI => Some(1000 * ONE), + LRNA => Some(1000 * ONE), + ACA => Some(1000 * ONE), + 42 => Some(1000 * ONE), + _ => None + } + }; +} + +impl orml_tokens::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type Amount = i128; + type CurrencyId = AssetId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type MaxLocks = (); + type DustRemovalWhitelist = Everything; + type MaxReserves = (); + type ReserveIdentifier = (); + type CurrencyHooks = (); +} + +parameter_types! { + pub const HDXAssetId: AssetId = HDX; + pub const LRNAAssetId: AssetId = LRNA; + pub const DAIAssetId: AssetId = DAI; + pub const PosiitionCollectionId: u32= 1000; + + pub AssetWeightCap: Permill =ASSET_WEIGHT_CAP.with(|v| *v.borrow()); + pub MinAddedLiquidity: Balance = MIN_ADDED_LIQUDIITY.with(|v| *v.borrow()); + pub MinTradeAmount: Balance = MIN_TRADE_AMOUNT.with(|v| *v.borrow()); + pub MaxInRatio: Balance = MAX_IN_RATIO.with(|v| *v.borrow()); + pub MaxOutRatio: Balance = MAX_OUT_RATIO.with(|v| *v.borrow()); + pub const TVLCap: Balance = Balance::MAX; + pub MinWithdrawFee: Permill = Permill::from_percent(0); +} + +impl pallet_omnipool::Config for Test { + type RuntimeEvent = RuntimeEvent; + type AssetId = AssetId; + type PositionItemId = u32; + type Currency = Tokens; + type AuthorityOrigin = EnsureRoot; + type HubAssetId = LRNAAssetId; + type StableCoinAssetId = DAIAssetId; + type WeightInfo = (); + type HdxAssetId = HDXAssetId; + type NFTCollectionId = PosiitionCollectionId; + type NFTHandler = DummyNFT; + type AssetRegistry = DummyRegistry; + type MinimumTradingLimit = MinTradeAmount; + type MinimumPoolLiquidity = MinAddedLiquidity; + type TechnicalOrigin = EnsureRoot; + type MaxInRatio = MaxInRatio; + type MaxOutRatio = MaxOutRatio; + type CollectionId = u32; + type OmnipoolHooks = (); + type PriceBarrier = (); + type MinWithdrawalFee = MinWithdrawFee; + type ExternalPriceOracle = WithdrawFeePriceOracle; + type Fee = FeeProvider; +} +use frame_support::traits::tokens::nonfungibles::{Create, Inspect, Mutate}; +use frame_support::weights::Weight; +use hydra_dx_math::ema::EmaPrice; + +pub struct DummyNFT; + +impl> Inspect for DummyNFT { + type ItemId = u32; + type CollectionId = u32; + + fn owner(_class: &Self::CollectionId, instance: &Self::ItemId) -> Option { + let mut owner: Option = None; + + POSITIONS.with(|v| { + if let Some(o) = v.borrow().get(instance) { + owner = Some((*o).into()); + } + }); + owner + } +} + +impl> Create for DummyNFT { + fn create_collection(_class: &Self::CollectionId, _who: &AccountId, _admin: &AccountId) -> DispatchResult { + Ok(()) + } +} + +impl + Into + Copy> Mutate for DummyNFT { + fn mint_into(_class: &Self::CollectionId, _instance: &Self::ItemId, _who: &AccountId) -> DispatchResult { + POSITIONS.with(|v| { + let mut m = v.borrow_mut(); + m.insert(*_instance, (*_who).into()); + }); + Ok(()) + } + + fn burn( + _class: &Self::CollectionId, + instance: &Self::ItemId, + _maybe_check_owner: Option<&AccountId>, + ) -> DispatchResult { + POSITIONS.with(|v| { + let mut m = v.borrow_mut(); + m.remove(instance); + }); + Ok(()) + } +} + +use crate::Config; +use hydradx_traits::Registry; +use pallet_omnipool::traits::ExternalPriceProvider; + +pub struct DummyRegistry(sp_std::marker::PhantomData); + +impl Registry, Balance, DispatchError> for DummyRegistry +where + T::AssetId: Into + From, +{ + fn exists(asset_id: T::AssetId) -> bool { + let asset = REGISTERED_ASSETS.with(|v| v.borrow().get(&(asset_id.into())).copied()); + matches!(asset, Some(_)) + } + + fn retrieve_asset(_name: &Vec) -> Result { + Ok(T::AssetId::default()) + } + + fn create_asset(_name: &Vec, _existential_deposit: Balance) -> Result { + let assigned = REGISTERED_ASSETS.with(|v| { + let l = v.borrow().len(); + v.borrow_mut().insert(l as u32, l as u32); + l as u32 + }); + Ok(T::AssetId::from(assigned)) + } +} + +pub struct ExtBuilder { + endowed_accounts: Vec<(u64, AssetId, Balance)>, + registered_assets: Vec, + asset_fee: Permill, + protocol_fee: Permill, + asset_weight_cap: Permill, + min_liquidity: u128, + min_trade_limit: u128, + register_stable_asset: bool, + max_in_ratio: Balance, + max_out_ratio: Balance, + tvl_cap: Balance, + init_pool: Option<(FixedU128, FixedU128)>, + pool_tokens: Vec<(AssetId, FixedU128, AccountId, Balance)>, +} + +impl Default for ExtBuilder { + fn default() -> Self { + // If eg. tests running on one thread only, this thread local is shared. + // let's make sure that it is empty for each test case + // or set to original default value + REGISTERED_ASSETS.with(|v| { + v.borrow_mut().clear(); + }); + POSITIONS.with(|v| { + v.borrow_mut().clear(); + }); + ASSET_WEIGHT_CAP.with(|v| { + *v.borrow_mut() = Permill::from_percent(100); + }); + ASSET_FEE.with(|v| { + *v.borrow_mut() = Permill::from_percent(0); + }); + PROTOCOL_FEE.with(|v| { + *v.borrow_mut() = Permill::from_percent(0); + }); + MIN_ADDED_LIQUDIITY.with(|v| { + *v.borrow_mut() = 1000u128; + }); + MIN_TRADE_AMOUNT.with(|v| { + *v.borrow_mut() = 1000u128; + }); + MAX_IN_RATIO.with(|v| { + *v.borrow_mut() = 1u128; + }); + MAX_OUT_RATIO.with(|v| { + *v.borrow_mut() = 1u128; + }); + + Self { + endowed_accounts: vec![ + (Omnipool::protocol_account(), DAI, 1000 * ONE), + (Omnipool::protocol_account(), HDX, NATIVE_AMOUNT), + ], + asset_fee: Permill::from_percent(0), + protocol_fee: Permill::from_percent(0), + asset_weight_cap: Permill::from_percent(100), + min_liquidity: 0, + registered_assets: vec![], + min_trade_limit: 0, + init_pool: None, + register_stable_asset: true, + pool_tokens: vec![], + max_in_ratio: 1u128, + max_out_ratio: 1u128, + tvl_cap: u128::MAX, + } + } +} + +impl ExtBuilder { + pub fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + // Add DAi and HDX as pre-registered assets + REGISTERED_ASSETS.with(|v| { + if self.register_stable_asset { + v.borrow_mut().insert(DAI, DAI); + } + v.borrow_mut().insert(HDX, HDX); + v.borrow_mut().insert(REGISTERED_ASSET, REGISTERED_ASSET); + self.registered_assets.iter().for_each(|asset| { + v.borrow_mut().insert(*asset, *asset); + }); + }); + + ASSET_FEE.with(|v| { + *v.borrow_mut() = self.asset_fee; + }); + ASSET_WEIGHT_CAP.with(|v| { + *v.borrow_mut() = self.asset_weight_cap; + }); + + PROTOCOL_FEE.with(|v| { + *v.borrow_mut() = self.protocol_fee; + }); + + MIN_ADDED_LIQUDIITY.with(|v| { + *v.borrow_mut() = self.min_liquidity; + }); + + MIN_TRADE_AMOUNT.with(|v| { + *v.borrow_mut() = self.min_trade_limit; + }); + MAX_IN_RATIO.with(|v| { + *v.borrow_mut() = self.max_in_ratio; + }); + MAX_OUT_RATIO.with(|v| { + *v.borrow_mut() = self.max_out_ratio; + }); + + orml_tokens::GenesisConfig:: { + balances: self + .endowed_accounts + .iter() + .flat_map(|(x, asset, amount)| vec![(*x, *asset, *amount)]) + .collect(), + } + .assimilate_storage(&mut t) + .unwrap(); + + let mut r: sp_io::TestExternalities = t.into(); + + r.execute_with(|| { + assert_ok!(Omnipool::set_tvl_cap(RuntimeOrigin::root(), self.tvl_cap,)); + }); + + if let Some((stable_price, native_price)) = self.init_pool { + r.execute_with(|| { + assert_ok!(Omnipool::initialize_pool( + RuntimeOrigin::root(), + stable_price, + native_price, + Permill::from_percent(100), + Permill::from_percent(100) + )); + + for (asset_id, price, owner, amount) in self.pool_tokens { + assert_ok!(Tokens::transfer( + RuntimeOrigin::signed(owner), + Omnipool::protocol_account(), + asset_id, + amount + )); + assert_ok!(Omnipool::add_token( + RuntimeOrigin::root(), + asset_id, + price, + self.asset_weight_cap, + owner + )); + } + }); + } + + r.execute_with(|| System::set_block_number(1)); + + r + } +} + +pub struct WithdrawFeePriceOracle; + +impl ExternalPriceProvider for WithdrawFeePriceOracle { + type Error = DispatchError; + + fn get_price(asset_a: AssetId, asset_b: AssetId) -> Result { + assert_eq!(asset_a, LRNA); + let asset_state = Omnipool::load_asset_state(asset_b)?; + let price = EmaPrice::new(asset_state.hub_reserve, asset_state.reserve); + Ok(price) + } + + fn get_price_weight() -> Weight { + Weight::default() + } +} + +pub struct FeeProvider; + +impl GetByKey for FeeProvider { + fn get(_: &AssetId) -> (Permill, Permill) { + (ASSET_FEE.with(|v| *v.borrow()), PROTOCOL_FEE.with(|v| *v.borrow())) + } +} diff --git a/pallets/xcm-rate-limiter/src/tests/mod.rs b/pallets/xcm-rate-limiter/src/tests/mod.rs new file mode 100644 index 000000000..1221969df --- /dev/null +++ b/pallets/xcm-rate-limiter/src/tests/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod defer_xcm; +pub(crate) mod mock; diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index b68cf1f97..a42eb1efc 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "primitives" -version = "5.8.1" +version = "5.8.2" authors = ["GalacticCouncil"] edition = "2021" repository = "https://github.com/galacticcouncil/HydraDX-node" @@ -26,5 +26,6 @@ std = [ "codec/std", "scale-info/std", "frame-support/std", + "polkadot-primitives/std", "sp-core/std", ] diff --git a/runtime/adapters/Cargo.toml b/runtime/adapters/Cargo.toml index 1efea0a61..6c0e162d0 100644 --- a/runtime/adapters/Cargo.toml +++ b/runtime/adapters/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hydradx-adapters" -version = "0.4.0" +version = "0.4.1" description = "Structs and other generic types for building runtimes." authors = ["GalacticCouncil"] edition = "2021" @@ -31,10 +31,15 @@ sp-std = { workspace = true } primitive-types = { workspace = true } # Polkadot dependencies +polkadot-parachain = { workspace = true } polkadot-xcm = { workspace = true } xcm-builder = { workspace = true } xcm-executor = { workspace = true } +# Cumulus dependencies +cumulus-pallet-parachain-system = { workspace = true } +cumulus-primitives-core = { workspace = true } + # ORML dependencies orml-xcm-support = { workspace = true } orml-traits = { workspace = true } @@ -51,6 +56,7 @@ runtime-benchmarks = [ std = [ "codec/std", "frame-support/std", + "frame-system/std", "hydradx-traits/std", "pallet-transaction-multi-payment/std", "polkadot-xcm/std", @@ -58,4 +64,6 @@ std = [ "sp-std/std", "xcm-builder/std", "xcm-executor/std", + "cumulus-pallet-parachain-system/std", + "polkadot-parachain/std", ] diff --git a/runtime/adapters/src/lib.rs b/runtime/adapters/src/lib.rs index aa2b089f9..c3c00de20 100644 --- a/runtime/adapters/src/lib.rs +++ b/runtime/adapters/src/lib.rs @@ -18,6 +18,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::FullCodec; +use cumulus_primitives_core::relay_chain::Hash; use frame_support::{ sp_runtime::{ traits::{AtLeast32BitUnsigned, Convert, Get, MaybeSerializeDeserialize, Saturating, Zero}, @@ -43,6 +44,7 @@ use pallet_transaction_multi_payment::DepositFee; use polkadot_xcm::latest::prelude::*; use primitive_types::U128; use primitives::{constants::chain::OMNIPOOL_SOURCE, AssetId, Balance, BlockNumber}; +use sp_runtime::traits::BlockNumberProvider; use sp_std::{collections::btree_map::BTreeMap, fmt::Debug, marker::PhantomData}; use warehouse_liquidity_mining::GlobalFarmData; use xcm_builder::TakeRevenue; @@ -241,6 +243,75 @@ impl< } } +// Relay chain Block number provider. +// Reason why the implementation is different for benchmarks is that it is not possible +// to set or change the block number in a benchmark using parachain system pallet. +// That's why we revert to using the system pallet in the benchmark. +pub struct RelayChainBlockNumberProvider(sp_std::marker::PhantomData); + +#[cfg(not(feature = "runtime-benchmarks"))] +impl BlockNumberProvider for RelayChainBlockNumberProvider { + type BlockNumber = polkadot_parachain::primitives::RelayChainBlockNumber; + + fn current_block_number() -> Self::BlockNumber { + let maybe_data = cumulus_pallet_parachain_system::Pallet::::validation_data(); + + if let Some(data) = maybe_data { + data.relay_parent_number + } else { + Self::BlockNumber::default() + } + } +} + +#[cfg(feature = "runtime-benchmarks")] +impl BlockNumberProvider for RelayChainBlockNumberProvider { + type BlockNumber = ::BlockNumber; + + fn current_block_number() -> Self::BlockNumber { + frame_system::Pallet::::current_block_number() + } +} + +pub trait RelayChainBlockHashProvider { + fn parent_hash() -> Option; +} +// The reason why there is difference between PROD and benchmark is that it is not possible +// to set validation data in parachain system pallet in the benchmarks. +// So for benchmarking, we mock it out and return some hardcoded parent hash +pub struct RelayChainBlockHashProviderAdapter(sp_std::marker::PhantomData); + +#[cfg(not(feature = "runtime-benchmarks"))] +impl RelayChainBlockHashProvider for RelayChainBlockHashProviderAdapter +where + Runtime: cumulus_pallet_parachain_system::Config, +{ + fn parent_hash() -> Option { + let validation_data = cumulus_pallet_parachain_system::Pallet::::validation_data(); + match validation_data { + Some(data) => Some(data.parent_head.hash()), + None => None, + } + } +} + +#[cfg(feature = "runtime-benchmarks")] +impl RelayChainBlockHashProvider for RelayChainBlockHashProviderAdapter +where + Runtime: cumulus_pallet_parachain_system::Config, +{ + fn parent_hash() -> Option { + // We use the same hash as for integration tests + // so the integration tests don't fail when they are run with 'runtime-benchmark' feature + let hash = [ + 14, 87, 81, 192, 38, 229, 67, 178, 232, 171, 46, 176, 96, 153, 218, 161, 209, 229, 223, 71, 119, 143, 119, + 135, 250, 171, 69, 205, 241, 47, 227, 168, + ] + .into(); + Some(hash) + } +} + /// Passes on trade and liquidity data from the omnipool to the oracle. pub struct OmnipoolHookAdapter(PhantomData<(Origin, Lrna, Runtime)>); diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml new file mode 100644 index 000000000..c54d9ee42 --- /dev/null +++ b/runtime/common/Cargo.toml @@ -0,0 +1,118 @@ +[package] +name = "common-runtime" +version = "102.4.1" +authors = ["GalacticCouncil"] +edition = "2021" +license = "Apache 2.0" +repository = "https://github.com/galacticcouncil/HydraDX-node" + +[package.metadata.docs.rs] +targets = ['x86_64-unknown-linux-gnu'] + +[build-dependencies] +substrate-wasm-builder = { workspace = true } + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.3.1", default-features = false, features = ["derive"] } +primitives = { workspace = true } +primitive-types = {default-features = false, version = '0.12.0'} + +pallet-omnipool = { workspace = true } +pallet-circuit-breaker = { workspace = true } +pallet-omnipool-liquidity-mining = { workspace = true } +pallet-claims = { workspace = true } +pallet-dca = { workspace = true } + +hydra-dx-math = { workspace = true } + +# Warehouse dependencies +hydradx-traits = { workspace = true } +pallet-transaction-multi-payment = { workspace = true } +pallet-asset-registry = { workspace = true } +pallet-currencies = { workspace = true } +pallet-transaction-pause = { workspace = true } +pallet-otc = { workspace = true } +pallet-ema-oracle = { workspace = true } +warehouse-liquidity-mining = { workspace = true } +pallet-route-executor = { workspace = true } +pallet-duster = { workspace = true } + +# Substrate dependencies +sp-runtime = { workspace = true } +sp-core = { workspace = true } +sp-std = { workspace = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +sp-npos-elections = { workspace = true } +pallet-transaction-payment = { workspace = true } +pallet-collective = { workspace = true } +pallet-treasury = { workspace = true } +pallet-utility = { workspace = true } +pallet-democracy = { workspace = true } +pallet-identity = { workspace = true } +pallet-preimage = { workspace = true } +pallet-proxy = { workspace = true } +pallet-scheduler = { workspace = true } +pallet-timestamp = { workspace = true } +pallet-balances = { workspace = true } +pallet-tips = { workspace = true } + +# Polkadot dependencies +pallet-xcm = { workspace = true } + +# ORML dependencies +orml-tokens = { workspace = true } +orml-vesting = { workspace = true } +orml-traits = { workspace = true } +orml-xcm-support = { workspace = true } + +# Cumulus dependencies +pallet-collator-selection = { workspace = true } +cumulus-pallet-xcmp-queue = { workspace = true } +cumulus-primitives-core = { workspace = true } +cumulus-pallet-parachain-system = { workspace = true } + +# Polkadot dependencies +xcm = { workspace = true } +xcm-executor = { workspace = true } + +[features] +default = ["std"] + +std = [ + "scale-info/std", + "primitives/std", + "pallet-omnipool/std", + "sp-runtime/std", + "sp-core/std", + "sp-std/std", + "frame-support/std", + "frame-system/std", + "sp-npos-elections/std", + "pallet-transaction-multi-payment/std", + "pallet-collective/std", + "pallet-treasury/std", + "pallet-utility/std", + "pallet-democracy/std", + "pallet-identity/std", + "pallet-preimage/std", + "pallet-proxy/std", + "pallet-route-executor/std", + "pallet-scheduler/std", + "pallet-timestamp/std", + "pallet-balances/std", + "pallet-claims/std", + "pallet-transaction-multi-payment/std", + "pallet-asset-registry/std", + "pallet-currencies/std", + "pallet-transaction-pause/std", + "orml-tokens/std", + "orml-vesting/std", + "orml-traits/std", + "orml-xcm-support/std", + "pallet-collator-selection/std", + "cumulus-pallet-xcmp-queue/std", + "xcm/std", + "xcm-executor/std", +] diff --git a/runtime/hydradx/Cargo.toml b/runtime/hydradx/Cargo.toml index ada7975e2..8aff00d07 100644 --- a/runtime/hydradx/Cargo.toml +++ b/runtime/hydradx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hydradx-runtime" -version = "166.0.0" +version = "167.0.0" authors = ["GalacticCouncil"] edition = "2021" license = "Apache 2.0" @@ -50,6 +50,7 @@ pallet-multisig = { workspace = true } pallet-democracy = { workspace = true } pallet-elections-phragmen = { workspace = true } pallet-uniques = { workspace = true } +pallet-xcm-rate-limiter = { workspace = true } # Warehouse dependencies hydradx-adapters = { workspace = true } @@ -156,7 +157,6 @@ runtime-benchmarks = [ "cumulus-pallet-xcmp-queue/runtime-benchmarks", "pallet-uniques/runtime-benchmarks", "pallet-omnipool/runtime-benchmarks", - "pallet-transaction-pause/runtime-benchmarks", "pallet-circuit-breaker/runtime-benchmarks", "pallet-ema-oracle/runtime-benchmarks", "pallet-duster/runtime-benchmarks", @@ -221,6 +221,7 @@ std = [ "pallet-currencies/std", "pallet-omnipool/std", "pallet-circuit-breaker/std", + "pallet-xcm-rate-limiter/std", "pallet-transaction-pause/std", "pallet-dca/std", "pallet-ema-oracle/std", @@ -296,6 +297,7 @@ try-runtime= [ "warehouse-liquidity-mining/try-runtime", "pallet-omnipool-liquidity-mining/try-runtime", "pallet-circuit-breaker/try-runtime", + "pallet-xcm-rate-limiter/try-runtime", "pallet-ema-oracle/try-runtime", "pallet-otc/try-runtime", "pallet-route-executor/try-runtime", diff --git a/runtime/hydradx/src/assets.rs b/runtime/hydradx/src/assets.rs index ed801dbec..66162f738 100644 --- a/runtime/hydradx/src/assets.rs +++ b/runtime/hydradx/src/assets.rs @@ -22,9 +22,9 @@ use hydradx_adapters::{ inspect::MultiInspectAdapter, EmaOraclePriceAdapter, OmnipoolHookAdapter, OracleAssetVolumeProvider, OraclePriceProviderAdapterForOmnipool, PriceAdjustmentAdapter, }; +use hydradx_adapters::{RelayChainBlockHashProvider, RelayChainBlockNumberProvider}; use hydradx_traits::{OraclePeriod, Source}; use pallet_currencies::BasicCurrencyAdapter; -use pallet_dca::RelayChainBlockHashProvider; use pallet_omnipool::traits::EnsurePriceWithin; use pallet_otc::NamedReserveIdentifier; use pallet_transaction_multi_payment::{AddTxAssetOnAccount, RemoveTxAssetOnKilled}; diff --git a/runtime/hydradx/src/lib.rs b/runtime/hydradx/src/lib.rs index 8ed051d13..8bcf9a6e3 100644 --- a/runtime/hydradx/src/lib.rs +++ b/runtime/hydradx/src/lib.rs @@ -64,7 +64,6 @@ pub use primitives::{ AccountId, Amount, AssetId, Balance, BlockNumber, CollectionId, Hash, Index, ItemId, Price, Signature, }; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use sp_runtime::traits::BlockNumberProvider; /// Import HydraDX pallets pub use pallet_claims; @@ -96,7 +95,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("hydradx"), impl_name: create_runtime_str!("hydradx"), authoring_version: 1, - spec_version: 166, + spec_version: 167, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -119,36 +118,6 @@ pub fn get_all_module_accounts() -> Vec { ] } -// Relay chain Block number provider. -// Reason why the implementation is different for benchmarks is that it is not possible -// to set or change the block number in a benchmark using parachain system pallet. -// That's why we revert to using the system pallet in the benchmark. -pub struct RelayChainBlockNumberProvider(sp_std::marker::PhantomData); - -#[cfg(not(feature = "runtime-benchmarks"))] -impl BlockNumberProvider for RelayChainBlockNumberProvider { - type BlockNumber = BlockNumber; - - fn current_block_number() -> Self::BlockNumber { - let maybe_data = cumulus_pallet_parachain_system::Pallet::::validation_data(); - - if let Some(data) = maybe_data { - data.relay_parent_number - } else { - Self::BlockNumber::default() - } - } -} - -#[cfg(feature = "runtime-benchmarks")] -impl BlockNumberProvider for RelayChainBlockNumberProvider { - type BlockNumber = ::BlockNumber; - - fn current_block_number() -> Self::BlockNumber { - frame_system::Pallet::::current_block_number() - } -} - // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime where @@ -186,6 +155,7 @@ construct_runtime!( OmnipoolLiquidityMining: pallet_omnipool_liquidity_mining = 63, OTC: pallet_otc = 64, CircuitBreaker: pallet_circuit_breaker = 65, + Router: pallet_route_executor = 67, DynamicFees: pallet_dynamic_fees = 68, diff --git a/runtime/hydradx/src/system.rs b/runtime/hydradx/src/system.rs index 1341f68b7..f52edd03d 100644 --- a/runtime/hydradx/src/system.rs +++ b/runtime/hydradx/src/system.rs @@ -37,6 +37,7 @@ use frame_support::{ }, PalletId, RuntimeDebug, }; +use hydradx_adapters::RelayChainBlockNumberProvider; use scale_info::TypeInfo; pub struct CallFilter; diff --git a/runtime/hydradx/src/weights/xcmp_queue.rs b/runtime/hydradx/src/weights/xcmp_queue.rs index a05c6a82f..bed7181f5 100644 --- a/runtime/hydradx/src/weights/xcmp_queue.rs +++ b/runtime/hydradx/src/weights/xcmp_queue.rs @@ -70,4 +70,28 @@ impl WeightInfo for HydraWeight { .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } + // Storage: XcmpQueue QueueConfig (r:1 w:0) + // Proof Skipped: XcmpQueue QueueConfig (max_values: Some(1), max_size: None, mode: Measured) + // Storage: XcmpQueue DeferredXcmMessages (r:1 w:1) + // Proof Skipped: XcmpQueue DeferredXcmMessages (max_values: None, max_size: None, mode: Measured) + // Storage: XcmpQueue CounterForOverweight (r:1 w:1) + // Proof: XcmpQueue CounterForOverweight (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Storage: XcmpQueue OverweightCount (r:1 w:1) + // Proof Skipped: XcmpQueue OverweightCount (max_values: Some(1), max_size: None, mode: Measured) + // Storage: XcmpQueue Overweight (r:100 w:100) + // Proof Skipped: XcmpQueue Overweight (max_values: None, max_size: None, mode: Measured) + fn service_deferred() -> Weight { + // Minimum execution time: 90_934_683 nanoseconds. + Weight::from_ref_time(91_491_151_000 as u64) + .saturating_add(T::DbWeight::get().reads(104 as u64)) + .saturating_add(T::DbWeight::get().writes(103 as u64)) + } + // Storage: XcmpQueue DeferredXcmMessages (r:1 w:1) + // Proof Skipped: XcmpQueue DeferredXcmMessages (max_values: None, max_size: None, mode: Measured) + fn discard_deferred() -> Weight { + // Minimum execution time: 62_131_073 nanoseconds. + Weight::from_ref_time(63_092_826_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } } diff --git a/runtime/hydradx/src/xcm.rs b/runtime/hydradx/src/xcm.rs index e471cb71e..9669b5ad9 100644 --- a/runtime/hydradx/src/xcm.rs +++ b/runtime/hydradx/src/xcm.rs @@ -1,6 +1,7 @@ use super::*; use codec::MaxEncodedLen; +use hydradx_adapters::RelayChainBlockNumberProvider; use hydradx_adapters::{MultiCurrencyTrader, ReroutingMultiCurrencyAdapter, ToFeeReceiver}; use pallet_transaction_multi_payment::DepositAll; use primitives::AssetId; // shadow glob import of polkadot_xcm::v3::prelude::AssetId @@ -140,6 +141,10 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ControllerOriginConverter = XcmOriginToCallOrigin; type PriceForSiblingDelivery = (); type WeightInfo = weights::xcmp_queue::HydraWeight; + type ExecuteDeferredOrigin = EnsureRoot; + type MaxDeferredMessages = ConstU32<100>; + type RelayChainBlockNumberProvider = RelayChainBlockNumberProvider; + type XcmDeferFilter = (); } impl cumulus_pallet_dmp_queue::Config for Runtime { @@ -209,7 +214,6 @@ impl pallet_xcm::Config for Runtime { #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; } - pub struct CurrencyIdConvert; use primitives::constants::chain::CORE_ASSET_ID;