diff --git a/Cargo.lock b/Cargo.lock index 0345843f39..c6842dfadb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -639,6 +639,73 @@ dependencies = [ "sp-api", ] +[[package]] +name = "bifrost-kusama-integration-tests" +version = "0.8.0" +dependencies = [ + "bifrost-asset-registry", + "bifrost-flexible-fee", + "bifrost-flexible-fee-rpc-runtime-api", + "bifrost-kusama-runtime", + "bifrost-liquidity-mining", + "bifrost-polkadot-runtime", + "bifrost-runtime-common", + "bifrost-salp", + "bifrost-salp-rpc-runtime-api", + "bifrost-slp", + "bifrost-vesting", + "bifrost-vsbond-auction", + "bifrost-vtoken-minting", + "cumulus-pallet-aura-ext", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-parachain-inherent", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "cumulus-test-relay-sproof-builder", + "env_logger", + "frame-support", + "frame-system", + "hex", + "hex-literal", + "kusama-runtime", + "log", + "node-primitives", + "orml-currencies", + "orml-tokens 0.4.1-dev (git+https://github.com/open-web3-stack/open-runtime-module-library?rev=20969f385bf77e41386e8d8aa9626b003a306204)", + "orml-traits 0.4.1-dev (git+https://github.com/open-web3-stack/open-runtime-module-library?rev=20969f385bf77e41386e8d8aa9626b003a306204)", + "orml-unknown-tokens", + "orml-xcm-support", + "orml-xtokens", + "pallet-balances", + "pallet-collator-selection", + "pallet-membership", + "pallet-staking", + "pallet-transaction-payment", + "pallet-xcm", + "parachain-info", + "parity-scale-codec", + "polkadot-parachain", + "polkadot-primitives", + "polkadot-runtime-parachains", + "serde", + "smallvec", + "sp-io", + "sp-runtime", + "sp-std", + "sp-trie", + "static_assertions", + "xcm", + "xcm-builder", + "xcm-emulator", + "xcm-executor", + "zenlink-protocol", + "zenlink-protocol-runtime-api", +] + [[package]] name = "bifrost-kusama-runtime" version = "0.8.0" @@ -810,6 +877,73 @@ dependencies = [ "sp-std", ] +[[package]] +name = "bifrost-polkadot-integration-tests" +version = "0.8.0" +dependencies = [ + "bifrost-asset-registry", + "bifrost-flexible-fee", + "bifrost-flexible-fee-rpc-runtime-api", + "bifrost-kusama-runtime", + "bifrost-liquidity-mining", + "bifrost-polkadot-runtime", + "bifrost-runtime-common", + "bifrost-salp", + "bifrost-salp-rpc-runtime-api", + "bifrost-slp", + "bifrost-vesting", + "bifrost-vsbond-auction", + "bifrost-vtoken-minting", + "cumulus-pallet-aura-ext", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-parachain-inherent", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "cumulus-test-relay-sproof-builder", + "env_logger", + "frame-support", + "frame-system", + "hex", + "hex-literal", + "log", + "node-primitives", + "orml-currencies", + "orml-tokens 0.4.1-dev (git+https://github.com/open-web3-stack/open-runtime-module-library?rev=20969f385bf77e41386e8d8aa9626b003a306204)", + "orml-traits 0.4.1-dev (git+https://github.com/open-web3-stack/open-runtime-module-library?rev=20969f385bf77e41386e8d8aa9626b003a306204)", + "orml-unknown-tokens", + "orml-xcm-support", + "orml-xtokens", + "pallet-balances", + "pallet-collator-selection", + "pallet-membership", + "pallet-staking", + "pallet-transaction-payment", + "pallet-xcm", + "parachain-info", + "parity-scale-codec", + "polkadot-parachain", + "polkadot-primitives", + "polkadot-runtime", + "polkadot-runtime-parachains", + "serde", + "smallvec", + "sp-io", + "sp-runtime", + "sp-std", + "sp-trie", + "static_assertions", + "xcm", + "xcm-builder", + "xcm-emulator", + "xcm-executor", + "zenlink-protocol", + "zenlink-protocol-runtime-api", +] + [[package]] name = "bifrost-polkadot-runtime" version = "0.8.0" @@ -2280,19 +2414,6 @@ dependencies = [ "syn", ] -[[package]] -name = "cumulus-pallet-session-benchmarking" -version = "3.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.28#15f48687e545e4b171a0af1065cec59002bc7145" -dependencies = [ - "frame-support", - "frame-system", - "pallet-session", - "parity-scale-codec", - "sp-runtime", - "sp-std", -] - [[package]] name = "cumulus-pallet-xcm" version = "0.1.0" @@ -2328,23 +2449,6 @@ dependencies = [ "xcm-executor", ] -[[package]] -name = "cumulus-ping" -version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.28#15f48687e545e4b171a0af1065cec59002bc7145" -dependencies = [ - "cumulus-pallet-xcm", - "cumulus-primitives-core", - "frame-support", - "frame-system", - "parity-scale-codec", - "scale-info", - "serde", - "sp-runtime", - "sp-std", - "xcm", -] - [[package]] name = "cumulus-primitives-core" version = "0.1.0" @@ -5995,37 +6099,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "pallet-asset-tx-payment" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.28#34a0621761c4a333cb2074ff720f7acbfb92dbb8" -dependencies = [ - "frame-support", - "frame-system", - "pallet-transaction-payment", - "parity-scale-codec", - "scale-info", - "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "pallet-assets" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.28#34a0621761c4a333cb2074ff720f7acbfb92dbb8" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "parity-scale-codec", - "scale-info", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-aura" version = "4.0.0-dev" @@ -6823,21 +6896,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-uniques" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.28#34a0621761c4a333cb2074ff720f7acbfb92dbb8" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "log", - "parity-scale-codec", - "scale-info", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-utility" version = "4.0.0-dev" @@ -6940,35 +6998,6 @@ dependencies = [ "substrate-fixed", ] -[[package]] -name = "parachains-common" -version = "1.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.28#15f48687e545e4b171a0af1065cec59002bc7145" -dependencies = [ - "cumulus-primitives-utility", - "frame-executive", - "frame-support", - "frame-system", - "pallet-asset-tx-payment", - "pallet-assets", - "pallet-authorship", - "pallet-balances", - "pallet-collator-selection", - "parity-scale-codec", - "polkadot-primitives", - "polkadot-runtime-common", - "scale-info", - "sp-consensus-aura", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "substrate-wasm-builder", - "xcm", - "xcm-builder", - "xcm-executor", -] - [[package]] name = "parity-db" version = "0.3.17" @@ -9051,106 +9080,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "runtime-integration-tests" -version = "0.8.0" -dependencies = [ - "bifrost-asset-registry", - "bifrost-flexible-fee", - "bifrost-flexible-fee-rpc-runtime-api", - "bifrost-kusama-runtime", - "bifrost-liquidity-mining", - "bifrost-polkadot-runtime", - "bifrost-runtime-common", - "bifrost-salp", - "bifrost-salp-rpc-runtime-api", - "bifrost-slp", - "bifrost-vesting", - "bifrost-vsbond-auction", - "bifrost-vtoken-minting", - "cumulus-pallet-aura-ext", - "cumulus-pallet-dmp-queue", - "cumulus-pallet-parachain-system", - "cumulus-pallet-xcm", - "cumulus-pallet-xcmp-queue", - "cumulus-primitives-core", - "cumulus-primitives-parachain-inherent", - "cumulus-primitives-timestamp", - "cumulus-primitives-utility", - "cumulus-test-relay-sproof-builder", - "env_logger", - "frame-benchmarking", - "frame-executive", - "frame-support", - "frame-system", - "frame-system-rpc-runtime-api", - "frame-try-runtime", - "hex", - "hex-literal", - "kusama-runtime", - "log", - "node-primitives", - "node-service", - "orml-currencies", - "orml-tokens 0.4.1-dev (git+https://github.com/open-web3-stack/open-runtime-module-library?rev=20969f385bf77e41386e8d8aa9626b003a306204)", - "orml-traits 0.4.1-dev (git+https://github.com/open-web3-stack/open-runtime-module-library?rev=20969f385bf77e41386e8d8aa9626b003a306204)", - "orml-unknown-tokens", - "orml-xcm-support", - "orml-xtokens", - "pallet-aura", - "pallet-authorship", - "pallet-balances", - "pallet-bounties", - "pallet-collator-selection", - "pallet-collective", - "pallet-democracy", - "pallet-elections-phragmen", - "pallet-indices", - "pallet-membership", - "pallet-multisig", - "pallet-proxy", - "pallet-scheduler", - "pallet-session", - "pallet-staking", - "pallet-sudo", - "pallet-timestamp", - "pallet-tips", - "pallet-transaction-payment", - "pallet-transaction-payment-rpc-runtime-api", - "pallet-treasury", - "pallet-utility", - "pallet-xcm", - "parachain-info", - "parity-scale-codec", - "polkadot-parachain", - "polkadot-primitives", - "polkadot-runtime-parachains", - "serde", - "smallvec", - "sp-api", - "sp-arithmetic", - "sp-block-builder", - "sp-consensus-aura", - "sp-core", - "sp-inherents", - "sp-io", - "sp-offchain", - "sp-runtime", - "sp-session", - "sp-std", - "sp-transaction-pool", - "sp-trie", - "sp-version", - "statemine-runtime", - "static_assertions", - "xcm", - "xcm-builder", - "xcm-emulator", - "xcm-executor", - "zenlink-protocol", - "zenlink-protocol-runtime-api", -] - [[package]] name = "rustc-demangle" version = "0.1.21" @@ -11503,69 +11432,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "statemine-runtime" -version = "2.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.28#15f48687e545e4b171a0af1065cec59002bc7145" -dependencies = [ - "cumulus-pallet-aura-ext", - "cumulus-pallet-dmp-queue", - "cumulus-pallet-parachain-system", - "cumulus-pallet-session-benchmarking", - "cumulus-pallet-xcm", - "cumulus-pallet-xcmp-queue", - "cumulus-ping", - "cumulus-primitives-core", - "cumulus-primitives-timestamp", - "cumulus-primitives-utility", - "frame-executive", - "frame-support", - "frame-system", - "frame-system-rpc-runtime-api", - "kusama-runtime-constants", - "log", - "pallet-asset-tx-payment", - "pallet-assets", - "pallet-aura", - "pallet-authorship", - "pallet-balances", - "pallet-collator-selection", - "pallet-multisig", - "pallet-proxy", - "pallet-session", - "pallet-timestamp", - "pallet-transaction-payment", - "pallet-transaction-payment-rpc-runtime-api", - "pallet-uniques", - "pallet-utility", - "pallet-xcm", - "parachain-info", - "parachains-common", - "parity-scale-codec", - "polkadot-core-primitives", - "polkadot-parachain", - "polkadot-runtime-common", - "scale-info", - "serde", - "smallvec", - "sp-api", - "sp-block-builder", - "sp-consensus-aura", - "sp-core", - "sp-inherents", - "sp-io", - "sp-offchain", - "sp-runtime", - "sp-session", - "sp-std", - "sp-transaction-pool", - "sp-version", - "substrate-wasm-builder", - "xcm", - "xcm-builder", - "xcm-executor", -] - [[package]] name = "static_assertions" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 5488e6f9e4..5870ebdf03 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ - "integration-tests", + "integration-tests/bifrost-kusama", + "integration-tests/bifrost-polkadot", "node/cli", "node/primitives", "node/rpc", diff --git a/Makefile b/Makefile index 8ea7995819..c2ff2e523e 100644 --- a/Makefile +++ b/Makefile @@ -36,11 +36,19 @@ check-all: format .PHONY: test-all # cargo test all runtime test-all: - SKIP_WASM_BUILD= cargo test --features "with-all-runtime" --workspace --exclude runtime-integration-tests + SKIP_WASM_BUILD= cargo test --features "with-all-runtime" .PHONY: integration-test # integration test integration-test: - SKIP_WASM_BUILD= cargo test -p runtime-integration-tests --features=with-bifrost-kusama-runtime + SKIP_WASM_BUILD= cargo test -p *-integration-tests + +.PHONY: kusama-integration-test # integration test +kusama-integration-test: + SKIP_WASM_BUILD= cargo test -p bifrost-kusama-integration-tests + +.PHONY: polkadot-integration-test # integration test +polkadot-integration-test: + SKIP_WASM_BUILD= cargo test -p bifrost-polkadot-integration-tests .PHONY: clean # cargo clean clean: diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml deleted file mode 100644 index 10c6af4c99..0000000000 --- a/integration-tests/Cargo.toml +++ /dev/null @@ -1,213 +0,0 @@ -[package] -name = "runtime-integration-tests" -version = "0.8.0" -authors = ["Ron Yang "] -edition = "2021" - -[dependencies] -# third-party dependencies -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ - "derive", - "max-encoded-len", -] } -log = { version = "0.4.17", default-features = false } -serde = { version = "1.0.143", optional = true } -static_assertions = "1.1.0" -hex = { version = "0.4", default-features = false, optional = true } -hex-literal = { version = "0.3.4" } -smallvec = "1.9.0" - -# primitives -node-primitives = { default-features = false, path = "../node/primitives" } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } - -# frame dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false, optional = true } -frame-try-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false, optional = true } -frame-executive = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-bounties = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-collective = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-democracy = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-elections-phragmen = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-indices = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-membership = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-multisig = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-proxy = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-scheduler = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-tips = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-treasury = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } -pallet-staking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28", default-features = false } - -# Cumulus dependencies -cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } -cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } -cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } -cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } -cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } -cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } -parachain-info = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } -pallet-collator-selection = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } - -# Polkadot dependencies -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28", default-features = false } -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28", default-features = false } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28", default-features = false } -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28", default-features = false } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28", default-features = false } - -# bifrost pallets -bifrost-asset-registry = { path = "../pallets/asset-registry", default-features = false } -bifrost-flexible-fee = { path = "../pallets/flexible-fee", default-features = false } -bifrost-flexible-fee-rpc-runtime-api = { path = "../pallets/flexible-fee/rpc/runtime-api", default-features = false } -bifrost-liquidity-mining = { path = "../pallets/liquidity-mining", default-features = false } -bifrost-runtime-common = { path = "../runtime/common", default-features = false } -bifrost-salp = { path = "../pallets/salp", default-features = false } -bifrost-salp-rpc-runtime-api = { path = "../pallets/salp/rpc/runtime-api", default-features = false } -bifrost-slp = { path = "../pallets/slp", default-features = false } -bifrost-vsbond-auction = { path = "../pallets/vsbond-auction", default-features = false } -bifrost-vtoken-minting = { path = "../pallets/vtoken-minting", default-features = false } -pallet-vesting = { package = "bifrost-vesting", path = "../pallets/vesting", default-features = false } -bifrost-kusama-runtime = { path = "../runtime/bifrost-kusama", default-features = false } -bifrost-polkadot-runtime = { path = "../runtime/bifrost-polkadot", default-features = false } - -# orml -orml-currencies = { version = "0.4.1-dev", default-features = false } -orml-tokens = { version = "0.4.1-dev", default-features = false } -orml-traits = { version = "0.4.1-dev", default-features = false } -orml-xtokens = { version = "0.4.1-dev", default-features = false } -orml-unknown-tokens = { version = "0.4.1-dev", default-features = false } -orml-xcm-support = { version = "0.4.1-dev", default-features = false } - -zenlink-protocol = { version = "*", default-features = false } -zenlink-protocol-runtime-api = { version = "*", default-features = false } - -[dev-dependencies] -env_logger = "0.9.0" -hex = "0.4.0" - -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } - -cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } -cumulus-test-relay-sproof-builder = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } - -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } -kusama-runtime = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } -xcm-emulator = { git = "https://github.com/shaunxw/xcm-simulator", rev = "6c02911a3eeb04c342e4eb273d2ffbedd45dabff" } - -node-service = { path = "../node/service", features = ["with-all-runtime"] } -statemine-runtime = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } - -[features] -default = ["std"] -no_std = [] -with-bifrost-runtime = [ - "node-service/with-bifrost-kusama-runtime", - "node-service/with-bifrost-polkadot-runtime", -] -with-bifrost-kusama-runtime = ["node-service/with-bifrost-kusama-runtime"] -with-bifrost-polkadot-runtime = ["node-service/with-bifrost-polkadot-runtime"] -std = [ - "codec/std", - "log/std", - "frame-benchmarking/std", - "frame-try-runtime/std", - "frame-executive/std", - "frame-support/std", - "frame-system-rpc-runtime-api/std", - "frame-system/std", - "node-primitives/std", - "pallet-aura/std", - "pallet-balances/std", - "pallet-bounties/std", - "pallet-collator-selection/std", - "pallet-collective/std", - "pallet-democracy/std", - "pallet-elections-phragmen/std", - "pallet-indices/std", - "pallet-membership/std", - "pallet-multisig/std", - "pallet-proxy/std", - "pallet-sudo/std", - "pallet-timestamp/std", - "pallet-tips/std", - "pallet-transaction-payment-rpc-runtime-api/std", - "pallet-transaction-payment/std", - "pallet-treasury/std", - "pallet-session/std", - "pallet-vesting/std", - "pallet-utility/std", - "sp-arithmetic/std", - "sp-api/std", - "sp-block-builder/std", - "sp-consensus-aura/std", - "sp-core/std", - "sp-inherents/std", - "sp-runtime/std", - "sp-offchain/std", - "sp-session/std", - "sp-std/std", - "sp-transaction-pool/std", - "parachain-info/std", - "cumulus-pallet-aura-ext/std", - "cumulus-pallet-dmp-queue/std", - "cumulus-pallet-parachain-system/std", - "cumulus-pallet-xcmp-queue/std", - "cumulus-pallet-xcm/std", - "cumulus-primitives-core/std", - "cumulus-primitives-timestamp/std", - "cumulus-primitives-utility/std", - "xcm/std", - "xcm-builder/std", - "xcm-executor/std", - "polkadot-primitives/std", - "polkadot-runtime-parachains/std", - "bifrost-asset-registry/std", - "bifrost-flexible-fee/std", - "bifrost-flexible-fee-rpc-runtime-api/std", - "bifrost-runtime-common/std", - "bifrost-salp/std", - "bifrost-salp-rpc-runtime-api/std", - "bifrost-slp/std", - "bifrost-vsbond-auction/std", - "bifrost-vtoken-minting/std", - "orml-currencies/std", - "orml-traits/std", - "orml-tokens/std", - "orml-xtokens/std", - "orml-unknown-tokens/std", - "orml-xcm-support/std", - "zenlink-protocol/std", - "zenlink-protocol-runtime-api/std", - "bifrost-kusama-runtime/std", - "bifrost-polkadot-runtime/std", -] diff --git a/integration-tests/bifrost-kusama/Cargo.toml b/integration-tests/bifrost-kusama/Cargo.toml new file mode 100644 index 0000000000..3a3a294af6 --- /dev/null +++ b/integration-tests/bifrost-kusama/Cargo.toml @@ -0,0 +1,91 @@ +[package] +name = "bifrost-kusama-integration-tests" +version = "0.8.0" +authors = ["Ron Yang "] +edition = "2021" + +[dependencies] +# third-party dependencies +codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +log = { version = "0.4.17" } +serde = { version = "1.0.143", optional = true } +static_assertions = "1.1.0" +hex = { version = "0.4", optional = true } +hex-literal = { version = "0.3.4" } +smallvec = "1.9.0" + +# primitives +node-primitives = { default-features = false, path = "../../node/primitives" } + +# frame dependencies +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +pallet-staking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +pallet-membership = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } + +# Cumulus dependencies +cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +pallet-collator-selection = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } + +# Polkadot dependencies +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } + +# bifrost pallets +bifrost-asset-registry = { path = "../../pallets/asset-registry" } +bifrost-flexible-fee = { path = "../../pallets/flexible-fee" } +bifrost-flexible-fee-rpc-runtime-api = { path = "../../pallets/flexible-fee/rpc/runtime-api" } +bifrost-liquidity-mining = { path = "../../pallets/liquidity-mining" } +bifrost-salp = { path = "../../pallets/salp" } +bifrost-salp-rpc-runtime-api = { path = "../../pallets/salp/rpc/runtime-api" } +bifrost-slp = { path = "../../pallets/slp" } +bifrost-vsbond-auction = { path = "../../pallets/vsbond-auction" } +bifrost-vtoken-minting = { path = "../../pallets/vtoken-minting" } +pallet-vesting = { package = "bifrost-vesting", path = "../../pallets/vesting" } +bifrost-runtime-common = { path = "../../runtime/common" } +bifrost-kusama-runtime = { path = "../../runtime/bifrost-kusama" } +bifrost-polkadot-runtime = { path = "../../runtime/bifrost-polkadot" } + +# orml +orml-currencies = { version = "0.4.1-dev" } +orml-tokens = { version = "0.4.1-dev" } +orml-traits = { version = "0.4.1-dev" } +orml-xtokens = { version = "0.4.1-dev" } +orml-unknown-tokens = { version = "0.4.1-dev" } +orml-xcm-support = { version = "0.4.1-dev" } + +zenlink-protocol = { version = "*" } +zenlink-protocol-runtime-api = { version = "*" } + +[dev-dependencies] +env_logger = "0.9.0" +hex = "0.4.0" + +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } + +cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-test-relay-sproof-builder = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } + +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +kusama-runtime = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +#statemine-runtime = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +xcm-emulator = { git = "https://github.com/shaunxw/xcm-simulator", rev = "6c02911a3eeb04c342e4eb273d2ffbedd45dabff" } diff --git a/integration-tests/bifrost-kusama/src/asset_registry.rs b/integration-tests/bifrost-kusama/src/asset_registry.rs new file mode 100644 index 0000000000..22de19dd6e --- /dev/null +++ b/integration-tests/bifrost-kusama/src/asset_registry.rs @@ -0,0 +1,480 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::{kusama_integration_tests::*, kusama_test_net::*}; +use bifrost_asset_registry::{ + AssetMetadata, AssetMetadatas, CurrencyIdToLocations, CurrencyIdToWeights, CurrencyMetadatas, + Error, Event, LocationToCurrencyIds, +}; +use frame_support::{assert_noop, assert_ok}; +use xcm::{latest::prelude::*, VersionedMultiLocation}; +use xcm_emulator::TestExt; + +#[test] +fn register_foreign_asset_work() { + sp_io::TestExternalities::default().execute_with(|| { + Bifrost::execute_with(|| { + let v0_location = VersionedMultiLocation::V0(xcm::v0::MultiLocation::X1( + xcm::v0::Junction::Parachain(1000), + )); + + assert_ok!(AssetRegistry::register_foreign_asset( + Origin::root(), + Box::new(v0_location.clone()), + Box::new(AssetMetadata { + name: b"Token Name".to_vec(), + symbol: b"TN".to_vec(), + decimals: 12, + minimal_balance: 1, + }) + )); + + let location: MultiLocation = v0_location.try_into().unwrap(); + System::assert_last_event(bifrost_kusama_runtime::Event::AssetRegistry( + Event::ForeignAssetRegistered { + asset_id: 0, + asset_address: location.clone(), + metadata: AssetMetadata { + name: b"Token Name".to_vec(), + symbol: b"TN".to_vec(), + decimals: 12, + minimal_balance: 1, + }, + }, + )); + + assert_eq!( + CurrencyIdToLocations::::get(CurrencyId::ForeignAsset(0)), + Some(location.clone()) + ); + assert_eq!( + AssetMetadatas::::get(AssetIds::ForeignAssetId(0)), + Some(AssetMetadata { + name: b"Token Name".to_vec(), + symbol: b"TN".to_vec(), + decimals: 12, + minimal_balance: 1, + }) + ); + assert_eq!( + LocationToCurrencyIds::::get(location), + Some(CurrencyId::ForeignAsset(0)) + ); + }); + }) +} + +#[test] +fn update_foreign_asset_work() { + sp_io::TestExternalities::default().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { + let v0_location = VersionedMultiLocation::V0(xcm::v0::MultiLocation::X1( + xcm::v0::Junction::Parachain(1000), + )); + + assert_ok!(AssetRegistry::register_foreign_asset( + Origin::root(), + Box::new(v0_location.clone()), + Box::new(AssetMetadata { + name: b"Token Name".to_vec(), + symbol: b"TN".to_vec(), + decimals: 12, + minimal_balance: 1, + }) + )); + + assert_ok!(AssetRegistry::update_foreign_asset( + Origin::root(), + 0, + Box::new(v0_location.clone()), + Box::new(AssetMetadata { + name: b"New Token Name".to_vec(), + symbol: b"NTN".to_vec(), + decimals: 13, + minimal_balance: 2, + }) + )); + + let location: MultiLocation = v0_location.try_into().unwrap(); + System::assert_last_event(bifrost_kusama_runtime::Event::AssetRegistry( + Event::ForeignAssetUpdated { + asset_id: 0, + asset_address: location.clone(), + metadata: AssetMetadata { + name: b"New Token Name".to_vec(), + symbol: b"NTN".to_vec(), + decimals: 13, + minimal_balance: 2, + }, + }, + )); + + assert_eq!( + AssetMetadatas::::get(AssetIds::ForeignAssetId(0)), + Some(AssetMetadata { + name: b"New Token Name".to_vec(), + symbol: b"NTN".to_vec(), + decimals: 13, + minimal_balance: 2, + }) + ); + assert_eq!( + CurrencyIdToLocations::::get(CurrencyId::ForeignAsset(0)), + Some(location.clone()) + ); + assert_eq!( + LocationToCurrencyIds::::get(location.clone()), + Some(CurrencyId::ForeignAsset(0)) + ); + + // modify location + let new_location = VersionedMultiLocation::V0(xcm::v0::MultiLocation::X1( + xcm::v0::Junction::Parachain(2000), + )); + assert_ok!(AssetRegistry::update_foreign_asset( + Origin::root(), + 0, + Box::new(new_location.clone()), + Box::new(AssetMetadata { + name: b"New Token Name".to_vec(), + symbol: b"NTN".to_vec(), + decimals: 13, + minimal_balance: 2, + }) + )); + assert_eq!( + AssetMetadatas::::get(AssetIds::ForeignAssetId(0)), + Some(AssetMetadata { + name: b"New Token Name".to_vec(), + symbol: b"NTN".to_vec(), + decimals: 13, + minimal_balance: 2, + }) + ); + let new_location: MultiLocation = new_location.try_into().unwrap(); + assert_eq!( + CurrencyIdToLocations::::get(CurrencyId::ForeignAsset(0)), + Some(new_location.clone()) + ); + assert_eq!(LocationToCurrencyIds::::get(location), None); + assert_eq!( + LocationToCurrencyIds::::get(new_location), + Some(CurrencyId::ForeignAsset(0)) + ); + }); + }) +} + +#[test] +fn register_native_asset_works() { + sp_io::TestExternalities::default().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { + let v0_location = VersionedMultiLocation::V0(xcm::v0::MultiLocation::X1( + xcm::v0::Junction::Parachain(1000), + )); + + assert_ok!(AssetRegistry::register_native_asset( + Origin::root(), + CurrencyId::Token(TokenSymbol::DOT), + Box::new(v0_location.clone()), + Box::new(AssetMetadata { + name: b"Token Name".to_vec(), + symbol: b"TN".to_vec(), + decimals: 12, + minimal_balance: 1, + }) + )); + System::assert_last_event(bifrost_kusama_runtime::Event::AssetRegistry( + Event::AssetRegistered { + asset_id: AssetIds::NativeAssetId(CurrencyId::Token(TokenSymbol::DOT)), + metadata: AssetMetadata { + name: b"Token Name".to_vec(), + symbol: b"TN".to_vec(), + decimals: 12, + minimal_balance: 1, + }, + }, + )); + + assert_eq!( + AssetMetadatas::::get(AssetIds::NativeAssetId(CurrencyId::Token( + TokenSymbol::DOT + ))), + Some(AssetMetadata { + name: b"Token Name".to_vec(), + symbol: b"TN".to_vec(), + decimals: 12, + minimal_balance: 1, + }) + ); + // Can't duplicate + assert_noop!( + AssetRegistry::register_native_asset( + Origin::root(), + CurrencyId::Token(TokenSymbol::DOT), + Box::new(v0_location.clone()), + Box::new(AssetMetadata { + name: b"Token Name".to_vec(), + symbol: b"TN".to_vec(), + decimals: 12, + minimal_balance: 1, + }) + ), + Error::::AssetIdExisted + ); + }); + }) +} + +#[test] +fn update_native_asset_works() { + sp_io::TestExternalities::default().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { + let v0_location = VersionedMultiLocation::V0(xcm::v0::MultiLocation::X1( + xcm::v0::Junction::Parachain(1000), + )); + assert_noop!( + AssetRegistry::update_native_asset( + Origin::root(), + CurrencyId::Token(TokenSymbol::DOT), + Box::new(v0_location.clone()), + Box::new(AssetMetadata { + name: b"New Token Name".to_vec(), + symbol: b"NTN".to_vec(), + decimals: 13, + minimal_balance: 2, + }) + ), + Error::::AssetIdNotExists + ); + + let new_location = VersionedMultiLocation::V0(xcm::v0::MultiLocation::X1( + xcm::v0::Junction::Parachain(2000), + )); + assert_ok!(AssetRegistry::register_native_asset( + Origin::root(), + CurrencyId::Token(TokenSymbol::DOT), + Box::new(new_location.clone()), + Box::new(AssetMetadata { + name: b"Token Name".to_vec(), + symbol: b"TN".to_vec(), + decimals: 12, + minimal_balance: 1, + }) + )); + + assert_ok!(AssetRegistry::update_native_asset( + Origin::root(), + CurrencyId::Token(TokenSymbol::DOT), + Box::new(new_location.clone()), + Box::new(AssetMetadata { + name: b"New Token Name".to_vec(), + symbol: b"NTN".to_vec(), + decimals: 13, + minimal_balance: 2, + }) + )); + + System::assert_last_event(bifrost_kusama_runtime::Event::AssetRegistry( + Event::AssetUpdated { + asset_id: AssetIds::NativeAssetId(CurrencyId::Token(TokenSymbol::DOT)), + metadata: AssetMetadata { + name: b"New Token Name".to_vec(), + symbol: b"NTN".to_vec(), + decimals: 13, + minimal_balance: 2, + }, + }, + )); + + assert_eq!( + AssetMetadatas::::get(AssetIds::NativeAssetId(CurrencyId::Token( + TokenSymbol::DOT + ))), + Some(AssetMetadata { + name: b"New Token Name".to_vec(), + symbol: b"NTN".to_vec(), + decimals: 13, + minimal_balance: 2, + }) + ); + }); + }) +} + +#[test] +fn register_token_metadata() { + sp_io::TestExternalities::default().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { + let metadata = AssetMetadata { + name: b"Bifrost Native Coin".to_vec(), + symbol: b"BNC".to_vec(), + decimals: 12, + minimal_balance: 0, + }; + + assert_ok!(AssetRegistry::register_token_metadata( + Origin::root(), + Box::new(metadata.clone()) + )); + + assert_eq!( + CurrencyMetadatas::::get(CurrencyId::Token2(0)), + Some(metadata.clone()) + ) + }) + }) +} + +#[test] +fn register_vtoken_metadata() { + sp_io::TestExternalities::default().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { + let metadata = AssetMetadata { + name: b"Bifrost Native Coin".to_vec(), + symbol: b"BNC".to_vec(), + decimals: 12, + minimal_balance: 0, + }; + let v_metadata = AssetMetadata { + name: b"Voucher BNC".to_vec(), + symbol: b"vBNC".to_vec(), + decimals: 12, + minimal_balance: 0, + }; + assert_noop!( + AssetRegistry::register_vtoken_metadata(Origin::root(), 1), + Error::::CurrencyIdNotExists + ); + + assert_ok!(AssetRegistry::register_token_metadata( + Origin::root(), + Box::new(metadata.clone()) + )); + + assert_ok!(AssetRegistry::register_vtoken_metadata(Origin::root(), 0)); + + assert_eq!( + CurrencyMetadatas::::get(CurrencyId::VToken2(0)), + Some(v_metadata.clone()) + ) + }) + }) +} + +#[test] +fn register_vsbond_metadata() { + sp_io::TestExternalities::default().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { + let metadata = AssetMetadata { + name: b"KSM Native Token".to_vec(), + symbol: b"KSM".to_vec(), + decimals: 12, + minimal_balance: 0, + }; + let name = "vsBOND-KSM-2001-10-20".as_bytes().to_vec(); + let v_metadata = AssetMetadata { + name: name.clone(), + symbol: name, + decimals: 12, + minimal_balance: 0, + }; + assert_noop!( + AssetRegistry::register_vtoken_metadata(Origin::root(), 1), + Error::::CurrencyIdNotExists + ); + + assert_ok!(AssetRegistry::register_token_metadata( + Origin::root(), + Box::new(metadata.clone()) + )); + + assert_ok!(AssetRegistry::register_vsbond_metadata(Origin::root(), 0, 2001, 10, 20)); + + assert_eq!( + CurrencyMetadatas::::get(CurrencyId::VSBond2(0, 2001, 10, 20)), + Some(v_metadata.clone()) + ) + }) + }) +} + +#[test] +fn register_multilocation() { + sp_io::TestExternalities::default().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { + let metadata = AssetMetadata { + name: b"Bifrost Native Coin".to_vec(), + symbol: b"BNC".to_vec(), + decimals: 12, + minimal_balance: 0, + }; + // v1 + let location = VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: xcm::v1::Junctions::X1(xcm::v1::Junction::Parachain(2001)), + }); + let multi_location: MultiLocation = location.clone().try_into().unwrap(); + + assert_noop!( + AssetRegistry::register_multilocation( + Origin::root(), + CurrencyId::Token2(0), + Box::new(location.clone()), + 2000_000_000 + ), + Error::::CurrencyIdNotExists + ); + + assert_ok!(AssetRegistry::register_token_metadata( + Origin::root(), + Box::new(metadata.clone()) + )); + + assert_ok!(AssetRegistry::register_multilocation( + Origin::root(), + CurrencyId::Token2(0), + Box::new(location.clone()), + 2000_000_000 + )); + + assert_noop!( + AssetRegistry::register_multilocation( + Origin::root(), + CurrencyId::Token2(0), + Box::new(location.clone()), + 2000_000_000 + ), + Error::::CurrencyIdExisted + ); + + assert_eq!( + LocationToCurrencyIds::::get(multi_location.clone()), + Some(CurrencyId::Token2(0)) + ); + assert_eq!( + CurrencyIdToLocations::::get(CurrencyId::Token2(0)), + Some(multi_location.clone()) + ); + assert_eq!( + CurrencyIdToWeights::::get(CurrencyId::Token2(0)), + Some(2000_000_000) + ); + }) + }) +} diff --git a/integration-tests/bifrost-kusama/src/dollor_tests.rs b/integration-tests/bifrost-kusama/src/dollor_tests.rs new file mode 100644 index 0000000000..e070e18e57 --- /dev/null +++ b/integration-tests/bifrost-kusama/src/dollor_tests.rs @@ -0,0 +1,127 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use bifrost_kusama_runtime::Runtime; +use bifrost_runtime_common::{cent, dollar, micro, microcent, milli, millicent}; +use node_primitives::{CurrencyId, TokenSymbol::*}; + +const DECIMAL_18: u128 = 1_000_000_000_000_000_000; +const DECIMAL_12: u128 = 1_000_000_000_000; +const DECIMAL_10: u128 = 10_000_000_000; + +#[test] +fn dollar_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + assert_eq!(dollar::(CurrencyId::Token(ASG)), DECIMAL_12); + assert_eq!(dollar::(CurrencyId::Token(BNC)), DECIMAL_12); + assert_eq!(dollar::(CurrencyId::Token(KUSD)), DECIMAL_12); + assert_eq!(dollar::(CurrencyId::Token(DOT)), DECIMAL_10); + assert_eq!(dollar::(CurrencyId::Token(KSM)), DECIMAL_12); + assert_eq!(dollar::(CurrencyId::Token(ETH)), DECIMAL_18); + assert_eq!(dollar::(CurrencyId::Token(KAR)), DECIMAL_12); + assert_eq!(dollar::(CurrencyId::Token(ZLK)), DECIMAL_18); + assert_eq!(dollar::(CurrencyId::Token(PHA)), DECIMAL_12); + assert_eq!(dollar::(CurrencyId::Token(RMRK)), DECIMAL_10); + assert_eq!(dollar::(CurrencyId::Token(MOVR)), DECIMAL_18); + }); +} + +#[test] +fn milli_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + assert_eq!(milli::(CurrencyId::Token(ASG)), DECIMAL_12 / 1000); + assert_eq!(milli::(CurrencyId::Token(BNC)), DECIMAL_12 / 1000); + assert_eq!(milli::(CurrencyId::Token(KUSD)), DECIMAL_12 / 1000); + assert_eq!(milli::(CurrencyId::Token(DOT)), DECIMAL_10 / 1000); + assert_eq!(milli::(CurrencyId::Token(KSM)), DECIMAL_12 / 1000); + assert_eq!(milli::(CurrencyId::Token(ETH)), DECIMAL_18 / 1000); + assert_eq!(milli::(CurrencyId::Token(KAR)), DECIMAL_12 / 1000); + assert_eq!(milli::(CurrencyId::Token(ZLK)), DECIMAL_18 / 1000); + assert_eq!(milli::(CurrencyId::Token(PHA)), DECIMAL_12 / 1000); + assert_eq!(milli::(CurrencyId::Token(RMRK)), DECIMAL_10 / 1000); + assert_eq!(milli::(CurrencyId::Token(MOVR)), DECIMAL_18 / 1000); + }); +} + +#[test] +fn micro_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + assert_eq!(micro::(CurrencyId::Token(ASG)), DECIMAL_12 / 1_000_000); + assert_eq!(micro::(CurrencyId::Token(BNC)), DECIMAL_12 / 1_000_000); + assert_eq!(micro::(CurrencyId::Token(KUSD)), DECIMAL_12 / 1_000_000); + assert_eq!(micro::(CurrencyId::Token(DOT)), DECIMAL_10 / 1_000_000); + assert_eq!(micro::(CurrencyId::Token(KSM)), DECIMAL_12 / 1_000_000); + assert_eq!(micro::(CurrencyId::Token(ETH)), DECIMAL_18 / 1_000_000); + assert_eq!(micro::(CurrencyId::Token(KAR)), DECIMAL_12 / 1_000_000); + assert_eq!(micro::(CurrencyId::Token(ZLK)), DECIMAL_18 / 1_000_000); + assert_eq!(micro::(CurrencyId::Token(PHA)), DECIMAL_12 / 1_000_000); + assert_eq!(micro::(CurrencyId::Token(RMRK)), DECIMAL_10 / 1_000_000); + assert_eq!(micro::(CurrencyId::Token(MOVR)), DECIMAL_18 / 1_000_000); + }); +} + +#[test] +fn cent_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + assert_eq!(cent::(CurrencyId::Token(ASG)), DECIMAL_12 / 100); + assert_eq!(cent::(CurrencyId::Token(BNC)), DECIMAL_12 / 100); + assert_eq!(cent::(CurrencyId::Token(KUSD)), DECIMAL_12 / 100); + assert_eq!(cent::(CurrencyId::Token(DOT)), DECIMAL_10 / 100); + assert_eq!(cent::(CurrencyId::Token(KSM)), DECIMAL_12 / 100); + assert_eq!(cent::(CurrencyId::Token(ETH)), DECIMAL_18 / 100); + assert_eq!(cent::(CurrencyId::Token(KAR)), DECIMAL_12 / 100); + assert_eq!(cent::(CurrencyId::Token(ZLK)), DECIMAL_18 / 100); + assert_eq!(cent::(CurrencyId::Token(PHA)), DECIMAL_12 / 100); + assert_eq!(cent::(CurrencyId::Token(RMRK)), DECIMAL_10 / 100); + assert_eq!(cent::(CurrencyId::Token(MOVR)), DECIMAL_18 / 100); + }); +} + +#[test] +fn millicent_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + assert_eq!(millicent::(CurrencyId::Token(ASG)), DECIMAL_12 / 100_000); + assert_eq!(millicent::(CurrencyId::Token(BNC)), DECIMAL_12 / 100_000); + assert_eq!(millicent::(CurrencyId::Token(KUSD)), DECIMAL_12 / 100_000); + assert_eq!(millicent::(CurrencyId::Token(DOT)), DECIMAL_10 / 100_000); + assert_eq!(millicent::(CurrencyId::Token(KSM)), DECIMAL_12 / 100_000); + assert_eq!(millicent::(CurrencyId::Token(ETH)), DECIMAL_18 / 100_000); + assert_eq!(millicent::(CurrencyId::Token(KAR)), DECIMAL_12 / 100_000); + assert_eq!(millicent::(CurrencyId::Token(ZLK)), DECIMAL_18 / 100_000); + assert_eq!(millicent::(CurrencyId::Token(PHA)), DECIMAL_12 / 100_000); + assert_eq!(millicent::(CurrencyId::Token(RMRK)), DECIMAL_10 / 100_000); + assert_eq!(millicent::(CurrencyId::Token(MOVR)), DECIMAL_18 / 100_000); + }); +} + +#[test] +fn microcent_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + assert_eq!(microcent::(CurrencyId::Token(ASG)), DECIMAL_12 / 100_000_000); + assert_eq!(microcent::(CurrencyId::Token(BNC)), DECIMAL_12 / 100_000_000); + assert_eq!(microcent::(CurrencyId::Token(KUSD)), DECIMAL_12 / 100_000_000); + assert_eq!(microcent::(CurrencyId::Token(DOT)), DECIMAL_10 / 100_000_000); + assert_eq!(microcent::(CurrencyId::Token(KSM)), DECIMAL_12 / 100_000_000); + assert_eq!(microcent::(CurrencyId::Token(ETH)), DECIMAL_18 / 100_000_000); + assert_eq!(microcent::(CurrencyId::Token(KAR)), DECIMAL_12 / 100_000_000); + assert_eq!(microcent::(CurrencyId::Token(ZLK)), DECIMAL_18 / 100_000_000); + assert_eq!(microcent::(CurrencyId::Token(PHA)), DECIMAL_12 / 100_000_000); + assert_eq!(microcent::(CurrencyId::Token(RMRK)), DECIMAL_10 / 100_000_000); + assert_eq!(microcent::(CurrencyId::Token(MOVR)), DECIMAL_18 / 100_000_000); + }); +} diff --git a/integration-tests/src/flexible_fee.rs b/integration-tests/bifrost-kusama/src/flexible_fee.rs similarity index 58% rename from integration-tests/src/flexible_fee.rs rename to integration-tests/bifrost-kusama/src/flexible_fee.rs index 49d63125a9..7e1fd03d4c 100644 --- a/integration-tests/src/flexible_fee.rs +++ b/integration-tests/bifrost-kusama/src/flexible_fee.rs @@ -16,21 +16,22 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{integration_tests::*, kusama_test_net::*}; use bifrost_flexible_fee::UserFeeChargeOrderList; -use bifrost_kusama_runtime::{Call, FlexibleFee, ZenlinkProtocol}; -use bifrost_runtime_common::milli; +use bifrost_kusama_runtime::{Call, Currencies, FlexibleFee, Origin, Runtime, ZenlinkProtocol}; +use bifrost_runtime_common::{dollar, milli}; use frame_support::{ assert_ok, weights::{GetDispatchInfo, Pays, PostDispatchInfo}, }; use frame_system::pallet_prelude::BlockNumberFor; -use node_primitives::TryConvertFrom; +use node_primitives::{AccountId, CurrencyId, TokenSymbol, TryConvertFrom}; use pallet_transaction_payment::OnChargeTransaction; use sp_runtime::testing::TestXt; use xcm_emulator::TestExt; use zenlink_protocol::AssetId; +use crate::kusama_test_net::Bifrost; + // some common variables pub const CHARLIE: AccountId = AccountId::new([0u8; 32]); pub const BOB: AccountId = AccountId::new([1u8; 32]); @@ -49,31 +50,31 @@ fn basic_setup() { Origin::root(), ALICE.into(), CURRENCY_ID_0, - 10 * milli(CURRENCY_ID_0) as i128 + 10 * milli::(CURRENCY_ID_0) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), ALICE.into(), CURRENCY_ID_1, - 10 * dollar(CURRENCY_ID_1) as i128 + 10 * dollar::(CURRENCY_ID_1) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), ALICE.into(), CURRENCY_ID_2, - 10 * dollar(CURRENCY_ID_2) as i128 + 10 * dollar::(CURRENCY_ID_2) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), ALICE.into(), CURRENCY_ID_3, - 100 * dollar(CURRENCY_ID_3) as i128 + 100 * dollar::(CURRENCY_ID_3) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), ALICE.into(), CURRENCY_ID_4, - 10 * dollar(CURRENCY_ID_4) as i128 + 10 * dollar::(CURRENCY_ID_4) as i128 )); // Bob @@ -81,31 +82,31 @@ fn basic_setup() { Origin::root(), BOB.into(), CURRENCY_ID_0, - 10 * dollar(CURRENCY_ID_0) as i128 + 10 * dollar::(CURRENCY_ID_0) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), BOB.into(), CURRENCY_ID_1, - 10 * dollar(CURRENCY_ID_1) as i128 + 10 * dollar::(CURRENCY_ID_1) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), BOB.into(), CURRENCY_ID_2, - 10 * dollar(CURRENCY_ID_2) as i128 + 10 * dollar::(CURRENCY_ID_2) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), BOB.into(), CURRENCY_ID_3, - 100 * dollar(CURRENCY_ID_3) as i128 + 100 * dollar::(CURRENCY_ID_3) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), BOB.into(), CURRENCY_ID_4, - 10 * dollar(CURRENCY_ID_4) as i128 + 10 * dollar::(CURRENCY_ID_4) as i128 )); // Charlie @@ -113,31 +114,31 @@ fn basic_setup() { Origin::root(), CHARLIE.into(), CURRENCY_ID_0, - 10 * dollar(CURRENCY_ID_0) as i128 + 10 * dollar::(CURRENCY_ID_0) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), CHARLIE.into(), CURRENCY_ID_1, - 10 * dollar(CURRENCY_ID_1) as i128 + 10 * dollar::(CURRENCY_ID_1) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), CHARLIE.into(), CURRENCY_ID_2, - 10 * dollar(CURRENCY_ID_2) as i128 + 10 * dollar::(CURRENCY_ID_2) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), CHARLIE.into(), CURRENCY_ID_3, - 100 * dollar(CURRENCY_ID_3) as i128 + 100 * dollar::(CURRENCY_ID_3) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), CHARLIE.into(), CURRENCY_ID_4, - 10 * dollar(CURRENCY_ID_4) as i128 + 10 * dollar::(CURRENCY_ID_4) as i128 )); // Dick @@ -145,31 +146,31 @@ fn basic_setup() { Origin::root(), DICK.into(), CURRENCY_ID_0, - 10 * dollar(CURRENCY_ID_0) as i128 + 10 * dollar::(CURRENCY_ID_0) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), DICK.into(), CURRENCY_ID_1, - 10 * dollar(CURRENCY_ID_1) as i128 + 10 * dollar::(CURRENCY_ID_1) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), DICK.into(), CURRENCY_ID_2, - 10 * dollar(CURRENCY_ID_2) as i128 + 10 * dollar::(CURRENCY_ID_2) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), DICK.into(), CURRENCY_ID_3, - 100 * dollar(CURRENCY_ID_3) as i128 + 100 * dollar::(CURRENCY_ID_3) as i128 )); assert_ok!(Currencies::update_balance( Origin::root(), DICK.into(), CURRENCY_ID_4, - 10 * dollar(CURRENCY_ID_4) as i128 + 10 * dollar::(CURRENCY_ID_4) as i128 )); // create DEX pair @@ -215,8 +216,8 @@ fn basic_setup() { Origin::signed(DICK), asset_0_currency_id, asset_1_currency_id, - 1 * dollar(CURRENCY_ID_0), - 1 * dollar(CURRENCY_ID_1), + 1 * dollar::(CURRENCY_ID_0), + 1 * dollar::(CURRENCY_ID_1), 1, 1, deadline @@ -229,8 +230,8 @@ fn basic_setup() { Origin::signed(DICK), asset_0_currency_id, asset_2_currency_id, - 1 * dollar(CURRENCY_ID_0), - 1 * dollar(CURRENCY_ID_2), + 1 * dollar::(CURRENCY_ID_0), + 1 * dollar::(CURRENCY_ID_2), 1, 1, deadline @@ -243,8 +244,8 @@ fn basic_setup() { Origin::signed(DICK), asset_0_currency_id, asset_3_currency_id, - 1 * dollar(CURRENCY_ID_0), - 1 * dollar(CURRENCY_ID_3), + 1 * dollar::(CURRENCY_ID_0), + 1 * dollar::(CURRENCY_ID_3), 1, 1, deadline @@ -257,8 +258,8 @@ fn basic_setup() { Origin::signed(DICK), asset_0_currency_id, asset_4_currency_id, - 1 * dollar(CURRENCY_ID_0), - 1 * dollar(CURRENCY_ID_4), + 1 * dollar::(CURRENCY_ID_0), + 1 * dollar::(CURRENCY_ID_4), 1, 1, deadline @@ -267,92 +268,98 @@ fn basic_setup() { #[test] fn set_user_fee_charge_order_should_work() { - Bifrost::execute_with(|| { - let origin_signed_alice = Origin::signed(ALICE); - let mut asset_order_list_vec: Vec = - vec![CURRENCY_ID_4, CURRENCY_ID_3, CURRENCY_ID_2, CURRENCY_ID_1, CURRENCY_ID_0]; - assert_ok!(FlexibleFee::set_user_fee_charge_order( - origin_signed_alice.clone(), - Some(asset_order_list_vec.clone()) - )); - - asset_order_list_vec.insert(0, CURRENCY_ID_0); - assert_eq!(UserFeeChargeOrderList::::get(ALICE), Some(asset_order_list_vec)); - - assert_ok!(FlexibleFee::set_user_fee_charge_order(origin_signed_alice, None)); - - assert_eq!(UserFeeChargeOrderList::::get(ALICE).is_none(), true); - }); + sp_io::TestExternalities::default().execute_with(|| { + Bifrost::execute_with(|| { + let origin_signed_alice = Origin::signed(ALICE); + let mut asset_order_list_vec: Vec = + vec![CURRENCY_ID_4, CURRENCY_ID_3, CURRENCY_ID_2, CURRENCY_ID_1, CURRENCY_ID_0]; + assert_ok!(FlexibleFee::set_user_fee_charge_order( + origin_signed_alice.clone(), + Some(asset_order_list_vec.clone()) + )); + + asset_order_list_vec.insert(0, CURRENCY_ID_0); + assert_eq!(UserFeeChargeOrderList::::get(ALICE), Some(asset_order_list_vec)); + + assert_ok!(FlexibleFee::set_user_fee_charge_order(origin_signed_alice, None)); + + assert_eq!(UserFeeChargeOrderList::::get(ALICE).is_none(), true); + }); + }) } #[test] fn withdraw_fee_should_work() { - Bifrost::execute_with(|| { - basic_setup(); - - // prepare call variable - let asset_order_list_vec: Vec = - vec![CURRENCY_ID_0, CURRENCY_ID_1, CURRENCY_ID_2, CURRENCY_ID_3, CURRENCY_ID_4]; - let call = Call::FlexibleFee(bifrost_flexible_fee::Call::set_user_fee_charge_order { - asset_order_list_vec: Some(asset_order_list_vec), + sp_io::TestExternalities::default().execute_with(|| { + Bifrost::execute_with(|| { + basic_setup(); + + // prepare call variable + let asset_order_list_vec: Vec = + vec![CURRENCY_ID_0, CURRENCY_ID_1, CURRENCY_ID_2, CURRENCY_ID_3, CURRENCY_ID_4]; + let call = Call::FlexibleFee(bifrost_flexible_fee::Call::set_user_fee_charge_order { + asset_order_list_vec: Some(asset_order_list_vec), + }); + + // prepare info variable + let extra = (); + let xt = TestXt::new(call.clone(), Some((0u64, extra))); + let info = xt.get_dispatch_info(); + + // 99 inclusion fee and a tip of 8 + assert_ok!(FlexibleFee::withdraw_fee(&CHARLIE, &call, &info, 107, 8)); + + assert_eq!( + ::Currency::free_balance(&CHARLIE), + 10 * dollar::(CURRENCY_ID_0) - 107 + ); }); - - // prepare info variable - let extra = (); - let xt = TestXt::new(call.clone(), Some((0u64, extra))); - let info = xt.get_dispatch_info(); - - // 99 inclusion fee and a tip of 8 - assert_ok!(FlexibleFee::withdraw_fee(&CHARLIE, &call, &info, 107, 8)); - - assert_eq!( - ::Currency::free_balance(&CHARLIE), - 10 * dollar(CURRENCY_ID_0) - 107 - ); - }); + }) } #[test] fn correct_and_deposit_fee_should_work() { - Bifrost::execute_with(|| { - basic_setup(); - // prepare call variable - let asset_order_list_vec: Vec = - vec![CURRENCY_ID_0, CURRENCY_ID_1, CURRENCY_ID_2, CURRENCY_ID_3, CURRENCY_ID_4]; - let call = Call::FlexibleFee(bifrost_flexible_fee::Call::set_user_fee_charge_order { - asset_order_list_vec: Some(asset_order_list_vec), + sp_io::TestExternalities::default().execute_with(|| { + Bifrost::execute_with(|| { + basic_setup(); + // prepare call variable + let asset_order_list_vec: Vec = + vec![CURRENCY_ID_0, CURRENCY_ID_1, CURRENCY_ID_2, CURRENCY_ID_3, CURRENCY_ID_4]; + let call = Call::FlexibleFee(bifrost_flexible_fee::Call::set_user_fee_charge_order { + asset_order_list_vec: Some(asset_order_list_vec), + }); + // prepare info variable + let extra = (); + let xt = TestXt::new(call.clone(), Some((0u64, extra))); + let info = xt.get_dispatch_info(); + + // prepare post info + let post_info = PostDispatchInfo { actual_weight: Some(20), pays_fee: Pays::Yes }; + + let corrected_fee = 80; + let tip = 8; + + let already_withdrawn = + FlexibleFee::withdraw_fee(&CHARLIE, &call, &info, corrected_fee, tip).unwrap(); + + assert_eq!( + ::Currency::free_balance(&CHARLIE), + 10 * dollar::(CURRENCY_ID_0) - 80 + ); + + assert_ok!(FlexibleFee::correct_and_deposit_fee( + &CHARLIE, + &info, + &post_info, + corrected_fee, + tip, + already_withdrawn + )); + + assert_eq!( + ::Currency::free_balance(&CHARLIE), + 10 * dollar::(CURRENCY_ID_0) - 80 + ); }); - // prepare info variable - let extra = (); - let xt = TestXt::new(call.clone(), Some((0u64, extra))); - let info = xt.get_dispatch_info(); - - // prepare post info - let post_info = PostDispatchInfo { actual_weight: Some(20), pays_fee: Pays::Yes }; - - let corrected_fee = 80; - let tip = 8; - - let already_withdrawn = - FlexibleFee::withdraw_fee(&CHARLIE, &call, &info, corrected_fee, tip).unwrap(); - - assert_eq!( - ::Currency::free_balance(&CHARLIE), - 10 * dollar(CURRENCY_ID_0) - 80 - ); - - assert_ok!(FlexibleFee::correct_and_deposit_fee( - &CHARLIE, - &info, - &post_info, - corrected_fee, - tip, - already_withdrawn - )); - - assert_eq!( - ::Currency::free_balance(&CHARLIE), - 10 * dollar(CURRENCY_ID_0) - 80 - ); - }); + }) } diff --git a/integration-tests/bifrost-kusama/src/kusama_cross_chain_transact.rs b/integration-tests/bifrost-kusama/src/kusama_cross_chain_transact.rs new file mode 100644 index 0000000000..45c2aec87c --- /dev/null +++ b/integration-tests/bifrost-kusama/src/kusama_cross_chain_transact.rs @@ -0,0 +1,59 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use frame_support::assert_ok; +use xcm::latest::prelude::*; +use xcm_emulator::TestExt; + +use crate::{kusama_integration_tests::*, kusama_test_net::*}; + +#[test] +fn relaychain_transact_works() { + sp_io::TestExternalities::default().execute_with(|| { + let remark = kusama_runtime::Call::System( + frame_system::Call::::remark_with_event { + remark: "Hello from Bifrost!".as_bytes().to_vec(), + }, + ); + + let asset: MultiAsset = + MultiAsset { id: Concrete(MultiLocation::here()), fun: Fungible(8000000000) }; + + let msg = Xcm(vec![ + WithdrawAsset(asset.clone().into()), + BuyExecution { fees: asset, weight_limit: WeightLimit::Limited(6000000000) }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: 2000000000 as u64, + call: remark.encode().into(), + }, + ]); + + Bifrost::execute_with(|| { + assert_ok!(pallet_xcm::Pallet::::send_xcm(Here, Parent, msg)); + }); + + KusamaNet::execute_with(|| { + use kusama_runtime::{Event, System}; + assert!(System::events().iter().any(|r| matches!( + r.event, + Event::System(frame_system::Event::Remarked { sender: _, hash: _ }) + ))); + }); + }) +} diff --git a/integration-tests/bifrost-kusama/src/kusama_cross_chain_transfer.rs b/integration-tests/bifrost-kusama/src/kusama_cross_chain_transfer.rs new file mode 100644 index 0000000000..e650db6d6a --- /dev/null +++ b/integration-tests/bifrost-kusama/src/kusama_cross_chain_transfer.rs @@ -0,0 +1,150 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Cross-chain transfer tests within Kusama network. +use bifrost_asset_registry::AssetMetadata; +use bifrost_kusama_runtime::{AssetRegistry, Runtime}; +use bifrost_runtime_common::millicent; +use frame_support::assert_ok; +use node_primitives::{CurrencyId, TokenSymbol}; +use orml_traits::MultiCurrency; +use xcm::{latest::prelude::*, VersionedMultiAssets, VersionedMultiLocation}; +use xcm_emulator::TestExt; + +use crate::{kusama_integration_tests::*, kusama_test_net::*}; + +#[test] +fn transfer_from_relay_chain() { + sp_io::TestExternalities::default().execute_with(|| { + register_asset(); + KusamaNet::execute_with(|| { + assert_ok!(kusama_runtime::XcmPallet::reserve_transfer_assets( + kusama_runtime::Origin::signed(ALICE.into()), + Box::new(VersionedMultiLocation::V1(X1(Parachain(2001)).into())), + Box::new(VersionedMultiLocation::V1( + X1(Junction::AccountId32 { id: BOB, network: NetworkId::Any }).into() + )), + Box::new(VersionedMultiAssets::V1( + (Here, dollar::(RelayCurrencyId::get())).into() + )), + 0, + )); + }); + Bifrost::execute_with(|| { + assert_eq!( + Tokens::free_balance(RelayCurrencyId::get(), &AccountId::from(BOB)), + 999907304000 + ); + }); + }) +} + +#[test] +fn transfer_to_relay_chain() { + sp_io::TestExternalities::default().execute_with(|| { + Bifrost::execute_with(|| { + assert_ok!(XTokens::transfer( + Origin::signed(ALICE.into()), + RelayCurrencyId::get(), + dollar::(RelayCurrencyId::get()), + Box::new(xcm::VersionedMultiLocation::V1(MultiLocation::new( + 1, + X1(Junction::AccountId32 { id: BOB, network: NetworkId::Any }) + ))), + 4_000_000_000 + )); + }); + + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Balances::free_balance(&AccountId::from(BOB)), + 999_988_476_752 + ); + }); + }) +} + +#[test] +fn transfer_to_sibling() { + sp_io::TestExternalities::default().execute_with(|| { + env_logger::init(); + + TestNet::reset(); + + fn bifrost_reserve_account() -> AccountId { + use sp_runtime::traits::AccountIdConversion; + polkadot_parachain::primitives::Sibling::from(2001).into_account_truncating() + } + + Bifrost::execute_with(|| { + assert_ok!(Tokens::deposit( + CurrencyId::Token(TokenSymbol::KAR), + &AccountId::from(ALICE), + 100_000_000_000_000 + )); + }); + + Sibling::execute_with(|| { + assert_ok!(Tokens::deposit( + CurrencyId::Token(TokenSymbol::KAR), + &bifrost_reserve_account(), + 100_000_000_000_000 + )); + }); + + Bifrost::execute_with(|| { + assert_ok!(XTokens::transfer( + Origin::signed(ALICE.into()), + CurrencyId::Token(TokenSymbol::KAR), + 10_000_000_000_000, + Box::new( + MultiLocation::new( + 1, + X2( + Parachain(2000), + Junction::AccountId32 { network: NetworkId::Any, id: BOB.into() } + ) + ) + .into() + ), + 1_000_000_000, + )); + + assert_eq!( + Tokens::free_balance(CurrencyId::Token(TokenSymbol::KAR), &AccountId::from(ALICE)), + 90_000_000_000_000 + ); + }); + }) +} + +fn register_asset() { + Bifrost::execute_with(|| { + let currency_id = CurrencyId::Token(TokenSymbol::KSM); + assert_ok!(AssetRegistry::do_register_native_asset( + currency_id, + &MultiLocation::parent(), + &AssetMetadata { + name: currency_id.name().map(|s| s.as_bytes().to_vec()).unwrap_or_default(), + symbol: currency_id.symbol().map(|s| s.as_bytes().to_vec()).unwrap_or_default(), + decimals: currency_id.decimals().unwrap_or_default(), + minimal_balance: 10 * millicent::(currency_id), + } + )); + }); +} diff --git a/integration-tests/src/integration_tests.rs b/integration-tests/bifrost-kusama/src/kusama_integration_tests.rs similarity index 96% rename from integration-tests/src/integration_tests.rs rename to integration-tests/bifrost-kusama/src/kusama_integration_tests.rs index 65b57471f7..0a36fcf77e 100644 --- a/integration-tests/src/integration_tests.rs +++ b/integration-tests/bifrost-kusama/src/kusama_integration_tests.rs @@ -39,11 +39,9 @@ const SECONDS_PER_YEAR: u32 = 31557600; const SECONDS_PER_BLOCK: u32 = 12; pub const BLOCKS_PER_YEAR: u32 = SECONDS_PER_YEAR / SECONDS_PER_BLOCK; -#[cfg(feature = "with-bifrost-kusama-runtime")] pub use bifrost_imports::*; use bifrost_kusama_runtime::{ExistentialDeposit, NativeCurrencyId}; -#[cfg(feature = "with-bifrost-kusama-runtime")] mod bifrost_imports { pub use bifrost_kusama_runtime::{ create_x2_multilocation, AccountId, AssetRegistry, Balance, Balances, BifrostCrowdloanId, @@ -186,11 +184,11 @@ fn sanity_check_weight_per_time_constants_are_as_expected() { #[test] fn parachain_subaccounts_are_unique() { - ExtBuilder::default().build().execute_with(|| { + sp_io::TestExternalities::default().execute_with(|| { let parachain: AccountId = ParachainInfo::parachain_id().into_account_truncating(); assert_eq!( parachain, - hex_literal::hex!["70617261d1070000000000000000000000000000000000000000000000000000"] + hex_literal::hex!["7061726164000000000000000000000000000000000000000000000000000000"] .into() ); }); diff --git a/integration-tests/src/kusama_test_net.rs b/integration-tests/bifrost-kusama/src/kusama_test_net.rs similarity index 83% rename from integration-tests/src/kusama_test_net.rs rename to integration-tests/bifrost-kusama/src/kusama_test_net.rs index 7ab82b4c45..93cae0375c 100644 --- a/integration-tests/src/kusama_test_net.rs +++ b/integration-tests/bifrost-kusama/src/kusama_test_net.rs @@ -27,7 +27,7 @@ use polkadot_runtime_parachains::configuration::HostConfiguration; use sp_runtime::traits::AccountIdConversion; use xcm_emulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain}; -use crate::integration_tests::*; +use crate::kusama_integration_tests::*; decl_test_relay_chain! { pub struct KusamaNet { @@ -67,21 +67,21 @@ decl_test_parachain! { } } -decl_test_parachain! { - pub struct Statemine { - Runtime = statemine_runtime::Runtime, - Origin = statemine_runtime::Origin, - XcmpMessageHandler = statemine_runtime::XcmpQueue, - DmpMessageHandler = statemine_runtime::DmpQueue, - new_ext = para_ext(1000), - } -} +// decl_test_parachain! { +// pub struct Statemine { +// Runtime = statemine_runtime::Runtime, +// Origin = statemine_runtime::Origin, +// XcmpMessageHandler = statemine_runtime::XcmpQueue, +// DmpMessageHandler = statemine_runtime::DmpQueue, +// new_ext = para_ext(1000), +// } +// } decl_test_network! { pub struct TestNet { relay_chain = KusamaNet, parachains = vec![ - (1000, Statemine), + // (1000, Statemine), (2001, Bifrost), (2000, Sibling), ], @@ -133,8 +133,14 @@ pub fn kusama_ext() -> sp_io::TestExternalities { pallet_balances::GenesisConfig:: { balances: vec![ - (AccountId::from(ALICE), 2002 * dollar(CurrencyId::Token(KSM))), - (ParaId::from(2001u32).into_account_truncating(), 2 * dollar(CurrencyId::Token(KSM))), + ( + AccountId::from(ALICE), + 2002 * dollar::(CurrencyId::Token(KSM)), + ), + ( + ParaId::from(2001u32).into_account_truncating(), + 2 * dollar::(CurrencyId::Token(KSM)), + ), ], } .assimilate_storage(&mut t) @@ -162,7 +168,7 @@ pub fn para_ext(parachain_id: u32) -> sp_io::TestExternalities { .balances(vec![( AccountId::from(ALICE), RelayCurrencyId::get(), - 10 * dollar(RelayCurrencyId::get()), + 10 * dollar::(RelayCurrencyId::get()), )]) .parachain_id(parachain_id) .build() @@ -170,8 +176,16 @@ pub fn para_ext(parachain_id: u32) -> sp_io::TestExternalities { pub fn para_ext_salp(parachain_id: u32) -> sp_io::TestExternalities { ExtBuilder::default() .balances(vec![ - (AccountId::from(ALICE), RelayCurrencyId::get(), 10 * dollar(RelayCurrencyId::get())), - (AccountId::from(BOB), RelayCurrencyId::get(), 10 * dollar(RelayCurrencyId::get())), + ( + AccountId::from(ALICE), + RelayCurrencyId::get(), + 10 * dollar::(RelayCurrencyId::get()), + ), + ( + AccountId::from(BOB), + RelayCurrencyId::get(), + 10 * dollar::(RelayCurrencyId::get()), + ), ]) .parachain_id(parachain_id) .build() diff --git a/integration-tests/src/lib.rs b/integration-tests/bifrost-kusama/src/lib.rs similarity index 62% rename from integration-tests/src/lib.rs rename to integration-tests/bifrost-kusama/src/lib.rs index 90087a1d01..5c74c8da83 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/bifrost-kusama/src/lib.rs @@ -17,25 +17,15 @@ // along with this program. If not, see . #![cfg(test)] -#[cfg(feature = "with-bifrost-kusama-runtime")] + mod asset_registry; -#[cfg(feature = "with-bifrost-kusama-runtime")] +mod dollor_tests; mod flexible_fee; -#[cfg(feature = "with-bifrost-kusama-runtime")] -mod general_key; -#[cfg(feature = "with-bifrost-kusama-runtime")] -mod integration_tests; -#[cfg(feature = "with-bifrost-kusama-runtime")] mod kusama_cross_chain_transact; -#[cfg(feature = "with-bifrost-kusama-runtime")] mod kusama_cross_chain_transfer; -#[cfg(feature = "with-bifrost-kusama-runtime")] +mod kusama_integration_tests; mod kusama_test_net; -#[cfg(feature = "with-bifrost-kusama-runtime")] mod salp; -#[cfg(feature = "with-bifrost-kusama-runtime")] mod slp; -#[cfg(feature = "with-bifrost-kusama-runtime")] -mod statemine; -#[cfg(feature = "with-bifrost-kusama-runtime")] +// mod statemine; mod treasury; diff --git a/integration-tests/bifrost-kusama/src/salp.rs b/integration-tests/bifrost-kusama/src/salp.rs new file mode 100644 index 0000000000..4b179edbfb --- /dev/null +++ b/integration-tests/bifrost-kusama/src/salp.rs @@ -0,0 +1,479 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::{kusama_integration_tests::*, kusama_test_net::*}; +use bifrost_kusama_runtime::{LeasePeriod, MinContribution}; +use bifrost_salp::{Error, FundStatus}; +use frame_support::{assert_noop, assert_ok}; +use frame_system::RawOrigin; +use xcm_emulator::TestExt; + +#[test] +fn create_fund_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + SalpTest::execute_with(|| { + assert_ok!(Salp::create( + RawOrigin::Root.into(), + 3_000, + 100_000_000_000, + 1, + SlotLength::get() + )); + assert_ok!(Salp::funds(3_000).ok_or(())); + assert_eq!(Salp::current_trie_index(), 1); + }); + }) +} + +#[test] +fn edit_fund_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + SalpTest::execute_with(|| { + assert_ok!(Salp::create( + RawOrigin::Root.into(), + 3_000, + 100_000_000_000, + 1, + SlotLength::get() + )); + + assert_ok!(Salp::edit( + RawOrigin::Root.into(), + 3_000, + 100_000_000_000, + 150, + 2, + SlotLength::get() + 1, + Some(FundStatus::Ongoing) + )); + }); + }) +} + +#[test] +fn contribute_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + SalpTest::execute_with(|| { + assert_ok!(Salp::create( + RawOrigin::Root.into(), + 3_000, + 1000_000_000_000, + 1, + SlotLength::get() + )); + assert_ok!(Salp::contribute( + Origin::signed(AccountId::new(BOB)), + 3_000, + 100_000_000_000 + )); + assert!(Salp::funds(3_000).is_some()); + }); + }) +} + +#[test] +fn double_contribute_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + SalpTest::execute_with(|| { + assert_ok!(Salp::create( + RawOrigin::Root.into(), + 3_000, + 1000_000_000_000, + 1, + SlotLength::get() + )); + assert_ok!(Salp::contribute( + Origin::signed(AccountId::new(BOB)), + 3_000, + 100_000_000_000 + )); + assert!(Salp::funds(3_000).is_some()); + + assert_ok!(Salp::confirm_contribute( + Origin::signed(AccountId::new(ALICE)), + AccountId::new(BOB), + 3_000, + true, + CONTRIBUTON_INDEX + )); + + assert_noop!( + Salp::contribute(Origin::signed(AccountId::new(BOB)), 3_000, 1000_000_000_001), + Error::::CapExceeded + ); + + assert_noop!( + Salp::contribute( + Origin::signed(AccountId::new(BOB)), + 3_000, + MinContribution::get() - 1 + ), + Error::::ContributionTooSmall + ); + + assert_ok!(Salp::contribute( + Origin::signed(AccountId::new(BOB)), + 3_000, + 100_000_000_000 + )); + }); + }) +} + +#[test] +fn withdraw_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + SalpTest::execute_with(|| { + assert_ok!(Salp::create( + RawOrigin::Root.into(), + 3_000, + 1000_000_000_000, + 1, + SlotLength::get() + )); + assert_ok!(Salp::contribute( + Origin::signed(AccountId::new(BOB)), + 3_000, + 100_000_000_000 + )); + assert_ok!(Salp::confirm_contribute( + Origin::signed(AccountId::new(ALICE)), + AccountId::new(BOB), + 3_000, + true, + CONTRIBUTON_INDEX + )); + assert_ok!(Salp::fund_success(RawOrigin::Root.into(), 3_000)); + assert_ok!(Salp::fund_retire(RawOrigin::Root.into(), 3_000)); + assert_ok!(Salp::withdraw(RawOrigin::Root.into(), 3_000)); + }); + }) +} + +#[test] +fn refund_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + SalpTest::execute_with(|| { + assert_ok!(Salp::create( + RawOrigin::Root.into(), + 3_000, + 1000_000_000_000, + 1, + SlotLength::get() + )); + assert_ok!(Salp::contribute( + Origin::signed(AccountId::new(BOB)), + 3_000, + 100_000_000_000 + )); + assert_ok!(Salp::confirm_contribute( + Origin::signed(AccountId::new(ALICE)), + AccountId::new(BOB), + 3_000, + true, + CONTRIBUTON_INDEX + )); + assert_ok!(Salp::fund_fail(RawOrigin::Root.into(), 3_000)); + assert_ok!(Salp::withdraw(RawOrigin::Root.into(), 3_000)); + assert_ok!(Salp::refund( + Origin::signed(AccountId::new(BOB)), + 3_000, + 1, + SlotLength::get(), + 100_000_000_000 + )); + + assert_noop!( + Salp::refund(Origin::signed(AccountId::new(BOB)), 3_000, 1, SlotLength::get(), 100), + Error::::NotEnoughBalanceInFund + ); + }); + }) +} + +#[test] +fn dissolve_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + SalpTest::execute_with(|| { + assert_ok!(Salp::create( + RawOrigin::Root.into(), + 3_000, + 1000_000_000_000, + 1, + SlotLength::get() + )); + assert_ok!(Salp::contribute( + Origin::signed(AccountId::new(BOB)), + 3_000, + 100_000_000_000 + )); + assert_ok!(Salp::confirm_contribute( + Origin::signed(AccountId::new(ALICE)), + AccountId::new(BOB), + 3_000, + true, + CONTRIBUTON_INDEX + )); + assert_ok!(Salp::fund_success(RawOrigin::Root.into(), 3_000)); + assert_ok!(Salp::fund_retire(RawOrigin::Root.into(), 3_000)); + assert_ok!(Salp::withdraw(RawOrigin::Root.into(), 3_000)); + assert_ok!(Salp::fund_end(RawOrigin::Root.into(), 3_000)); + + assert_ok!(Salp::dissolve(RawOrigin::Root.into(), 3_000)); + + assert!(Salp::funds(3_000).is_none()); + }); + }) +} + +#[test] +fn redeem_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + SalpTest::execute_with(|| { + assert_ok!(Salp::create( + RawOrigin::Root.into(), + 3_000, + 1000_000_000_000, + 1, + SlotLength::get() + )); + assert_ok!(Salp::contribute( + Origin::signed(AccountId::new(BOB)), + 3_000, + 100_000_000_000 + )); + assert_ok!(Salp::confirm_contribute( + Origin::signed(AccountId::new(ALICE)), + AccountId::new(BOB), + 3_000, + true, + CONTRIBUTON_INDEX + )); + + assert_ok!(Salp::fund_success(RawOrigin::Root.into(), 3_000)); + assert_ok!(Salp::unlock( + Origin::signed(AccountId::new(ALICE)), + AccountId::new(BOB), + 3_000 + )); + + // Mock the BlockNumber + let block_begin_redeem = (SlotLength::get() + 1) * LeasePeriod::get(); + System::set_block_number(block_begin_redeem); + + assert_ok!(Salp::fund_retire(RawOrigin::Root.into(), 3_000)); + assert_ok!(Salp::withdraw(RawOrigin::Root.into(), 3_000)); + let vs_token = + ::CurrencyIdConversion::convert_to_vstoken( + RelayCurrencyId::get(), + ) + .unwrap(); + let vs_bond = + ::CurrencyIdConversion::convert_to_vsbond( + RelayCurrencyId::get(), + 3_000, + 1, + SlotLength::get(), + ) + .unwrap(); + + assert_ok!(>::transfer( + vs_token, + &AccountId::new(BOB), + &AccountId::new(CATHI), + 500_000_000 + )); + assert_ok!(>::transfer( + vs_bond, + &AccountId::new(BOB), + &AccountId::new(CATHI), + 500_000_000 + )); + + assert_ok!(Salp::redeem(Origin::signed(AccountId::new(BOB)), 3_000, 500_000_000)); + assert_ok!(Salp::redeem(Origin::signed(AccountId::new(CATHI)), 3_000, 500_000_000)); + }); + }) +} + +#[test] +fn redeem_with_speical_vsbond_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + SalpTest::execute_with(|| { + assert_ok!(Salp::create(RawOrigin::Root.into(), 2001, 1000_000_000_000, 13, 20)); + assert_ok!(Salp::contribute( + Origin::signed(AccountId::new(BOB)), + 2001, + 100_000_000_000 + )); + assert_ok!(Salp::confirm_contribute( + Origin::signed(AccountId::new(ALICE)), + AccountId::new(BOB), + 2001, + true, + CONTRIBUTON_INDEX + )); + + assert_ok!(Salp::fund_success(RawOrigin::Root.into(), 2001)); + assert_ok!(Salp::unlock( + Origin::signed(AccountId::new(ALICE)), + AccountId::new(BOB), + 2001 + )); + + // Mock the BlockNumber + let block_begin_redeem = (SlotLength::get() + 1) * LeasePeriod::get(); + System::set_block_number(block_begin_redeem); + + assert_ok!(Salp::fund_retire(RawOrigin::Root.into(), 2001)); + assert_ok!(Salp::withdraw(RawOrigin::Root.into(), 2001)); + + let vs_token = + ::CurrencyIdConversion::convert_to_vstoken( + RelayCurrencyId::get(), + ) + .unwrap(); + let vs_bond = + ::CurrencyIdConversion::convert_to_vsbond( + RelayCurrencyId::get(), + 2001, + 13, + 20, + ) + .unwrap(); + + assert_ok!(>::transfer( + vs_token, + &AccountId::new(BOB), + &AccountId::new(CATHI), + 500_000_000 + )); + assert_ok!(>::transfer( + vs_bond, + &AccountId::new(BOB), + &AccountId::new(CATHI), + 500_000_000 + )); + assert_ok!(Salp::redeem(Origin::signed(AccountId::new(BOB)), 2001, 500_000_000)); + assert_ok!(Salp::redeem(Origin::signed(AccountId::new(CATHI)), 2001, 500_000_000)); + }); + }) +} + +#[test] +fn batch_unlock_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + SalpTest::execute_with(|| { + assert_ok!(Salp::create( + RawOrigin::Root.into(), + 3_000, + 1000_000_000_000, + 1, + SlotLength::get() + )); + assert_ok!(Salp::contribute( + Origin::signed(AccountId::new(BOB)), + 3_000, + 100_000_000_000 + )); + assert_ok!(Salp::confirm_contribute( + Origin::signed(AccountId::new(ALICE)), + AccountId::new(BOB), + 3_000, + true, + CONTRIBUTON_INDEX + )); + + assert_ok!(Salp::fund_success(RawOrigin::Root.into(), 3_000)); + assert_ok!(Salp::batch_unlock(Origin::signed(AccountId::new(ALICE)), 3_000)); + }) + }) +} + +#[test] +fn unlock_when_fund_ongoing_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + SalpTest::execute_with(|| { + assert_ok!(Salp::create( + RawOrigin::Root.into(), + 3_000, + 1000_000_000_000, + 1, + SlotLength::get() + )); + assert_ok!(Salp::contribute( + Origin::signed(AccountId::new(BOB)), + 3_000, + 100_000_000_000 + )); + assert_ok!(Salp::confirm_contribute( + Origin::signed(AccountId::new(ALICE)), + AccountId::new(BOB), + 3_000, + true, + CONTRIBUTON_INDEX + )); + assert_ok!(Salp::unlock( + Origin::signed(AccountId::new(BOB)), + AccountId::new(BOB), + 3_000 + )); + }); + }) +} + +#[test] +fn set_confirm_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + SalpTest::execute_with(|| { + assert_ok!(Salp::create( + RawOrigin::Root.into(), + 3_000, + 1000_000_000_000, + 1, + SlotLength::get() + )); + assert_ok!(Salp::contribute( + Origin::signed(AccountId::new(BOB)), + 3_000, + 100_000_000_000 + )); + assert_noop!( + Salp::confirm_contribute( + Origin::signed(AccountId::new(BOB)), + AccountId::new(BOB), + 3_000, + true, + CONTRIBUTON_INDEX + ), + DispatchError::BadOrigin, + ); + assert_ok!(Salp::set_multisig_confirm_account( + RawOrigin::Root.into(), + AccountId::new(BOB) + )); + assert_ok!(Salp::confirm_contribute( + Origin::signed(AccountId::new(BOB)), + AccountId::new(BOB), + 3_000, + true, + CONTRIBUTON_INDEX + )); + }); + }) +} diff --git a/integration-tests/bifrost-kusama/src/slp.rs b/integration-tests/bifrost-kusama/src/slp.rs new file mode 100644 index 0000000000..261a090f78 --- /dev/null +++ b/integration-tests/bifrost-kusama/src/slp.rs @@ -0,0 +1,2352 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Cross-chain transfer tests within Kusama network. +#![cfg(test)] + +use bifrost_polkadot_runtime::PolkadotXcm; +use bifrost_slp::{ + primitives::{ + SubstrateLedgerUpdateEntry, SubstrateLedgerUpdateOperation, + SubstrateValidatorsByDelegatorUpdateEntry, UnlockChunk, + }, + Delays, Ledger, LedgerUpdateEntry, MinimumsMaximums, SubstrateLedger, + ValidatorsByDelegatorUpdateEntry, XcmOperation, +}; +use cumulus_primitives_core::relay_chain::HashT; +use frame_support::{assert_ok, BoundedVec}; +use node_primitives::TimeUnit; +use orml_traits::MultiCurrency; +use pallet_staking::{Nominations, StakingLedger}; +use pallet_xcm::QueryStatus; +use xcm::{latest::prelude::*, VersionedMultiAssets, VersionedMultiLocation}; +use xcm_emulator::TestExt; + +use crate::{kusama_integration_tests::*, kusama_test_net::*}; + +/// **************************************************** +/// ********* Preparation section ******************** +/// **************************************************** + +// parachain 2001 subaccount index 0 +pub fn subaccount_0() -> AccountId { + // 5E78xTBiaN3nAGYtcNnqTJQJqYAkSDGggKqaDfpNsKyPpbcb + let subaccount_0: AccountId = + hex_literal::hex!["5a53736d8e96f1c007cf0d630acf5209b20611617af23ce924c8e25328eb5d28"] + .into(); + + subaccount_0 +} + +pub fn para_account_2001() -> AccountId { + // 5Ec4AhPV91i9yNuiWuNunPf6AQCYDhFTTA4G5QCbtqYApH9E + let para_account_2001: AccountId = + hex_literal::hex!["70617261d1070000000000000000000000000000000000000000000000000000"] + .into(); + + para_account_2001 +} + +// Preparation: register sub-account index 0. +fn register_subaccount_index_0() { + let subaccount_0 = subaccount_0(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = Slp::account_id_to_account_32(subaccount_0).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Set OngoingTimeUnitUpdateInterval as 1/3 Era(1800 blocks per Era, 12 seconds per + // block) + assert_ok!(Slp::set_ongoing_time_unit_update_interval( + Origin::root(), + RelayCurrencyId::get(), + Some(600) + )); + + System::set_block_number(600); + + // Initialize ongoing timeunit as 0. + assert_ok!(Slp::update_ongoing_time_unit( + Origin::root(), + RelayCurrencyId::get(), + TimeUnit::Era(0) + )); + + // Initialize currency delays. + let delay = + Delays { unlock_delay: TimeUnit::Era(10), leave_delegators_delay: Default::default() }; + assert_ok!(Slp::set_currency_delays(Origin::root(), RelayCurrencyId::get(), Some(delay))); + + let mins_and_maxs = MinimumsMaximums { + delegator_bonded_minimum: 100_000_000_000, + bond_extra_minimum: 0, + unbond_minimum: 0, + rebond_minimum: 0, + unbond_record_maximum: 32, + validators_back_maximum: 36, + delegator_active_staking_maximum: 200_000_000_000_000, + validators_reward_maximum: 0, + delegation_amount_minimum: 0, + delegators_maximum: 100, + validators_maximum: 300, + }; + + // Set minimums and maximums + assert_ok!(Slp::set_minimums_and_maximums( + Origin::root(), + RelayCurrencyId::get(), + Some(mins_and_maxs) + )); + + // First to setup index-multilocation relationship of subaccount_0 + assert_ok!(Slp::add_delegator( + Origin::root(), + RelayCurrencyId::get(), + 0u16, + Box::new(subaccount_0_location.clone()), + )); + + // Register Operation weight and fee + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + Origin::root(), + RelayCurrencyId::get(), + XcmOperation::TransferTo, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + Origin::root(), + RelayCurrencyId::get(), + XcmOperation::Bond, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + Origin::root(), + RelayCurrencyId::get(), + XcmOperation::BondExtra, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + Origin::root(), + RelayCurrencyId::get(), + XcmOperation::Unbond, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + Origin::root(), + RelayCurrencyId::get(), + XcmOperation::Rebond, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + Origin::root(), + RelayCurrencyId::get(), + XcmOperation::Delegate, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + Origin::root(), + RelayCurrencyId::get(), + XcmOperation::Payout, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + Origin::root(), + RelayCurrencyId::get(), + XcmOperation::Liquidize, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + Origin::root(), + RelayCurrencyId::get(), + XcmOperation::Chill, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + Origin::root(), + RelayCurrencyId::get(), + XcmOperation::TransferBack, + Some((20_000_000_000, 10_000_000_000)), + )); + }); +} + +fn register_delegator_ledger() { + let subaccount_0 = subaccount_0(); + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = Slp::account_id_to_account_32(subaccount_0).unwrap(); + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + let sb_ledger = SubstrateLedger { + account: subaccount_0_location.clone(), + total: dollar::(RelayCurrencyId::get()), + active: dollar::(RelayCurrencyId::get()), + unlocking: vec![], + }; + let ledger = Ledger::Substrate(sb_ledger); + + // Set delegator ledger + assert_ok!(Slp::set_delegator_ledger( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + Box::new(Some(ledger)) + )); + }); +} + +#[test] +fn register_validators() { + sp_io::TestExternalities::default().execute_with(|| { + // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz + let validator_0: AccountId = + hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] + .into(); + + // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 + let validator_1: AccountId = + hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] + .into(); + + Bifrost::execute_with(|| { + let mut valis = vec![]; + + let validator_0_32: [u8; 32] = Slp::account_id_to_account_32(validator_0).unwrap(); + let validator_0_location: MultiLocation = + Slp::account_32_to_parent_location(validator_0_32).unwrap(); + let multi_hash_0 = + ::Hashing::hash(&validator_0_location.encode()); + + let mins_and_maxs = MinimumsMaximums { + delegator_bonded_minimum: 100_000_000_000, + bond_extra_minimum: 0, + unbond_minimum: 0, + rebond_minimum: 0, + unbond_record_maximum: 32, + validators_back_maximum: 36, + delegator_active_staking_maximum: 200_000_000_000_000, + validators_reward_maximum: 0, + delegation_amount_minimum: 0, + delegators_maximum: 100, + validators_maximum: 300, + }; + + // Set minimums and maximums + assert_ok!(Slp::set_minimums_and_maximums( + Origin::root(), + RelayCurrencyId::get(), + Some(mins_and_maxs) + )); + + // Set delegator ledger + assert_ok!(Slp::add_validator( + Origin::root(), + RelayCurrencyId::get(), + Box::new(validator_0_location.clone()), + )); + + let validator_1_32: [u8; 32] = Slp::account_id_to_account_32(validator_1).unwrap(); + let validator_1_location: MultiLocation = + Slp::account_32_to_parent_location(validator_1_32).unwrap(); + let multi_hash_1 = + ::Hashing::hash(&validator_1_location.encode()); + + // The storage is reordered by hash. So we need to adjust the push order here. + valis.push((validator_1_location.clone(), multi_hash_1)); + valis.push((validator_0_location.clone(), multi_hash_0)); + + // Set delegator ledger + assert_ok!(Slp::add_validator( + Origin::root(), + RelayCurrencyId::get(), + Box::new(validator_1_location), + )); + + assert_eq!(Slp::get_validators(RelayCurrencyId::get()), Some(valis)); + }); + }) +} + +// Preparation: transfer 1 KSM from Alice in Kusama to Bob in Bifrost. +// Bob has a balance of +#[test] +fn transfer_2_ksm_to_entrance_account_in_bifrost() { + sp_io::TestExternalities::default().execute_with(|| { + let para_account_2001 = para_account_2001(); + + let entrance_account_32: [u8; 32] = + hex_literal::hex!["6d6f646c62662f76746b696e0000000000000000000000000000000000000000"] + .into(); + + // Cross-chain transfer some KSM to Bob account in Bifrost + KusamaNet::execute_with(|| { + assert_ok!(kusama_runtime::XcmPallet::reserve_transfer_assets( + kusama_runtime::Origin::signed(ALICE.into()), + Box::new(VersionedMultiLocation::V1(X1(Parachain(2001)).into())), + Box::new(VersionedMultiLocation::V1( + X1(Junction::AccountId32 { id: entrance_account_32, network: NetworkId::Any }) + .into() + )), + Box::new(VersionedMultiAssets::V1( + (Here, 2 * dollar::(RelayCurrencyId::get())).into() + )), + 0, + )); + + // predefined 2 dollars + 2 dollar:: from cross-chain transfer = 3 dollars + assert_eq!( + kusama_runtime::Balances::free_balance(¶_account_2001.clone()), + 4 * dollar::(RelayCurrencyId::get()) + ); + }); + + Bifrost::execute_with(|| { + // entrance_account get the cross-transferred 2 dollar:: KSM minus transaction + // fee. + assert_eq!( + Tokens::free_balance(RelayCurrencyId::get(), &entrance_account_32.into()), + 1999907304000 + ); + }); + }) +} + +// Preparation: transfer 1 KSM from Alice in Kusama to Bob in Bifrost. +// Bob has a balance of +#[test] +fn transfer_2_ksm_to_subaccount_in_kusama() { + sp_io::TestExternalities::default().execute_with(|| { + let subaccount_0 = subaccount_0(); + + KusamaNet::execute_with(|| { + assert_ok!(kusama_runtime::Balances::transfer( + kusama_runtime::Origin::signed(ALICE.into()), + MultiAddress::Id(subaccount_0.clone()), + 2 * dollar::(RelayCurrencyId::get()) + )); + + assert_eq!( + kusama_runtime::Balances::free_balance(&subaccount_0.clone()), + 2 * dollar::(RelayCurrencyId::get()) + ); + }); + }) +} + +#[test] +fn locally_bond_subaccount_0_1ksm_in_kusama() { + sp_io::TestExternalities::default().execute_with(|| { + transfer_2_ksm_to_subaccount_in_kusama(); + let subaccount_0 = subaccount_0(); + + KusamaNet::execute_with(|| { + assert_ok!(kusama_runtime::Staking::bond( + kusama_runtime::Origin::signed(subaccount_0.clone()), + MultiAddress::Id(subaccount_0.clone()), + dollar::(RelayCurrencyId::get()), + pallet_staking::RewardDestination::::Staked, + )); + + assert_eq!( + kusama_runtime::Staking::ledger(&subaccount_0), + Some(StakingLedger { + stash: subaccount_0.clone(), + total: dollar::(RelayCurrencyId::get()), + active: dollar::(RelayCurrencyId::get()), + unlocking: BoundedVec::try_from(vec![]).unwrap(), + claimed_rewards: vec![], + }) + ); + }); + }) +} + +/// **************************************************** +/// ********* Test section ******************** +/// **************************************************** + +#[test] +fn transfer_to_works() { + sp_io::TestExternalities::default().execute_with(|| { + register_subaccount_index_0(); + transfer_2_ksm_to_entrance_account_in_bifrost(); + transfer_2_ksm_to_subaccount_in_kusama(); + let subaccount_0 = subaccount_0(); + let para_account_2001 = para_account_2001(); + + let entrance_account: AccountId = + hex_literal::hex!["6d6f646c62662f76746b696e0000000000000000000000000000000000000000"] + .into(); + + let entrance_account_32 = Slp::account_id_to_account_32(entrance_account.clone()).unwrap(); + let entrance_account_location: MultiLocation = + Slp::account_32_to_local_location(entrance_account_32).unwrap(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // We use transfer_to to transfer some KSM to subaccount_0 + assert_ok!(Slp::transfer_to( + Origin::root(), + RelayCurrencyId::get(), + Box::new(entrance_account_location), + Box::new(subaccount_0_location), + dollar::(RelayCurrencyId::get()), + )); + }); + + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Balances::free_balance(¶_account_2001.clone()), + 3 * dollar::(RelayCurrencyId::get()) + ); + + // Why not the transferred amount reach the sub-account? + assert_eq!( + kusama_runtime::Balances::free_balance(&subaccount_0.clone()), + 2999988476752 + ); + }); + }) +} + +#[test] +fn bond_works() { + sp_io::TestExternalities::default().execute_with(|| { + register_subaccount_index_0(); + transfer_2_ksm_to_subaccount_in_kusama(); + let subaccount_0 = subaccount_0(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Bond 1 ksm for sub-account index 0 + assert_ok!(Slp::bond( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location), + dollar::(RelayCurrencyId::get()), + None + )); + }); + + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Staking::ledger(&subaccount_0), + Some(StakingLedger { + stash: subaccount_0.clone(), + total: dollar::(RelayCurrencyId::get()), + active: dollar::(RelayCurrencyId::get()), + unlocking: BoundedVec::try_from(vec![]).unwrap(), + claimed_rewards: vec![], + }) + ); + + assert!(kusama_runtime::System::events().iter().any(|r| matches!( + r.event, + kusama_runtime::Event::System(frame_system::Event::Remarked { sender: _, hash: _ }) + ))); + }); + }) +} + +#[test] +fn bond_extra_works() { + sp_io::TestExternalities::default().execute_with(|| { + // bond 1 ksm for sub-account index 0 + locally_bond_subaccount_0_1ksm_in_kusama(); + register_subaccount_index_0(); + register_delegator_ledger(); + let subaccount_0 = subaccount_0(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Bond_extra 1 ksm for sub-account index 0 + assert_ok!(Slp::bond_extra( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location), + None, + dollar::(RelayCurrencyId::get()), + )); + }); + + // So the bonded amount should be 2 ksm + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Staking::ledger(&subaccount_0), + Some(StakingLedger { + stash: subaccount_0.clone(), + total: 2 * dollar::(RelayCurrencyId::get()), + active: 2 * dollar::(RelayCurrencyId::get()), + unlocking: BoundedVec::try_from(vec![]).unwrap(), + claimed_rewards: vec![], + }) + ); + }); + }) +} + +#[test] +fn unbond_works() { + sp_io::TestExternalities::default().execute_with(|| { + // bond 1 ksm for sub-account index 0 + locally_bond_subaccount_0_1ksm_in_kusama(); + register_subaccount_index_0(); + register_delegator_ledger(); + let subaccount_0 = subaccount_0(); + + KusamaNet::execute_with(|| { + kusama_runtime::Staking::trigger_new_era(0, vec![]); + }); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Unbond 0.5 ksm, 0.5 ksm left. + assert_ok!(Slp::unbond( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location), + None, + 500_000_000_000, + )); + }); + }) + + // Can be uncommented to check if the result is correct. + // Due to the reason of private fields for struct UnlockChunk, + // it is not able to construct an instance of UnlockChunk directly. + // // So the bonded amount should be 2 ksm + // KusamaNet::execute_with(|| { + // assert_eq!( + // kusama_runtime::Staking::ledger(&subaccount_0), + // Some(StakingLedger { + // stash: subaccount_0.clone(), + // total: dollar::(RelayCurrencyId::get()), + // active: 500_000_000_000, + // unlocking: vec![UnlockChunk { value: 500000000000, era: 28 }], + // claimed_rewards: vec![], + // }) + // ); + // }); +} + +#[test] +fn unbond_all_works() { + sp_io::TestExternalities::default().execute_with(|| { + // bond 1 ksm for sub-account index 0 + locally_bond_subaccount_0_1ksm_in_kusama(); + register_subaccount_index_0(); + register_delegator_ledger(); + let subaccount_0 = subaccount_0(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Unbond the only bonded 1 ksm. + assert_ok!(Slp::unbond_all( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location), + )); + }); + }) + + // Can be uncommented to check if the result is correct. + // Due to the reason of private fields for struct UnlockChunk, + // it is not able to construct an instance of UnlockChunk directly. + // KusamaNet::execute_with(|| { + // assert_eq!( + // kusama_runtime::Staking::ledger(&subaccount_0), + // Some(StakingLedger { + // stash: subaccount_0.clone(), + // total: dollar::(RelayCurrencyId::get()), + // active: 0, + // unlocking: vec![UnlockChunk { value: 1000000000000, era: 28 }], + // claimed_rewards: vec![], + // }) + // ); + // }); +} + +#[test] +fn rebond_works() { + sp_io::TestExternalities::default().execute_with(|| { + // bond 1 ksm for sub-account index 0 + locally_bond_subaccount_0_1ksm_in_kusama(); + register_subaccount_index_0(); + register_delegator_ledger(); + let subaccount_0 = subaccount_0(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Unbond 0.5 ksm, 0.5 ksm left. + assert_ok!(Slp::unbond( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + None, + 500_000_000_000, + )); + + // Update Bifrost local ledger. This should be done by backend services. + let chunk = UnlockChunk { value: 500_000_000_000, unlock_time: TimeUnit::Era(8) }; + let sb_ledger = SubstrateLedger { + account: subaccount_0_location.clone(), + total: dollar::(RelayCurrencyId::get()), + active: 500_000_000_000, + unlocking: vec![chunk], + }; + let ledger = Ledger::Substrate(sb_ledger); + + assert_ok!(Slp::set_delegator_ledger( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + Box::new(Some(ledger)) + )); + + // rebond 0.5 ksm. + assert_ok!(Slp::rebond( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location), + None, + Some(500_000_000_000), + )); + }); + + // So the bonded amount should be 1 ksm + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Staking::ledger(&subaccount_0), + Some(StakingLedger { + stash: subaccount_0.clone(), + total: dollar::(RelayCurrencyId::get()), + active: dollar::(RelayCurrencyId::get()), + unlocking: BoundedVec::try_from(vec![]).unwrap(), + claimed_rewards: vec![], + }) + ); + }); + }) +} + +#[test] +fn delegate_works() { + sp_io::TestExternalities::default().execute_with(|| { + // bond 1 ksm for sub-account index 0 + locally_bond_subaccount_0_1ksm_in_kusama(); + register_subaccount_index_0(); + register_validators(); + register_delegator_ledger(); + let subaccount_0 = subaccount_0(); + + // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz + let validator_0: AccountId = + hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] + .into(); + + // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 + let validator_1: AccountId = + hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] + .into(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + let mut targets = vec![]; + + let validator_0_32: [u8; 32] = + Slp::account_id_to_account_32(validator_0.clone()).unwrap(); + let validator_0_location: MultiLocation = + Slp::account_32_to_parent_location(validator_0_32).unwrap(); + targets.push(validator_0_location.clone()); + + let validator_1_32: [u8; 32] = + Slp::account_id_to_account_32(validator_1.clone()).unwrap(); + let validator_1_location: MultiLocation = + Slp::account_32_to_parent_location(validator_1_32).unwrap(); + targets.push(validator_1_location.clone()); + + // delegate + assert_ok!(Slp::delegate( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + targets.clone(), + )); + + assert_ok!(Slp::set_validators_by_delegator( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + targets, + )); + }); + + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Staking::nominators(&subaccount_0), + Some(Nominations { + targets: BoundedVec::try_from(vec![validator_1, validator_0]).unwrap(), + submitted_in: 0, + suppressed: false + },) + ); + }); + }) +} + +#[test] +fn undelegate_works() { + sp_io::TestExternalities::default().execute_with(|| { + delegate_works(); + + let subaccount_0 = subaccount_0(); + + // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz + let validator_0: AccountId = + hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] + .into(); + + // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 + let validator_1: AccountId = + hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] + .into(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + let mut targets = vec![]; + + let validator_0_32: [u8; 32] = + Slp::account_id_to_account_32(validator_0.clone()).unwrap(); + let validator_0_location: MultiLocation = + Slp::account_32_to_parent_location(validator_0_32).unwrap(); + targets.push(validator_0_location.clone()); + + // Undelegate validator 0. Only validator 1 left. + assert_ok!(Slp::undelegate( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location), + targets.clone(), + )); + }); + + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Staking::nominators(&subaccount_0), + Some(Nominations { + targets: BoundedVec::try_from(vec![validator_1]).unwrap(), + submitted_in: 0, + suppressed: false + },) + ); + }); + }) +} + +#[test] +fn redelegate_works() { + sp_io::TestExternalities::default().execute_with(|| { + undelegate_works(); + + let subaccount_0 = subaccount_0(); + + // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz + let validator_0: AccountId = + hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] + .into(); + + // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 + let validator_1: AccountId = + hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] + .into(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + let mut targets = vec![]; + + let validator_0_32: [u8; 32] = + Slp::account_id_to_account_32(validator_0.clone()).unwrap(); + let validator_0_location: MultiLocation = + Slp::account_32_to_parent_location(validator_0_32).unwrap(); + + let validator_1_32: [u8; 32] = + Slp::account_id_to_account_32(validator_1.clone()).unwrap(); + let validator_1_location: MultiLocation = + Slp::account_32_to_parent_location(validator_1_32).unwrap(); + + targets.push(validator_1_location.clone()); + targets.push(validator_0_location.clone()); + + // Redelegate to a set of validator_0 and validator_1. + assert_ok!(Slp::redelegate( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location), + Some(targets.clone()), + )); + }); + + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Staking::nominators(&subaccount_0), + Some(Nominations { + targets: BoundedVec::try_from(vec![validator_1, validator_0]).unwrap(), + submitted_in: 0, + suppressed: false + },) + ); + }); + }) +} + +#[test] +fn payout_works() { + sp_io::TestExternalities::default().execute_with(|| { + register_subaccount_index_0(); + transfer_2_ksm_to_subaccount_in_kusama(); + let subaccount_0 = subaccount_0(); + + // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz + let validator_0: AccountId = + hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] + .into(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + let validator_0_32: [u8; 32] = + Slp::account_id_to_account_32(validator_0.clone()).unwrap(); + let validator_0_location: MultiLocation = + Slp::account_32_to_parent_location(validator_0_32).unwrap(); + + // Bond 1 ksm for sub-account index 0 + assert_ok!(Slp::payout( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location), + Box::new(validator_0_location), + Some(TimeUnit::Era(27)) + )); + }); + }) +} + +#[test] +fn liquidize_works() { + sp_io::TestExternalities::default().execute_with(|| { + unbond_works(); + let subaccount_0 = subaccount_0(); + + KusamaNet::execute_with(|| { + // Kusama's unbonding period is 27 days = 100_800 blocks + kusama_runtime::System::set_block_number(101_000); + for _i in 0..29 { + kusama_runtime::Staking::trigger_new_era(0, vec![]); + } + + assert_eq!( + kusama_runtime::Balances::free_balance(&subaccount_0.clone()), + 2 * dollar::(RelayCurrencyId::get()) + ); + + // 1ksm is locked for half bonded and half unbonding. + assert_eq!( + kusama_runtime::Balances::usable_balance(&subaccount_0.clone()), + dollar::(RelayCurrencyId::get()) + ); + }); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + assert_ok!(Slp::liquidize( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location), + Some(TimeUnit::SlashingSpan(5)), + None + )); + }); + + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Balances::free_balance(&subaccount_0.clone()), + 2 * dollar::(RelayCurrencyId::get()) + ); + + // half of 1ksm unlocking has been freed. So the usable balance should be 1.5 ksm + assert_eq!( + kusama_runtime::Balances::usable_balance(&subaccount_0.clone()), + 1_500_000_000_000 + ); + }); + }) +} + +#[test] +fn chill_works() { + sp_io::TestExternalities::default().execute_with(|| { + delegate_works(); + let subaccount_0 = subaccount_0(); + + // check if sub-account index 0 belongs to the group of nominators + KusamaNet::execute_with(|| { + assert_eq!(kusama_runtime::Staking::nominators(&subaccount_0.clone()).is_some(), true); + }); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + assert_ok!(Slp::chill( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location), + )); + }); + + // check if sub-account index 0 belongs to the group of nominators + KusamaNet::execute_with(|| { + assert_eq!(kusama_runtime::Staking::nominators(&subaccount_0.clone()).is_some(), false); + }); + }) +} + +#[test] +fn transfer_back_works() { + sp_io::TestExternalities::default().execute_with(|| { + bond_works(); + let subaccount_0 = subaccount_0(); + let para_account_2001 = para_account_2001(); + + let exit_account: AccountId = + hex_literal::hex!["6d6f646c62662f76746f75740000000000000000000000000000000000000000"] + .into(); + + let exit_account_32 = Slp::account_id_to_account_32(exit_account.clone()).unwrap(); + let exit_account_location: MultiLocation = + Slp::account_32_to_local_location(exit_account_32).unwrap(); + + KusamaNet::execute_with(|| { + // 1ksm is locked for half bonded and half unbonding. + assert_eq!( + kusama_runtime::Balances::usable_balance(&subaccount_0.clone()), + dollar::(RelayCurrencyId::get()) + ); + + assert_eq!( + kusama_runtime::Balances::free_balance(¶_account_2001.clone()), + 1999215574218 + ); + }); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + assert_eq!(Tokens::free_balance(RelayCurrencyId::get(), &exit_account), 0); + + assert_ok!(Slp::transfer_back( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location), + Box::new(exit_account_location), + 500_000_000_000 + )); + }); + + // Parachain account has been deposited the transferred amount. + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Balances::usable_balance(&subaccount_0.clone()), + 500_000_000_000 + ); + assert_eq!( + kusama_runtime::Balances::free_balance(¶_account_2001.clone()), + 2498431148436 + ); + }); + + Bifrost::execute_with(|| { + assert_eq!(Tokens::free_balance(RelayCurrencyId::get(), &exit_account), 499907304000); + }); + }) +} + +#[test] +fn supplement_fee_reserve_works() { + sp_io::TestExternalities::default().execute_with(|| { + let subaccount_0 = subaccount_0(); + delegate_works(); + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Balances::free_balance(&subaccount_0.clone()), + 2 * dollar::(RelayCurrencyId::get()) + ); + }); + + Bifrost::execute_with(|| { + // set fee source + let alice_location = Slp::account_32_to_local_location(ALICE).unwrap(); + assert_ok!(Slp::set_fee_source( + Origin::root(), + RelayCurrencyId::get(), + Some((alice_location.clone(), dollar::(RelayCurrencyId::get()))) + )); + + // We use supplement_fee_reserve to transfer some KSM to subaccount_0 + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + assert_ok!(Slp::supplement_fee_reserve( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location), + )); + }); + + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Balances::free_balance(&subaccount_0.clone()), + 2999988476752 + ); + }); + }) +} + +#[test] +fn confirm_delegator_ledger_query_response_with_bond_works() { + sp_io::TestExternalities::default().execute_with(|| { + register_subaccount_index_0(); + transfer_2_ksm_to_subaccount_in_kusama(); + let subaccount_0 = subaccount_0(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // First call bond function, it will insert a query. + // Bond 1 ksm for sub-account index 0 + assert_ok!(Slp::bond( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + dollar::(RelayCurrencyId::get()), + None + )); + + // Check the existence of the query in pallet_xcm Queries storage. + assert_eq!( + PolkadotXcm::query(0), + Some(QueryStatus::Pending { + responder: VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: Here + }), + maybe_notify: None, + timeout: 1600 + }) + ); + + // Check the existence of query in the response update queue storage. + assert_eq!( + Slp::get_delegator_ledger_update_entry(0), + Some(( + LedgerUpdateEntry::Substrate(SubstrateLedgerUpdateEntry { + currency_id: RelayCurrencyId::get(), + delegator_id: subaccount_0_location.clone(), + update_operation: SubstrateLedgerUpdateOperation::Bond, + amount: dollar::(RelayCurrencyId::get()), + unlock_time: None + }), + 1600 + )) + ); + }); + + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Staking::ledger(&subaccount_0), + Some(StakingLedger { + stash: subaccount_0.clone(), + total: dollar::(RelayCurrencyId::get()), + active: dollar::(RelayCurrencyId::get()), + unlocking: BoundedVec::try_from(vec![]).unwrap(), + claimed_rewards: vec![], + }) + ); + }); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Call confirm_delegator_ledger_query_response. + assert_ok!(Slp::confirm_delegator_ledger_query_response( + Origin::root(), + RelayCurrencyId::get(), + 0 + )); + + // Check the ledger update. + assert_eq!( + Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), + Some(Ledger::Substrate(SubstrateLedger { + account: subaccount_0_location.clone(), + total: dollar::(RelayCurrencyId::get()), + active: dollar::(RelayCurrencyId::get()), + unlocking: vec![] + })) + ); + + // Check the existence of the query in pallet_xcm Queries storage. + // If xcm version 3 is introduced. We'll add instruction ReportTransactStatus into the + // xcm message. And this query will be set to ready status after we received a query + // response. At that point, this check should be set to equal None. + assert_eq!( + PolkadotXcm::query(0), + Some(QueryStatus::Pending { + responder: VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: Here + }), + maybe_notify: None, + timeout: 1600 + }) + ); + + // Check the inexistence of query in the response update queue storage. + assert_eq!(Slp::get_delegator_ledger_update_entry(0), None); + }); + }) +} + +#[test] +fn confirm_delegator_ledger_query_response_with_bond_extra_works() { + sp_io::TestExternalities::default().execute_with(|| { + // bond 1 ksm for sub-account index 0 + locally_bond_subaccount_0_1ksm_in_kusama(); + register_subaccount_index_0(); + register_delegator_ledger(); + let subaccount_0 = subaccount_0(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Bond_extra 1 ksm for sub-account index 0 + assert_ok!(Slp::bond_extra( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + None, + dollar::(RelayCurrencyId::get()), + )); + + assert_eq!( + Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), + Some(Ledger::Substrate(SubstrateLedger { + account: subaccount_0_location.clone(), + total: dollar::(RelayCurrencyId::get()), + active: dollar::(RelayCurrencyId::get()), + unlocking: vec![] + })) + ); + + // Check the existence of the query in pallet_xcm Queries storage. + assert_eq!( + PolkadotXcm::query(0), + Some(QueryStatus::Pending { + responder: VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: Here + }), + maybe_notify: None, + timeout: 1600 + }) + ); + + // Check the existence of query in the response update queue storage. + assert_eq!( + Slp::get_delegator_ledger_update_entry(0), + Some(( + LedgerUpdateEntry::Substrate(SubstrateLedgerUpdateEntry { + currency_id: RelayCurrencyId::get(), + delegator_id: subaccount_0_location.clone(), + update_operation: SubstrateLedgerUpdateOperation::Bond, + amount: dollar::(RelayCurrencyId::get()), + unlock_time: None + }), + 1600 + )) + ); + }); + + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Staking::ledger(&subaccount_0), + Some(StakingLedger { + stash: subaccount_0.clone(), + total: 2 * dollar::(RelayCurrencyId::get()), + active: 2 * dollar::(RelayCurrencyId::get()), + unlocking: BoundedVec::try_from(vec![]).unwrap(), + claimed_rewards: vec![], + }) + ); + }); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Call confirm_delegator_ledger_query_response. + assert_ok!(Slp::confirm_delegator_ledger_query_response( + Origin::root(), + RelayCurrencyId::get(), + 0 + )); + + // Check the ledger update. + assert_eq!( + Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), + Some(Ledger::Substrate(SubstrateLedger { + account: subaccount_0_location.clone(), + total: 2 * dollar::(RelayCurrencyId::get()), + active: 2 * dollar::(RelayCurrencyId::get()), + unlocking: vec![] + })) + ); + + // Check the existence of the query in pallet_xcm Queries storage. + // If xcm version 3 is introduced. We'll add instruction ReportTransactStatus into the + // xcm message. And this query will be set to ready status after we received a query + // response. At that point, this check should be set to equal None. + assert_eq!( + PolkadotXcm::query(0), + Some(QueryStatus::Pending { + responder: VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: Here + }), + maybe_notify: None, + timeout: 1600 + }) + ); + + // Check the inexistence of query in the response update queue storage. + assert_eq!(Slp::get_delegator_ledger_update_entry(0), None); + }); + }) +} + +#[test] +fn confirm_delegator_ledger_query_response_with_unbond_works() { + sp_io::TestExternalities::default().execute_with(|| { + // bond 1 ksm for sub-account index 0 + locally_bond_subaccount_0_1ksm_in_kusama(); + register_subaccount_index_0(); + register_delegator_ledger(); + let subaccount_0 = subaccount_0(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Unbond 0.5 ksm, 0.5 ksm left. + assert_ok!(Slp::unbond( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + None, + 500_000_000_000, + )); + + assert_eq!( + Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), + Some(Ledger::Substrate(SubstrateLedger { + account: subaccount_0_location.clone(), + total: dollar::(RelayCurrencyId::get()), + active: dollar::(RelayCurrencyId::get()), + unlocking: vec![] + })) + ); + + // Check the existence of the query in pallet_xcm Queries storage. + assert_eq!( + PolkadotXcm::query(0), + Some(QueryStatus::Pending { + responder: VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: Here + }), + maybe_notify: None, + timeout: 1600 + }) + ); + + // Check the existence of query in the response update queue storage. + assert_eq!( + Slp::get_delegator_ledger_update_entry(0), + Some(( + LedgerUpdateEntry::Substrate(SubstrateLedgerUpdateEntry { + currency_id: RelayCurrencyId::get(), + delegator_id: subaccount_0_location.clone(), + update_operation: SubstrateLedgerUpdateOperation::Unlock, + amount: 500_000_000_000, + unlock_time: Some(TimeUnit::Era(10)) + }), + 1600 + )) + ); + }); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Call confirm_delegator_ledger_query_response. + assert_ok!(Slp::confirm_delegator_ledger_query_response( + Origin::root(), + RelayCurrencyId::get(), + 0 + )); + + // Check the ledger update. + assert_eq!( + Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), + Some(Ledger::Substrate(SubstrateLedger { + account: subaccount_0_location.clone(), + total: dollar::(RelayCurrencyId::get()), + active: 500_000_000_000, + unlocking: vec![UnlockChunk { + value: 500000000000, + unlock_time: TimeUnit::Era(10) + }] + })) + ); + + // Check the existence of the query in pallet_xcm Queries storage. + // If xcm version 3 is introduced. We'll add instruction ReportTransactStatus into the + // xcm message. And this query will be set to ready status after we received a query + // response. At that point, this check should be set to equal None. + assert_eq!( + PolkadotXcm::query(0), + Some(QueryStatus::Pending { + responder: VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: Here + }), + maybe_notify: None, + timeout: 1600 + }) + ); + + // Check the inexistence of query in the response update queue storage. + assert_eq!(Slp::get_delegator_ledger_update_entry(0), None); + }); + }) +} + +#[test] +fn confirm_delegator_ledger_query_response_with_unbond_all_works() { + sp_io::TestExternalities::default().execute_with(|| { + // bond 1 ksm for sub-account index 0 + locally_bond_subaccount_0_1ksm_in_kusama(); + register_subaccount_index_0(); + register_delegator_ledger(); + let subaccount_0 = subaccount_0(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Unbond the only bonded 1 ksm. + assert_ok!(Slp::unbond_all( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + )); + + assert_eq!( + Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), + Some(Ledger::Substrate(SubstrateLedger { + account: subaccount_0_location.clone(), + total: dollar::(RelayCurrencyId::get()), + active: dollar::(RelayCurrencyId::get()), + unlocking: vec![] + })) + ); + + // Check the existence of the query in pallet_xcm Queries storage. + assert_eq!( + PolkadotXcm::query(0), + Some(QueryStatus::Pending { + responder: VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: Here + }), + maybe_notify: None, + timeout: 1600 + }) + ); + + // Check the existence of query in the response update queue storage. + assert_eq!( + Slp::get_delegator_ledger_update_entry(0), + Some(( + LedgerUpdateEntry::Substrate(SubstrateLedgerUpdateEntry { + currency_id: RelayCurrencyId::get(), + delegator_id: subaccount_0_location.clone(), + update_operation: SubstrateLedgerUpdateOperation::Unlock, + amount: dollar::(RelayCurrencyId::get()), + unlock_time: Some(TimeUnit::Era(10)) + }), + 1600 + )) + ); + }); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Call confirm_delegator_ledger_query_response. + assert_ok!(Slp::confirm_delegator_ledger_query_response( + Origin::root(), + RelayCurrencyId::get(), + 0 + )); + + // Check the ledger update. + assert_eq!( + Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), + Some(Ledger::Substrate(SubstrateLedger { + account: subaccount_0_location.clone(), + total: dollar::(RelayCurrencyId::get()), + active: 0, + unlocking: vec![UnlockChunk { + value: dollar::(RelayCurrencyId::get()), + unlock_time: TimeUnit::Era(10) + }] + })) + ); + + // Check the existence of the query in pallet_xcm Queries storage. + // If xcm version 3 is introduced. We'll add instruction ReportTransactStatus into the + // xcm message. And this query will be set to ready status after we received a query + // response. At that point, this check should be set to equal None. + assert_eq!( + PolkadotXcm::query(0), + Some(QueryStatus::Pending { + responder: VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: Here + }), + maybe_notify: None, + timeout: 1600 + }) + ); + + // Check the inexistence of query in the response update queue storage. + assert_eq!(Slp::get_delegator_ledger_update_entry(0), None); + }); + }) +} + +#[test] +fn confirm_delegator_ledger_query_response_with_rebond_works() { + sp_io::TestExternalities::default().execute_with(|| { + // bond 1 ksm for sub-account index 0 + locally_bond_subaccount_0_1ksm_in_kusama(); + register_subaccount_index_0(); + register_delegator_ledger(); + let subaccount_0 = subaccount_0(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Unbond 0.5 ksm, 0.5 ksm left. + assert_ok!(Slp::unbond( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + None, + 500_000_000_000, + )); + + // Update Bifrost local ledger. This should be done by backend services. + let chunk = UnlockChunk { value: 500_000_000_000, unlock_time: TimeUnit::Era(10) }; + let sb_ledger = SubstrateLedger { + account: subaccount_0_location.clone(), + total: dollar::(RelayCurrencyId::get()), + active: 500_000_000_000, + unlocking: vec![chunk], + }; + let ledger = Ledger::Substrate(sb_ledger); + + assert_ok!(Slp::set_delegator_ledger( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + Box::new(Some(ledger)) + )); + + // rebond 0.5 ksm. + assert_ok!(Slp::rebond( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + None, + Some(500_000_000_000), + )); + + assert_eq!( + Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), + Some(Ledger::Substrate(SubstrateLedger { + account: subaccount_0_location.clone(), + total: dollar::(RelayCurrencyId::get()), + active: 500_000_000_000, + unlocking: vec![UnlockChunk { + value: 500_000_000_000, + unlock_time: TimeUnit::Era(10) + }] + })) + ); + + // Check the existence of the query in pallet_xcm Queries storage. + assert_eq!( + PolkadotXcm::query(1), + Some(QueryStatus::Pending { + responder: VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: Here + }), + maybe_notify: None, + timeout: 1600 + }) + ); + + // Check the existence of query in the response update queue storage. + assert_eq!( + Slp::get_delegator_ledger_update_entry(1), + Some(( + LedgerUpdateEntry::Substrate(SubstrateLedgerUpdateEntry { + currency_id: RelayCurrencyId::get(), + delegator_id: subaccount_0_location.clone(), + update_operation: SubstrateLedgerUpdateOperation::Rebond, + amount: 500_000_000_000, + unlock_time: None + }), + 1600 + )) + ); + }); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Call confirm_delegator_ledger_query_response. + assert_ok!(Slp::confirm_delegator_ledger_query_response( + Origin::root(), + RelayCurrencyId::get(), + 1 + )); + + // Check the ledger update. + assert_eq!( + Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), + Some(Ledger::Substrate(SubstrateLedger { + account: subaccount_0_location.clone(), + total: dollar::(RelayCurrencyId::get()), + active: dollar::(RelayCurrencyId::get()), + unlocking: vec![] + })) + ); + + // Check the existence of the query in pallet_xcm Queries storage. + // If xcm version 3 is introduced. We'll add instruction ReportTransactStatus into the + // xcm message. And this query will be set to ready status after we received a query + // response. At that point, this check should be set to equal None. + assert_eq!( + PolkadotXcm::query(1), + Some(QueryStatus::Pending { + responder: VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: Here + }), + maybe_notify: None, + timeout: 1600 + }) + ); + + // Check the inexistence of query in the response update queue storage. + assert_eq!(Slp::get_delegator_ledger_update_entry(1), None); + }); + }) +} + +#[test] +fn confirm_delegator_ledger_query_response_with_liquidize_works() { + sp_io::TestExternalities::default().execute_with(|| { + confirm_delegator_ledger_query_response_with_unbond_works(); + let subaccount_0 = subaccount_0(); + + KusamaNet::execute_with(|| { + // Kusama's unbonding period is 27 days = 100_800 blocks + kusama_runtime::System::set_block_number(101_000); + for _i in 0..29 { + kusama_runtime::Staking::trigger_new_era(0, vec![]); + } + + assert_eq!( + kusama_runtime::Balances::free_balance(&subaccount_0.clone()), + 2 * dollar::(RelayCurrencyId::get()) + ); + + // 1ksm is locked for half bonded and half unbonding. + assert_eq!( + kusama_runtime::Balances::usable_balance(&subaccount_0.clone()), + dollar::(RelayCurrencyId::get()) + ); + }); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + System::set_block_number(1200); + + // set ongoing era to be 11 which is greater than due era 10. + assert_ok!(Slp::update_ongoing_time_unit( + Origin::root(), + RelayCurrencyId::get(), + TimeUnit::Era(11) + )); + + assert_ok!(Slp::liquidize( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + Some(TimeUnit::SlashingSpan(5)), + None + )); + + assert_eq!( + Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), + Some(Ledger::Substrate(SubstrateLedger { + account: subaccount_0_location.clone(), + total: dollar::(RelayCurrencyId::get()), + active: 500_000_000_000, + unlocking: vec![UnlockChunk { + value: 500_000_000_000, + unlock_time: TimeUnit::Era(10) + }] + })) + ); + + // Check the existence of the query in pallet_xcm Queries storage. + assert_eq!( + PolkadotXcm::query(1), + Some(QueryStatus::Pending { + responder: VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: Here + }), + maybe_notify: None, + timeout: 2200 + }) + ); + + // Check the existence of query in the response update queue storage. + assert_eq!( + Slp::get_delegator_ledger_update_entry(1), + Some(( + LedgerUpdateEntry::Substrate(SubstrateLedgerUpdateEntry { + currency_id: RelayCurrencyId::get(), + delegator_id: subaccount_0_location.clone(), + update_operation: SubstrateLedgerUpdateOperation::Liquidize, + amount: 0, + unlock_time: Some(TimeUnit::Era(11)) + }), + 2200 + )) + ); + }); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Call confirm_delegator_ledger_query_response. + assert_ok!(Slp::confirm_delegator_ledger_query_response( + Origin::root(), + RelayCurrencyId::get(), + 1 + )); + + // Check the ledger update. + assert_eq!( + Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), + Some(Ledger::Substrate(SubstrateLedger { + account: subaccount_0_location.clone(), + total: 500_000_000_000, + active: 500_000_000_000, + unlocking: vec![] + })) + ); + + // Check the existence of the query in pallet_xcm Queries storage. + // If xcm version 3 is introduced. We'll add instruction ReportTransactStatus into the + // xcm message. And this query will be set to ready status after we received a query + // response. At that point, this check should be set to equal None. + assert_eq!( + PolkadotXcm::query(1), + Some(QueryStatus::Pending { + responder: VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: Here + }), + maybe_notify: None, + timeout: 2200 + }) + ); + + // Check the inexistence of query in the response update queue storage. + assert_eq!(Slp::get_delegator_ledger_update_entry(1), None); + }); + + KusamaNet::execute_with(|| { + assert_eq!( + kusama_runtime::Balances::free_balance(&subaccount_0.clone()), + 2 * dollar::(RelayCurrencyId::get()) + ); + + // half of 1ksm unlocking has been freed. So the usable balance should be 1.5 ksm + assert_eq!( + kusama_runtime::Balances::usable_balance(&subaccount_0.clone()), + 1_500_000_000_000 + ); + }); + }) +} + +#[test] +fn fail_delegator_ledger_query_response_works() { + sp_io::TestExternalities::default().execute_with(|| { + register_subaccount_index_0(); + transfer_2_ksm_to_subaccount_in_kusama(); + let subaccount_0 = subaccount_0(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // First call bond function, it will insert a query. + // Bond 1 ksm for sub-account index 0 + assert_ok!(Slp::bond( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + dollar::(RelayCurrencyId::get()), + None + )); + + // Check the existence of the query in pallet_xcm Queries storage. + assert_eq!( + PolkadotXcm::query(0), + Some(QueryStatus::Pending { + responder: VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: Here + }), + maybe_notify: None, + timeout: 1600 + }) + ); + + // Check the existence of query in the response update queue storage. + assert_eq!( + Slp::get_delegator_ledger_update_entry(0), + Some(( + LedgerUpdateEntry::Substrate(SubstrateLedgerUpdateEntry { + currency_id: RelayCurrencyId::get(), + delegator_id: subaccount_0_location.clone(), + update_operation: SubstrateLedgerUpdateOperation::Bond, + amount: dollar::(RelayCurrencyId::get()), + unlock_time: None + }), + 1600 + )) + ); + }); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + // Call confirm_delegator_ledger_query_response. + assert_ok!(Slp::fail_delegator_ledger_query_response( + Origin::root(), + RelayCurrencyId::get(), + 0 + )); + + // Check the ledger update. + assert_eq!( + Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), + Some(Ledger::Substrate(SubstrateLedger { + account: subaccount_0_location.clone(), + total: 0, + active: 0, + unlocking: vec![] + })) + ); + + // Check the existence of the query in pallet_xcm Queries storage. + // If xcm version 3 is introduced. We'll add instruction ReportTransactStatus into the + // xcm message. And this query will be set to ready status after we received a query + // response. At that point, this check should be set to equal None. + assert_eq!( + PolkadotXcm::query(0), + Some(QueryStatus::Pending { + responder: VersionedMultiLocation::V1(MultiLocation { + parents: 1, + interior: Here + }), + maybe_notify: None, + timeout: 1600 + }) + ); + + // Check the inexistence of query in the response update queue storage. + assert_eq!(Slp::get_delegator_ledger_update_entry(0), None); + }); + }) +} + +#[test] +fn confirm_validators_by_delegator_query_response_with_delegate_works() { + sp_io::TestExternalities::default().execute_with(|| { + // bond 1 ksm for sub-account index 0 + register_validators(); + locally_bond_subaccount_0_1ksm_in_kusama(); + register_subaccount_index_0(); + register_delegator_ledger(); + let subaccount_0 = subaccount_0(); + + // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz + let validator_0: AccountId = + hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] + .into(); + + // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 + let validator_1: AccountId = + hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] + .into(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + let mut targets = vec![]; + let mut valis = vec![]; + + let validator_0_32: [u8; 32] = + Slp::account_id_to_account_32(validator_0.clone()).unwrap(); + let validator_0_location: MultiLocation = + Slp::account_32_to_parent_location(validator_0_32).unwrap(); + targets.push(validator_0_location.clone()); + let multi_hash_0 = + ::Hashing::hash(&validator_0_location.encode()); + + let validator_1_32: [u8; 32] = + Slp::account_id_to_account_32(validator_1.clone()).unwrap(); + let validator_1_location: MultiLocation = + Slp::account_32_to_parent_location(validator_1_32).unwrap(); + targets.push(validator_1_location.clone()); + let multi_hash_1 = + ::Hashing::hash(&validator_1_location.encode()); + + valis.push((validator_1_location.clone(), multi_hash_1)); + valis.push((validator_0_location.clone(), multi_hash_0)); + + // delegate + assert_ok!(Slp::delegate( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + targets.clone(), + )); + + // Before data: Delegate nobody. + assert_eq!( + Slp::get_validators_by_delegator( + RelayCurrencyId::get(), + subaccount_0_location.clone() + ), + None + ); + + assert_eq!( + Slp::get_validators_by_delegator_update_entry(0), + Some(( + ValidatorsByDelegatorUpdateEntry::Substrate( + SubstrateValidatorsByDelegatorUpdateEntry { + currency_id: RelayCurrencyId::get(), + delegator_id: subaccount_0_location.clone(), + validators: valis.clone(), + } + ), + 1600 + )) + ); + + // confirm call + assert_ok!(Slp::confirm_validators_by_delegator_query_response( + Origin::root(), + RelayCurrencyId::get(), + 0 + )); + + // After delegation data. + assert_eq!( + Slp::get_validators_by_delegator( + RelayCurrencyId::get(), + subaccount_0_location.clone() + ), + Some(valis) + ); + + assert_eq!(Slp::get_validators_by_delegator_update_entry(0), None); + }); + }) +} + +#[test] +fn confirm_validators_by_delegator_query_response_with_undelegate_works() { + sp_io::TestExternalities::default().execute_with(|| { + delegate_works(); + + let subaccount_0 = subaccount_0(); + + // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz + let validator_0: AccountId = + hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] + .into(); + + // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 + let validator_1: AccountId = + hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] + .into(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + let mut targets = vec![]; + let mut valis_1 = vec![]; + let mut valis_2 = vec![]; + + let validator_0_32: [u8; 32] = + Slp::account_id_to_account_32(validator_0.clone()).unwrap(); + let validator_0_location: MultiLocation = + Slp::account_32_to_parent_location(validator_0_32).unwrap(); + targets.push(validator_0_location.clone()); + let multi_hash_0 = + ::Hashing::hash(&validator_0_location.encode()); + + let validator_1_32: [u8; 32] = + Slp::account_id_to_account_32(validator_1.clone()).unwrap(); + let validator_1_location: MultiLocation = + Slp::account_32_to_parent_location(validator_1_32).unwrap(); + let multi_hash_1 = + ::Hashing::hash(&validator_1_location.encode()); + + valis_1.push((validator_1_location.clone(), multi_hash_1.clone())); + + valis_2.push((validator_1_location.clone(), multi_hash_1)); + valis_2.push((validator_0_location.clone(), multi_hash_0)); + + // Undelegate validator 0. Only validator 1 left. + assert_ok!(Slp::undelegate( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + targets.clone(), + )); + + // Before data: Delegate 2 validators. + assert_eq!( + Slp::get_validators_by_delegator( + RelayCurrencyId::get(), + subaccount_0_location.clone() + ), + Some(valis_2) + ); + + assert_eq!( + Slp::get_validators_by_delegator_update_entry(1), + Some(( + ValidatorsByDelegatorUpdateEntry::Substrate( + SubstrateValidatorsByDelegatorUpdateEntry { + currency_id: RelayCurrencyId::get(), + delegator_id: subaccount_0_location.clone(), + validators: valis_1.clone(), + } + ), + 1600 + )) + ); + + // confirm call + assert_ok!(Slp::confirm_validators_by_delegator_query_response( + Origin::root(), + RelayCurrencyId::get(), + 1, + )); + + // After delegation data: delegate only 1 validator. + assert_eq!( + Slp::get_validators_by_delegator( + RelayCurrencyId::get(), + subaccount_0_location.clone() + ), + Some(valis_1) + ); + + assert_eq!(Slp::get_validators_by_delegator_update_entry(1), None); + }); + }) +} + +#[test] +fn confirm_validators_by_delegator_query_response_with_redelegate_works() { + sp_io::TestExternalities::default().execute_with(|| { + confirm_validators_by_delegator_query_response_with_undelegate_works(); + + let subaccount_0 = subaccount_0(); + + // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz + let validator_0: AccountId = + hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] + .into(); + + // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 + let validator_1: AccountId = + hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] + .into(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + let mut targets = vec![]; + let mut valis_1 = vec![]; + let mut valis_2 = vec![]; + + let validator_0_32: [u8; 32] = + Slp::account_id_to_account_32(validator_0.clone()).unwrap(); + let validator_0_location: MultiLocation = + Slp::account_32_to_parent_location(validator_0_32).unwrap(); + targets.push(validator_0_location.clone()); + let multi_hash_0 = + ::Hashing::hash(&validator_0_location.encode()); + + let validator_1_32: [u8; 32] = + Slp::account_id_to_account_32(validator_1.clone()).unwrap(); + let validator_1_location: MultiLocation = + Slp::account_32_to_parent_location(validator_1_32).unwrap(); + targets.push(validator_1_location.clone()); + let multi_hash_1 = + ::Hashing::hash(&validator_1_location.encode()); + + valis_1.push((validator_1_location.clone(), multi_hash_1.clone())); + valis_2.push((validator_1_location.clone(), multi_hash_1)); + valis_2.push((validator_0_location.clone(), multi_hash_0)); + + // Redelegate to a set of validator_0 and validator_1. + assert_ok!(Slp::redelegate( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + Some(targets.clone()), + )); + + // Before data: Delegate only 1 validator. + assert_eq!( + Slp::get_validators_by_delegator( + RelayCurrencyId::get(), + subaccount_0_location.clone() + ), + Some(valis_1) + ); + + assert_eq!( + Slp::get_validators_by_delegator_update_entry(2), + Some(( + ValidatorsByDelegatorUpdateEntry::Substrate( + SubstrateValidatorsByDelegatorUpdateEntry { + currency_id: RelayCurrencyId::get(), + delegator_id: subaccount_0_location.clone(), + validators: valis_2.clone(), + } + ), + 1600 + )) + ); + + // confirm call + assert_ok!(Slp::confirm_validators_by_delegator_query_response( + Origin::root(), + RelayCurrencyId::get(), + 2, + )); + + // After delegation data: delegate 2 validators. + assert_eq!( + Slp::get_validators_by_delegator( + RelayCurrencyId::get(), + subaccount_0_location.clone() + ), + Some(valis_2) + ); + + assert_eq!(Slp::get_validators_by_delegator_update_entry(2), None); + }); + }) +} + +#[test] +fn fail_validators_by_delegator_query_response_works() { + sp_io::TestExternalities::default().execute_with(|| { + // bond 1 ksm for sub-account index 0 + register_validators(); + locally_bond_subaccount_0_1ksm_in_kusama(); + register_subaccount_index_0(); + register_delegator_ledger(); + let subaccount_0 = subaccount_0(); + + // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz + let validator_0: AccountId = + hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] + .into(); + + // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 + let validator_1: AccountId = + hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] + .into(); + + Bifrost::execute_with(|| { + let subaccount_0_32: [u8; 32] = + Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); + let subaccount_0_location: MultiLocation = + Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); + + let mut targets = vec![]; + let mut valis = vec![]; + + let validator_0_32: [u8; 32] = + Slp::account_id_to_account_32(validator_0.clone()).unwrap(); + let validator_0_location: MultiLocation = + Slp::account_32_to_parent_location(validator_0_32).unwrap(); + targets.push(validator_0_location.clone()); + let multi_hash_0 = + ::Hashing::hash(&validator_0_location.encode()); + + let validator_1_32: [u8; 32] = + Slp::account_id_to_account_32(validator_1.clone()).unwrap(); + let validator_1_location: MultiLocation = + Slp::account_32_to_parent_location(validator_1_32).unwrap(); + targets.push(validator_1_location.clone()); + let multi_hash_1 = + ::Hashing::hash(&validator_1_location.encode()); + + valis.push((validator_1_location.clone(), multi_hash_1)); + valis.push((validator_0_location.clone(), multi_hash_0)); + + // delegate + assert_ok!(Slp::delegate( + Origin::root(), + RelayCurrencyId::get(), + Box::new(subaccount_0_location.clone()), + targets.clone(), + )); + + // check before data: delegate nobody. + assert_eq!( + Slp::get_validators_by_delegator( + RelayCurrencyId::get(), + subaccount_0_location.clone() + ), + None + ); + + assert_eq!( + Slp::get_validators_by_delegator_update_entry(0), + Some(( + ValidatorsByDelegatorUpdateEntry::Substrate( + SubstrateValidatorsByDelegatorUpdateEntry { + currency_id: RelayCurrencyId::get(), + delegator_id: subaccount_0_location.clone(), + validators: valis, + } + ), + 1600 + )) + ); + + // call fail function + assert_ok!(Slp::fail_validators_by_delegator_query_response( + Origin::root(), + RelayCurrencyId::get(), + 0, + )); + + // check after data + assert_eq!( + Slp::get_validators_by_delegator( + RelayCurrencyId::get(), + subaccount_0_location.clone() + ), + None + ); + + assert_eq!(Slp::get_validators_by_delegator_update_entry(0), None); + }); + }) +} diff --git a/integration-tests/bifrost-kusama/src/statemine.rs b/integration-tests/bifrost-kusama/src/statemine.rs new file mode 100644 index 0000000000..625ca3b45f --- /dev/null +++ b/integration-tests/bifrost-kusama/src/statemine.rs @@ -0,0 +1,64 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// use frame_support::assert_ok; +// use polkadot_parachain::primitives::Sibling; +// use sp_runtime::traits::AccountIdConversion; +// use xcm::latest::prelude::*; +// use xcm_emulator::TestExt; +// +// use crate::{integration_tests::*, kusama_test_net::*}; +// #[test] +// fn statemine() { +// // env_logger::init(); +// Statemine::execute_with(|| { +// use frame_support::traits::Currency; +// use statemine_runtime::*; +// +// let origin = Origin::signed(ALICE.into()); +// +// statemine_runtime::Balances::make_free_balance_be( +// &ALICE.into(), +// 10 * dollar(RelayCurrencyId::get()), +// ); +// +// // need to have some KSM to be able to receive user assets +// statemine_runtime::Balances::make_free_balance_be( +// &Sibling::from(2001).into_account_truncating(), +// 10 * dollar(RelayCurrencyId::get()), +// ); +// +// assert_ok!(Assets::create(origin.clone(), 0, MultiAddress::Id(ALICE.into()), 10,)); +// +// assert_ok!(Assets::mint(origin.clone(), 0, MultiAddress::Id(ALICE.into()), 1000)); +// +// System::reset_events(); +// +// let para_acc: AccountId = Sibling::from(2001).into_account_truncating(); +// println!("{:?}", para_acc); +// +// assert_ok!(PolkadotXcm::reserve_transfer_assets( +// origin.clone(), +// Box::new(MultiLocation::new(1, X1(Parachain(2001))).into()), +// Box::new(Junction::AccountId32 { id: BOB, network: NetworkId::Any }.into().into()), +// Box::new((X2(PalletInstance(50), GeneralIndex(0)), 100).into()), +// 0 +// )); +// println!("{:?}", System::events()); +// }); +// } diff --git a/integration-tests/bifrost-kusama/src/treasury.rs b/integration-tests/bifrost-kusama/src/treasury.rs new file mode 100644 index 0000000000..9c043c4a25 --- /dev/null +++ b/integration-tests/bifrost-kusama/src/treasury.rs @@ -0,0 +1,139 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use frame_support::assert_ok; +use sp_runtime::{traits::AccountIdConversion, AccountId32}; +use xcm_emulator::TestExt; + +use crate::{ + kusama_integration_tests::{Origin, RelayCurrencyId, TimeUnit, ALICE, BLOCKS_PER_YEAR}, + kusama_test_net::{Bifrost, KusamaNet}, +}; +use node_primitives::{AccountId, CurrencyId, TokenSymbol, TryConvertFrom, VtokenMintingOperator}; + +pub const KSM: CurrencyId = CurrencyId::Token(TokenSymbol::KSM); +pub const VKSM: CurrencyId = CurrencyId::VToken(TokenSymbol::KSM); + +pub fn para_account_2001() -> AccountId { + // 5Ec4AhPV91i9yNuiWuNunPf6AQCYDhFTTA4G5QCbtqYApH9E + let para_account_2001: AccountId = + hex_literal::hex!["70617261d1070000000000000000000000000000000000000000000000000000"] + .into(); + + para_account_2001 +} + +#[test] +fn kusama_treasury_propose_spend() { + sp_io::TestExternalities::default().execute_with(|| { + KusamaNet::execute_with(|| { + assert_ok!(kusama_runtime::Treasury::propose_spend( + kusama_runtime::Origin::signed(ALICE.into()), + 50_000_000_000_000_000, + sp_runtime::MultiAddress::Id(para_account_2001()), + )); + }); + }) +} + +#[test] +fn bifrost_treasury_operations() { + sp_io::TestExternalities::default().execute_with(|| { + let para_id = 2001u32; + let treasury_account: AccountId32 = + bifrost_kusama_runtime::TreasuryPalletId::get().into_account_truncating(); + Bifrost::execute_with(|| { + let treasury_derivative_account_id = + bifrost_kusama_runtime::Utility::derivative_account_id(treasury_account.clone(), 0); + assert_ok!(bifrost_kusama_runtime::Tokens::set_balance( + bifrost_kusama_runtime::Origin::root(), + sp_runtime::MultiAddress::Id(treasury_derivative_account_id.clone()), + RelayCurrencyId::get(), + 50_000_000_000_000_000, + 0, + )); + assert_ok!(bifrost_kusama_runtime::Tokens::force_transfer( + bifrost_kusama_runtime::Origin::root(), + sp_runtime::MultiAddress::Id(treasury_derivative_account_id), + sp_runtime::MultiAddress::Id(treasury_account.clone()), + RelayCurrencyId::get(), + 50_000_000_000_000_000, + )); + + assert_ok!(bifrost_kusama_runtime::VtokenMinting::mint( + bifrost_kusama_runtime::Origin::signed(treasury_account.clone()), + RelayCurrencyId::get(), + 25_000_000_000_000_000, + )); + + assert_ok!(bifrost_kusama_runtime::ZenlinkProtocol::create_pair( + bifrost_kusama_runtime::Origin::root(), + zenlink_protocol::AssetId::try_convert_from(KSM, para_id).unwrap(), + zenlink_protocol::AssetId::try_convert_from(VKSM, para_id).unwrap(), + )); + + assert_ok!(bifrost_kusama_runtime::ZenlinkProtocol::add_liquidity( + bifrost_kusama_runtime::Origin::signed(treasury_account.clone()), + zenlink_protocol::AssetId::try_convert_from(KSM, para_id).unwrap(), + zenlink_protocol::AssetId::try_convert_from(VKSM, para_id).unwrap(), + 25_000_000_000_000_000, + 25_000_000_000_000_000, + 0, + 0, + BLOCKS_PER_YEAR, + )); + + let lp_asset_id = bifrost_kusama_runtime::ZenlinkProtocol::lp_asset_id( + &zenlink_protocol::AssetId::try_convert_from(KSM, para_id).unwrap(), + &zenlink_protocol::AssetId::try_convert_from(VKSM, para_id).unwrap(), + ); + + let lp = bifrost_kusama_runtime::ZenlinkProtocol::foreign_balance_of( + lp_asset_id, + &treasury_account, + ); + + assert_ok!(bifrost_kusama_runtime::ZenlinkProtocol::remove_liquidity( + bifrost_kusama_runtime::Origin::signed(treasury_account.clone()), + zenlink_protocol::AssetId::try_convert_from(KSM, para_id).unwrap(), + zenlink_protocol::AssetId::try_convert_from(VKSM, para_id).unwrap(), + lp, + 0, + 0, + sp_runtime::MultiAddress::Id(treasury_account.clone()), + BLOCKS_PER_YEAR, + )); + + assert_ok!(bifrost_kusama_runtime::VtokenMinting::set_unlock_duration( + Origin::root(), + KSM, + TimeUnit::Era(0) + )); + assert_ok!(bifrost_kusama_runtime::VtokenMinting::update_ongoing_time_unit( + KSM, + TimeUnit::Era(1) + )); + + assert_ok!(bifrost_kusama_runtime::VtokenMinting::redeem( + bifrost_kusama_runtime::Origin::signed(treasury_account), + VKSM, + 0, + )); + }); + }) +} diff --git a/integration-tests/bifrost-polkadot/Cargo.toml b/integration-tests/bifrost-polkadot/Cargo.toml new file mode 100644 index 0000000000..457ad23c50 --- /dev/null +++ b/integration-tests/bifrost-polkadot/Cargo.toml @@ -0,0 +1,91 @@ +[package] +name = "bifrost-polkadot-integration-tests" +version = "0.8.0" +authors = ["Ron Yang "] +edition = "2021" + +[dependencies] +# third-party dependencies +codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +log = { version = "0.4.17" } +serde = { version = "1.0.143", optional = true } +static_assertions = "1.1.0" +hex = { version = "0.4", optional = true } +hex-literal = { version = "0.3.4" } +smallvec = "1.9.0" + +# primitives +node-primitives = { default-features = false, path = "../../node/primitives" } + +# frame dependencies +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +pallet-staking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +pallet-membership = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } + +# Cumulus dependencies +cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +pallet-collator-selection = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } + +# Polkadot dependencies +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } + +# bifrost pallets +bifrost-asset-registry = { path = "../../pallets/asset-registry" } +bifrost-flexible-fee = { path = "../../pallets/flexible-fee" } +bifrost-flexible-fee-rpc-runtime-api = { path = "../../pallets/flexible-fee/rpc/runtime-api" } +bifrost-liquidity-mining = { path = "../../pallets/liquidity-mining" } +bifrost-salp = { path = "../../pallets/salp" } +bifrost-salp-rpc-runtime-api = { path = "../../pallets/salp/rpc/runtime-api" } +bifrost-slp = { path = "../../pallets/slp" } +bifrost-vsbond-auction = { path = "../../pallets/vsbond-auction" } +bifrost-vtoken-minting = { path = "../../pallets/vtoken-minting" } +pallet-vesting = { package = "bifrost-vesting", path = "../../pallets/vesting" } +bifrost-runtime-common = { path = "../../runtime/common" } +bifrost-kusama-runtime = { path = "../../runtime/bifrost-kusama" } +bifrost-polkadot-runtime = { path = "../../runtime/bifrost-polkadot" } + +# orml +orml-currencies = { version = "0.4.1-dev" } +orml-tokens = { version = "0.4.1-dev" } +orml-traits = { version = "0.4.1-dev" } +orml-xtokens = { version = "0.4.1-dev" } +orml-unknown-tokens = { version = "0.4.1-dev" } +orml-xcm-support = { version = "0.4.1-dev" } + +zenlink-protocol = { version = "*" } +zenlink-protocol-runtime-api = { version = "*" } + +[dev-dependencies] +env_logger = "0.9.0" +hex = "0.4.0" + +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } + +cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-test-relay-sproof-builder = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } + +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +polkadot-runtime = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +#statemine-runtime = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +xcm-emulator = { git = "https://github.com/shaunxw/xcm-simulator", rev = "6c02911a3eeb04c342e4eb273d2ffbedd45dabff" } diff --git a/integration-tests/bifrost-polkadot/src/dollor_tests.rs b/integration-tests/bifrost-polkadot/src/dollor_tests.rs new file mode 100644 index 0000000000..235ea414ef --- /dev/null +++ b/integration-tests/bifrost-polkadot/src/dollor_tests.rs @@ -0,0 +1,122 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::polkadot_test_net::{ + register_token2_asset, Bifrost, DECIMAL_10, DECIMAL_18, DOT_TOKEN_ID, GLMR_TOKEN_ID, +}; +use bifrost_asset_registry::AssetMetadata; +use bifrost_polkadot_runtime::{AssetRegistry, Runtime}; +use bifrost_runtime_common::{cent, dollar, micro, microcent, milli, millicent}; +use node_primitives::CurrencyId; +use xcm_emulator::TestExt; + +#[test] +fn dollar_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + register_token2_asset(); + Bifrost::execute_with(|| { + assert_eq!( + AssetRegistry::currency_metadatas(CurrencyId::Token2(DOT_TOKEN_ID)), + Some(AssetMetadata { + name: b"Polkadot DOT".to_vec(), + symbol: b"DOT".to_vec(), + decimals: 10u8, + minimal_balance: 1_000_000, + }) + ); + assert_eq!( + AssetRegistry::currency_metadatas(CurrencyId::Token2(GLMR_TOKEN_ID)), + Some(AssetMetadata { + name: b"Moonbeam Native Token".to_vec(), + symbol: b"GLMR".to_vec(), + decimals: 18u8, + minimal_balance: 1_000_000_000_000, + }) + ); + assert_eq!(dollar::(CurrencyId::Token2(DOT_TOKEN_ID)), DECIMAL_10); + assert_eq!(dollar::(CurrencyId::Token2(GLMR_TOKEN_ID)), DECIMAL_18); + }); + }) +} + +#[test] +fn milli_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + register_token2_asset(); + Bifrost::execute_with(|| { + assert_eq!(milli::(CurrencyId::Token2(DOT_TOKEN_ID)), DECIMAL_10 / 1000); + assert_eq!(milli::(CurrencyId::Token2(GLMR_TOKEN_ID)), DECIMAL_18 / 1000); + }) + }) +} + +#[test] +fn micro_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + register_token2_asset(); + Bifrost::execute_with(|| { + assert_eq!(micro::(CurrencyId::Token2(DOT_TOKEN_ID)), DECIMAL_10 / 1_000_000); + assert_eq!(micro::(CurrencyId::Token2(GLMR_TOKEN_ID)), DECIMAL_18 / 1_000_000); + }) + }) +} + +#[test] +fn cent_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + register_token2_asset(); + Bifrost::execute_with(|| { + assert_eq!(cent::(CurrencyId::Token2(DOT_TOKEN_ID)), DECIMAL_10 / 100); + assert_eq!(cent::(CurrencyId::Token2(GLMR_TOKEN_ID)), DECIMAL_18 / 100); + }) + }) +} + +#[test] +fn millicent_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + register_token2_asset(); + Bifrost::execute_with(|| { + assert_eq!( + millicent::(CurrencyId::Token2(DOT_TOKEN_ID)), + DECIMAL_10 / 100_000 + ); + assert_eq!( + millicent::(CurrencyId::Token2(GLMR_TOKEN_ID)), + DECIMAL_18 / 100_000 + ); + }) + }) +} + +#[test] +fn microcent_should_work() { + sp_io::TestExternalities::default().execute_with(|| { + register_token2_asset(); + Bifrost::execute_with(|| { + assert_eq!( + microcent::(CurrencyId::Token2(DOT_TOKEN_ID)), + DECIMAL_10 / 100_000_000 + ); + assert_eq!( + microcent::(CurrencyId::Token2(GLMR_TOKEN_ID)), + DECIMAL_18 / 100_000_000 + ); + }) + }) +} diff --git a/integration-tests/bifrost-polkadot/src/lib.rs b/integration-tests/bifrost-polkadot/src/lib.rs new file mode 100644 index 0000000000..0c8e0a89b5 --- /dev/null +++ b/integration-tests/bifrost-polkadot/src/lib.rs @@ -0,0 +1,24 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#![cfg(test)] + +mod dollor_tests; +mod polkadot_cross_chain_transfer; +mod polkadot_integration_tests; +mod polkadot_test_net; diff --git a/integration-tests/bifrost-polkadot/src/polkadot_cross_chain_transfer.rs b/integration-tests/bifrost-polkadot/src/polkadot_cross_chain_transfer.rs new file mode 100644 index 0000000000..902cdd2604 --- /dev/null +++ b/integration-tests/bifrost-polkadot/src/polkadot_cross_chain_transfer.rs @@ -0,0 +1,126 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Cross-chain transfer tests within Kusama network. +use frame_support::assert_ok; +use node_primitives::CurrencyId; +use orml_traits::MultiCurrency; +use xcm::{latest::prelude::*, VersionedMultiAssets, VersionedMultiLocation}; +use xcm_emulator::TestExt; + +use crate::{ + polkadot_integration_tests::{ALICE, BOB}, + polkadot_test_net::{register_token2_asset, Bifrost, PolkadotNet, DOT_TOKEN_ID}, +}; +use bifrost_polkadot_runtime::{ + AccountId, Balances, Origin, RelayCurrencyId, Runtime, Tokens, XTokens, +}; +use bifrost_runtime_common::dollar; + +#[test] +fn transfer_from_relay_chain() { + sp_io::TestExternalities::default().execute_with(|| { + register_token2_asset(); + PolkadotNet::execute_with(|| { + assert_ok!(polkadot_runtime::XcmPallet::reserve_transfer_assets( + polkadot_runtime::Origin::signed(ALICE.into()), + Box::new(VersionedMultiLocation::V1(X1(Parachain(2010)).into())), + Box::new(VersionedMultiLocation::V1( + X1(Junction::AccountId32 { id: BOB, network: NetworkId::Any }).into() + )), + Box::new(VersionedMultiAssets::V1( + (Here, 10 * dollar::(RelayCurrencyId::get())).into() + )), + 0, + )); + assert_eq!( + Balances::free_balance(&AccountId::from(ALICE)), + 90 * dollar::(RelayCurrencyId::get()) + ); + }); + + Bifrost::execute_with(|| { + assert_eq!( + Tokens::free_balance(RelayCurrencyId::get(), &AccountId::from(BOB)), + 9999990730400 + ); + }); + }) +} + +#[test] +fn transfer_to_relay_chain() { + sp_io::TestExternalities::default().execute_with(|| { + register_token2_asset(); + + Bifrost::execute_with(|| { + assert_ok!(XTokens::transfer( + Origin::signed(ALICE.into()), + RelayCurrencyId::get(), + 2 * dollar::(RelayCurrencyId::get()), + Box::new(xcm::VersionedMultiLocation::V1(MultiLocation::new( + 1, + X1(Junction::AccountId32 { id: BOB, network: NetworkId::Any }) + ))), + 4_000_000_000 + )); + assert_eq!( + Tokens::free_balance(RelayCurrencyId::get(), &AccountId::from(ALICE)), + 8 * dollar::(RelayCurrencyId::get()), + ); + }); + + PolkadotNet::execute_with(|| { + assert_eq!( + polkadot_runtime::Balances::free_balance(&AccountId::from(BOB)), + 19530582548 + ); + }); + }) +} + +#[test] +fn transfer_to_sibling() { + sp_io::TestExternalities::default().execute_with(|| { + register_token2_asset(); + + Bifrost::execute_with(|| { + assert_ok!(XTokens::transfer( + Origin::signed(ALICE.into()), + CurrencyId::Token2(DOT_TOKEN_ID), + 2 * dollar::(CurrencyId::Token2(DOT_TOKEN_ID)), + Box::new( + MultiLocation::new( + 1, + X2( + Parachain(2000), + Junction::AccountId32 { network: NetworkId::Any, id: BOB.into() } + ) + ) + .into() + ), + 1_000_000_000, + )); + + assert_eq!( + Tokens::free_balance(CurrencyId::Token2(DOT_TOKEN_ID), &AccountId::from(ALICE)), + 8 * dollar::(CurrencyId::Token2(DOT_TOKEN_ID)) + ); + }); + }) +} diff --git a/integration-tests/bifrost-polkadot/src/polkadot_integration_tests.rs b/integration-tests/bifrost-polkadot/src/polkadot_integration_tests.rs new file mode 100644 index 0000000000..dea711c976 --- /dev/null +++ b/integration-tests/bifrost-polkadot/src/polkadot_integration_tests.rs @@ -0,0 +1,151 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +pub use codec::Encode; +use frame_support::{traits::GenesisBuild, weights::constants::*}; +pub use node_primitives::*; +pub use orml_traits::{Change, GetByKey, MultiCurrency}; +pub use sp_runtime::{ + traits::{AccountIdConversion, BadOrigin, Convert, Zero}, + BuildStorage, DispatchError, DispatchResult, FixedPointNumber, MultiAddress, +}; + +pub const ALICE: [u8; 32] = [0u8; 32]; +pub const BOB: [u8; 32] = [1u8; 32]; + +pub use bifrost_imports::*; +use bifrost_polkadot_runtime::{ExistentialDeposit, NativeCurrencyId}; + +mod bifrost_imports { + pub use bifrost_polkadot_runtime::{ + create_x2_multilocation, AccountId, AssetRegistry, Balance, Balances, BifrostCrowdloanId, + BlockNumber, Call, Currencies, CurrencyId, Event, ExistentialDeposit, ExistentialDeposits, + NativeCurrencyId, Origin, OriginCaller, ParachainInfo, ParachainSystem, Proxy, + RelayCurrencyId, Runtime, Salp, Scheduler, Session, SlotLength, Slp, System, Tokens, + TreasuryPalletId, Utility, Vesting, XTokens, XcmConfig, + }; + pub use frame_support::parameter_types; + pub use sp_runtime::traits::AccountIdConversion; +} + +pub fn get_all_module_accounts() -> Vec { + vec![BifrostCrowdloanId::get().into_account_truncating()] +} + +pub struct ExtBuilder { + balances: Vec<(AccountId, CurrencyId, Balance)>, + parachain_id: u32, +} + +impl Default for ExtBuilder { + fn default() -> Self { + Self { balances: vec![], parachain_id: 2010 } + } +} + +impl ExtBuilder { + pub fn balances(mut self, balances: Vec<(AccountId, CurrencyId, Balance)>) -> Self { + self.balances = balances; + self + } + + #[allow(dead_code)] + pub fn parachain_id(mut self, parachain_id: u32) -> Self { + self.parachain_id = parachain_id; + self + } + + pub fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + let native_currency_id = NativeCurrencyId::get(); + let existential_deposit = ExistentialDeposit::get(); + + pallet_balances::GenesisConfig:: { + balances: self + .balances + .clone() + .into_iter() + .filter(|(_, currency_id, _)| *currency_id == native_currency_id) + .map(|(account_id, _, initial_balance)| (account_id, initial_balance)) + .chain(get_all_module_accounts().iter().map(|x| (x.clone(), existential_deposit))) + .collect::>(), + } + .assimilate_storage(&mut t) + .unwrap(); + + orml_tokens::GenesisConfig:: { + balances: self + .balances + .into_iter() + .filter(|(_, currency_id, _)| *currency_id != native_currency_id) + .collect::>(), + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_membership::GenesisConfig:: { + members: Default::default(), + phantom: Default::default(), + } + .assimilate_storage(&mut t) + .unwrap(); + + >::assimilate_storage( + ¶chain_info::GenesisConfig { parachain_id: self.parachain_id.into() }, + &mut t, + ) + .unwrap(); + + >::assimilate_storage( + &pallet_xcm::GenesisConfig { safe_xcm_version: Some(2) }, + &mut t, + ) + .unwrap(); + + as GenesisBuild>::assimilate_storage( + &bifrost_salp::GenesisConfig { initial_multisig_account: Some(AccountId::new(ALICE)) }, + &mut t, + ) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext + } +} + +#[test] +fn sanity_check_weight_per_time_constants_are_as_expected() { + assert_eq!(WEIGHT_PER_SECOND, 1_000_000_000_000); + assert_eq!(WEIGHT_PER_MILLIS, WEIGHT_PER_SECOND / 1000); + assert_eq!(WEIGHT_PER_MICROS, WEIGHT_PER_MILLIS / 1000); + assert_eq!(WEIGHT_PER_NANOS, WEIGHT_PER_MICROS / 1000); +} + +#[test] +fn parachain_subaccounts_are_unique() { + ExtBuilder::default().build().execute_with(|| { + let parachain: AccountId = ParachainInfo::parachain_id().into_account_truncating(); + assert_eq!( + parachain, + hex_literal::hex!["70617261da070000000000000000000000000000000000000000000000000000"] + .into() + ); + }); +} diff --git a/integration-tests/bifrost-polkadot/src/polkadot_test_net.rs b/integration-tests/bifrost-polkadot/src/polkadot_test_net.rs new file mode 100644 index 0000000000..7d5f0d5103 --- /dev/null +++ b/integration-tests/bifrost-polkadot/src/polkadot_test_net.rs @@ -0,0 +1,190 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Relay chain and parachains emulation. + +use bifrost_runtime_common::dollar; +use cumulus_primitives_core::ParaId; +use frame_support::{assert_ok, traits::GenesisBuild}; +use polkadot_primitives::v2::{BlockNumber, MAX_CODE_SIZE, MAX_POV_SIZE}; +use polkadot_runtime_parachains::configuration::HostConfiguration; +use sp_runtime::traits::AccountIdConversion; +use xcm_emulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt}; + +use crate::polkadot_integration_tests::*; + +pub const DECIMAL_18: u128 = 1_000_000_000_000_000_000; +pub const DECIMAL_10: u128 = 10_000_000_000; + +pub const DOT_TOKEN_ID: u8 = 0; +pub const GLMR_TOKEN_ID: u8 = 1; +pub const DOT_MINIMAL_BALANCE: u128 = 1_000_000; +pub const GLMR_MINIMAL_BALANCE: u128 = 1_000_000_000_000; + +decl_test_relay_chain! { + pub struct PolkadotNet { + Runtime = polkadot_runtime::Runtime, + XcmConfig = polkadot_runtime::xcm_config::XcmConfig, + new_ext = polkadot_ext(), + } +} + +decl_test_parachain! { + pub struct Bifrost { + Runtime = Runtime, + Origin = Origin, + XcmpMessageHandler = bifrost_polkadot_runtime ::XcmpQueue, + DmpMessageHandler = bifrost_polkadot_runtime::DmpQueue, + new_ext = para_ext(2010), + } +} + +decl_test_parachain! { + pub struct Sibling { + Runtime = Runtime, + Origin = Origin, + XcmpMessageHandler = bifrost_polkadot_runtime ::XcmpQueue, + DmpMessageHandler = bifrost_polkadot_runtime::DmpQueue, + new_ext = para_ext(2000), + } +} + +decl_test_network! { + pub struct TestNet { + relay_chain = PolkadotNet, + parachains = vec![ + (2010, Bifrost), + (2000, Sibling), + ], + } +} + +fn default_parachains_host_configuration() -> HostConfiguration { + HostConfiguration { + minimum_validation_upgrade_delay: 5, + validation_upgrade_cooldown: 5u32, + validation_upgrade_delay: 5, + code_retention_period: 1200, + max_code_size: MAX_CODE_SIZE, + max_pov_size: MAX_POV_SIZE, + max_head_data_size: 32 * 1024, + group_rotation_frequency: 20, + chain_availability_period: 4, + thread_availability_period: 4, + max_upward_queue_count: 8, + max_upward_queue_size: 1024 * 1024, + max_downward_message_size: 1024, + ump_service_total_weight: 4 * 1_000_000_000, + max_upward_message_size: 1024 * 50, + max_upward_message_num_per_candidate: 5, + hrmp_sender_deposit: 0, + hrmp_recipient_deposit: 0, + hrmp_channel_max_capacity: 8, + hrmp_channel_max_total_size: 8 * 1024, + hrmp_max_parachain_inbound_channels: 4, + hrmp_max_parathread_inbound_channels: 4, + hrmp_channel_max_message_size: 1024 * 1024, + hrmp_max_parachain_outbound_channels: 4, + hrmp_max_parathread_outbound_channels: 4, + hrmp_max_message_num_per_candidate: 5, + dispute_period: 6, + no_show_slots: 2, + n_delay_tranches: 25, + needed_approvals: 2, + relay_vrf_modulo_samples: 2, + zeroth_delay_tranche_width: 0, + ..Default::default() + } +} + +pub fn polkadot_ext() -> sp_io::TestExternalities { + use polkadot_runtime::{Runtime, System}; + + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + pallet_balances::GenesisConfig:: { + balances: vec![ + (AccountId::from(ALICE), 100 * dollar::(DOT)), + ( + ParaId::from(2010u32).into_account_truncating(), + 2 * dollar::(DOT), + ), + ], + } + .assimilate_storage(&mut t) + .unwrap(); + + polkadot_runtime_parachains::configuration::GenesisConfig:: { + config: default_parachains_host_configuration(), + } + .assimilate_storage(&mut t) + .unwrap(); + + >::assimilate_storage( + &pallet_xcm::GenesisConfig { safe_xcm_version: Some(2) }, + &mut t, + ) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext +} + +pub fn para_ext(parachain_id: u32) -> sp_io::TestExternalities { + ExtBuilder::default() + .balances(vec![(AccountId::from(ALICE), RelayCurrencyId::get(), 10 * 10_000_000_000)]) + .parachain_id(parachain_id) + .build() +} + +pub fn register_token2_asset() { + Bifrost::execute_with(|| { + // Token + let items = vec![ + ( + CurrencyId::Token2(DOT_TOKEN_ID), + b"Polkadot DOT".to_vec(), + b"DOT".to_vec(), + 10u8, + DOT_MINIMAL_BALANCE, + ), + ( + CurrencyId::Token2(GLMR_TOKEN_ID), + b"Moonbeam Native Token".to_vec(), + b"GLMR".to_vec(), + 18u8, + GLMR_MINIMAL_BALANCE, + ), + ]; + for (currency_id, metadata) in + items.iter().map(|(currency_id, name, symbol, decimals, minimal_balance)| { + ( + currency_id, + bifrost_asset_registry::AssetMetadata { + name: (*name.clone()).to_vec(), + symbol: (*symbol.clone()).to_vec(), + decimals: *decimals, + minimal_balance: *minimal_balance, + }, + ) + }) { + assert_ok!(AssetRegistry::do_register_metadata(*currency_id, &metadata)); + } + }); +} diff --git a/integration-tests/src/asset_registry.rs b/integration-tests/src/asset_registry.rs deleted file mode 100644 index 343c199e1d..0000000000 --- a/integration-tests/src/asset_registry.rs +++ /dev/null @@ -1,454 +0,0 @@ -// This file is part of Bifrost. - -// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -use crate::{integration_tests::*, kusama_test_net::*}; -use bifrost_asset_registry::{ - AssetMetadata, AssetMetadatas, CurrencyIdToLocations, CurrencyIdToWeights, CurrencyMetadatas, - Error, Event, LocationToCurrencyIds, -}; -use frame_support::{assert_noop, assert_ok}; -use xcm::{latest::prelude::*, VersionedMultiLocation}; -use xcm_emulator::TestExt; - -#[test] -fn register_foreign_asset_work() { - Bifrost::execute_with(|| { - let v0_location = VersionedMultiLocation::V0(xcm::v0::MultiLocation::X1( - xcm::v0::Junction::Parachain(1000), - )); - - assert_ok!(AssetRegistry::register_foreign_asset( - Origin::root(), - Box::new(v0_location.clone()), - Box::new(AssetMetadata { - name: b"Token Name".to_vec(), - symbol: b"TN".to_vec(), - decimals: 12, - minimal_balance: 1, - }) - )); - - let location: MultiLocation = v0_location.try_into().unwrap(); - System::assert_last_event(bifrost_kusama_runtime::Event::AssetRegistry( - Event::ForeignAssetRegistered { - asset_id: 0, - asset_address: location.clone(), - metadata: AssetMetadata { - name: b"Token Name".to_vec(), - symbol: b"TN".to_vec(), - decimals: 12, - minimal_balance: 1, - }, - }, - )); - - assert_eq!( - CurrencyIdToLocations::::get(CurrencyId::ForeignAsset(0)), - Some(location.clone()) - ); - assert_eq!( - AssetMetadatas::::get(AssetIds::ForeignAssetId(0)), - Some(AssetMetadata { - name: b"Token Name".to_vec(), - symbol: b"TN".to_vec(), - decimals: 12, - minimal_balance: 1, - }) - ); - assert_eq!( - LocationToCurrencyIds::::get(location), - Some(CurrencyId::ForeignAsset(0)) - ); - }); -} - -#[test] -fn update_foreign_asset_work() { - ExtBuilder::default().build().execute_with(|| { - let v0_location = VersionedMultiLocation::V0(xcm::v0::MultiLocation::X1( - xcm::v0::Junction::Parachain(1000), - )); - - assert_ok!(AssetRegistry::register_foreign_asset( - Origin::root(), - Box::new(v0_location.clone()), - Box::new(AssetMetadata { - name: b"Token Name".to_vec(), - symbol: b"TN".to_vec(), - decimals: 12, - minimal_balance: 1, - }) - )); - - assert_ok!(AssetRegistry::update_foreign_asset( - Origin::root(), - 0, - Box::new(v0_location.clone()), - Box::new(AssetMetadata { - name: b"New Token Name".to_vec(), - symbol: b"NTN".to_vec(), - decimals: 13, - minimal_balance: 2, - }) - )); - - let location: MultiLocation = v0_location.try_into().unwrap(); - System::assert_last_event(bifrost_kusama_runtime::Event::AssetRegistry( - Event::ForeignAssetUpdated { - asset_id: 0, - asset_address: location.clone(), - metadata: AssetMetadata { - name: b"New Token Name".to_vec(), - symbol: b"NTN".to_vec(), - decimals: 13, - minimal_balance: 2, - }, - }, - )); - - assert_eq!( - AssetMetadatas::::get(AssetIds::ForeignAssetId(0)), - Some(AssetMetadata { - name: b"New Token Name".to_vec(), - symbol: b"NTN".to_vec(), - decimals: 13, - minimal_balance: 2, - }) - ); - assert_eq!( - CurrencyIdToLocations::::get(CurrencyId::ForeignAsset(0)), - Some(location.clone()) - ); - assert_eq!( - LocationToCurrencyIds::::get(location.clone()), - Some(CurrencyId::ForeignAsset(0)) - ); - - // modify location - let new_location = VersionedMultiLocation::V0(xcm::v0::MultiLocation::X1( - xcm::v0::Junction::Parachain(2000), - )); - assert_ok!(AssetRegistry::update_foreign_asset( - Origin::root(), - 0, - Box::new(new_location.clone()), - Box::new(AssetMetadata { - name: b"New Token Name".to_vec(), - symbol: b"NTN".to_vec(), - decimals: 13, - minimal_balance: 2, - }) - )); - assert_eq!( - AssetMetadatas::::get(AssetIds::ForeignAssetId(0)), - Some(AssetMetadata { - name: b"New Token Name".to_vec(), - symbol: b"NTN".to_vec(), - decimals: 13, - minimal_balance: 2, - }) - ); - let new_location: MultiLocation = new_location.try_into().unwrap(); - assert_eq!( - CurrencyIdToLocations::::get(CurrencyId::ForeignAsset(0)), - Some(new_location.clone()) - ); - assert_eq!(LocationToCurrencyIds::::get(location), None); - assert_eq!( - LocationToCurrencyIds::::get(new_location), - Some(CurrencyId::ForeignAsset(0)) - ); - }); -} - -#[test] -fn register_native_asset_works() { - ExtBuilder::default().build().execute_with(|| { - let v0_location = VersionedMultiLocation::V0(xcm::v0::MultiLocation::X1( - xcm::v0::Junction::Parachain(1000), - )); - - assert_ok!(AssetRegistry::register_native_asset( - Origin::root(), - CurrencyId::Token(TokenSymbol::DOT), - Box::new(v0_location.clone()), - Box::new(AssetMetadata { - name: b"Token Name".to_vec(), - symbol: b"TN".to_vec(), - decimals: 12, - minimal_balance: 1, - }) - )); - System::assert_last_event(bifrost_kusama_runtime::Event::AssetRegistry( - Event::AssetRegistered { - asset_id: AssetIds::NativeAssetId(CurrencyId::Token(TokenSymbol::DOT)), - metadata: AssetMetadata { - name: b"Token Name".to_vec(), - symbol: b"TN".to_vec(), - decimals: 12, - minimal_balance: 1, - }, - }, - )); - - assert_eq!( - AssetMetadatas::::get(AssetIds::NativeAssetId(CurrencyId::Token( - TokenSymbol::DOT - ))), - Some(AssetMetadata { - name: b"Token Name".to_vec(), - symbol: b"TN".to_vec(), - decimals: 12, - minimal_balance: 1, - }) - ); - // Can't duplicate - assert_noop!( - AssetRegistry::register_native_asset( - Origin::root(), - CurrencyId::Token(TokenSymbol::DOT), - Box::new(v0_location.clone()), - Box::new(AssetMetadata { - name: b"Token Name".to_vec(), - symbol: b"TN".to_vec(), - decimals: 12, - minimal_balance: 1, - }) - ), - Error::::AssetIdExisted - ); - }); -} - -#[test] -fn update_native_asset_works() { - ExtBuilder::default().build().execute_with(|| { - let v0_location = VersionedMultiLocation::V0(xcm::v0::MultiLocation::X1( - xcm::v0::Junction::Parachain(1000), - )); - assert_noop!( - AssetRegistry::update_native_asset( - Origin::root(), - CurrencyId::Token(TokenSymbol::DOT), - Box::new(v0_location.clone()), - Box::new(AssetMetadata { - name: b"New Token Name".to_vec(), - symbol: b"NTN".to_vec(), - decimals: 13, - minimal_balance: 2, - }) - ), - Error::::AssetIdNotExists - ); - - let new_location = VersionedMultiLocation::V0(xcm::v0::MultiLocation::X1( - xcm::v0::Junction::Parachain(2000), - )); - assert_ok!(AssetRegistry::register_native_asset( - Origin::root(), - CurrencyId::Token(TokenSymbol::DOT), - Box::new(new_location.clone()), - Box::new(AssetMetadata { - name: b"Token Name".to_vec(), - symbol: b"TN".to_vec(), - decimals: 12, - minimal_balance: 1, - }) - )); - - assert_ok!(AssetRegistry::update_native_asset( - Origin::root(), - CurrencyId::Token(TokenSymbol::DOT), - Box::new(new_location.clone()), - Box::new(AssetMetadata { - name: b"New Token Name".to_vec(), - symbol: b"NTN".to_vec(), - decimals: 13, - minimal_balance: 2, - }) - )); - - System::assert_last_event(bifrost_kusama_runtime::Event::AssetRegistry( - Event::AssetUpdated { - asset_id: AssetIds::NativeAssetId(CurrencyId::Token(TokenSymbol::DOT)), - metadata: AssetMetadata { - name: b"New Token Name".to_vec(), - symbol: b"NTN".to_vec(), - decimals: 13, - minimal_balance: 2, - }, - }, - )); - - assert_eq!( - AssetMetadatas::::get(AssetIds::NativeAssetId(CurrencyId::Token( - TokenSymbol::DOT - ))), - Some(AssetMetadata { - name: b"New Token Name".to_vec(), - symbol: b"NTN".to_vec(), - decimals: 13, - minimal_balance: 2, - }) - ); - }); -} - -#[test] -fn register_token_metadata() { - ExtBuilder::default().build().execute_with(|| { - let metadata = AssetMetadata { - name: b"Bifrost Native Coin".to_vec(), - symbol: b"BNC".to_vec(), - decimals: 12, - minimal_balance: 0, - }; - - assert_ok!(AssetRegistry::register_token_metadata( - Origin::root(), - Box::new(metadata.clone()) - )); - - assert_eq!(CurrencyMetadatas::::get(CurrencyId::Token2(0)), Some(metadata.clone())) - }) -} - -#[test] -fn register_vtoken_metadata() { - ExtBuilder::default().build().execute_with(|| { - let metadata = AssetMetadata { - name: b"Bifrost Native Coin".to_vec(), - symbol: b"BNC".to_vec(), - decimals: 12, - minimal_balance: 0, - }; - let v_metadata = AssetMetadata { - name: b"Voucher BNC".to_vec(), - symbol: b"vBNC".to_vec(), - decimals: 12, - minimal_balance: 0, - }; - assert_noop!( - AssetRegistry::register_vtoken_metadata(Origin::root(), 1), - Error::::CurrencyIdNotExists - ); - - assert_ok!(AssetRegistry::register_token_metadata( - Origin::root(), - Box::new(metadata.clone()) - )); - - assert_ok!(AssetRegistry::register_vtoken_metadata(Origin::root(), 0)); - - assert_eq!( - CurrencyMetadatas::::get(CurrencyId::VToken2(0)), - Some(v_metadata.clone()) - ) - }) -} - -#[test] -fn register_vsbond_metadata() { - ExtBuilder::default().build().execute_with(|| { - let metadata = AssetMetadata { - name: b"KSM Native Token".to_vec(), - symbol: b"KSM".to_vec(), - decimals: 12, - minimal_balance: 0, - }; - let name = "vsBOND-KSM-2001-10-20".as_bytes().to_vec(); - let v_metadata = - AssetMetadata { name: name.clone(), symbol: name, decimals: 12, minimal_balance: 0 }; - assert_noop!( - AssetRegistry::register_vtoken_metadata(Origin::root(), 1), - Error::::CurrencyIdNotExists - ); - - assert_ok!(AssetRegistry::register_token_metadata( - Origin::root(), - Box::new(metadata.clone()) - )); - - assert_ok!(AssetRegistry::register_vsbond_metadata(Origin::root(), 0, 2001, 10, 20)); - - assert_eq!( - CurrencyMetadatas::::get(CurrencyId::VSBond2(0, 2001, 10, 20)), - Some(v_metadata.clone()) - ) - }) -} - -#[test] -fn register_multilocation() { - ExtBuilder::default().build().execute_with(|| { - let metadata = AssetMetadata { - name: b"Bifrost Native Coin".to_vec(), - symbol: b"BNC".to_vec(), - decimals: 12, - minimal_balance: 0, - }; - // v1 - let location = VersionedMultiLocation::V1(MultiLocation { - parents: 1, - interior: xcm::v1::Junctions::X1(xcm::v1::Junction::Parachain(2001)), - }); - let multi_location: MultiLocation = location.clone().try_into().unwrap(); - - assert_noop!( - AssetRegistry::register_multilocation( - Origin::root(), - CurrencyId::Token2(0), - Box::new(location.clone()), - 2000_000_000 - ), - Error::::CurrencyIdNotExists - ); - - assert_ok!(AssetRegistry::register_token_metadata( - Origin::root(), - Box::new(metadata.clone()) - )); - - assert_ok!(AssetRegistry::register_multilocation( - Origin::root(), - CurrencyId::Token2(0), - Box::new(location.clone()), - 2000_000_000 - )); - - assert_noop!( - AssetRegistry::register_multilocation( - Origin::root(), - CurrencyId::Token2(0), - Box::new(location.clone()), - 2000_000_000 - ), - Error::::CurrencyIdExisted - ); - - assert_eq!( - LocationToCurrencyIds::::get(multi_location.clone()), - Some(CurrencyId::Token2(0)) - ); - assert_eq!( - CurrencyIdToLocations::::get(CurrencyId::Token2(0)), - Some(multi_location.clone()) - ); - assert_eq!(CurrencyIdToWeights::::get(CurrencyId::Token2(0)), Some(2000_000_000)); - }) -} diff --git a/integration-tests/src/general_key.rs b/integration-tests/src/general_key.rs deleted file mode 100644 index 62b4557c78..0000000000 --- a/integration-tests/src/general_key.rs +++ /dev/null @@ -1,175 +0,0 @@ -// This file is part of Bifrost. - -// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#![allow(unused)] - -use crate::integration_tests::*; -use xcm::latest::prelude::*; - -/// Currency ID, it might be extended with more variants in the future. -const TEST_33: [u8; 33] = [1u8; 33]; - -#[test] -fn general_key_works() { - GeneralKey(CurrencyId::ForeignAsset(3).encode().try_into().unwrap()); - GeneralKey(CurrencyId::ForeignAsset(3).encode().try_into().unwrap()); - GeneralKey(CurrencyId::ForeignAsset(3).encode().try_into().unwrap()); - GeneralKey(CurrencyId::ForeignAsset(3).encode().try_into().unwrap()); - GeneralKey(CurrencyId::ForeignAsset(3).encode().try_into().unwrap()); - GeneralKey(CurrencyId::ForeignAsset(3).encode().try_into().unwrap()); - GeneralKey(CurrencyId::ForeignAsset(3).encode().try_into().unwrap()); - GeneralKey(CurrencyId::ForeignAsset(3).encode().try_into().unwrap()); - GeneralKey(CurrencyId::ForeignAsset(3).encode().try_into().unwrap()); - GeneralKey(CurrencyId::ForeignAsset(3).encode().try_into().unwrap()); - GeneralKey(CurrencyId::ForeignAsset(3).encode().try_into().unwrap()); - - GeneralKey( - CurrencyId::LPToken(TokenSymbol::ASG, 100, TokenSymbol::BNC, 100) - .encode() - .try_into() - .unwrap(), - ); - GeneralKey( - CurrencyId::LPToken(TokenSymbol::BNC, 100, TokenSymbol::ASG, 100) - .encode() - .try_into() - .unwrap(), - ); - GeneralKey( - CurrencyId::LPToken(TokenSymbol::KUSD, 100, TokenSymbol::ASG, 100) - .encode() - .try_into() - .unwrap(), - ); - GeneralKey( - CurrencyId::LPToken(TokenSymbol::DOT, 100, TokenSymbol::ASG, 100) - .encode() - .try_into() - .unwrap(), - ); - GeneralKey( - CurrencyId::LPToken(TokenSymbol::KSM, 100, TokenSymbol::ASG, 100) - .encode() - .try_into() - .unwrap(), - ); - GeneralKey( - CurrencyId::LPToken(TokenSymbol::ETH, 100, TokenSymbol::ASG, 100) - .encode() - .try_into() - .unwrap(), - ); - GeneralKey( - CurrencyId::LPToken(TokenSymbol::KAR, 100, TokenSymbol::ASG, 100) - .encode() - .try_into() - .unwrap(), - ); - GeneralKey( - CurrencyId::LPToken(TokenSymbol::ZLK, 100, TokenSymbol::ASG, 100) - .encode() - .try_into() - .unwrap(), - ); - GeneralKey( - CurrencyId::LPToken(TokenSymbol::PHA, 100, TokenSymbol::ASG, 100) - .encode() - .try_into() - .unwrap(), - ); - GeneralKey( - CurrencyId::LPToken(TokenSymbol::RMRK, 100, TokenSymbol::ASG, 100) - .encode() - .try_into() - .unwrap(), - ); - GeneralKey( - CurrencyId::LPToken(TokenSymbol::MOVR, 100, TokenSymbol::ASG, 100) - .encode() - .try_into() - .unwrap(), - ); - - GeneralKey(CurrencyId::VSBond(TokenSymbol::ASG, 2001, 1, 100).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSBond(TokenSymbol::BNC, 2001, 1, 100).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSBond(TokenSymbol::KUSD, 2001, 1, 100).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSBond(TokenSymbol::DOT, 2001, 1, 100).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSBond(TokenSymbol::KSM, 2001, 1, 100).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSBond(TokenSymbol::ETH, 2001, 1, 100).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSBond(TokenSymbol::KAR, 2001, 1, 100).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSBond(TokenSymbol::ZLK, 2001, 1, 100).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSBond(TokenSymbol::PHA, 2001, 1, 100).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSBond(TokenSymbol::RMRK, 2001, 1, 100).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSBond(TokenSymbol::MOVR, 2001, 1, 100).encode().try_into().unwrap()); - - GeneralKey(CurrencyId::VSToken(TokenSymbol::ASG).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::BNC).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::KUSD).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::DOT).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::KSM).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::ETH).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::KAR).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::ZLK).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::PHA).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::RMRK).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::MOVR).encode().try_into().unwrap()); - - GeneralKey(CurrencyId::VSToken(TokenSymbol::ASG).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::BNC).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::KUSD).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::DOT).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::KSM).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::ETH).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::KAR).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::ZLK).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::PHA).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::RMRK).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VSToken(TokenSymbol::MOVR).encode().try_into().unwrap()); - - GeneralKey(CurrencyId::VToken(TokenSymbol::ASG).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VToken(TokenSymbol::BNC).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VToken(TokenSymbol::KUSD).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VToken(TokenSymbol::DOT).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VToken(TokenSymbol::KSM).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VToken(TokenSymbol::ETH).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VToken(TokenSymbol::KAR).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VToken(TokenSymbol::ZLK).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VToken(TokenSymbol::PHA).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VToken(TokenSymbol::RMRK).encode().try_into().unwrap()); - GeneralKey(CurrencyId::VToken(TokenSymbol::MOVR).encode().try_into().unwrap()); - - GeneralKey(CurrencyId::Native(TokenSymbol::ASG).encode().try_into().unwrap()); - GeneralKey(CurrencyId::Native(TokenSymbol::BNC).encode().try_into().unwrap()); - GeneralKey(CurrencyId::Native(TokenSymbol::KUSD).encode().try_into().unwrap()); - GeneralKey(CurrencyId::Native(TokenSymbol::DOT).encode().try_into().unwrap()); - GeneralKey(CurrencyId::Native(TokenSymbol::KSM).encode().try_into().unwrap()); - GeneralKey(CurrencyId::Native(TokenSymbol::ETH).encode().try_into().unwrap()); - GeneralKey(CurrencyId::Native(TokenSymbol::KAR).encode().try_into().unwrap()); - GeneralKey(CurrencyId::Native(TokenSymbol::ZLK).encode().try_into().unwrap()); - GeneralKey(CurrencyId::Native(TokenSymbol::PHA).encode().try_into().unwrap()); - GeneralKey(CurrencyId::Native(TokenSymbol::RMRK).encode().try_into().unwrap()); - GeneralKey(CurrencyId::Native(TokenSymbol::MOVR).encode().try_into().unwrap()); - - GeneralKey(CurrencyId::Native(TokenSymbol::MOVR).encode().try_into().unwrap()); - - assert_eq!(CurrencyId::LPToken(TokenSymbol::ASG, 254, TokenSymbol::BNC, 100).encode().len(), 5); - assert_eq!(TEST_33.len(), 33) - - // 'called `Result::unwrap()` on an `Err` value: ()' - //GeneralKey(test_33.encode().try_into().unwrap()); -} diff --git a/integration-tests/src/kusama_cross_chain_transact.rs b/integration-tests/src/kusama_cross_chain_transact.rs deleted file mode 100644 index 74bdc914ca..0000000000 --- a/integration-tests/src/kusama_cross_chain_transact.rs +++ /dev/null @@ -1,57 +0,0 @@ -// This file is part of Bifrost. - -// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -use frame_support::assert_ok; -use xcm::latest::prelude::*; -use xcm_emulator::TestExt; - -use crate::{integration_tests::*, kusama_test_net::*}; - -#[test] -fn relaychain_transact_works() { - let remark = kusama_runtime::Call::System( - frame_system::Call::::remark_with_event { - remark: "Hello from Bifrost!".as_bytes().to_vec(), - }, - ); - - let asset: MultiAsset = - MultiAsset { id: Concrete(MultiLocation::here()), fun: Fungible(8000000000) }; - - let msg = Xcm(vec![ - WithdrawAsset(asset.clone().into()), - BuyExecution { fees: asset, weight_limit: WeightLimit::Limited(6000000000) }, - Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: 2000000000 as u64, - call: remark.encode().into(), - }, - ]); - - Bifrost::execute_with(|| { - assert_ok!(pallet_xcm::Pallet::::send_xcm(Here, Parent, msg)); - }); - - KusamaNet::execute_with(|| { - use kusama_runtime::{Event, System}; - assert!(System::events().iter().any(|r| matches!( - r.event, - Event::System(frame_system::Event::Remarked { sender: _, hash: _ }) - ))); - }); -} diff --git a/integration-tests/src/kusama_cross_chain_transfer.rs b/integration-tests/src/kusama_cross_chain_transfer.rs deleted file mode 100644 index f26b63c0e5..0000000000 --- a/integration-tests/src/kusama_cross_chain_transfer.rs +++ /dev/null @@ -1,141 +0,0 @@ -// This file is part of Bifrost. - -// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -//! Cross-chain transfer tests within Kusama network. -use bifrost_asset_registry::AssetMetadata; -use bifrost_kusama_runtime::AssetRegistry; -use bifrost_runtime_common::millicent; -use frame_support::assert_ok; -use node_primitives::{CurrencyId, TokenSymbol}; -use orml_traits::MultiCurrency; -use xcm::{latest::prelude::*, VersionedMultiAssets, VersionedMultiLocation}; -use xcm_emulator::TestExt; - -use crate::{integration_tests::*, kusama_test_net::*}; - -#[test] -fn transfer_from_relay_chain() { - register_asset(); - - KusamaNet::execute_with(|| { - assert_ok!(kusama_runtime::XcmPallet::reserve_transfer_assets( - kusama_runtime::Origin::signed(ALICE.into()), - Box::new(VersionedMultiLocation::V1(X1(Parachain(2001)).into())), - Box::new(VersionedMultiLocation::V1( - X1(Junction::AccountId32 { id: BOB, network: NetworkId::Any }).into() - )), - Box::new(VersionedMultiAssets::V1((Here, dollar(RelayCurrencyId::get())).into())), - 0, - )); - }); - - Bifrost::execute_with(|| { - assert_eq!( - Tokens::free_balance(RelayCurrencyId::get(), &AccountId::from(BOB)), - 999907304000 - ); - }); -} - -#[test] -fn transfer_to_relay_chain() { - Bifrost::execute_with(|| { - assert_ok!(XTokens::transfer( - Origin::signed(ALICE.into()), - RelayCurrencyId::get(), - dollar(RelayCurrencyId::get()), - Box::new(xcm::VersionedMultiLocation::V1(MultiLocation::new( - 1, - X1(Junction::AccountId32 { id: BOB, network: NetworkId::Any }) - ))), - 4_000_000_000 - )); - }); - - KusamaNet::execute_with(|| { - assert_eq!(kusama_runtime::Balances::free_balance(&AccountId::from(BOB)), 999_988_476_752); - }); -} - -#[test] -fn transfer_to_sibling() { - env_logger::init(); - - TestNet::reset(); - - fn bifrost_reserve_account() -> AccountId { - use sp_runtime::traits::AccountIdConversion; - polkadot_parachain::primitives::Sibling::from(2001).into_account_truncating() - } - - Bifrost::execute_with(|| { - assert_ok!(Tokens::deposit( - CurrencyId::Token(TokenSymbol::KAR), - &AccountId::from(ALICE), - 100_000_000_000_000 - )); - }); - - Sibling::execute_with(|| { - assert_ok!(Tokens::deposit( - CurrencyId::Token(TokenSymbol::KAR), - &bifrost_reserve_account(), - 100_000_000_000_000 - )); - }); - - Bifrost::execute_with(|| { - assert_ok!(XTokens::transfer( - Origin::signed(ALICE.into()), - CurrencyId::Token(TokenSymbol::KAR), - 10_000_000_000_000, - Box::new( - MultiLocation::new( - 1, - X2( - Parachain(2000), - Junction::AccountId32 { network: NetworkId::Any, id: BOB.into() } - ) - ) - .into() - ), - 1_000_000_000, - )); - - assert_eq!( - Tokens::free_balance(CurrencyId::Token(TokenSymbol::KAR), &AccountId::from(ALICE)), - 90_000_000_000_000 - ); - }); -} - -fn register_asset() { - Bifrost::execute_with(|| { - let currency_id = CurrencyId::Token(TokenSymbol::KSM); - assert_ok!(AssetRegistry::do_register_native_asset( - currency_id, - &MultiLocation::parent(), - &AssetMetadata { - name: currency_id.name().map(|s| s.as_bytes().to_vec()).unwrap_or_default(), - symbol: currency_id.symbol().map(|s| s.as_bytes().to_vec()).unwrap_or_default(), - decimals: currency_id.decimals().unwrap_or_default(), - minimal_balance: 10 * millicent(currency_id), - } - )); - }); -} diff --git a/integration-tests/src/salp.rs b/integration-tests/src/salp.rs deleted file mode 100644 index ad20a08d66..0000000000 --- a/integration-tests/src/salp.rs +++ /dev/null @@ -1,392 +0,0 @@ -// This file is part of Bifrost. - -// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -use crate::{integration_tests::*, kusama_test_net::*}; -use bifrost_kusama_runtime::{LeasePeriod, MinContribution}; -use bifrost_salp::{Error, FundStatus}; -use frame_support::{assert_noop, assert_ok}; -use frame_system::RawOrigin; -use xcm_emulator::TestExt; - -#[test] -fn create_fund_should_work() { - SalpTest::execute_with(|| { - assert_ok!(Salp::create( - RawOrigin::Root.into(), - 3_000, - 100_000_000_000, - 1, - SlotLength::get() - )); - assert_ok!(Salp::funds(3_000).ok_or(())); - assert_eq!(Salp::current_trie_index(), 1); - }); -} - -#[test] -fn edit_fund_should_work() { - SalpTest::execute_with(|| { - assert_ok!(Salp::create( - RawOrigin::Root.into(), - 3_000, - 100_000_000_000, - 1, - SlotLength::get() - )); - - assert_ok!(Salp::edit( - RawOrigin::Root.into(), - 3_000, - 100_000_000_000, - 150, - 2, - SlotLength::get() + 1, - Some(FundStatus::Ongoing) - )); - }); -} - -#[test] -fn contribute_should_work() { - SalpTest::execute_with(|| { - assert_ok!(Salp::create( - RawOrigin::Root.into(), - 3_000, - 1000_000_000_000, - 1, - SlotLength::get() - )); - assert_ok!(Salp::contribute(Origin::signed(AccountId::new(BOB)), 3_000, 100_000_000_000)); - assert!(Salp::funds(3_000).is_some()); - }); -} - -#[test] -fn double_contribute_should_work() { - SalpTest::execute_with(|| { - assert_ok!(Salp::create( - RawOrigin::Root.into(), - 3_000, - 1000_000_000_000, - 1, - SlotLength::get() - )); - assert_ok!(Salp::contribute(Origin::signed(AccountId::new(BOB)), 3_000, 100_000_000_000)); - assert!(Salp::funds(3_000).is_some()); - - assert_ok!(Salp::confirm_contribute( - Origin::signed(AccountId::new(ALICE)), - AccountId::new(BOB), - 3_000, - true, - CONTRIBUTON_INDEX - )); - - assert_noop!( - Salp::contribute(Origin::signed(AccountId::new(BOB)), 3_000, 1000_000_000_001), - Error::::CapExceeded - ); - - assert_noop!( - Salp::contribute( - Origin::signed(AccountId::new(BOB)), - 3_000, - MinContribution::get() - 1 - ), - Error::::ContributionTooSmall - ); - - assert_ok!(Salp::contribute(Origin::signed(AccountId::new(BOB)), 3_000, 100_000_000_000)); - }); -} - -#[test] -fn withdraw_should_work() { - SalpTest::execute_with(|| { - assert_ok!(Salp::create( - RawOrigin::Root.into(), - 3_000, - 1000_000_000_000, - 1, - SlotLength::get() - )); - assert_ok!(Salp::contribute(Origin::signed(AccountId::new(BOB)), 3_000, 100_000_000_000)); - assert_ok!(Salp::confirm_contribute( - Origin::signed(AccountId::new(ALICE)), - AccountId::new(BOB), - 3_000, - true, - CONTRIBUTON_INDEX - )); - assert_ok!(Salp::fund_success(RawOrigin::Root.into(), 3_000)); - assert_ok!(Salp::fund_retire(RawOrigin::Root.into(), 3_000)); - assert_ok!(Salp::withdraw(RawOrigin::Root.into(), 3_000)); - }); -} - -#[test] -fn refund_should_work() { - SalpTest::execute_with(|| { - assert_ok!(Salp::create( - RawOrigin::Root.into(), - 3_000, - 1000_000_000_000, - 1, - SlotLength::get() - )); - assert_ok!(Salp::contribute(Origin::signed(AccountId::new(BOB)), 3_000, 100_000_000_000)); - assert_ok!(Salp::confirm_contribute( - Origin::signed(AccountId::new(ALICE)), - AccountId::new(BOB), - 3_000, - true, - CONTRIBUTON_INDEX - )); - assert_ok!(Salp::fund_fail(RawOrigin::Root.into(), 3_000)); - assert_ok!(Salp::withdraw(RawOrigin::Root.into(), 3_000)); - assert_ok!(Salp::refund( - Origin::signed(AccountId::new(BOB)), - 3_000, - 1, - SlotLength::get(), - 100_000_000_000 - )); - - assert_noop!( - Salp::refund(Origin::signed(AccountId::new(BOB)), 3_000, 1, SlotLength::get(), 100), - Error::::NotEnoughBalanceInFund - ); - }); -} - -#[test] -fn dissolve_should_work() { - SalpTest::execute_with(|| { - assert_ok!(Salp::create( - RawOrigin::Root.into(), - 3_000, - 1000_000_000_000, - 1, - SlotLength::get() - )); - assert_ok!(Salp::contribute(Origin::signed(AccountId::new(BOB)), 3_000, 100_000_000_000)); - assert_ok!(Salp::confirm_contribute( - Origin::signed(AccountId::new(ALICE)), - AccountId::new(BOB), - 3_000, - true, - CONTRIBUTON_INDEX - )); - assert_ok!(Salp::fund_success(RawOrigin::Root.into(), 3_000)); - assert_ok!(Salp::fund_retire(RawOrigin::Root.into(), 3_000)); - assert_ok!(Salp::withdraw(RawOrigin::Root.into(), 3_000)); - assert_ok!(Salp::fund_end(RawOrigin::Root.into(), 3_000)); - - assert_ok!(Salp::dissolve(RawOrigin::Root.into(), 3_000)); - - assert!(Salp::funds(3_000).is_none()); - }); -} - -#[test] -fn redeem_should_work() { - SalpTest::execute_with(|| { - assert_ok!(Salp::create( - RawOrigin::Root.into(), - 3_000, - 1000_000_000_000, - 1, - SlotLength::get() - )); - assert_ok!(Salp::contribute(Origin::signed(AccountId::new(BOB)), 3_000, 100_000_000_000)); - assert_ok!(Salp::confirm_contribute( - Origin::signed(AccountId::new(ALICE)), - AccountId::new(BOB), - 3_000, - true, - CONTRIBUTON_INDEX - )); - - assert_ok!(Salp::fund_success(RawOrigin::Root.into(), 3_000)); - assert_ok!(Salp::unlock(Origin::signed(AccountId::new(ALICE)), AccountId::new(BOB), 3_000)); - - // Mock the BlockNumber - let block_begin_redeem = (SlotLength::get() + 1) * LeasePeriod::get(); - System::set_block_number(block_begin_redeem); - - assert_ok!(Salp::fund_retire(RawOrigin::Root.into(), 3_000)); - assert_ok!(Salp::withdraw(RawOrigin::Root.into(), 3_000)); - let vs_token = ::CurrencyIdConversion::convert_to_vstoken( - RelayCurrencyId::get(), - ) - .unwrap(); - let vs_bond = ::CurrencyIdConversion::convert_to_vsbond( - RelayCurrencyId::get(), - 3_000, - 1, - SlotLength::get(), - ) - .unwrap(); - - assert_ok!(>::transfer( - vs_token, - &AccountId::new(BOB), - &AccountId::new(CATHI), - 500_000_000 - )); - assert_ok!(>::transfer( - vs_bond, - &AccountId::new(BOB), - &AccountId::new(CATHI), - 500_000_000 - )); - - assert_ok!(Salp::redeem(Origin::signed(AccountId::new(BOB)), 3_000, 500_000_000)); - assert_ok!(Salp::redeem(Origin::signed(AccountId::new(CATHI)), 3_000, 500_000_000)); - }); -} - -#[test] -fn redeem_with_speical_vsbond_should_work() { - SalpTest::execute_with(|| { - assert_ok!(Salp::create(RawOrigin::Root.into(), 2001, 1000_000_000_000, 13, 20)); - assert_ok!(Salp::contribute(Origin::signed(AccountId::new(BOB)), 2001, 100_000_000_000)); - assert_ok!(Salp::confirm_contribute( - Origin::signed(AccountId::new(ALICE)), - AccountId::new(BOB), - 2001, - true, - CONTRIBUTON_INDEX - )); - - assert_ok!(Salp::fund_success(RawOrigin::Root.into(), 2001)); - assert_ok!(Salp::unlock(Origin::signed(AccountId::new(ALICE)), AccountId::new(BOB), 2001)); - - // Mock the BlockNumber - let block_begin_redeem = (SlotLength::get() + 1) * LeasePeriod::get(); - System::set_block_number(block_begin_redeem); - - assert_ok!(Salp::fund_retire(RawOrigin::Root.into(), 2001)); - assert_ok!(Salp::withdraw(RawOrigin::Root.into(), 2001)); - - let vs_token = ::CurrencyIdConversion::convert_to_vstoken( - RelayCurrencyId::get(), - ) - .unwrap(); - let vs_bond = ::CurrencyIdConversion::convert_to_vsbond( - RelayCurrencyId::get(), - 2001, - 13, - 20, - ) - .unwrap(); - - assert_ok!(>::transfer( - vs_token, - &AccountId::new(BOB), - &AccountId::new(CATHI), - 500_000_000 - )); - assert_ok!(>::transfer( - vs_bond, - &AccountId::new(BOB), - &AccountId::new(CATHI), - 500_000_000 - )); - assert_ok!(Salp::redeem(Origin::signed(AccountId::new(BOB)), 2001, 500_000_000)); - assert_ok!(Salp::redeem(Origin::signed(AccountId::new(CATHI)), 2001, 500_000_000)); - }); -} - -#[test] -fn batch_unlock_should_work() { - SalpTest::execute_with(|| { - assert_ok!(Salp::create( - RawOrigin::Root.into(), - 3_000, - 1000_000_000_000, - 1, - SlotLength::get() - )); - assert_ok!(Salp::contribute(Origin::signed(AccountId::new(BOB)), 3_000, 100_000_000_000)); - assert_ok!(Salp::confirm_contribute( - Origin::signed(AccountId::new(ALICE)), - AccountId::new(BOB), - 3_000, - true, - CONTRIBUTON_INDEX - )); - - assert_ok!(Salp::fund_success(RawOrigin::Root.into(), 3_000)); - assert_ok!(Salp::batch_unlock(Origin::signed(AccountId::new(ALICE)), 3_000)); - }) -} - -#[test] -fn unlock_when_fund_ongoing_should_work() { - SalpTest::execute_with(|| { - assert_ok!(Salp::create( - RawOrigin::Root.into(), - 3_000, - 1000_000_000_000, - 1, - SlotLength::get() - )); - assert_ok!(Salp::contribute(Origin::signed(AccountId::new(BOB)), 3_000, 100_000_000_000)); - assert_ok!(Salp::confirm_contribute( - Origin::signed(AccountId::new(ALICE)), - AccountId::new(BOB), - 3_000, - true, - CONTRIBUTON_INDEX - )); - assert_ok!(Salp::unlock(Origin::signed(AccountId::new(BOB)), AccountId::new(BOB), 3_000)); - }); -} - -#[test] -fn set_confirmor_should_work() { - SalpTest::execute_with(|| { - assert_ok!(Salp::create( - RawOrigin::Root.into(), - 3_000, - 1000_000_000_000, - 1, - SlotLength::get() - )); - assert_ok!(Salp::contribute(Origin::signed(AccountId::new(BOB)), 3_000, 100_000_000_000)); - assert_noop!( - Salp::confirm_contribute( - Origin::signed(AccountId::new(BOB)), - AccountId::new(BOB), - 3_000, - true, - CONTRIBUTON_INDEX - ), - DispatchError::BadOrigin, - ); - assert_ok!(Salp::set_multisig_confirm_account(RawOrigin::Root.into(), AccountId::new(BOB))); - assert_ok!(Salp::confirm_contribute( - Origin::signed(AccountId::new(BOB)), - AccountId::new(BOB), - 3_000, - true, - CONTRIBUTON_INDEX - )); - }); -} diff --git a/integration-tests/src/slp.rs b/integration-tests/src/slp.rs deleted file mode 100644 index 0a7767981a..0000000000 --- a/integration-tests/src/slp.rs +++ /dev/null @@ -1,2205 +0,0 @@ -// This file is part of Bifrost. - -// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -//! Cross-chain transfer tests within Kusama network. -#![cfg(test)] - -use bifrost_polkadot_runtime::PolkadotXcm; -use bifrost_slp::{ - primitives::{ - SubstrateLedgerUpdateEntry, SubstrateLedgerUpdateOperation, - SubstrateValidatorsByDelegatorUpdateEntry, UnlockChunk, - }, - Delays, Ledger, LedgerUpdateEntry, MinimumsMaximums, SubstrateLedger, - ValidatorsByDelegatorUpdateEntry, XcmOperation, -}; -use cumulus_primitives_core::relay_chain::HashT; -use frame_support::{assert_ok, BoundedVec}; -use node_primitives::TimeUnit; -use orml_traits::MultiCurrency; -use pallet_staking::{Nominations, StakingLedger}; -use pallet_xcm::QueryStatus; -use xcm::{latest::prelude::*, VersionedMultiAssets, VersionedMultiLocation}; -use xcm_emulator::TestExt; - -use crate::{integration_tests::*, kusama_test_net::*}; - -/// **************************************************** -/// ********* Preparation section ******************** -/// **************************************************** - -// parachain 2001 subaccount index 0 -pub fn subaccount_0() -> AccountId { - // 5E78xTBiaN3nAGYtcNnqTJQJqYAkSDGggKqaDfpNsKyPpbcb - let subaccount_0: AccountId = - hex_literal::hex!["5a53736d8e96f1c007cf0d630acf5209b20611617af23ce924c8e25328eb5d28"] - .into(); - - subaccount_0 -} - -pub fn para_account_2001() -> AccountId { - // 5Ec4AhPV91i9yNuiWuNunPf6AQCYDhFTTA4G5QCbtqYApH9E - let para_account_2001: AccountId = - hex_literal::hex!["70617261d1070000000000000000000000000000000000000000000000000000"] - .into(); - - para_account_2001 -} - -// Preparation: register sub-account index 0. -fn register_subaccount_index_0() { - let subaccount_0 = subaccount_0(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = Slp::account_id_to_account_32(subaccount_0).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Set OngoingTimeUnitUpdateInterval as 1/3 Era(1800 blocks per Era, 12 seconds per - // block) - assert_ok!(Slp::set_ongoing_time_unit_update_interval( - Origin::root(), - RelayCurrencyId::get(), - Some(600) - )); - - System::set_block_number(600); - - // Initialize ongoing timeunit as 0. - assert_ok!(Slp::update_ongoing_time_unit( - Origin::root(), - RelayCurrencyId::get(), - TimeUnit::Era(0) - )); - - // Initialize currency delays. - let delay = - Delays { unlock_delay: TimeUnit::Era(10), leave_delegators_delay: Default::default() }; - assert_ok!(Slp::set_currency_delays(Origin::root(), RelayCurrencyId::get(), Some(delay))); - - let mins_and_maxs = MinimumsMaximums { - delegator_bonded_minimum: 100_000_000_000, - bond_extra_minimum: 0, - unbond_minimum: 0, - rebond_minimum: 0, - unbond_record_maximum: 32, - validators_back_maximum: 36, - delegator_active_staking_maximum: 200_000_000_000_000, - validators_reward_maximum: 0, - delegation_amount_minimum: 0, - delegators_maximum: 100, - validators_maximum: 300, - }; - - // Set minimums and maximums - assert_ok!(Slp::set_minimums_and_maximums( - Origin::root(), - RelayCurrencyId::get(), - Some(mins_and_maxs) - )); - - // First to setup index-multilocation relationship of subaccount_0 - assert_ok!(Slp::add_delegator( - Origin::root(), - RelayCurrencyId::get(), - 0u16, - Box::new(subaccount_0_location.clone()), - )); - - // Register Operation weight and fee - assert_ok!(Slp::set_xcm_dest_weight_and_fee( - Origin::root(), - RelayCurrencyId::get(), - XcmOperation::TransferTo, - Some((20_000_000_000, 10_000_000_000)), - )); - - assert_ok!(Slp::set_xcm_dest_weight_and_fee( - Origin::root(), - RelayCurrencyId::get(), - XcmOperation::Bond, - Some((20_000_000_000, 10_000_000_000)), - )); - - assert_ok!(Slp::set_xcm_dest_weight_and_fee( - Origin::root(), - RelayCurrencyId::get(), - XcmOperation::BondExtra, - Some((20_000_000_000, 10_000_000_000)), - )); - - assert_ok!(Slp::set_xcm_dest_weight_and_fee( - Origin::root(), - RelayCurrencyId::get(), - XcmOperation::Unbond, - Some((20_000_000_000, 10_000_000_000)), - )); - - assert_ok!(Slp::set_xcm_dest_weight_and_fee( - Origin::root(), - RelayCurrencyId::get(), - XcmOperation::Rebond, - Some((20_000_000_000, 10_000_000_000)), - )); - - assert_ok!(Slp::set_xcm_dest_weight_and_fee( - Origin::root(), - RelayCurrencyId::get(), - XcmOperation::Delegate, - Some((20_000_000_000, 10_000_000_000)), - )); - - assert_ok!(Slp::set_xcm_dest_weight_and_fee( - Origin::root(), - RelayCurrencyId::get(), - XcmOperation::Payout, - Some((20_000_000_000, 10_000_000_000)), - )); - - assert_ok!(Slp::set_xcm_dest_weight_and_fee( - Origin::root(), - RelayCurrencyId::get(), - XcmOperation::Liquidize, - Some((20_000_000_000, 10_000_000_000)), - )); - - assert_ok!(Slp::set_xcm_dest_weight_and_fee( - Origin::root(), - RelayCurrencyId::get(), - XcmOperation::Chill, - Some((20_000_000_000, 10_000_000_000)), - )); - - assert_ok!(Slp::set_xcm_dest_weight_and_fee( - Origin::root(), - RelayCurrencyId::get(), - XcmOperation::TransferBack, - Some((20_000_000_000, 10_000_000_000)), - )); - }); -} - -fn register_delegator_ledger() { - let subaccount_0 = subaccount_0(); - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = Slp::account_id_to_account_32(subaccount_0).unwrap(); - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - let sb_ledger = SubstrateLedger { - account: subaccount_0_location.clone(), - total: dollar(RelayCurrencyId::get()), - active: dollar(RelayCurrencyId::get()), - unlocking: vec![], - }; - let ledger = Ledger::Substrate(sb_ledger); - - // Set delegator ledger - assert_ok!(Slp::set_delegator_ledger( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - Box::new(Some(ledger)) - )); - }); -} - -#[test] -fn register_validators() { - // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz - let validator_0: AccountId = - hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] - .into(); - - // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 - let validator_1: AccountId = - hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] - .into(); - - Bifrost::execute_with(|| { - let mut valis = vec![]; - - let validator_0_32: [u8; 32] = Slp::account_id_to_account_32(validator_0).unwrap(); - let validator_0_location: MultiLocation = - Slp::account_32_to_parent_location(validator_0_32).unwrap(); - let multi_hash_0 = - ::Hashing::hash(&validator_0_location.encode()); - - let mins_and_maxs = MinimumsMaximums { - delegator_bonded_minimum: 100_000_000_000, - bond_extra_minimum: 0, - unbond_minimum: 0, - rebond_minimum: 0, - unbond_record_maximum: 32, - validators_back_maximum: 36, - delegator_active_staking_maximum: 200_000_000_000_000, - validators_reward_maximum: 0, - delegation_amount_minimum: 0, - delegators_maximum: 100, - validators_maximum: 300, - }; - - // Set minimums and maximums - assert_ok!(Slp::set_minimums_and_maximums( - Origin::root(), - RelayCurrencyId::get(), - Some(mins_and_maxs) - )); - - // Set delegator ledger - assert_ok!(Slp::add_validator( - Origin::root(), - RelayCurrencyId::get(), - Box::new(validator_0_location.clone()), - )); - - let validator_1_32: [u8; 32] = Slp::account_id_to_account_32(validator_1).unwrap(); - let validator_1_location: MultiLocation = - Slp::account_32_to_parent_location(validator_1_32).unwrap(); - let multi_hash_1 = - ::Hashing::hash(&validator_1_location.encode()); - - // The storage is reordered by hash. So we need to adjust the push order here. - valis.push((validator_1_location.clone(), multi_hash_1)); - valis.push((validator_0_location.clone(), multi_hash_0)); - - // Set delegator ledger - assert_ok!(Slp::add_validator( - Origin::root(), - RelayCurrencyId::get(), - Box::new(validator_1_location), - )); - - assert_eq!(Slp::get_validators(RelayCurrencyId::get()), Some(valis)); - }); -} - -// Preparation: transfer 1 KSM from Alice in Kusama to Bob in Bifrost. -// Bob has a balance of -#[test] -fn transfer_2_ksm_to_entrance_account_in_bifrost() { - let para_account_2001 = para_account_2001(); - - let entrance_account_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f76746b696e0000000000000000000000000000000000000000"] - .into(); - - // Cross-chain transfer some KSM to Bob account in Bifrost - KusamaNet::execute_with(|| { - assert_ok!(kusama_runtime::XcmPallet::reserve_transfer_assets( - kusama_runtime::Origin::signed(ALICE.into()), - Box::new(VersionedMultiLocation::V1(X1(Parachain(2001)).into())), - Box::new(VersionedMultiLocation::V1( - X1(Junction::AccountId32 { id: entrance_account_32, network: NetworkId::Any }) - .into() - )), - Box::new(VersionedMultiAssets::V1((Here, 2 * dollar(RelayCurrencyId::get())).into())), - 0, - )); - - // predefined 2 dollars + 2 dollar from cross-chain transfer = 3 dollars - assert_eq!( - kusama_runtime::Balances::free_balance(¶_account_2001.clone()), - 4 * dollar(RelayCurrencyId::get()) - ); - }); - - Bifrost::execute_with(|| { - // entrance_account get the cross-transferred 2 dollar KSM minus transaction fee. - assert_eq!( - Tokens::free_balance(RelayCurrencyId::get(), &entrance_account_32.into()), - 1999907304000 - ); - }); -} - -// Preparation: transfer 1 KSM from Alice in Kusama to Bob in Bifrost. -// Bob has a balance of -#[test] -fn transfer_2_ksm_to_subaccount_in_kusama() { - let subaccount_0 = subaccount_0(); - - KusamaNet::execute_with(|| { - assert_ok!(kusama_runtime::Balances::transfer( - kusama_runtime::Origin::signed(ALICE.into()), - MultiAddress::Id(subaccount_0.clone()), - 2 * dollar(RelayCurrencyId::get()) - )); - - assert_eq!( - kusama_runtime::Balances::free_balance(&subaccount_0.clone()), - 2 * dollar(RelayCurrencyId::get()) - ); - }); -} - -#[test] -fn locally_bond_subaccount_0_1ksm_in_kusama() { - transfer_2_ksm_to_subaccount_in_kusama(); - let subaccount_0 = subaccount_0(); - - KusamaNet::execute_with(|| { - assert_ok!(kusama_runtime::Staking::bond( - kusama_runtime::Origin::signed(subaccount_0.clone()), - MultiAddress::Id(subaccount_0.clone()), - dollar(RelayCurrencyId::get()), - pallet_staking::RewardDestination::::Staked, - )); - - assert_eq!( - kusama_runtime::Staking::ledger(&subaccount_0), - Some(StakingLedger { - stash: subaccount_0.clone(), - total: dollar(RelayCurrencyId::get()), - active: dollar(RelayCurrencyId::get()), - unlocking: BoundedVec::try_from(vec![]).unwrap(), - claimed_rewards: vec![], - }) - ); - }); -} - -/// **************************************************** -/// ********* Test section ******************** -/// **************************************************** - -#[test] -fn transfer_to_works() { - register_subaccount_index_0(); - transfer_2_ksm_to_entrance_account_in_bifrost(); - transfer_2_ksm_to_subaccount_in_kusama(); - let subaccount_0 = subaccount_0(); - let para_account_2001 = para_account_2001(); - - let entrance_account: AccountId = - hex_literal::hex!["6d6f646c62662f76746b696e0000000000000000000000000000000000000000"] - .into(); - - let entrance_account_32 = Slp::account_id_to_account_32(entrance_account.clone()).unwrap(); - let entrance_account_location: MultiLocation = - Slp::account_32_to_local_location(entrance_account_32).unwrap(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // We use transfer_to to transfer some KSM to subaccount_0 - assert_ok!(Slp::transfer_to( - Origin::root(), - RelayCurrencyId::get(), - Box::new(entrance_account_location), - Box::new(subaccount_0_location), - dollar(RelayCurrencyId::get()), - )); - }); - - KusamaNet::execute_with(|| { - assert_eq!( - kusama_runtime::Balances::free_balance(¶_account_2001.clone()), - 3 * dollar(RelayCurrencyId::get()) - ); - - // Why not the transferred amount reach the sub-account? - assert_eq!(kusama_runtime::Balances::free_balance(&subaccount_0.clone()), 2999988476752); - }); -} - -#[test] -fn bond_works() { - register_subaccount_index_0(); - transfer_2_ksm_to_subaccount_in_kusama(); - let subaccount_0 = subaccount_0(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Bond 1 ksm for sub-account index 0 - assert_ok!(Slp::bond( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location), - dollar(RelayCurrencyId::get()), - None - )); - }); - - KusamaNet::execute_with(|| { - assert_eq!( - kusama_runtime::Staking::ledger(&subaccount_0), - Some(StakingLedger { - stash: subaccount_0.clone(), - total: dollar(RelayCurrencyId::get()), - active: dollar(RelayCurrencyId::get()), - unlocking: BoundedVec::try_from(vec![]).unwrap(), - claimed_rewards: vec![], - }) - ); - - assert!(kusama_runtime::System::events().iter().any(|r| matches!( - r.event, - kusama_runtime::Event::System(frame_system::Event::Remarked { sender: _, hash: _ }) - ))); - }); -} - -#[test] -fn bond_extra_works() { - // bond 1 ksm for sub-account index 0 - locally_bond_subaccount_0_1ksm_in_kusama(); - register_subaccount_index_0(); - register_delegator_ledger(); - let subaccount_0 = subaccount_0(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Bond_extra 1 ksm for sub-account index 0 - assert_ok!(Slp::bond_extra( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location), - None, - dollar(RelayCurrencyId::get()), - )); - }); - - // So the bonded amount should be 2 ksm - KusamaNet::execute_with(|| { - assert_eq!( - kusama_runtime::Staking::ledger(&subaccount_0), - Some(StakingLedger { - stash: subaccount_0.clone(), - total: 2 * dollar(RelayCurrencyId::get()), - active: 2 * dollar(RelayCurrencyId::get()), - unlocking: BoundedVec::try_from(vec![]).unwrap(), - claimed_rewards: vec![], - }) - ); - }); -} - -#[test] -fn unbond_works() { - // bond 1 ksm for sub-account index 0 - locally_bond_subaccount_0_1ksm_in_kusama(); - register_subaccount_index_0(); - register_delegator_ledger(); - let subaccount_0 = subaccount_0(); - - KusamaNet::execute_with(|| { - kusama_runtime::Staking::trigger_new_era(0, vec![]); - }); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Unbond 0.5 ksm, 0.5 ksm left. - assert_ok!(Slp::unbond( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location), - None, - 500_000_000_000, - )); - }); - - // Can be uncommented to check if the result is correct. - // Due to the reason of private fields for struct UnlockChunk, - // it is not able to construct an instance of UnlockChunk directly. - // // So the bonded amount should be 2 ksm - // KusamaNet::execute_with(|| { - // assert_eq!( - // kusama_runtime::Staking::ledger(&subaccount_0), - // Some(StakingLedger { - // stash: subaccount_0.clone(), - // total: dollar(RelayCurrencyId::get()), - // active: 500_000_000_000, - // unlocking: vec![UnlockChunk { value: 500000000000, era: 28 }], - // claimed_rewards: vec![], - // }) - // ); - // }); -} - -#[test] -fn unbond_all_works() { - // bond 1 ksm for sub-account index 0 - locally_bond_subaccount_0_1ksm_in_kusama(); - register_subaccount_index_0(); - register_delegator_ledger(); - let subaccount_0 = subaccount_0(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Unbond the only bonded 1 ksm. - assert_ok!(Slp::unbond_all( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location), - )); - }); - - // Can be uncommented to check if the result is correct. - // Due to the reason of private fields for struct UnlockChunk, - // it is not able to construct an instance of UnlockChunk directly. - // KusamaNet::execute_with(|| { - // assert_eq!( - // kusama_runtime::Staking::ledger(&subaccount_0), - // Some(StakingLedger { - // stash: subaccount_0.clone(), - // total: dollar(RelayCurrencyId::get()), - // active: 0, - // unlocking: vec![UnlockChunk { value: 1000000000000, era: 28 }], - // claimed_rewards: vec![], - // }) - // ); - // }); -} - -#[test] -fn rebond_works() { - // bond 1 ksm for sub-account index 0 - locally_bond_subaccount_0_1ksm_in_kusama(); - register_subaccount_index_0(); - register_delegator_ledger(); - let subaccount_0 = subaccount_0(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Unbond 0.5 ksm, 0.5 ksm left. - assert_ok!(Slp::unbond( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - None, - 500_000_000_000, - )); - - // Update Bifrost local ledger. This should be done by backend services. - let chunk = UnlockChunk { value: 500_000_000_000, unlock_time: TimeUnit::Era(8) }; - let sb_ledger = SubstrateLedger { - account: subaccount_0_location.clone(), - total: dollar(RelayCurrencyId::get()), - active: 500_000_000_000, - unlocking: vec![chunk], - }; - let ledger = Ledger::Substrate(sb_ledger); - - assert_ok!(Slp::set_delegator_ledger( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - Box::new(Some(ledger)) - )); - - // rebond 0.5 ksm. - assert_ok!(Slp::rebond( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location), - None, - Some(500_000_000_000), - )); - }); - - // So the bonded amount should be 1 ksm - KusamaNet::execute_with(|| { - assert_eq!( - kusama_runtime::Staking::ledger(&subaccount_0), - Some(StakingLedger { - stash: subaccount_0.clone(), - total: dollar(RelayCurrencyId::get()), - active: dollar(RelayCurrencyId::get()), - unlocking: BoundedVec::try_from(vec![]).unwrap(), - claimed_rewards: vec![], - }) - ); - }); -} - -#[test] -fn delegate_works() { - // bond 1 ksm for sub-account index 0 - locally_bond_subaccount_0_1ksm_in_kusama(); - register_subaccount_index_0(); - register_validators(); - register_delegator_ledger(); - let subaccount_0 = subaccount_0(); - - // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz - let validator_0: AccountId = - hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] - .into(); - - // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 - let validator_1: AccountId = - hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] - .into(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - let mut targets = vec![]; - - let validator_0_32: [u8; 32] = Slp::account_id_to_account_32(validator_0.clone()).unwrap(); - let validator_0_location: MultiLocation = - Slp::account_32_to_parent_location(validator_0_32).unwrap(); - targets.push(validator_0_location.clone()); - - let validator_1_32: [u8; 32] = Slp::account_id_to_account_32(validator_1.clone()).unwrap(); - let validator_1_location: MultiLocation = - Slp::account_32_to_parent_location(validator_1_32).unwrap(); - targets.push(validator_1_location.clone()); - - // delegate - assert_ok!(Slp::delegate( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - targets.clone(), - )); - - assert_ok!(Slp::set_validators_by_delegator( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - targets, - )); - }); - - KusamaNet::execute_with(|| { - assert_eq!( - kusama_runtime::Staking::nominators(&subaccount_0), - Some(Nominations { - targets: BoundedVec::try_from(vec![validator_1, validator_0]).unwrap(), - submitted_in: 0, - suppressed: false - },) - ); - }); -} - -#[test] -fn undelegate_works() { - delegate_works(); - - let subaccount_0 = subaccount_0(); - - // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz - let validator_0: AccountId = - hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] - .into(); - - // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 - let validator_1: AccountId = - hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] - .into(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - let mut targets = vec![]; - - let validator_0_32: [u8; 32] = Slp::account_id_to_account_32(validator_0.clone()).unwrap(); - let validator_0_location: MultiLocation = - Slp::account_32_to_parent_location(validator_0_32).unwrap(); - targets.push(validator_0_location.clone()); - - // Undelegate validator 0. Only validator 1 left. - assert_ok!(Slp::undelegate( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location), - targets.clone(), - )); - }); - - KusamaNet::execute_with(|| { - assert_eq!( - kusama_runtime::Staking::nominators(&subaccount_0), - Some(Nominations { - targets: BoundedVec::try_from(vec![validator_1]).unwrap(), - submitted_in: 0, - suppressed: false - },) - ); - }); -} - -#[test] -fn redelegate_works() { - undelegate_works(); - - let subaccount_0 = subaccount_0(); - - // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz - let validator_0: AccountId = - hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] - .into(); - - // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 - let validator_1: AccountId = - hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] - .into(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - let mut targets = vec![]; - - let validator_0_32: [u8; 32] = Slp::account_id_to_account_32(validator_0.clone()).unwrap(); - let validator_0_location: MultiLocation = - Slp::account_32_to_parent_location(validator_0_32).unwrap(); - - let validator_1_32: [u8; 32] = Slp::account_id_to_account_32(validator_1.clone()).unwrap(); - let validator_1_location: MultiLocation = - Slp::account_32_to_parent_location(validator_1_32).unwrap(); - - targets.push(validator_1_location.clone()); - targets.push(validator_0_location.clone()); - - // Redelegate to a set of validator_0 and validator_1. - assert_ok!(Slp::redelegate( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location), - Some(targets.clone()), - )); - }); - - KusamaNet::execute_with(|| { - assert_eq!( - kusama_runtime::Staking::nominators(&subaccount_0), - Some(Nominations { - targets: BoundedVec::try_from(vec![validator_1, validator_0]).unwrap(), - submitted_in: 0, - suppressed: false - },) - ); - }); -} - -#[test] -fn payout_works() { - register_subaccount_index_0(); - transfer_2_ksm_to_subaccount_in_kusama(); - let subaccount_0 = subaccount_0(); - - // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz - let validator_0: AccountId = - hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] - .into(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - let validator_0_32: [u8; 32] = Slp::account_id_to_account_32(validator_0.clone()).unwrap(); - let validator_0_location: MultiLocation = - Slp::account_32_to_parent_location(validator_0_32).unwrap(); - - // Bond 1 ksm for sub-account index 0 - assert_ok!(Slp::payout( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location), - Box::new(validator_0_location), - Some(TimeUnit::Era(27)) - )); - }); -} - -#[test] -fn liquidize_works() { - unbond_works(); - let subaccount_0 = subaccount_0(); - - KusamaNet::execute_with(|| { - // Kusama's unbonding period is 27 days = 100_800 blocks - kusama_runtime::System::set_block_number(101_000); - for _i in 0..29 { - kusama_runtime::Staking::trigger_new_era(0, vec![]); - } - - assert_eq!( - kusama_runtime::Balances::free_balance(&subaccount_0.clone()), - 2 * dollar(RelayCurrencyId::get()) - ); - - // 1ksm is locked for half bonded and half unbonding. - assert_eq!( - kusama_runtime::Balances::usable_balance(&subaccount_0.clone()), - dollar(RelayCurrencyId::get()) - ); - }); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - assert_ok!(Slp::liquidize( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location), - Some(TimeUnit::SlashingSpan(5)), - None - )); - }); - - KusamaNet::execute_with(|| { - assert_eq!( - kusama_runtime::Balances::free_balance(&subaccount_0.clone()), - 2 * dollar(RelayCurrencyId::get()) - ); - - // half of 1ksm unlocking has been freed. So the usable balance should be 1.5 ksm - assert_eq!( - kusama_runtime::Balances::usable_balance(&subaccount_0.clone()), - 1_500_000_000_000 - ); - }); -} - -#[test] -fn chill_works() { - delegate_works(); - let subaccount_0 = subaccount_0(); - - // check if sub-account index 0 belongs to the group of nominators - KusamaNet::execute_with(|| { - assert_eq!(kusama_runtime::Staking::nominators(&subaccount_0.clone()).is_some(), true); - }); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - assert_ok!(Slp::chill( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location), - )); - }); - - // check if sub-account index 0 belongs to the group of nominators - KusamaNet::execute_with(|| { - assert_eq!(kusama_runtime::Staking::nominators(&subaccount_0.clone()).is_some(), false); - }); -} - -#[test] -fn transfer_back_works() { - bond_works(); - let subaccount_0 = subaccount_0(); - let para_account_2001 = para_account_2001(); - - let exit_account: AccountId = - hex_literal::hex!["6d6f646c62662f76746f75740000000000000000000000000000000000000000"] - .into(); - - let exit_account_32 = Slp::account_id_to_account_32(exit_account.clone()).unwrap(); - let exit_account_location: MultiLocation = - Slp::account_32_to_local_location(exit_account_32).unwrap(); - - KusamaNet::execute_with(|| { - // 1ksm is locked for half bonded and half unbonding. - assert_eq!( - kusama_runtime::Balances::usable_balance(&subaccount_0.clone()), - dollar(RelayCurrencyId::get()) - ); - - assert_eq!( - kusama_runtime::Balances::free_balance(¶_account_2001.clone()), - 1999215574218 - ); - }); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - assert_eq!(Tokens::free_balance(RelayCurrencyId::get(), &exit_account), 0); - - assert_ok!(Slp::transfer_back( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location), - Box::new(exit_account_location), - 500_000_000_000 - )); - }); - - // Parachain account has been deposited the transferred amount. - KusamaNet::execute_with(|| { - assert_eq!( - kusama_runtime::Balances::usable_balance(&subaccount_0.clone()), - 500_000_000_000 - ); - assert_eq!( - kusama_runtime::Balances::free_balance(¶_account_2001.clone()), - 2498431148436 - ); - }); - - Bifrost::execute_with(|| { - assert_eq!(Tokens::free_balance(RelayCurrencyId::get(), &exit_account), 499907304000); - }); -} - -#[test] -fn supplement_fee_reserve_works() { - let subaccount_0 = subaccount_0(); - delegate_works(); - KusamaNet::execute_with(|| { - assert_eq!( - kusama_runtime::Balances::free_balance(&subaccount_0.clone()), - 2 * dollar(RelayCurrencyId::get()) - ); - }); - - Bifrost::execute_with(|| { - // set fee source - let alice_location = Slp::account_32_to_local_location(ALICE).unwrap(); - assert_ok!(Slp::set_fee_source( - Origin::root(), - RelayCurrencyId::get(), - Some((alice_location.clone(), dollar(RelayCurrencyId::get()))) - )); - - // We use supplement_fee_reserve to transfer some KSM to subaccount_0 - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - assert_ok!(Slp::supplement_fee_reserve( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location), - )); - }); - - KusamaNet::execute_with(|| { - assert_eq!(kusama_runtime::Balances::free_balance(&subaccount_0.clone()), 2999988476752); - }); -} - -#[test] -fn confirm_delegator_ledger_query_response_with_bond_works() { - register_subaccount_index_0(); - transfer_2_ksm_to_subaccount_in_kusama(); - let subaccount_0 = subaccount_0(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // First call bond function, it will insert a query. - // Bond 1 ksm for sub-account index 0 - assert_ok!(Slp::bond( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - dollar(RelayCurrencyId::get()), - None - )); - - // Check the existence of the query in pallet_xcm Queries storage. - assert_eq!( - PolkadotXcm::query(0), - Some(QueryStatus::Pending { - responder: VersionedMultiLocation::V1(MultiLocation { parents: 1, interior: Here }), - maybe_notify: None, - timeout: 1600 - }) - ); - - // Check the existence of query in the response update queue storage. - assert_eq!( - Slp::get_delegator_ledger_update_entry(0), - Some(( - LedgerUpdateEntry::Substrate(SubstrateLedgerUpdateEntry { - currency_id: RelayCurrencyId::get(), - delegator_id: subaccount_0_location.clone(), - update_operation: SubstrateLedgerUpdateOperation::Bond, - amount: dollar(RelayCurrencyId::get()), - unlock_time: None - }), - 1600 - )) - ); - }); - - KusamaNet::execute_with(|| { - assert_eq!( - kusama_runtime::Staking::ledger(&subaccount_0), - Some(StakingLedger { - stash: subaccount_0.clone(), - total: dollar(RelayCurrencyId::get()), - active: dollar(RelayCurrencyId::get()), - unlocking: BoundedVec::try_from(vec![]).unwrap(), - claimed_rewards: vec![], - }) - ); - }); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Call confirm_delegator_ledger_query_response. - assert_ok!(Slp::confirm_delegator_ledger_query_response( - Origin::root(), - RelayCurrencyId::get(), - 0 - )); - - // Check the ledger update. - assert_eq!( - Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(Ledger::Substrate(SubstrateLedger { - account: subaccount_0_location.clone(), - total: dollar(RelayCurrencyId::get()), - active: dollar(RelayCurrencyId::get()), - unlocking: vec![] - })) - ); - - // Check the existence of the query in pallet_xcm Queries storage. - // If xcm version 3 is introduced. We'll add instruction ReportTransactStatus into the xcm - // message. And this query will be set to ready status after we received a query response. - // At that point, this check should be set to equal None. - assert_eq!( - PolkadotXcm::query(0), - Some(QueryStatus::Pending { - responder: VersionedMultiLocation::V1(MultiLocation { parents: 1, interior: Here }), - maybe_notify: None, - timeout: 1600 - }) - ); - - // Check the inexistence of query in the response update queue storage. - assert_eq!(Slp::get_delegator_ledger_update_entry(0), None); - }); -} - -#[test] -fn confirm_delegator_ledger_query_response_with_bond_extra_works() { - // bond 1 ksm for sub-account index 0 - locally_bond_subaccount_0_1ksm_in_kusama(); - register_subaccount_index_0(); - register_delegator_ledger(); - let subaccount_0 = subaccount_0(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Bond_extra 1 ksm for sub-account index 0 - assert_ok!(Slp::bond_extra( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - None, - dollar(RelayCurrencyId::get()), - )); - - assert_eq!( - Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(Ledger::Substrate(SubstrateLedger { - account: subaccount_0_location.clone(), - total: dollar(RelayCurrencyId::get()), - active: dollar(RelayCurrencyId::get()), - unlocking: vec![] - })) - ); - - // Check the existence of the query in pallet_xcm Queries storage. - assert_eq!( - PolkadotXcm::query(0), - Some(QueryStatus::Pending { - responder: VersionedMultiLocation::V1(MultiLocation { parents: 1, interior: Here }), - maybe_notify: None, - timeout: 1600 - }) - ); - - // Check the existence of query in the response update queue storage. - assert_eq!( - Slp::get_delegator_ledger_update_entry(0), - Some(( - LedgerUpdateEntry::Substrate(SubstrateLedgerUpdateEntry { - currency_id: RelayCurrencyId::get(), - delegator_id: subaccount_0_location.clone(), - update_operation: SubstrateLedgerUpdateOperation::Bond, - amount: dollar(RelayCurrencyId::get()), - unlock_time: None - }), - 1600 - )) - ); - }); - - KusamaNet::execute_with(|| { - assert_eq!( - kusama_runtime::Staking::ledger(&subaccount_0), - Some(StakingLedger { - stash: subaccount_0.clone(), - total: 2 * dollar(RelayCurrencyId::get()), - active: 2 * dollar(RelayCurrencyId::get()), - unlocking: BoundedVec::try_from(vec![]).unwrap(), - claimed_rewards: vec![], - }) - ); - }); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Call confirm_delegator_ledger_query_response. - assert_ok!(Slp::confirm_delegator_ledger_query_response( - Origin::root(), - RelayCurrencyId::get(), - 0 - )); - - // Check the ledger update. - assert_eq!( - Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(Ledger::Substrate(SubstrateLedger { - account: subaccount_0_location.clone(), - total: 2 * dollar(RelayCurrencyId::get()), - active: 2 * dollar(RelayCurrencyId::get()), - unlocking: vec![] - })) - ); - - // Check the existence of the query in pallet_xcm Queries storage. - // If xcm version 3 is introduced. We'll add instruction ReportTransactStatus into the xcm - // message. And this query will be set to ready status after we received a query response. - // At that point, this check should be set to equal None. - assert_eq!( - PolkadotXcm::query(0), - Some(QueryStatus::Pending { - responder: VersionedMultiLocation::V1(MultiLocation { parents: 1, interior: Here }), - maybe_notify: None, - timeout: 1600 - }) - ); - - // Check the inexistence of query in the response update queue storage. - assert_eq!(Slp::get_delegator_ledger_update_entry(0), None); - }); -} - -#[test] -fn confirm_delegator_ledger_query_response_with_unbond_works() { - // bond 1 ksm for sub-account index 0 - locally_bond_subaccount_0_1ksm_in_kusama(); - register_subaccount_index_0(); - register_delegator_ledger(); - let subaccount_0 = subaccount_0(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Unbond 0.5 ksm, 0.5 ksm left. - assert_ok!(Slp::unbond( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - None, - 500_000_000_000, - )); - - assert_eq!( - Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(Ledger::Substrate(SubstrateLedger { - account: subaccount_0_location.clone(), - total: dollar(RelayCurrencyId::get()), - active: dollar(RelayCurrencyId::get()), - unlocking: vec![] - })) - ); - - // Check the existence of the query in pallet_xcm Queries storage. - assert_eq!( - PolkadotXcm::query(0), - Some(QueryStatus::Pending { - responder: VersionedMultiLocation::V1(MultiLocation { parents: 1, interior: Here }), - maybe_notify: None, - timeout: 1600 - }) - ); - - // Check the existence of query in the response update queue storage. - assert_eq!( - Slp::get_delegator_ledger_update_entry(0), - Some(( - LedgerUpdateEntry::Substrate(SubstrateLedgerUpdateEntry { - currency_id: RelayCurrencyId::get(), - delegator_id: subaccount_0_location.clone(), - update_operation: SubstrateLedgerUpdateOperation::Unlock, - amount: 500_000_000_000, - unlock_time: Some(TimeUnit::Era(10)) - }), - 1600 - )) - ); - }); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Call confirm_delegator_ledger_query_response. - assert_ok!(Slp::confirm_delegator_ledger_query_response( - Origin::root(), - RelayCurrencyId::get(), - 0 - )); - - // Check the ledger update. - assert_eq!( - Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(Ledger::Substrate(SubstrateLedger { - account: subaccount_0_location.clone(), - total: dollar(RelayCurrencyId::get()), - active: 500_000_000_000, - unlocking: vec![UnlockChunk { - value: 500000000000, - unlock_time: TimeUnit::Era(10) - }] - })) - ); - - // Check the existence of the query in pallet_xcm Queries storage. - // If xcm version 3 is introduced. We'll add instruction ReportTransactStatus into the xcm - // message. And this query will be set to ready status after we received a query response. - // At that point, this check should be set to equal None. - assert_eq!( - PolkadotXcm::query(0), - Some(QueryStatus::Pending { - responder: VersionedMultiLocation::V1(MultiLocation { parents: 1, interior: Here }), - maybe_notify: None, - timeout: 1600 - }) - ); - - // Check the inexistence of query in the response update queue storage. - assert_eq!(Slp::get_delegator_ledger_update_entry(0), None); - }); -} - -#[test] -fn confirm_delegator_ledger_query_response_with_unbond_all_works() { - // bond 1 ksm for sub-account index 0 - locally_bond_subaccount_0_1ksm_in_kusama(); - register_subaccount_index_0(); - register_delegator_ledger(); - let subaccount_0 = subaccount_0(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Unbond the only bonded 1 ksm. - assert_ok!(Slp::unbond_all( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - )); - - assert_eq!( - Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(Ledger::Substrate(SubstrateLedger { - account: subaccount_0_location.clone(), - total: dollar(RelayCurrencyId::get()), - active: dollar(RelayCurrencyId::get()), - unlocking: vec![] - })) - ); - - // Check the existence of the query in pallet_xcm Queries storage. - assert_eq!( - PolkadotXcm::query(0), - Some(QueryStatus::Pending { - responder: VersionedMultiLocation::V1(MultiLocation { parents: 1, interior: Here }), - maybe_notify: None, - timeout: 1600 - }) - ); - - // Check the existence of query in the response update queue storage. - assert_eq!( - Slp::get_delegator_ledger_update_entry(0), - Some(( - LedgerUpdateEntry::Substrate(SubstrateLedgerUpdateEntry { - currency_id: RelayCurrencyId::get(), - delegator_id: subaccount_0_location.clone(), - update_operation: SubstrateLedgerUpdateOperation::Unlock, - amount: dollar(RelayCurrencyId::get()), - unlock_time: Some(TimeUnit::Era(10)) - }), - 1600 - )) - ); - }); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Call confirm_delegator_ledger_query_response. - assert_ok!(Slp::confirm_delegator_ledger_query_response( - Origin::root(), - RelayCurrencyId::get(), - 0 - )); - - // Check the ledger update. - assert_eq!( - Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(Ledger::Substrate(SubstrateLedger { - account: subaccount_0_location.clone(), - total: dollar(RelayCurrencyId::get()), - active: 0, - unlocking: vec![UnlockChunk { - value: dollar(RelayCurrencyId::get()), - unlock_time: TimeUnit::Era(10) - }] - })) - ); - - // Check the existence of the query in pallet_xcm Queries storage. - // If xcm version 3 is introduced. We'll add instruction ReportTransactStatus into the xcm - // message. And this query will be set to ready status after we received a query response. - // At that point, this check should be set to equal None. - assert_eq!( - PolkadotXcm::query(0), - Some(QueryStatus::Pending { - responder: VersionedMultiLocation::V1(MultiLocation { parents: 1, interior: Here }), - maybe_notify: None, - timeout: 1600 - }) - ); - - // Check the inexistence of query in the response update queue storage. - assert_eq!(Slp::get_delegator_ledger_update_entry(0), None); - }); -} - -#[test] -fn confirm_delegator_ledger_query_response_with_rebond_works() { - // bond 1 ksm for sub-account index 0 - locally_bond_subaccount_0_1ksm_in_kusama(); - register_subaccount_index_0(); - register_delegator_ledger(); - let subaccount_0 = subaccount_0(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Unbond 0.5 ksm, 0.5 ksm left. - assert_ok!(Slp::unbond( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - None, - 500_000_000_000, - )); - - // Update Bifrost local ledger. This should be done by backend services. - let chunk = UnlockChunk { value: 500_000_000_000, unlock_time: TimeUnit::Era(10) }; - let sb_ledger = SubstrateLedger { - account: subaccount_0_location.clone(), - total: dollar(RelayCurrencyId::get()), - active: 500_000_000_000, - unlocking: vec![chunk], - }; - let ledger = Ledger::Substrate(sb_ledger); - - assert_ok!(Slp::set_delegator_ledger( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - Box::new(Some(ledger)) - )); - - // rebond 0.5 ksm. - assert_ok!(Slp::rebond( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - None, - Some(500_000_000_000), - )); - - assert_eq!( - Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(Ledger::Substrate(SubstrateLedger { - account: subaccount_0_location.clone(), - total: dollar(RelayCurrencyId::get()), - active: 500_000_000_000, - unlocking: vec![UnlockChunk { - value: 500_000_000_000, - unlock_time: TimeUnit::Era(10) - }] - })) - ); - - // Check the existence of the query in pallet_xcm Queries storage. - assert_eq!( - PolkadotXcm::query(1), - Some(QueryStatus::Pending { - responder: VersionedMultiLocation::V1(MultiLocation { parents: 1, interior: Here }), - maybe_notify: None, - timeout: 1600 - }) - ); - - // Check the existence of query in the response update queue storage. - assert_eq!( - Slp::get_delegator_ledger_update_entry(1), - Some(( - LedgerUpdateEntry::Substrate(SubstrateLedgerUpdateEntry { - currency_id: RelayCurrencyId::get(), - delegator_id: subaccount_0_location.clone(), - update_operation: SubstrateLedgerUpdateOperation::Rebond, - amount: 500_000_000_000, - unlock_time: None - }), - 1600 - )) - ); - }); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Call confirm_delegator_ledger_query_response. - assert_ok!(Slp::confirm_delegator_ledger_query_response( - Origin::root(), - RelayCurrencyId::get(), - 1 - )); - - // Check the ledger update. - assert_eq!( - Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(Ledger::Substrate(SubstrateLedger { - account: subaccount_0_location.clone(), - total: dollar(RelayCurrencyId::get()), - active: dollar(RelayCurrencyId::get()), - unlocking: vec![] - })) - ); - - // Check the existence of the query in pallet_xcm Queries storage. - // If xcm version 3 is introduced. We'll add instruction ReportTransactStatus into the xcm - // message. And this query will be set to ready status after we received a query response. - // At that point, this check should be set to equal None. - assert_eq!( - PolkadotXcm::query(1), - Some(QueryStatus::Pending { - responder: VersionedMultiLocation::V1(MultiLocation { parents: 1, interior: Here }), - maybe_notify: None, - timeout: 1600 - }) - ); - - // Check the inexistence of query in the response update queue storage. - assert_eq!(Slp::get_delegator_ledger_update_entry(1), None); - }); -} - -#[test] -fn confirm_delegator_ledger_query_response_with_liquidize_works() { - confirm_delegator_ledger_query_response_with_unbond_works(); - let subaccount_0 = subaccount_0(); - - KusamaNet::execute_with(|| { - // Kusama's unbonding period is 27 days = 100_800 blocks - kusama_runtime::System::set_block_number(101_000); - for _i in 0..29 { - kusama_runtime::Staking::trigger_new_era(0, vec![]); - } - - assert_eq!( - kusama_runtime::Balances::free_balance(&subaccount_0.clone()), - 2 * dollar(RelayCurrencyId::get()) - ); - - // 1ksm is locked for half bonded and half unbonding. - assert_eq!( - kusama_runtime::Balances::usable_balance(&subaccount_0.clone()), - dollar(RelayCurrencyId::get()) - ); - }); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - System::set_block_number(1200); - - // set ongoing era to be 11 which is greater than due era 10. - assert_ok!(Slp::update_ongoing_time_unit( - Origin::root(), - RelayCurrencyId::get(), - TimeUnit::Era(11) - )); - - assert_ok!(Slp::liquidize( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - Some(TimeUnit::SlashingSpan(5)), - None - )); - - assert_eq!( - Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(Ledger::Substrate(SubstrateLedger { - account: subaccount_0_location.clone(), - total: dollar(RelayCurrencyId::get()), - active: 500_000_000_000, - unlocking: vec![UnlockChunk { - value: 500_000_000_000, - unlock_time: TimeUnit::Era(10) - }] - })) - ); - - // Check the existence of the query in pallet_xcm Queries storage. - assert_eq!( - PolkadotXcm::query(1), - Some(QueryStatus::Pending { - responder: VersionedMultiLocation::V1(MultiLocation { parents: 1, interior: Here }), - maybe_notify: None, - timeout: 2200 - }) - ); - - // Check the existence of query in the response update queue storage. - assert_eq!( - Slp::get_delegator_ledger_update_entry(1), - Some(( - LedgerUpdateEntry::Substrate(SubstrateLedgerUpdateEntry { - currency_id: RelayCurrencyId::get(), - delegator_id: subaccount_0_location.clone(), - update_operation: SubstrateLedgerUpdateOperation::Liquidize, - amount: 0, - unlock_time: Some(TimeUnit::Era(11)) - }), - 2200 - )) - ); - }); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Call confirm_delegator_ledger_query_response. - assert_ok!(Slp::confirm_delegator_ledger_query_response( - Origin::root(), - RelayCurrencyId::get(), - 1 - )); - - // Check the ledger update. - assert_eq!( - Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(Ledger::Substrate(SubstrateLedger { - account: subaccount_0_location.clone(), - total: 500_000_000_000, - active: 500_000_000_000, - unlocking: vec![] - })) - ); - - // Check the existence of the query in pallet_xcm Queries storage. - // If xcm version 3 is introduced. We'll add instruction ReportTransactStatus into the xcm - // message. And this query will be set to ready status after we received a query response. - // At that point, this check should be set to equal None. - assert_eq!( - PolkadotXcm::query(1), - Some(QueryStatus::Pending { - responder: VersionedMultiLocation::V1(MultiLocation { parents: 1, interior: Here }), - maybe_notify: None, - timeout: 2200 - }) - ); - - // Check the inexistence of query in the response update queue storage. - assert_eq!(Slp::get_delegator_ledger_update_entry(1), None); - }); - - KusamaNet::execute_with(|| { - assert_eq!( - kusama_runtime::Balances::free_balance(&subaccount_0.clone()), - 2 * dollar(RelayCurrencyId::get()) - ); - - // half of 1ksm unlocking has been freed. So the usable balance should be 1.5 ksm - assert_eq!( - kusama_runtime::Balances::usable_balance(&subaccount_0.clone()), - 1_500_000_000_000 - ); - }); -} - -#[test] -fn fail_delegator_ledger_query_response_works() { - register_subaccount_index_0(); - transfer_2_ksm_to_subaccount_in_kusama(); - let subaccount_0 = subaccount_0(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // First call bond function, it will insert a query. - // Bond 1 ksm for sub-account index 0 - assert_ok!(Slp::bond( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - dollar(RelayCurrencyId::get()), - None - )); - - // Check the existence of the query in pallet_xcm Queries storage. - assert_eq!( - PolkadotXcm::query(0), - Some(QueryStatus::Pending { - responder: VersionedMultiLocation::V1(MultiLocation { parents: 1, interior: Here }), - maybe_notify: None, - timeout: 1600 - }) - ); - - // Check the existence of query in the response update queue storage. - assert_eq!( - Slp::get_delegator_ledger_update_entry(0), - Some(( - LedgerUpdateEntry::Substrate(SubstrateLedgerUpdateEntry { - currency_id: RelayCurrencyId::get(), - delegator_id: subaccount_0_location.clone(), - update_operation: SubstrateLedgerUpdateOperation::Bond, - amount: dollar(RelayCurrencyId::get()), - unlock_time: None - }), - 1600 - )) - ); - }); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - // Call confirm_delegator_ledger_query_response. - assert_ok!(Slp::fail_delegator_ledger_query_response( - Origin::root(), - RelayCurrencyId::get(), - 0 - )); - - // Check the ledger update. - assert_eq!( - Slp::get_delegator_ledger(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(Ledger::Substrate(SubstrateLedger { - account: subaccount_0_location.clone(), - total: 0, - active: 0, - unlocking: vec![] - })) - ); - - // Check the existence of the query in pallet_xcm Queries storage. - // If xcm version 3 is introduced. We'll add instruction ReportTransactStatus into the xcm - // message. And this query will be set to ready status after we received a query response. - // At that point, this check should be set to equal None. - assert_eq!( - PolkadotXcm::query(0), - Some(QueryStatus::Pending { - responder: VersionedMultiLocation::V1(MultiLocation { parents: 1, interior: Here }), - maybe_notify: None, - timeout: 1600 - }) - ); - - // Check the inexistence of query in the response update queue storage. - assert_eq!(Slp::get_delegator_ledger_update_entry(0), None); - }); -} - -#[test] -fn confirm_validators_by_delegator_query_response_with_delegate_works() { - // bond 1 ksm for sub-account index 0 - register_validators(); - locally_bond_subaccount_0_1ksm_in_kusama(); - register_subaccount_index_0(); - register_delegator_ledger(); - let subaccount_0 = subaccount_0(); - - // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz - let validator_0: AccountId = - hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] - .into(); - - // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 - let validator_1: AccountId = - hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] - .into(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - let mut targets = vec![]; - let mut valis = vec![]; - - let validator_0_32: [u8; 32] = Slp::account_id_to_account_32(validator_0.clone()).unwrap(); - let validator_0_location: MultiLocation = - Slp::account_32_to_parent_location(validator_0_32).unwrap(); - targets.push(validator_0_location.clone()); - let multi_hash_0 = - ::Hashing::hash(&validator_0_location.encode()); - - let validator_1_32: [u8; 32] = Slp::account_id_to_account_32(validator_1.clone()).unwrap(); - let validator_1_location: MultiLocation = - Slp::account_32_to_parent_location(validator_1_32).unwrap(); - targets.push(validator_1_location.clone()); - let multi_hash_1 = - ::Hashing::hash(&validator_1_location.encode()); - - valis.push((validator_1_location.clone(), multi_hash_1)); - valis.push((validator_0_location.clone(), multi_hash_0)); - - // delegate - assert_ok!(Slp::delegate( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - targets.clone(), - )); - - // Before data: Delegate nobody. - assert_eq!( - Slp::get_validators_by_delegator(RelayCurrencyId::get(), subaccount_0_location.clone()), - None - ); - - assert_eq!( - Slp::get_validators_by_delegator_update_entry(0), - Some(( - ValidatorsByDelegatorUpdateEntry::Substrate( - SubstrateValidatorsByDelegatorUpdateEntry { - currency_id: RelayCurrencyId::get(), - delegator_id: subaccount_0_location.clone(), - validators: valis.clone(), - } - ), - 1600 - )) - ); - - // confirm call - assert_ok!(Slp::confirm_validators_by_delegator_query_response( - Origin::root(), - RelayCurrencyId::get(), - 0 - )); - - // After delegation data. - assert_eq!( - Slp::get_validators_by_delegator(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(valis) - ); - - assert_eq!(Slp::get_validators_by_delegator_update_entry(0), None); - }); -} - -#[test] -fn confirm_validators_by_delegator_query_response_with_undelegate_works() { - delegate_works(); - - let subaccount_0 = subaccount_0(); - - // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz - let validator_0: AccountId = - hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] - .into(); - - // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 - let validator_1: AccountId = - hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] - .into(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - let mut targets = vec![]; - let mut valis_1 = vec![]; - let mut valis_2 = vec![]; - - let validator_0_32: [u8; 32] = Slp::account_id_to_account_32(validator_0.clone()).unwrap(); - let validator_0_location: MultiLocation = - Slp::account_32_to_parent_location(validator_0_32).unwrap(); - targets.push(validator_0_location.clone()); - let multi_hash_0 = - ::Hashing::hash(&validator_0_location.encode()); - - let validator_1_32: [u8; 32] = Slp::account_id_to_account_32(validator_1.clone()).unwrap(); - let validator_1_location: MultiLocation = - Slp::account_32_to_parent_location(validator_1_32).unwrap(); - let multi_hash_1 = - ::Hashing::hash(&validator_1_location.encode()); - - valis_1.push((validator_1_location.clone(), multi_hash_1.clone())); - - valis_2.push((validator_1_location.clone(), multi_hash_1)); - valis_2.push((validator_0_location.clone(), multi_hash_0)); - - // Undelegate validator 0. Only validator 1 left. - assert_ok!(Slp::undelegate( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - targets.clone(), - )); - - // Before data: Delegate 2 validators. - assert_eq!( - Slp::get_validators_by_delegator(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(valis_2) - ); - - assert_eq!( - Slp::get_validators_by_delegator_update_entry(1), - Some(( - ValidatorsByDelegatorUpdateEntry::Substrate( - SubstrateValidatorsByDelegatorUpdateEntry { - currency_id: RelayCurrencyId::get(), - delegator_id: subaccount_0_location.clone(), - validators: valis_1.clone(), - } - ), - 1600 - )) - ); - - // confirm call - assert_ok!(Slp::confirm_validators_by_delegator_query_response( - Origin::root(), - RelayCurrencyId::get(), - 1, - )); - - // After delegation data: delegate only 1 validator. - assert_eq!( - Slp::get_validators_by_delegator(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(valis_1) - ); - - assert_eq!(Slp::get_validators_by_delegator_update_entry(1), None); - }); -} - -#[test] -fn confirm_validators_by_delegator_query_response_with_redelegate_works() { - confirm_validators_by_delegator_query_response_with_undelegate_works(); - - let subaccount_0 = subaccount_0(); - - // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz - let validator_0: AccountId = - hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] - .into(); - - // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 - let validator_1: AccountId = - hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] - .into(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - let mut targets = vec![]; - let mut valis_1 = vec![]; - let mut valis_2 = vec![]; - - let validator_0_32: [u8; 32] = Slp::account_id_to_account_32(validator_0.clone()).unwrap(); - let validator_0_location: MultiLocation = - Slp::account_32_to_parent_location(validator_0_32).unwrap(); - targets.push(validator_0_location.clone()); - let multi_hash_0 = - ::Hashing::hash(&validator_0_location.encode()); - - let validator_1_32: [u8; 32] = Slp::account_id_to_account_32(validator_1.clone()).unwrap(); - let validator_1_location: MultiLocation = - Slp::account_32_to_parent_location(validator_1_32).unwrap(); - targets.push(validator_1_location.clone()); - let multi_hash_1 = - ::Hashing::hash(&validator_1_location.encode()); - - valis_1.push((validator_1_location.clone(), multi_hash_1.clone())); - valis_2.push((validator_1_location.clone(), multi_hash_1)); - valis_2.push((validator_0_location.clone(), multi_hash_0)); - - // Redelegate to a set of validator_0 and validator_1. - assert_ok!(Slp::redelegate( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - Some(targets.clone()), - )); - - // Before data: Delegate only 1 validator. - assert_eq!( - Slp::get_validators_by_delegator(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(valis_1) - ); - - assert_eq!( - Slp::get_validators_by_delegator_update_entry(2), - Some(( - ValidatorsByDelegatorUpdateEntry::Substrate( - SubstrateValidatorsByDelegatorUpdateEntry { - currency_id: RelayCurrencyId::get(), - delegator_id: subaccount_0_location.clone(), - validators: valis_2.clone(), - } - ), - 1600 - )) - ); - - // confirm call - assert_ok!(Slp::confirm_validators_by_delegator_query_response( - Origin::root(), - RelayCurrencyId::get(), - 2, - )); - - // After delegation data: delegate 2 validators. - assert_eq!( - Slp::get_validators_by_delegator(RelayCurrencyId::get(), subaccount_0_location.clone()), - Some(valis_2) - ); - - assert_eq!(Slp::get_validators_by_delegator_update_entry(2), None); - }); -} - -#[test] -fn fail_validators_by_delegator_query_response_works() { - // bond 1 ksm for sub-account index 0 - register_validators(); - locally_bond_subaccount_0_1ksm_in_kusama(); - register_subaccount_index_0(); - register_delegator_ledger(); - let subaccount_0 = subaccount_0(); - - // GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz - let validator_0: AccountId = - hex_literal::hex!["be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f"] - .into(); - - // JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5 - let validator_1: AccountId = - hex_literal::hex!["fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e"] - .into(); - - Bifrost::execute_with(|| { - let subaccount_0_32: [u8; 32] = - Slp::account_id_to_account_32(subaccount_0.clone()).unwrap(); - let subaccount_0_location: MultiLocation = - Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); - - let mut targets = vec![]; - let mut valis = vec![]; - - let validator_0_32: [u8; 32] = Slp::account_id_to_account_32(validator_0.clone()).unwrap(); - let validator_0_location: MultiLocation = - Slp::account_32_to_parent_location(validator_0_32).unwrap(); - targets.push(validator_0_location.clone()); - let multi_hash_0 = - ::Hashing::hash(&validator_0_location.encode()); - - let validator_1_32: [u8; 32] = Slp::account_id_to_account_32(validator_1.clone()).unwrap(); - let validator_1_location: MultiLocation = - Slp::account_32_to_parent_location(validator_1_32).unwrap(); - targets.push(validator_1_location.clone()); - let multi_hash_1 = - ::Hashing::hash(&validator_1_location.encode()); - - valis.push((validator_1_location.clone(), multi_hash_1)); - valis.push((validator_0_location.clone(), multi_hash_0)); - - // delegate - assert_ok!(Slp::delegate( - Origin::root(), - RelayCurrencyId::get(), - Box::new(subaccount_0_location.clone()), - targets.clone(), - )); - - // check before data: delegate nobody. - assert_eq!( - Slp::get_validators_by_delegator(RelayCurrencyId::get(), subaccount_0_location.clone()), - None - ); - - assert_eq!( - Slp::get_validators_by_delegator_update_entry(0), - Some(( - ValidatorsByDelegatorUpdateEntry::Substrate( - SubstrateValidatorsByDelegatorUpdateEntry { - currency_id: RelayCurrencyId::get(), - delegator_id: subaccount_0_location.clone(), - validators: valis, - } - ), - 1600 - )) - ); - - // call fail function - assert_ok!(Slp::fail_validators_by_delegator_query_response( - Origin::root(), - RelayCurrencyId::get(), - 0, - )); - - // check after data - assert_eq!( - Slp::get_validators_by_delegator(RelayCurrencyId::get(), subaccount_0_location.clone()), - None - ); - - assert_eq!(Slp::get_validators_by_delegator_update_entry(0), None); - }); -} diff --git a/integration-tests/src/statemine.rs b/integration-tests/src/statemine.rs deleted file mode 100644 index ff069e99ba..0000000000 --- a/integration-tests/src/statemine.rs +++ /dev/null @@ -1,64 +0,0 @@ -// This file is part of Bifrost. - -// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -use frame_support::assert_ok; -use polkadot_parachain::primitives::Sibling; -use sp_runtime::traits::AccountIdConversion; -use xcm::latest::prelude::*; -use xcm_emulator::TestExt; - -use crate::{integration_tests::*, kusama_test_net::*}; -#[test] -fn statemine() { - // env_logger::init(); - Statemine::execute_with(|| { - use frame_support::traits::Currency; - use statemine_runtime::*; - - let origin = Origin::signed(ALICE.into()); - - statemine_runtime::Balances::make_free_balance_be( - &ALICE.into(), - 10 * dollar(RelayCurrencyId::get()), - ); - - // need to have some KSM to be able to receive user assets - statemine_runtime::Balances::make_free_balance_be( - &Sibling::from(2001).into_account_truncating(), - 10 * dollar(RelayCurrencyId::get()), - ); - - assert_ok!(Assets::create(origin.clone(), 0, MultiAddress::Id(ALICE.into()), 10,)); - - assert_ok!(Assets::mint(origin.clone(), 0, MultiAddress::Id(ALICE.into()), 1000)); - - System::reset_events(); - - let para_acc: AccountId = Sibling::from(2001).into_account_truncating(); - println!("{:?}", para_acc); - - assert_ok!(PolkadotXcm::reserve_transfer_assets( - origin.clone(), - Box::new(MultiLocation::new(1, X1(Parachain(2001))).into()), - Box::new(Junction::AccountId32 { id: BOB, network: NetworkId::Any }.into().into()), - Box::new((X2(PalletInstance(50), GeneralIndex(0)), 100).into()), - 0 - )); - println!("{:?}", System::events()); - }); -} diff --git a/integration-tests/src/treasury.rs b/integration-tests/src/treasury.rs deleted file mode 100644 index bf396ed2c6..0000000000 --- a/integration-tests/src/treasury.rs +++ /dev/null @@ -1,125 +0,0 @@ -// This file is part of Bifrost. - -// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -use crate::{integration_tests::*, kusama_test_net::*, slp::*}; -use frame_support::assert_ok; -// use xcm::latest::prelude::*; -use xcm_emulator::TestExt; -// use node_primitives::*; -// use zenlink_protocol::LIQUIDITY; -use node_primitives::TryConvertFrom; -use sp_runtime::AccountId32; -// use bifrost_polkadot_runtime::Permill; - -pub const KSM: CurrencyId = CurrencyId::Token(TokenSymbol::KSM); -pub const VKSM: CurrencyId = CurrencyId::VToken(TokenSymbol::KSM); - -#[test] -fn kusama_treasury_propose_spend() { - KusamaNet::execute_with(|| { - assert_ok!(kusama_runtime::Treasury::propose_spend( - kusama_runtime::Origin::signed(ALICE.into()), - 50_000_000_000_000_000, - sp_runtime::MultiAddress::Id(para_account_2001()), - )); - }); -} - -#[test] -fn bifrost_treasury_operations() { - let para_id = 2001u32; - let treasury_account: AccountId32 = - bifrost_kusama_runtime::TreasuryPalletId::get().into_account_truncating(); - Bifrost::execute_with(|| { - let treasury_derivative_account_id = - bifrost_kusama_runtime::Utility::derivative_account_id(treasury_account.clone(), 0); - assert_ok!(bifrost_kusama_runtime::Tokens::set_balance( - bifrost_kusama_runtime::Origin::root(), - sp_runtime::MultiAddress::Id(treasury_derivative_account_id.clone()), - RelayCurrencyId::get(), - 50_000_000_000_000_000, - 0, - )); - assert_ok!(bifrost_kusama_runtime::Tokens::force_transfer( - bifrost_kusama_runtime::Origin::root(), - sp_runtime::MultiAddress::Id(treasury_derivative_account_id), - sp_runtime::MultiAddress::Id(treasury_account.clone()), - RelayCurrencyId::get(), - 50_000_000_000_000_000, - )); - - assert_ok!(bifrost_kusama_runtime::VtokenMinting::mint( - bifrost_kusama_runtime::Origin::signed(treasury_account.clone()), - RelayCurrencyId::get(), - 25_000_000_000_000_000, - )); - - assert_ok!(bifrost_kusama_runtime::ZenlinkProtocol::create_pair( - bifrost_kusama_runtime::Origin::root(), - zenlink_protocol::AssetId::try_convert_from(KSM, para_id).unwrap(), - zenlink_protocol::AssetId::try_convert_from(VKSM, para_id).unwrap(), - )); - - assert_ok!(bifrost_kusama_runtime::ZenlinkProtocol::add_liquidity( - bifrost_kusama_runtime::Origin::signed(treasury_account.clone()), - zenlink_protocol::AssetId::try_convert_from(KSM, para_id).unwrap(), - zenlink_protocol::AssetId::try_convert_from(VKSM, para_id).unwrap(), - 25_000_000_000_000_000, - 25_000_000_000_000_000, - 0, - 0, - BLOCKS_PER_YEAR, - )); - - let lp_asset_id = bifrost_kusama_runtime::ZenlinkProtocol::lp_asset_id( - &zenlink_protocol::AssetId::try_convert_from(KSM, para_id).unwrap(), - &zenlink_protocol::AssetId::try_convert_from(VKSM, para_id).unwrap(), - ); - - let lp = bifrost_kusama_runtime::ZenlinkProtocol::foreign_balance_of( - lp_asset_id, - &treasury_account, - ); - - assert_ok!(bifrost_kusama_runtime::ZenlinkProtocol::remove_liquidity( - bifrost_kusama_runtime::Origin::signed(treasury_account.clone()), - zenlink_protocol::AssetId::try_convert_from(KSM, para_id).unwrap(), - zenlink_protocol::AssetId::try_convert_from(VKSM, para_id).unwrap(), - lp, - 0, - 0, - sp_runtime::MultiAddress::Id(treasury_account.clone()), - BLOCKS_PER_YEAR, - )); - - assert_ok!(bifrost_kusama_runtime::VtokenMinting::set_unlock_duration( - Origin::root(), - KSM, - TimeUnit::Era(0) - )); - assert_ok!(bifrost_kusama_runtime::VtokenMinting::update_ongoing_time_unit( - KSM, - TimeUnit::Era(1) - )); - - assert_ok!(bifrost_kusama_runtime::VtokenMinting::redeem( - bifrost_kusama_runtime::Origin::signed(treasury_account), - VKSM, - 0, - )); - }); -}