[Feature] XCM-Emulator (#2447)

* [Feature] XCM-Emulator

* ".git/.scripts/commands/fmt/fmt.sh"

* rename

* readme

* more rename

* rename directory

* implement AssetTransactor

* Update xcm/xcm-emulator/README.md

Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com>

* address review comments (#2502)

* Update xcm/xcm-emulator/example/src/lib.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update xcm/xcm-emulator/README.md

* Use 2d weights.

* Point out nearer the failure why it should fail

* Move test-runtime to under examples

* Walk through how to use it

* proof needs to be non-zero

* Apply suggestions from code review

* Update xcm/xcm-emulator/README.md

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Improve xcm emulator (#2593)

* folder restructutre

* common created

* make macros repetitions

* messenger traits for relay and para

* default Messenger impls

* messenger traits refactor

* declared two networks

* init network approach works

* queues use HashMap but relay block number

* init and reset refactor

* messengers trait name changed

* relay block number suboptimal

* fix reset hashmap keys

* genesis added

* test ext added for parachains

* genesis added relay chains

* genesis to storage

* new_ext replaced by on_init

* new relay block number approach

* ext_wrapper added

* added types to Parachain trait

* relay chain with types

* restructure

* para_ids working

* replace para_id getter

* replace para_id getter 2

* tests restructure + common variables

* added sovereign and balances helpers

* more helpers + tess pass

* expected events macro added

* added events trait method

* expect_events macro improve

* expect_events macro done

* network traits added

* reserve_transfer test added

* para & relay macro inputs redefined

* added collectives & BH paras

* test restructure

* statemine removed

* nitpick

* rename test folder + events logs

* clean

* weight threshold helper

* update readme

* remove cumulus-test-service dependancy

* fmt

* comment docs

* update e2e tests to xcm v3

* clippy + runtime-benchmark + clean docs

---------

Co-authored-by: command-bot <>
Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com>
Co-authored-by: Squirrel <gilescope@gmail.com>
Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
Co-authored-by: Ignacio Palacios <ignacio.palacios.santos@gmail.com>
This commit is contained in:
Roman Useinov
2023-05-19 19:53:41 +02:00
committed by GitHub
parent 8425e2a5c0
commit 944ab483d5
40 changed files with 3848 additions and 1859 deletions
+108
View File
@@ -1347,6 +1347,15 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "casey"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fabe85130dda9cf267715582ce6cf1ab581c8dfe3cb33f7065fee0f14e3fea14"
dependencies = [
"syn 1.0.109",
]
[[package]] [[package]]
name = "cast" name = "cast"
version = "0.3.0" version = "0.3.0"
@@ -4861,6 +4870,47 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "integration-tests-common"
version = "1.0.0"
dependencies = [
"bridge-hub-kusama-runtime",
"bridge-hub-polkadot-runtime",
"collectives-polkadot-runtime",
"cumulus-primitives-core",
"frame-support",
"frame-system",
"kusama-runtime",
"kusama-runtime-constants",
"pallet-assets",
"pallet-balances",
"pallet-im-online",
"pallet-staking",
"pallet-xcm",
"parachain-info",
"parachains-common",
"parity-scale-codec",
"penpal-runtime",
"polkadot-core-primitives",
"polkadot-parachain",
"polkadot-primitives",
"polkadot-runtime",
"polkadot-runtime-constants",
"polkadot-runtime-parachains",
"polkadot-service",
"sc-consensus-grandpa",
"sp-authority-discovery",
"sp-consensus-babe",
"sp-core",
"sp-runtime",
"sp-weights",
"statemine-runtime",
"statemint-runtime",
"xcm",
"xcm-emulator",
"xcm-executor",
]
[[package]] [[package]]
name = "interceptor" name = "interceptor"
version = "0.8.2" version = "0.8.2"
@@ -13536,6 +13586,32 @@ dependencies = [
"xcm-executor", "xcm-executor",
] ]
[[package]]
name = "statemint-it"
version = "1.0.0"
dependencies = [
"frame-support",
"frame-system",
"integration-tests-common",
"pallet-assets",
"pallet-balances",
"pallet-xcm",
"parachains-common",
"parity-scale-codec",
"penpal-runtime",
"polkadot-core-primitives",
"polkadot-parachain",
"polkadot-runtime",
"polkadot-runtime-parachains",
"sp-core",
"sp-runtime",
"sp-weights",
"statemint-runtime",
"xcm",
"xcm-emulator",
"xcm-executor",
]
[[package]] [[package]]
name = "statemint-runtime" name = "statemint-runtime"
version = "1.0.0" version = "1.0.0"
@@ -16058,6 +16134,38 @@ dependencies = [
"xcm-executor", "xcm-executor",
] ]
[[package]]
name = "xcm-emulator"
version = "0.1.0"
dependencies = [
"casey",
"cumulus-pallet-dmp-queue",
"cumulus-pallet-parachain-system",
"cumulus-pallet-xcmp-queue",
"cumulus-primitives-core",
"cumulus-primitives-parachain-inherent",
"cumulus-test-relay-sproof-builder",
"cumulus-test-service",
"frame-support",
"frame-system",
"log",
"pallet-balances",
"parachain-info",
"parachains-common",
"parity-scale-codec",
"paste",
"polkadot-primitives",
"polkadot-runtime-parachains",
"quote",
"sp-arithmetic",
"sp-core",
"sp-io",
"sp-std",
"sp-trie",
"xcm",
"xcm-executor",
]
[[package]] [[package]]
name = "xcm-executor" name = "xcm-executor"
version = "0.9.41" version = "0.9.41"
+3 -1
View File
@@ -52,11 +52,14 @@ members = [
"parachains/runtimes/contracts/contracts-rococo", "parachains/runtimes/contracts/contracts-rococo",
"parachains/runtimes/glutton/glutton-kusama", "parachains/runtimes/glutton/glutton-kusama",
"parachains/runtimes/testing/penpal", "parachains/runtimes/testing/penpal",
"parachains/integration-tests/emulated/common",
"parachains/integration-tests/emulated/assets/statemint",
"test/client", "test/client",
"test/relay-sproof-builder", "test/relay-sproof-builder",
"test/relay-validation-worker-provider", "test/relay-validation-worker-provider",
"test/runtime", "test/runtime",
"test/service", "test/service",
"xcm/xcm-emulator",
] ]
[profile.release] [profile.release]
@@ -67,4 +70,3 @@ opt-level = 3
inherits = "release" inherits = "release"
lto = true lto = true
codegen-units = 1 codegen-units = 1
@@ -11,12 +11,12 @@ settings:
paraId: &pp_id 2000 paraId: &pp_id 2000
variables: variables:
common: common:
xcm_verison: &xcm_version '2' xcm_version: &xcm_version '3'
require_weight_at_most: &weight_at_most 1000000000 require_weight_at_most: &weight_at_most {refTime: 1000000000, proofSize: 200000}
chains: chains:
relay_chain: relay_chain:
signer: &rc_signer //Alice signer: &rc_signer //Alice
assets_parachain_destination: &ap_dest { v1: { 0, interior: { x1: { parachain: *ap_id }}}} assets_parachain_destination: &ap_dest { v3: { 0, interior: { x1: { parachain: *ap_id }}}}
penpal_parachain: penpal_parachain:
signer: &pp_signer //Alice signer: &pp_signer //Alice
decodedCalls: decodedCalls:
@@ -37,7 +37,7 @@ tests:
its: its:
- name: XCM supported versions between chains - name: XCM supported versions between chains
actions: actions:
- extrinsics: # Relay Chain sets supported version for Assset Parachain - extrinsics: # Relay Chain sets supported version for Asset Parachain
- chain: *relay_chain - chain: *relay_chain
sudo: true sudo: true
signer: *rc_signer signer: *rc_signer
@@ -56,12 +56,12 @@ tests:
] ]
events: events:
- name: sudo.Sudid - name: sudo.Sudid
attribute: attributes:
type: Result<Null, SpRuntimeDispatchError> - type: Result<Null, SpRuntimeDispatchError>
value: Ok value: Ok
- name: xcmPallet.SupportedVersionChanged - name: xcmPallet.SupportedVersionChanged
attribute: attributes:
type: u32 - type: u32
value: *xcm_version value: *xcm_version
- extrinsics: # Relay Chain sets supported version for Penpal Parachain - extrinsics: # Relay Chain sets supported version for Penpal Parachain
- chain: *relay_chain - chain: *relay_chain
@@ -82,14 +82,14 @@ tests:
] ]
events: events:
- name: sudo.Sudid - name: sudo.Sudid
attribute: attributes:
type: Result<Null, SpRuntimeDispatchError> - type: Result<Null, SpRuntimeDispatchError>
value: Ok value: Ok
- name: xcmPallet.SupportedVersionChanged - name: xcmPallet.SupportedVersionChanged
attribute: attributes:
type: u32 - type: u32
value: *xcm_version value: *xcm_version
- extrinsics: # Assset Parachain sets supported version for Relay Chain through it - extrinsics: # Asset Parachain sets supported version for Relay Chain through it
- chain: *relay_chain - chain: *relay_chain
signer: *rc_signer signer: *rc_signer
sudo: true sudo: true
@@ -98,10 +98,20 @@ tests:
args: [ args: [
*ap_dest, # destination *ap_dest, # destination
{ {
v2: [ #message v3: [ #message
{
UnpaidExecution: {
weightLimit: {
limited: {
refTime: 2200000000,
proofSize: 200000
}
}
}
},
{ {
Transact: { Transact: {
originType: Superuser, originKind: Superuser,
requireWeightAtMost: *weight_at_most, requireWeightAtMost: *weight_at_most,
call: $ap_force_xcm_version call: $ap_force_xcm_version
} }
@@ -111,14 +121,14 @@ tests:
] ]
events: events:
- name: sudo.Sudid - name: sudo.Sudid
attribute: attributes:
type: Result<Null, SpRuntimeDispatchError> - type: Result<Null, SpRuntimeDispatchError>
value: Ok value: Ok
- name: xcmPallet.Sent - name: xcmPallet.Sent
- name: polkadotXcm.SupportedVersionChanged - name: polkadotXcm.SupportedVersionChanged
chain: *assets_parachain chain: *assets_parachain
attribute: attributes:
type: u32 - type: u32
value: *xcm_version value: *xcm_version
- extrinsics: # Penpal Parachain sets supported version for Relay Chain - extrinsics: # Penpal Parachain sets supported version for Relay Chain
- chain: *penpal_parachain - chain: *penpal_parachain
@@ -135,10 +145,10 @@ tests:
] ]
events: events:
- name: sudo.Sudid - name: sudo.Sudid
attribute: attributes:
type: Result<Null, SpRuntimeDispatchError> - type: Result<Null, SpRuntimeDispatchError>
value: Ok value: Ok
- name: polkadotXcm.SupportedVersionChanged - name: polkadotXcm.SupportedVersionChanged
attribute: attributes:
type: u32 - type: u32
value: *xcm_version value: *xcm_version
@@ -10,13 +10,13 @@ settings:
relay_chain: relay_chain:
signer: &rc_signer //Alice signer: &rc_signer //Alice
wallet: &rc_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F wallet: &rc_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F
assets_parachain_destination: &ap_dest { v1: { parents: 0, interior: { x1: { parachain: *ap_id }}}} assets_parachain_destination: &ap_dest { v3: { parents: 0, interior: { x1: { parachain: *ap_id }}}}
assets_parachain_account: &ap_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d' assets_parachain_account: &ap_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'
assets_parachain_beneficiary: &ap_benf {v1: { parents: 0, interior: { x1: { accountId32: { network: { any: true }, id: *ap_acc }}}}} assets_parachain_beneficiary: &ap_benf {v3: { parents: 0, interior: { x1: { accountId32: { id: *ap_acc }}}}}
ksm: &rc_ksm { concrete: { parents: 0, interior: { here: true }}} ksm: &rc_ksm { concrete: { parents: 0, interior: { here: true }}}
amount: &amount 1000000000000 amount: &amount 1000000000000
ksm_fungible: &rc_ksm_fungible { id: *rc_ksm, fun: { fungible: *amount }} ksm_fungible: &rc_ksm_fungible { id: *rc_ksm, fun: { fungible: *amount }}
require_weight_at_most: &rc_weight_at_most 1000000000 require_weight_at_most: &rc_weight_at_most {refTime: 1000000000, proofSize: 200000}
assets_parachain_account: assets_parachain_account:
wallet: &ap_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F wallet: &ap_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F
asset_id: &asset_id 1 asset_id: &asset_id 1
@@ -63,22 +63,22 @@ tests:
args: [ args: [
*ap_dest, # destination *ap_dest, # destination
*ap_benf, # beneficiary *ap_benf, # beneficiary
{ v1: [ *rc_ksm_fungible ] }, # assets { v3: [ *rc_ksm_fungible ] },
0, # feeAssetItem 0, # feeAssetItem
{ unlimited: true } # weightLimit { unlimited: true } # weightLimit
] ]
events: events:
- name: xcmPallet.Attempted - name: xcmPallet.Attempted
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
- name: dmpQueue.ExecutedDownward - name: dmpQueue.ExecutedDownward
chain: *assets_parachain chain: *assets_parachain
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
threshold: [10, 10] threshold: [10, 10]
value: 1,021,635,000 value: {"refTime":"162,379,000","proofSize":"0"}
- queries: - queries:
balance_rc_sender_after: balance_rc_sender_after:
chain: *relay_chain chain: *relay_chain
@@ -131,10 +131,15 @@ tests:
args: [ args: [
*ap_dest, # destination *ap_dest, # destination
{ {
v2: [ #message v3: [ #message
{
UnpaidExecution: {
weightLimit: Unlimited
}
},
{ {
Transact: { Transact: {
originType: Superuser, originKind: Superuser,
requireWeightAtMost: *rc_weight_at_most, requireWeightAtMost: *rc_weight_at_most,
call: $force_create_asset call: $force_create_asset
} }
@@ -146,11 +151,11 @@ tests:
- name: xcmPallet.Sent - name: xcmPallet.Sent
- name: dmpQueue.ExecutedDownward - name: dmpQueue.ExecutedDownward
chain: *assets_parachain chain: *assets_parachain
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
threshold: [10, 10] threshold: [10, 10]
value: 1,020,807,000 value: {"refTime":"1,014,103,000","proofSize":"200,000"}
- queries: - queries:
forced_created_asset: forced_created_asset:
chain: *assets_parachain chain: *assets_parachain
@@ -173,10 +178,15 @@ tests:
args: [ args: [
*ap_dest, # destination *ap_dest, # destination
{ {
v2: [ #message v3: [ #message
{
UnpaidExecution: {
weightLimit: Unlimited
}
},
{ {
Transact: { Transact: {
originType: Native, originKind: Native,
requireWeightAtMost: *rc_weight_at_most, requireWeightAtMost: *rc_weight_at_most,
call: $force_create_asset call: $force_create_asset
} }
@@ -186,8 +196,8 @@ tests:
] ]
events: events:
- name: system.ExtrinsicFailed - name: system.ExtrinsicFailed
attribute: attributes:
type: SpRuntimeDispatchError - type: SpRuntimeDispatchError
value: BadOrigin value: BadOrigin
- name: xcmPallet.limitedReserveTransferAssets - name: xcmPallet.limitedReserveTransferAssets
@@ -203,22 +213,23 @@ tests:
args: [ args: [
*ap_dest, # destination *ap_dest, # destination
*ap_benf, # beneficiary *ap_benf, # beneficiary
{ v1: [ *rc_ksm_fungible ] }, # assets { v3: [ *rc_ksm_fungible ] }, # assets
0, # feeAssetItem 0, # feeAssetItem
{ unlimited: true } # weightLimit { unlimited: true } # weightLimit
] ]
events: events:
- name: xcmPallet.Attempted - name: xcmPallet.Attempted
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
value: 1,000,000,000 threshold: [10, 10]
value: {"refTime":"750,645,000","proofSize":"0"}
- name: dmpQueue.ExecutedDownward - name: dmpQueue.ExecutedDownward
chain: *assets_parachain chain: *assets_parachain
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isError: true xcmOutcome: Incomplete
value: "WeightNotComputable" value: [{"refTime":"1,000,000,000","proofSize":"0"},"UntrustedReserveLocation"]
- queries: - queries:
balance_rc_sender_after: balance_rc_sender_after:
chain: *relay_chain chain: *relay_chain
@@ -9,21 +9,21 @@ settings:
variables: variables:
common: common:
amount: &amount 1000000000000 amount: &amount 1000000000000
require_weight_at_most: &weight_at_most 1000000000 require_weight_at_most: &weight_at_most {refTime: 1000000000, proofSize: 0}
relay_chain: relay_chain:
signer: &rc_signer //Alice signer: &rc_signer //Alice
wallet: &rc_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F #Alice wallet: &rc_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F #Alice
assets_parachain_destination: &ap_dest { v1: { 0, interior: { x1: { parachain: *ap_id }}}} assets_parachain_destination: &ap_dest { v3: { 0, interior: { x1: { parachain: *ap_id }}}}
assets_parachain_account: &ap_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d' assets_parachain_account: &ap_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'
assets_parachain_beneficiary: &ap_benf {v1: { parents: 0, interior: { x1: { accountId32: { network: { any: true }, id: *ap_acc }}}}} assets_parachain_beneficiary: &ap_benf {v3: { parents: 0, interior: { x1: { accountId32: { id: *ap_acc }}}}}
ksm: &rc_ksm { concrete: { 0, interior: { here: true }}} ksm: &rc_ksm { concrete: { 0, interior: { here: true }}}
ksm_fungible: &rc_ksm_fungible { id: *rc_ksm, fun: { fungible: *amount }} ksm_fungible: &rc_ksm_fungible { id: *rc_ksm, fun: { fungible: *amount }}
assets_parachain_account: assets_parachain_account:
signer: &ap_signer //Alice signer: &ap_signer //Alice
wallet: &ap_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F wallet: &ap_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F
relay_chain_destination: &rc_dest { v1: { parents: 1, interior: { here: true }}} relay_chain_destination: &rc_dest { v3: { parents: 1, interior: { here: true }}}
assets_parachain_account: &rc_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d' #Alice assets_parachain_account: &rc_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d' #Alice
relay_chain_beneficiary: &rc_benf {v1: { parents: 0, interior: { x1: { accountId32: { network: { any: true }, id: *rc_acc }}}}} relay_chain_beneficiary: &rc_benf {v3: { parents: 0, interior: { x1: { accountId32: { id: *rc_acc }}}}}
ksm: &ap_ksm { concrete: { parents: 1, interior: { here: true }}} ksm: &ap_ksm { concrete: { parents: 1, interior: { here: true }}}
ksm_fungible: &ap_ksm_fungible { id: *ap_ksm, fun: { fungible: *amount }} ksm_fungible: &ap_ksm_fungible { id: *ap_ksm, fun: { fungible: *amount }}
decodedCalls: decodedCalls:
@@ -38,7 +38,7 @@ tests:
describes: describes:
- name: polkadotXcm.limitedTeleportAssets - name: polkadotXcm.limitedTeleportAssets
before: before:
- name: DEPENDANCY | Do a 'limitedTeleportAssets' from the Relay Chain to the Assets Parachain to have funds to send them back - name: DEPENDENCY | Do a 'limitedTeleportAssets' from the Relay Chain to the Assets Parachain to have funds to send them back
actions: actions:
- extrinsics: - extrinsics:
- chain: *relay_chain - chain: *relay_chain
@@ -48,22 +48,24 @@ tests:
args: [ args: [
*ap_dest, # destination *ap_dest, # destination
*ap_benf, # beneficiary *ap_benf, # beneficiary
{ v1: [ *rc_ksm_fungible ] }, # assets { v3: [ *rc_ksm_fungible ] }, # assets
0, # feeAssetItem 0, # feeAssetItem
{ unlimited: true } # weightLimit { unlimited: true } # weightLimit
] ]
events: events:
- name: xcmPallet.Attempted - name: xcmPallet.Attempted
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
threshold: [10, 10]
value: {"refTime":"761,173,000","proofSize":"0"}
- name: dmpQueue.ExecutedDownward - name: dmpQueue.ExecutedDownward
chain: *assets_parachain chain: *assets_parachain
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
threshold: [10, 10] threshold: [10, 10]
value: 1,021,973,000 value: {"refTime":"162,379,000","proofSize":"0"}
- name: Get the balances of the Assets Parachain's sender & Relay Chain's receiver - name: Get the balances of the Assets Parachain's sender & Relay Chain's receiver
actions: actions:
@@ -89,24 +91,24 @@ tests:
args: [ args: [
*rc_dest, # destination *rc_dest, # destination
*rc_benf, # beneficiary *rc_benf, # beneficiary
{ v1: [ *ap_ksm_fungible ] }, # assets { v3: [ *ap_ksm_fungible ] }, # assets
0, # feeAssetItem 0, # feeAssetItem
{ unlimited: true } # weightLimit { unlimited: true } # weightLimit
] ]
events: events:
- name: polkadotXcm.Attempted - name: polkadotXcm.Attempted
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
threshold: [10, 10] threshold: [10, 10]
value: 360,315,000 value: {"refTime":"539,494,000","proofSize":"7,133"}
- name: ump.ExecutedUpward - name: ump.ExecutedUpward
chain: *relay_chain chain: *relay_chain
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
threshold: [10, 10] threshold: [10, 10]
value: 297,578,000 value: {"refTime":"298,716,000","proofSize":"0"}
- queries: - queries:
balance_ap_sender_after: balance_ap_sender_after:
chain: *assets_parachain chain: *assets_parachain
@@ -148,7 +150,7 @@ tests:
- name: polkadotXcm.send | Native - Transact(system.remark) - name: polkadotXcm.send | Native - Transact(system.remark)
its: its:
- name: Assets Parachain SHOULD NOT be able to dipatch 'send' call - name: Assets Parachain SHOULD NOT be able to dispatch 'send' call
actions: actions:
- extrinsics: - extrinsics:
- chain: *assets_parachain - chain: *assets_parachain
@@ -158,10 +160,15 @@ tests:
args: [ args: [
*rc_dest, # destination *rc_dest, # destination
{ {
v2: [ #message v3: [ #message
{
UnpaidExecution: {
weightLimit: Unlimited
}
},
{ {
Transact: { Transact: {
originType: Native, originKind: Native,
requireWeightAtMost: *weight_at_most, requireWeightAtMost: *weight_at_most,
call: $system_remark call: $system_remark
} }
@@ -171,8 +178,8 @@ tests:
] ]
events: events:
- name: system.ExtrinsicFailed - name: system.ExtrinsicFailed
attribute: attributes:
type: SpRuntimeDispatchError - type: SpRuntimeDispatchError
value: BadOrigin value: BadOrigin
- name: polkadotXcm.limitedReserveTransferAssets - name: polkadotXcm.limitedReserveTransferAssets
@@ -187,13 +194,13 @@ tests:
args: [ args: [
*rc_dest, # destination *rc_dest, # destination
*rc_benf, # beneficiary *rc_benf, # beneficiary
{ v1: [ *ap_ksm_fungible ] }, # assets { v3: [ *ap_ksm_fungible ] }, # assets
0, # feeAssetItem 0, # feeAssetItem
{ unlimited: true } # weightLimit { unlimited: true } # weightLimit
] ]
events: events:
- name: polkadotXcm.Attempted - name: polkadotXcm.Attempted
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isError: true xcmOutcome: Error
value: Barrier value: Barrier
@@ -0,0 +1,134 @@
---
settings:
chains:
relay_chain: &relay_chain
wsPort: 9900
assets_parachain: &assets_parachain
wsPort: 9910
paraId: &ap_id 1000
penpal_parachain: &penpal_parachain
wsPort: 9920
paraId: &pp_id 2000
variables:
common:
amount: &amount 2000000000000
require_weight_at_most: &weight_at_most {refTime: 1000000000, proofSize: 20000}
hrmp_channels:
proposed_max_capacity: &max_capacity 8
proposed_max_message_size: &max_message_size 8192
channel: &channel {
maxCapacity: 8,
maxTotalSize: 8192,
maxMessageSize: 8192,
msgCount: 0,
totalSize: 0,
mqcHead: null,
senderDeposit: 0,
recipientDeposit: 0
}
chains:
relay_chain:
signer: &rc_signer //Alice
assets_parachain_destination: &ap_dest { v3: { 0, interior: { x1: { parachain: *ap_id }}}}
assets_parachain_account: &ap_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'
assets_parachain_beneficiary: &ap_benf {v3: { parents: 0, interior: { x1: { accountId32: { id: *ap_acc }}}}}
ksm: &rc_ksm { concrete: { 0, interior: { here: true }}}
ksm_fungible: &rc_ksm_fungible { id: *rc_ksm, fun: { fungible: *amount }}
assets_parachain_account:
sovereign_account: &ap_sovereign F7fq1jSNVTPfJmaHaXCMtatT1EZefCUsa7rRiQVNR5efcah
relay_chain_destination: &rc_dest { v3: { parents: 1, interior: { here: true }}}
penpal_parachain:
sovereign_account: &pp_sovereign F7fq1jMZkfuCuoMTyiEVAP2DMpMt18WopgBqTJznLihLNbZ
signer: &pp_signer //Alice
tests:
- name: HRMP
beforeEach:
- name: DEPENDENCY | Penpal Parachain Sovereign account in the Relay Chain needs to be funded
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
pallet: balances
call: transfer
args: [
*pp_sovereign, # destination
*amount, # value
]
events:
- name: balances.Transfer
- name: DEPENDENCY | Assets Parachain Sovereign account in the Relay Chain needs to be funded
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
pallet: balances
call: transfer
args: [
*ap_sovereign, # destination
*amount, # value
]
events:
- name: balances.Transfer
describes:
- name: hrmp.hrmpInitOpenChannel (Penpal Parachain → Assets Parachain)
its:
- name: Open Penpal Parachain to Assets Parachain
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
sudo: true
pallet: hrmp
call: forceOpenHrmpChannel
args: [
2000,
1000,
8,
8192
]
events:
- name: sudo.Sudid
attributes:
- type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: hrmp.HrmpChannelForceOpened
- name: hrmp.hrmpInitOpenChannel (Assets Parachain → PenPal Parachain)
its:
- name: Open Assets Parachain to PenPal Parachain
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
sudo: true
pallet: hrmp
call: forceOpenHrmpChannel
args: [
1000,
2000,
8,
8192
]
events:
- name: sudo.Sudid
attributes:
- type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: hrmp.HrmpChannelForceOpened
- name: hrmp.forceProcessHrmpOpen (make sure all the channels are open)
its:
- name: Make sure all the pending channels are open
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
sudo: true
pallet: hrmp
call: forceProcessHrmpOpen
args: [ 2 ]
events:
- name: sudo.Sudid
attributes:
- type: Result<Null, SpRuntimeDispatchError>
value: Ok
@@ -0,0 +1,403 @@
---
# Note: This tests depends on the 3_hrmp-open-channels.yml for opening channels, otherwise teleports aren't going to
# work.
settings:
chains:
relay_chain: &relay_chain
wsPort: 9900
assets_parachain: &assets_parachain
wsPort: 9910
paraId: &ap_id 1000
penpal_parachain: &penpal_parachain
wsPort: 9920
paraId: &pp_id 2000
variables:
common:
mint_amount: &mint_amount 1000000000000
amount: &amount 100000000000
require_weight_at_most: &weight_at_most {refTime: 1200000000, proofSize: 20000}
amount_to_send: &amount_to_send 500000000000
chains:
relay_chain:
signer: &rc_signer //Alice
assets_parachain_destination: &ap_dest { v3: { 0, interior: { x1: { parachain: *ap_id }}}}
assets_parachain_dest_routed: &ap_dest_routed { v3: { parents: 1, interior: { x1: { parachain: *ap_id } }}}
assets_parachain_account:
signer: &ap_signer //Alice
wallet: &ap_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F
asset_id: &asset_id 2
assets_pallet_id: &assets_pallet_id 50
asset_min_balance: &asset_ed 1000
penpal_parachain_destination: &pp_dest { v3: { parents: 1, interior: { x1: { parachain: *pp_id } }}}
ksm: &ap_ksm { concrete: { parents: 1, interior: { here: true }}}
ksm_fungible: &ap_ksm_fungible { id: *ap_ksm, fun: { fungible: *amount }}
suff_asset: &suff_asset { concrete: { parents: 0, interior: { x2: [ { PalletInstance: *assets_pallet_id }, { GeneralIndex: *asset_id } ] }}}
suff_asset_fail: &suff_asset_fail { concrete: { parents: 0, interior: { x2: [ { PalletInstance: *assets_pallet_id }, { GeneralIndex: 3 } ] }}}
suff_asset_fungible_fail: &ap_suff_asset_fungible_fail { id: *suff_asset_fail, fun: { fungible: 200000000000 }}
penpal_parachain:
sovereign_account: &pp_sovereign_sibl FBeL7EAeUroLWXW1yfKboiqTqVfbRBcsUKd6QqVf4kGBySS
signer: &pp_signer //Alice
penpal_parachain_account: &pp_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'
decodedCalls:
force_create_asset:
chain: *assets_parachain
pallet: assets
call: forceCreate
args: [
*asset_id,
{ Id: *ap_wallet }, # owner
true, # isSufficient
*asset_ed # minBalance
]
force_create_asset2:
chain: *assets_parachain
pallet: assets
call: forceCreate
args: [
*asset_id,
{ Id: *ap_wallet }, # owner
true, # isSufficient
*asset_ed # minBalance
]
tests:
- name: HRMP
describes:
- name: polkadotXcm.limitedReserveTransferAssets (Asset) | Assets Parachain -> Penpal Parachain
before:
- name: DEPENDENCY | A sufficient Asset should exist in the Assets Parachain
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
sudo: true
pallet: xcmPallet
call: send
args: [
*ap_dest, # destination
{
v3: [ #message
{
UnpaidExecution: {
weightLimit: Unlimited
}
},
{
SetTopic: "0x0123456789012345678901234567891201234567890123456789012345678912"
},
{
Transact: {
originKind: Superuser,
requireWeightAtMost: *weight_at_most,
call: $force_create_asset
}
}
]
}
]
events:
- name: xcmPallet.Sent
- name: dmpQueue.ExecutedDownward
chain: *assets_parachain
attributes:
- type: XcmV3TraitsOutcome
xcmOutcome: Complete
threshold: [10, 10]
value: {"refTime":"1,216,703,000","proofSize":"20,000"}
- queries:
forced_created_asset:
chain: *assets_parachain
pallet: assets
call: asset
args: [ *asset_id ]
- asserts:
isSome:
args: [ $forced_created_asset ]
- name: DEPENDENCY | Some Assets should be minted for the sender
actions:
- extrinsics:
- chain: *assets_parachain
signer: *ap_signer
pallet: assets
call: mint
args: [
*asset_id,
*ap_wallet,
*mint_amount
]
events:
- name: assets.Issued
its:
- name: Assets Parachain should be able to reserve transfer an Asset to Penpal Parachain
actions:
- extrinsics:
- chain: *assets_parachain
signer: *ap_signer
pallet: polkadotXcm
call: limitedReserveTransferAssets
args: [
*pp_dest, # destination
{ # beneficiary
V3: {
parents: 0,
interior: {
X1: {
AccountId32: {
id: *pp_acc
}
}
}
}
},
{ # assets
V3: [
{
id: {
Concrete: {
parents: 0,
interior: {
X2: [
{
PalletInstance: *assets_pallet_id
},
{
GeneralIndex: *asset_id
}
]
}
}
},
fun: {
Fungible: *amount_to_send
}
}
]
},
0, # feeAssetItem
Unlimited # weightLimit
]
events:
- name: polkadotXcm.Attempted
attributes:
- type: XcmV3TraitsOutcome
xcmOutcome: Complete
threshold: [10, 10]
value: {"refTime":"679,150,000","proofSize":"6,196"}
- name: assets.Transferred
attributes:
- type: AccountId32
value: *pp_sovereign_sibl
- name: assets.Transferred
attributes:
- type: u128
value: *amount_to_send
- name: polkadotXcm.limitedReserveTransferAssets (KSM) | Assets Parachain -> Penpal Parachain
its:
- name: Assets Parachain should be able to reserve transfer KSM to Penpal Parachain
actions:
- extrinsics:
- chain: *assets_parachain
signer: *ap_signer
pallet: polkadotXcm
call: limitedReserveTransferAssets
args: [
*pp_dest, # destination
{ # beneficiary
V3: {
parents: 0,
interior: {
X1: {
AccountId32: {
id: *pp_acc
}
}
}
}
},
{ # assets
V3: [
*ap_ksm_fungible
]
},
0, # feeAssetItem
Unlimited # weightLimit
]
events:
- name: polkadotXcm.Attempted
attributes:
- type: XcmV3TraitsOutcome
xcmOutcome: Complete
threshold: [10, 10]
value: {"refTime":"679,150,000","proofSize":"6,196"}
- name: balances.Endowed
attributes:
- type: AccountId32
value: *pp_sovereign_sibl
- name: balances.Endowed
attributes:
- type: u128
value: *amount
- name: polkadotXcm.send( assets.forceCreateAsset ) | Penpal Parachain -> Assets Parachain
before:
- name: Get the asset balance of the Penpal Parachain Sovereign account in Assets Parachain
actions:
- queries:
assets_balance_pp_sovereign_before:
chain: *assets_parachain
pallet: assets
call: account
args: [
*asset_id,
*pp_sovereign_sibl
]
its:
- name: Penpal Parachain should be able to send XCM message paying its fee with sufficient asset in Assets Parachain
actions:
- extrinsics:
- chain: *penpal_parachain
signer: *pp_signer
sudo: true
pallet: polkadotXcm
call: send
args: [
*ap_dest_routed, # destination
{
v3: [ #message
{
WithdrawAsset: [
{
id: {
concrete: {
parents: 0,
interior: {
X2: [
{ PalletInstance: *assets_pallet_id },
{ GeneralIndex: *asset_id }
]
}
}
},
fun: { fungible: *amount }}
]
},
{
BuyExecution: {
fees: { id: *suff_asset, fun: { fungible: *amount }},
weightLimit: Unlimited
}
},
{
Transact: {
originKind: SovereignAccount,
requireWeightAtMost: *weight_at_most,
call: $force_create_asset2
}
},
{
RefundSurplus
},
{
DepositAsset: {
assets: { Wild: All },
beneficiary: {
parents: 0,
interior: {
X1: {
AccountId32: {
network: , # None
id: *pp_acc
}
}
}}
}
}
]
}
]
events:
- name: sudo.Sudid
attributes:
- type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: polkadotXcm.Sent
- name: assets.Burned
chain: *assets_parachain
attributes:
- type: AccountId32
value: *pp_sovereign_sibl
- name: assets.Issued
chain: *assets_parachain
attributes:
- type: u32
value: *asset_id
- queries:
assets_balance_pp_sovereign_after:
chain: *assets_parachain
pallet: assets
call: account
args: [
*asset_id,
*pp_sovereign_sibl
]
forced_created_asset2:
chain: *assets_parachain
pallet: assets
call: asset
args: [ 3 ]
- asserts:
isSome:
args: [ $forced_created_asset2 ]
- name: Should reduce the assets balance of the Penpal Parachain's SovereignAccount in the Assets Parachain
actions:
- asserts:
assetsDecreased:
args: [
{
balances: {
before: $assets_balance_pp_sovereign_before,
after: $assets_balance_pp_sovereign_after,
},
}
]
- name: Penpal Parachain SHOULD NOT be able to send XCM message paying its fee with sufficient assets if not enough balance
actions:
- extrinsics:
- chain: *penpal_parachain
signer: *pp_signer
sudo: true
pallet: polkadotXcm
call: send
args: [
*ap_dest_routed, # destination
{
v3: [ #message
{
WithdrawAsset: [*ap_suff_asset_fungible_fail]
},
{
BuyExecution: {
fees: *ap_suff_asset_fungible_fail,
weightLimit: Unlimited
}
},
{
Transact: {
originKind: SovereignAccount,
requireWeightAtMost: *weight_at_most,
call: $force_create_asset2
}
}
]
}
]
events:
- name: xcmpQueue.Fail
chain: *assets_parachain
attributes:
- type: XcmV3TraitsError
value: FailedToTransactAsset
@@ -0,0 +1,70 @@
[relaychain]
default_command = "./bin/polkadot"
default_args = [ "-lparachain=debug", "-lxcm=trace" ]
chain = "kusama-local"
[[relaychain.nodes]]
name = "alice"
ws_port = 9900
validator = true
[[relaychain.nodes]]
name = "bob"
ws_port = 9901
validator = true
[[relaychain.nodes]]
name = "charlie"
ws_port = 9902
validator = true
[[relaychain.nodes]]
name = "dave"
ws_port = 9903
validator = true
[[parachains]]
id = 1000
chain = "statemine-local"
cumulus_based = true
[[parachains.collators]]
name = "collator1"
ws_port = 9910
command = "./bin/polkadot-parachain"
args = [ "-lxcm=trace" ]
[[parachains.collators]]
name = "collator2"
ws_port = 9911
command = "./bin/polkadot-parachain"
args = [ "-lxcm=trace" ]
[[parachains]]
id = 2000
chain = "penpal-kusama-2000"
cumulus_based = true
[[parachains.collators]]
name = "collator3"
ws_port = 9920
command = "./bin/polkadot-parachain"
args = [ "-lxcm=trace" ]
[[parachains.collators]]
name = "collator4"
ws_port = 9921
command = "./bin/polkadot-parachain"
args = [ "-lxcm=trace" ]
# [[hrmpChannels]]
# sender = 1000
# recipient = 2000
# maxCapacity = 8
# maxMessageSize = 8192
# [[hrmpChannels]]
# sender = 2000
# recipient = 1000
# maxCapacity = 8
# maxMessageSize = 8192
@@ -2,21 +2,21 @@
settings: settings:
chains: chains:
relay_chain: &relay_chain relay_chain: &relay_chain
wsPort: 9900 wsPort: 9800
assets_parachain: &assets_parachain assets_parachain: &assets_parachain
wsPort: 9910 wsPort: 9810
paraId: &ap_id 1000 paraId: &ap_id 1000
penpal_parachain: &penpal_parachain penpal_parachain: &penpal_parachain
wsPort: 9920 wsPort: 9820
paraId: &pp_id 2000 paraId: &pp_id 2000
variables: variables:
common: common:
xcm_verison: &xcm_version '2' xcm_version: &xcm_version '3'
require_weight_at_most: &weight_at_most 1000000000 require_weight_at_most: &weight_at_most {refTime: 1000000000, proofSize: 200000}
chains: chains:
relay_chain: relay_chain:
signer: &rc_signer //Alice signer: &rc_signer //Alice
assets_parachain_destination: &ap_dest { v1: { 0, interior: { x1: { parachain: *ap_id }}}} assets_parachain_destination: &ap_dest { v3: { 0, interior: { x1: { parachain: *ap_id }}}}
penpal_parachain: penpal_parachain:
signer: &pp_signer //Alice signer: &pp_signer //Alice
decodedCalls: decodedCalls:
@@ -37,7 +37,7 @@ tests:
its: its:
- name: XCM supported versions between chains - name: XCM supported versions between chains
actions: actions:
- extrinsics: # Relay Chain sets supported version for Assset Parachain - extrinsics: # Relay Chain sets supported version for Asset Parachain
- chain: *relay_chain - chain: *relay_chain
sudo: true sudo: true
signer: *rc_signer signer: *rc_signer
@@ -56,12 +56,12 @@ tests:
] ]
events: events:
- name: sudo.Sudid - name: sudo.Sudid
attribute: attributes:
type: Result<Null, SpRuntimeDispatchError> - type: Result<Null, SpRuntimeDispatchError>
value: Ok value: Ok
- name: xcmPallet.SupportedVersionChanged - name: xcmPallet.SupportedVersionChanged
attribute: attributes:
type: u32 - type: u32
value: *xcm_version value: *xcm_version
- extrinsics: # Relay Chain sets supported version for Penpal Parachain - extrinsics: # Relay Chain sets supported version for Penpal Parachain
- chain: *relay_chain - chain: *relay_chain
@@ -82,14 +82,14 @@ tests:
] ]
events: events:
- name: sudo.Sudid - name: sudo.Sudid
attribute: attributes:
type: Result<Null, SpRuntimeDispatchError> - type: Result<Null, SpRuntimeDispatchError>
value: Ok value: Ok
- name: xcmPallet.SupportedVersionChanged - name: xcmPallet.SupportedVersionChanged
attribute: attributes:
type: u32 - type: u32
value: *xcm_version value: *xcm_version
- extrinsics: # Assset Parachain sets supported version for Relay Chain through it - extrinsics: # Asset Parachain sets supported version for Relay Chain through it
- chain: *relay_chain - chain: *relay_chain
signer: *rc_signer signer: *rc_signer
sudo: true sudo: true
@@ -98,10 +98,20 @@ tests:
args: [ args: [
*ap_dest, # destination *ap_dest, # destination
{ {
v2: [ #message v3: [ #message
{
UnpaidExecution: {
weightLimit: {
limited: {
refTime: 3200000000,
proofSize: 200000
}
}
}
},
{ {
Transact: { Transact: {
originType: Superuser, originKind: Superuser,
requireWeightAtMost: *weight_at_most, requireWeightAtMost: *weight_at_most,
call: $ap_force_xcm_version call: $ap_force_xcm_version
} }
@@ -111,14 +121,14 @@ tests:
] ]
events: events:
- name: sudo.Sudid - name: sudo.Sudid
attribute: attributes:
type: Result<Null, SpRuntimeDispatchError> - type: Result<Null, SpRuntimeDispatchError>
value: Ok value: Ok
- name: xcmPallet.Sent - name: xcmPallet.Sent
- name: polkadotXcm.SupportedVersionChanged - name: polkadotXcm.SupportedVersionChanged
chain: *assets_parachain chain: *assets_parachain
attribute: attributes:
type: u32 - type: u32
value: *xcm_version value: *xcm_version
- extrinsics: # Penpal Parachain sets supported version for Relay Chain - extrinsics: # Penpal Parachain sets supported version for Relay Chain
- chain: *penpal_parachain - chain: *penpal_parachain
@@ -135,10 +145,10 @@ tests:
] ]
events: events:
- name: sudo.Sudid - name: sudo.Sudid
attribute: attributes:
type: Result<Null, SpRuntimeDispatchError> - type: Result<Null, SpRuntimeDispatchError>
value: Ok value: Ok
- name: polkadotXcm.SupportedVersionChanged - name: polkadotXcm.SupportedVersionChanged
attribute: attributes:
type: u32 - type: u32
value: *xcm_version value: *xcm_version
@@ -2,21 +2,21 @@
settings: settings:
chains: chains:
relay_chain: &relay_chain relay_chain: &relay_chain
wsPort: 9900 wsPort: 9800
assets_parachain: &assets_parachain assets_parachain: &assets_parachain
wsPort: 9910 wsPort: 9810
paraId: &ap_id 1000 paraId: &ap_id 1000
variables: variables:
relay_chain: relay_chain:
signer: &rc_signer //Alice signer: &rc_signer //Alice
wallet: &rc_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F wallet: &rc_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F
assets_parachain_destination: &ap_dest { v1: { parents: 0, interior: { x1: { parachain: *ap_id }}}} assets_parachain_destination: &ap_dest { v3: { parents: 0, interior: { x1: { parachain: *ap_id }}}}
assets_parachain_account: &ap_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d' assets_parachain_account: &ap_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'
assets_parachain_beneficiary: &ap_benf {v1: { parents: 0, interior: { x1: { accountId32: { network: { any: true }, id: *ap_acc }}}}} assets_parachain_beneficiary: &ap_benf {v3: { parents: 0, interior: { x1: { accountId32: { id: *ap_acc }}}}}
ksm: &rc_ksm { concrete: { parents: 0, interior: { here: true }}} ksm: &rc_ksm { concrete: { parents: 0, interior: { here: true }}}
amount: &amount 1000000000000 amount: &amount 1000000000000
ksm_fungible: &rc_ksm_fungible { id: *rc_ksm, fun: { fungible: *amount }} ksm_fungible: &rc_ksm_fungible { id: *rc_ksm, fun: { fungible: *amount }}
require_weight_at_most: &rc_weight_at_most 1000000000 require_weight_at_most: &rc_weight_at_most {refTime: 1000000000, proofSize: 200000}
assets_parachain_account: assets_parachain_account:
wallet: &ap_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F wallet: &ap_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F
asset_id: &asset_id 1 asset_id: &asset_id 1
@@ -63,22 +63,22 @@ tests:
args: [ args: [
*ap_dest, # destination *ap_dest, # destination
*ap_benf, # beneficiary *ap_benf, # beneficiary
{ v1: [ *rc_ksm_fungible ] }, # assets { v3: [ *rc_ksm_fungible ] }, # assets
0, # feeAssetItem 0, # feeAssetItem
{ unlimited: true } # weightLimit { unlimited: true } # weightLimit
] ]
events: events:
- name: xcmPallet.Attempted - name: xcmPallet.Attempted
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
- name: dmpQueue.ExecutedDownward - name: dmpQueue.ExecutedDownward
chain: *assets_parachain chain: *assets_parachain
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
threshold: [10, 10] threshold: [10, 10]
value: 1,021,973,000 value: {"refTime":"162,909,000","proofSize":"0"}
- queries: - queries:
balance_rc_sender_after: balance_rc_sender_after:
chain: *relay_chain chain: *relay_chain
@@ -131,7 +131,12 @@ tests:
args: [ args: [
*ap_dest, # destination *ap_dest, # destination
{ {
v2: [ #message v3: [ #message
{
UnpaidExecution: {
weightLimit: Unlimited
}
},
{ {
Transact: { Transact: {
originType: Superuser, originType: Superuser,
@@ -146,11 +151,11 @@ tests:
- name: xcmPallet.Sent - name: xcmPallet.Sent
- name: dmpQueue.ExecutedDownward - name: dmpQueue.ExecutedDownward
chain: *assets_parachain chain: *assets_parachain
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
threshold: [10, 10] threshold: [10, 10]
value: 1,021,258,000 value: {"refTime":"1,015,234,000","proofSize":"200,000"}
- queries: - queries:
forced_created_asset: forced_created_asset:
chain: *assets_parachain chain: *assets_parachain
@@ -173,7 +178,12 @@ tests:
args: [ args: [
*ap_dest, # destination *ap_dest, # destination
{ {
v2: [ #message v3: [ #message
{
UnpaidExecution: {
weightLimit: Unlimited
}
},
{ {
Transact: { Transact: {
originType: Native, originType: Native,
@@ -186,8 +196,8 @@ tests:
] ]
events: events:
- name: system.ExtrinsicFailed - name: system.ExtrinsicFailed
attribute: attributes:
type: SpRuntimeDispatchError - type: SpRuntimeDispatchError
value: BadOrigin value: BadOrigin
- name: xcmPallet.limitedReserveTransferAssets - name: xcmPallet.limitedReserveTransferAssets
@@ -203,23 +213,22 @@ tests:
args: [ args: [
*ap_dest, # destination *ap_dest, # destination
*ap_benf, # beneficiary *ap_benf, # beneficiary
{ v1: [ *rc_ksm_fungible ] }, # assets { v3: [ *rc_ksm_fungible ] }, # assets
0, # feeAssetItem 0, # feeAssetItem
{ unlimited: true } # weightLimit { unlimited: true } # weightLimit
] ]
events: events:
- name: xcmPallet.Attempted - name: xcmPallet.Attempted
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
threshold: [10, 10] value: {"refTime":"2,000,000,000","proofSize":"0"}
value: 750,645,000
- name: dmpQueue.ExecutedDownward - name: dmpQueue.ExecutedDownward
chain: *assets_parachain chain: *assets_parachain
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isError: true xcmOutcome: Incomplete
value: "WeightNotComputable" value: [{"refTime":"1,000,000,000","proofSize":"0"},"UntrustedReserveLocation"]
- queries: - queries:
balance_rc_sender_after: balance_rc_sender_after:
chain: *relay_chain chain: *relay_chain
@@ -2,28 +2,28 @@
settings: settings:
chains: chains:
relay_chain: &relay_chain relay_chain: &relay_chain
wsPort: 9900 wsPort: 9800
assets_parachain: &assets_parachain assets_parachain: &assets_parachain
wsPort: 9910 wsPort: 9810
paraId: &ap_id 1000 paraId: &ap_id 1000
variables: variables:
common: common:
amount: &amount 1000000000000 amount: &amount 1000000000000
require_weight_at_most: &weight_at_most 1000000000 require_weight_at_most: &weight_at_most {refTime: 1000000000, proofSize: 0}
relay_chain: relay_chain:
signer: &rc_signer //Alice signer: &rc_signer //Alice
wallet: &rc_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F wallet: &rc_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F
assets_parachain_destination: &ap_dest { v1: { 0, interior: { x1: { parachain: *ap_id }}}} assets_parachain_destination: &ap_dest { v3: { 0, interior: { x1: { parachain: *ap_id }}}}
assets_parachain_account: &ap_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d' assets_parachain_account: &ap_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'
assets_parachain_beneficiary: &ap_benf {v1: { parents: 0, interior: { x1: { accountId32: { network: { any: true }, id: *ap_acc }}}}} assets_parachain_beneficiary: &ap_benf {v3: { parents: 0, interior: { x1: { accountId32: { id: *ap_acc }}}}}
ksm: &rc_ksm { concrete: { 0, interior: { here: true }}} ksm: &rc_ksm { concrete: { 0, interior: { here: true }}}
ksm_fungible: &rc_ksm_fungible { id: *rc_ksm, fun: { fungible: *amount }} ksm_fungible: &rc_ksm_fungible { id: *rc_ksm, fun: { fungible: *amount }}
assets_parachain_account: assets_parachain_account:
signer: &ap_signer //Alice signer: &ap_signer //Alice
wallet: &ap_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F wallet: &ap_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F
relay_chain_destination: &rc_dest { v1: { parents: 1, interior: { here: true }}} relay_chain_destination: &rc_dest { v3: { parents: 1, interior: { here: true }}}
assets_parachain_account: &rc_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d' assets_parachain_account: &rc_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'
relay_chain_beneficiary: &rc_benf {v1: { parents: 0, interior: { x1: { accountId32: { network: { any: true }, id: *rc_acc }}}}} relay_chain_beneficiary: &rc_benf {v3: { parents: 0, interior: { x1: { accountId32: { id: *rc_acc }}}}}
ksm: &ap_ksm { concrete: { parents: 1, interior: { here: true }}} ksm: &ap_ksm { concrete: { parents: 1, interior: { here: true }}}
ksm_fungible: &ap_ksm_fungible { id: *ap_ksm, fun: { fungible: *amount }} ksm_fungible: &ap_ksm_fungible { id: *ap_ksm, fun: { fungible: *amount }}
decodedCalls: decodedCalls:
@@ -38,7 +38,7 @@ tests:
describes: describes:
- name: polkadotXcm.limitedTeleportAssets - name: polkadotXcm.limitedTeleportAssets
before: before:
- name: DEPENDANCY | Do a 'limitedTeleportAssets' from the Relay Chain to the Assets Parachain to have funds to send them back - name: DEPENDENCY | Do a 'limitedTeleportAssets' from the Relay Chain to the Assets Parachain to have funds to send them back
actions: actions:
- extrinsics: - extrinsics:
- chain: *relay_chain - chain: *relay_chain
@@ -48,22 +48,23 @@ tests:
args: [ args: [
*ap_dest, # destination *ap_dest, # destination
*ap_benf, # beneficiary *ap_benf, # beneficiary
{ v1: [ *rc_ksm_fungible ] }, # assets { v3: [ *rc_ksm_fungible ] }, # assets
0, # feeAssetItem 0, # feeAssetItem
{ unlimited: true } # weightLimit { unlimited: true } # weightLimit
] ]
events: events:
- name: xcmPallet.Attempted - name: xcmPallet.Attempted
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
value: {"refTime":"3,000,000,000","proofSize":"0"}
- name: dmpQueue.ExecutedDownward - name: dmpQueue.ExecutedDownward
chain: *assets_parachain chain: *assets_parachain
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
threshold: [10, 10] threshold: [10, 10]
value: 1,021,635,000 value: {"refTime":"162,909,000","proofSize":"0"}
- name: Get the balances of the Assets Parachain's sender & Relay Chain's receiver - name: Get the balances of the Assets Parachain's sender & Relay Chain's receiver
actions: actions:
@@ -90,23 +91,23 @@ tests:
args: [ args: [
*rc_dest, # destination *rc_dest, # destination
*rc_benf, # beneficiary *rc_benf, # beneficiary
{ v1: [ *ap_ksm_fungible ] }, # assets { v3: [ *ap_ksm_fungible ] }, # assets
0, # feeAssetItem 0, # feeAssetItem
{ unlimited: true } # weightLimit { unlimited: true } # weightLimit
] ]
events: events:
- name: polkadotXcm.Attempted - name: polkadotXcm.Attempted
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
threshold: [10, 10] threshold: [10, 10]
value: 358,878,000 value: {"refTime":"533,283,000","proofSize":"7,096"}
- name: ump.ExecutedUpward - name: ump.ExecutedUpward
chain: *relay_chain chain: *relay_chain
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isComplete: true xcmOutcome: Complete
value: 4,000,000,000 value: {"refTime":"4,000,000,000","proofSize":"0"}
- queries: - queries:
balance_ap_sender_after: balance_ap_sender_after:
chain: *assets_parachain chain: *assets_parachain
@@ -148,7 +149,7 @@ tests:
- name: polkadotXcm.send | Native - Transact(system.remark) - name: polkadotXcm.send | Native - Transact(system.remark)
its: its:
- name: Assets Parachain SHOULD NOT be able to dipatch 'send' call - name: Assets Parachain SHOULD NOT be able to dispatch 'send' call
actions: actions:
- extrinsics: - extrinsics:
- chain: *assets_parachain - chain: *assets_parachain
@@ -158,7 +159,12 @@ tests:
args: [ args: [
*rc_dest, # destination *rc_dest, # destination
{ {
v2: [ #message v3: [ #message
{
UnpaidExecution: {
weightLimit: Unlimited
}
},
{ {
Transact: { Transact: {
originType: Native, originType: Native,
@@ -171,8 +177,8 @@ tests:
] ]
events: events:
- name: system.ExtrinsicFailed - name: system.ExtrinsicFailed
attribute: attributes:
type: SpRuntimeDispatchError - type: SpRuntimeDispatchError
value: BadOrigin value: BadOrigin
- name: polkadotXcm.limitedReserveTransferAssets - name: polkadotXcm.limitedReserveTransferAssets
@@ -187,13 +193,13 @@ tests:
args: [ args: [
*rc_dest, # destination *rc_dest, # destination
*rc_benf, # beneficiary *rc_benf, # beneficiary
{ v1: [ *ap_ksm_fungible ] }, # assets { v3: [ *ap_ksm_fungible ] }, # assets
0, # feeAssetItem 0, # feeAssetItem
{ unlimited: true } # weightLimit { unlimited: true } # weightLimit
] ]
events: events:
- name: polkadotXcm.Attempted - name: polkadotXcm.Attempted
attribute: attributes:
type: XcmV2TraitsOutcome - type: XcmV3TraitsOutcome
isError: true xcmOutcome: Error
value: Barrier value: Barrier
@@ -0,0 +1,132 @@
---
settings:
chains:
relay_chain: &relay_chain
wsPort: 9800
assets_parachain: &assets_parachain
wsPort: 9810
paraId: &ap_id 1000
penpal_parachain: &penpal_parachain
wsPort: 9820
paraId: &pp_id 2000
variables:
common:
amount: &amount 2000000000000
require_weight_at_most: &weight_at_most {refTime: 1000000000, proofSize: 20000}
hrmp_channels:
proposed_max_capacity: &max_capacity 8
proposed_max_message_size: &max_message_size 8192
channel: &channel {
maxCapacity: 8,
maxTotalSize: 8192,
maxMessageSize: 8192,
msgCount: 0,
totalSize: 0,
mqcHead: null,
senderDeposit: 0,
recipientDeposit: 0
}
chains:
relay_chain:
signer: &rc_signer //Alice
assets_parachain_destination: &ap_dest { v3: { 0, interior: { x1: { parachain: *ap_id }}}}
ksm: &rc_ksm { concrete: { 0, interior: { here: true }}}
ksm_fungible: &rc_ksm_fungible { id: *rc_ksm, fun: { fungible: *amount }}
assets_parachain_account:
sovereign_account: &ap_sovereign 5Ec4AhPZk8STuex8Wsi9TwDtJQxKqzPJRCH7348Xtcs9vZLJ
relay_chain_destination: &rc_dest { v3: { parents: 1, interior: { here: true }}}
penpal_parachain:
sovereign_account: &pp_sovereign F7fq1jMZkfuCuoMTyiEVAP2DMpMt18WopgBqTJznLihLNbZ
signer: &pp_signer //Alice
tests:
- name: HRMP
beforeEach:
- name: DEPENDENCY | Penpal Parachain Sovereign account in the Relay Chain needs to be funded
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
pallet: balances
call: transfer
args: [
*pp_sovereign, # destination
*amount, # value
]
events:
- name: balances.Transfer
- name: DEPENDENCY | Assets Parachain Sovereign account in the Relay Chain needs to be funded
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
pallet: balances
call: transfer
args: [
*ap_sovereign, # destination
*amount, # value
]
events:
- name: balances.Transfer
describes:
- name: hrmp.hrmpInitOpenChannel (Penpal Parachain → Assets Parachain)
its:
- name: Open Penpal Parachain to Assets Parachain
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
sudo: true
pallet: hrmp
call: forceOpenHrmpChannel
args: [
2000,
1000,
8,
8192
]
events:
- name: sudo.Sudid
attributes:
- type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: hrmp.HrmpChannelForceOpened
- name: hrmp.hrmpInitOpenChannel (Assets Parachain → PenPal Parachain)
its:
- name: Open Assets Parachain to PenPal Parachain
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
sudo: true
pallet: hrmp
call: forceOpenHrmpChannel
args: [
1000,
2000,
8,
8192
]
events:
- name: sudo.Sudid
attributes:
- type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: hrmp.HrmpChannelForceOpened
- name: hrmp.forceProcessHrmpOpen (make sure all the channels are open)
its:
- name: Make sure all the pending channels are open
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
sudo: true
pallet: hrmp
call: forceProcessHrmpOpen
args: [ 2 ]
events:
- name: sudo.Sudid
attributes:
- type: Result<Null, SpRuntimeDispatchError>
value: Ok
@@ -0,0 +1,401 @@
---
settings:
chains:
relay_chain: &relay_chain
wsPort: 9800
assets_parachain: &assets_parachain
wsPort: 9810
paraId: &ap_id 1000
penpal_parachain: &penpal_parachain
wsPort: 9820
paraId: &pp_id 2000
variables:
common:
mint_amount: &mint_amount 1000000000000
amount: &amount 1000000000000
require_weight_at_most: &weight_at_most {refTime: 1200000000, proofSize: 20000}
amount_to_send: &amount_to_send 500000000000
chains:
relay_chain:
signer: &rc_signer //Alice
assets_parachain_destination: &ap_dest { v3: { 0, interior: { x1: { parachain: *ap_id }}}}
assets_parachain_dest_routed: &ap_dest_routed { v3: { parents: 1, interior: { x1: { parachain: *ap_id } }}}
assets_parachain_account:
signer: &ap_signer //Alice
wallet: &ap_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F
asset_id: &asset_id 2
assets_pallet_id: &assets_pallet_id 50
asset_min_balance: &asset_ed 1000
penpal_parachain_destination: &pp_dest { v3: { parents: 1, interior: { x1: { parachain: *pp_id } }}}
ksm: &ap_ksm { concrete: { parents: 1, interior: { here: true }}}
ksm_fungible: &ap_ksm_fungible { id: *ap_ksm, fun: { fungible: *amount }}
suff_asset: &suff_asset { concrete: { parents: 0, interior: { x2: [ { PalletInstance: *assets_pallet_id }, { GeneralIndex: *asset_id } ] }}}
suff_asset_fail: &suff_asset_fail { concrete: { parents: 0, interior: { x2: [ { PalletInstance: *assets_pallet_id }, { GeneralIndex: 3 } ] }}}
suff_asset_fungible_fail: &ap_suff_asset_fungible_fail { id: *suff_asset_fail, fun: { fungible: 200000000000 }}
penpal_parachain:
sovereign_account: &pp_sovereign_sibl 13cKp89Msu7M2PiaCuuGr1BzAsD5V3vaVbDMs3YtjMZHdGwR
signer: &pp_signer //Alice
penpal_parachain_account: &pp_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'
decodedCalls:
force_create_asset:
chain: *assets_parachain
pallet: assets
call: forceCreate
args: [
*asset_id,
{ Id: *ap_wallet }, # owner
true, # isSufficient
*asset_ed # minBalance
]
force_create_asset2:
chain: *assets_parachain
pallet: assets
call: forceCreate
args: [
*asset_id,
{ Id: *ap_wallet }, # owner
true, # isSufficient
*asset_ed # minBalance
]
tests:
- name: HRMP
describes:
- name: polkadotXcm.limitedReserveTransferAssets (Asset) | Assets Parachain -> Penpal Parachain
before:
- name: DEPENDENCY | A sufficient Asset should exist in the Assets Parachain
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
sudo: true
pallet: xcmPallet
call: send
args: [
*ap_dest, # destination
{
v3: [ #message
{
UnpaidExecution: {
weightLimit: Unlimited
}
},
{
SetTopic: "0x0123456789012345678901234567891201234567890123456789012345678912"
},
{
Transact: {
originKind: Superuser,
requireWeightAtMost: *weight_at_most,
call: $force_create_asset
}
}
]
}
]
events:
- name: xcmPallet.Sent
- name: dmpQueue.ExecutedDownward
chain: *assets_parachain
attributes:
- type: XcmV3TraitsOutcome
xcmOutcome: Complete
threshold: [10, 10]
value: {"refTime":"1,218,405,000","proofSize":"20,000"}
- queries:
forced_created_asset:
chain: *assets_parachain
pallet: assets
call: asset
args: [ *asset_id ]
- asserts:
isSome:
args: [ $forced_created_asset ]
- name: DEPENDENCY | Some Assets should be minted for the sender
actions:
- extrinsics:
- chain: *assets_parachain
signer: *ap_signer
pallet: assets
call: mint
args: [
*asset_id,
*ap_wallet,
*mint_amount
]
events:
- name: assets.Issued
its:
- name: Assets Parachain should be able to reserve transfer an Asset to Penpal Parachain
actions:
- extrinsics:
- chain: *assets_parachain
signer: *ap_signer
pallet: polkadotXcm
call: limitedReserveTransferAssets
args: [
*pp_dest, # destination
{ # beneficiary
V3: {
parents: 0,
interior: {
X1: {
AccountId32: {
id: *pp_acc
}
}
}
}
},
{ # assets
V3: [
{
id: {
Concrete: {
parents: 0,
interior: {
X2: [
{
PalletInstance: *assets_pallet_id
},
{
GeneralIndex: *asset_id
}
]
}
}
},
fun: {
Fungible: *amount_to_send
}
}
]
},
0, # feeAssetItem
Unlimited # weightLimit
]
events:
- name: polkadotXcm.Attempted
attributes:
- type: XcmV3TraitsOutcome
xcmOutcome: Complete
threshold: [10, 10]
value: {"refTime":"673,627,000","proofSize":"6,196"}
- name: assets.Transferred
attributes:
- type: AccountId32
value: *pp_sovereign_sibl
- name: assets.Transferred
attributes:
- type: u128
value: *amount_to_send
- name: polkadotXcm.limitedReserveTransferAssets (KSM) | Assets Parachain -> Penpal Parachain
its:
- name: Assets Parachain should be able to reserve transfer KSM to Penpal Parachain
actions:
- extrinsics:
- chain: *assets_parachain
signer: *ap_signer
pallet: polkadotXcm
call: limitedReserveTransferAssets
args: [
*pp_dest, # destination
{ # beneficiary
V3: {
parents: 0,
interior: {
X1: {
AccountId32: {
id: *pp_acc
}
}
}
}
},
{ # assets
V3: [
*ap_ksm_fungible
]
},
0, # feeAssetItem
Unlimited # weightLimit
]
events:
- name: polkadotXcm.Attempted
attributes:
- type: XcmV3TraitsOutcome
xcmOutcome: Complete
threshold: [10, 10]
value: {"refTime":"673,627,000","proofSize":"6,196"}
- name: balances.Endowed
attributes:
- type: AccountId32
value: *pp_sovereign_sibl
- name: balances.Endowed
attributes:
- type: u128
value: *amount
- name: polkadotXcm.send( assets.forceCreateAsset ) | Penpal Parachain -> Assets Parachain
before:
- name: Get the asset balance of the Penpal Parachain Sovereign account in Assets Parachain
actions:
- queries:
assets_balance_pp_sovereign_before:
chain: *assets_parachain
pallet: assets
call: account
args: [
*asset_id,
*pp_sovereign_sibl
]
its:
- name: Penpal Parachain should be able to send XCM message paying its fee with sufficient asset in Assets Parachain
actions:
- extrinsics:
- chain: *penpal_parachain
signer: *pp_signer
sudo: true
pallet: polkadotXcm
call: send
args: [
*ap_dest_routed, # destination
{
v3: [ #message
{
WithdrawAsset: [
{
id: {
concrete: {
parents: 0,
interior: {
X2: [
{ PalletInstance: *assets_pallet_id },
{ GeneralIndex: *asset_id }
]
}
}
},
fun: { fungible: *amount_to_send }}
]
},
{
BuyExecution: {
fees: { id: *suff_asset, fun: { fungible: *amount_to_send }},
weightLimit: Unlimited
}
},
{
Transact: {
originKind: SovereignAccount,
requireWeightAtMost: *weight_at_most,
call: $force_create_asset2
}
},
{
RefundSurplus
},
{
DepositAsset: {
assets: { Wild: All },
beneficiary: {
parents: 0,
interior: {
X1: {
AccountId32: {
network: , # None
id: *pp_acc
}
}
}}
}
}
]
}
]
events:
- name: sudo.Sudid
attributes:
- type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: polkadotXcm.Sent
- name: assets.Burned
chain: *assets_parachain
attributes:
- type: AccountId32
value: *pp_sovereign_sibl
- name: assets.Issued
chain: *assets_parachain
attributes:
- type: u32
value: *asset_id
- queries:
assets_balance_pp_sovereign_after:
chain: *assets_parachain
pallet: assets
call: account
args: [
*asset_id,
*pp_sovereign_sibl
]
forced_created_asset2:
chain: *assets_parachain
pallet: assets
call: asset
args: [ 3 ]
- asserts:
isSome:
args: [ $forced_created_asset2 ]
- name: Should reduce the assets balance of the Penpal Parachain's SovereignAccount in the Assets Parachain
actions:
- asserts:
assetsDecreased:
args: [
{
balances: {
before: $assets_balance_pp_sovereign_before,
after: $assets_balance_pp_sovereign_after,
},
}
]
- name: Penpal Parachain SHOULD NOT be able to send XCM message paying its fee with sufficient assets if not enough balance
actions:
- extrinsics:
- chain: *penpal_parachain
signer: *pp_signer
sudo: true
pallet: polkadotXcm
call: send
args: [
*ap_dest_routed, # destination
{
v3: [ #message
{
WithdrawAsset: [*ap_suff_asset_fungible_fail]
},
{
BuyExecution: {
fees: *ap_suff_asset_fungible_fail,
weightLimit: Unlimited
}
},
{
Transact: {
originKind: SovereignAccount,
requireWeightAtMost: *weight_at_most,
call: $force_create_asset2
}
}
]
}
]
events:
- name: xcmpQueue.Fail
chain: *assets_parachain
attributes:
- type: XcmV3TraitsError
value: FailedToTransactAsset
@@ -0,0 +1,71 @@
[relaychain]
default_command = "./bin/polkadot"
default_args = [ "-lparachain=debug", "-lxcm=trace" ]
chain = "polkadot-local"
[[relaychain.nodes]]
name = "alice"
ws_port = 9800
validator = true
[[relaychain.nodes]]
name = "bob"
ws_port = 9801
validator = true
[[relaychain.nodes]]
name = "charlie"
ws_port = 9802
validator = true
[[relaychain.nodes]]
name = "dave"
ws_port = 9803
validator = true
[[parachains]]
id = 1000
chain = "statemint-local"
cumulus_based = true
[[parachains.collators]]
name = "collator1"
ws_port = 9810
command = "./bin/polkadot-parachain"
args = [ "-lxcm=trace" ]
[[parachains.collators]]
name = "collator2"
ws_port = 9811
command = "./bin/polkadot-parachain"
args = [ "-lxcm=trace" ]
[[parachains]]
id = 2000
chain = "penpal-polkadot-2000"
cumulus_based = true
[[parachains.collators]]
name = "collator3"
ws_port = 9820
command = "./bin/polkadot-parachain"
args = [ "-lxcm=trace" ]
[[parachains.collators]]
name = "collator4"
ws_port = 9821
command = "./bin/polkadot-parachain"
args = [ "-lxcm=trace" ]
# [[hrmpChannels]]
# sender = 1000
# recipient = 2000
# maxCapacity = 8
# maxMessageSize = 8192
# [[hrmpChannels]]
# sender = 2000
# recipient = 1000
# maxCapacity = 8
# maxMessageSize = 8192
@@ -278,4 +278,3 @@ tests:
attributes: attributes:
- type: XcmV3TraitsOutcome - type: XcmV3TraitsOutcome
xcmOutcome: Complete xcmOutcome: Complete
@@ -10,10 +10,17 @@ chain = "polkadot-local"
[[relaychain.nodes]] [[relaychain.nodes]]
name = "bob" name = "bob"
ws_port = 9701
validator = true validator = true
[[relaychain.nodes]] [[relaychain.nodes]]
name = "charlie" name = "charlie"
ws_port = 9702
validator = true
[[relaychain.nodes]]
name = "dave"
ws_port = 9703
validator = true validator = true
[[parachains]] [[parachains]]
@@ -29,5 +36,6 @@ cumulus_based = true
[[parachains.collators]] [[parachains.collators]]
name = "collator2" name = "collator2"
ws_port = 9711
command = "./bin/polkadot-parachain" command = "./bin/polkadot-parachain"
args = ["-lxcm=trace"] args = ["-lxcm=trace"]
@@ -0,0 +1,36 @@
[package]
name = "statemint-it"
version = "1.0.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
description = "Statemint parachain runtime integration tests with xcm-emulator"
[dependencies]
codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false }
# Substrate
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
sp-weights = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-assets = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot
polkadot-core-primitives = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-parachain = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-runtime = { git = "https://github.com/paritytech/polkadot", branch = "master" }
xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
xcm-executor = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
pallet-xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus
parachains-common = { path = "../../../../common" }
penpal-runtime = { path = "../../../../runtimes/testing/penpal" }
statemint-runtime = { path = "../../../../runtimes/assets/statemint" }
# Local
xcm-emulator = { default-features = false, path = "../../../../../xcm/xcm-emulator" }
integration-tests-common = { default-features = false, path = "../../common" }
@@ -0,0 +1,33 @@
pub use codec::Encode;
pub use frame_support::{
assert_ok, instances::Instance1, pallet_prelude::Weight, traits::fungibles::Inspect,
};
pub use integration_tests_common::{
constants::{
accounts::{ALICE, BOB},
polkadot::ED as POLKADOT_ED,
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
},
AccountId, BHKusama, BHKusamaPallet, BHKusamaReceiver, BHKusamaSender, BHPolkadot,
BHPolkadotPallet, BHPolkadotReceiver, BHPolkadotSender, Collectives, CollectivesPallet,
CollectivesReceiver, CollectivesSender, Kusama, KusamaMockNet, KusamaPallet, KusamaReceiver,
KusamaSender, PenpalKusama, PenpalKusamaReceiver, PenpalKusamaSender, PenpalPolkadot,
PenpalPolkadotReceiver, PenpalPolkadotSender, Polkadot, PolkadotMockNet, PolkadotPallet,
PolkadotReceiver, PolkadotSender, Statemine, StateminePallet, StatemineReceiver,
StatemineSender, Statemint, StatemintPallet, StatemintReceiver, StatemintSender,
};
pub use polkadot_core_primitives::InboundDownwardMessage;
pub use xcm::{
prelude::*,
v3::{
Error,
NetworkId::{Kusama as KusamaId, Polkadot as PolkadotId},
},
};
pub use xcm_emulator::{
assert_expected_events, bx, cumulus_pallet_dmp_queue, helpers::weight_within_threshold,
Parachain as Para, RelayChain as Relay, TestExt,
};
#[cfg(test)]
mod tests;
@@ -0,0 +1,3 @@
mod reserve_transfer;
mod teleport;
mod transact;
@@ -0,0 +1,63 @@
use crate::*;
#[test]
fn reserve_transfer_native_asset_from_relay_to_assets() {
// Init tests variables
let amount = POLKADOT_ED * 1000;
let relay_sender_balance_before = Polkadot::account_data_of(PolkadotSender::get()).free;
let para_receiver_balance_before = Statemint::account_data_of(StatemintReceiver::get()).free;
let origin = <Polkadot as Relay>::RuntimeOrigin::signed(PolkadotSender::get());
let assets_para_destination: VersionedMultiLocation =
Polkadot::child_location_of(Statemint::para_id()).into();
let beneficiary: VersionedMultiLocation =
AccountId32 { network: None, id: StatemintReceiver::get().into() }.into();
let native_assets: VersionedMultiAssets = (Here, amount).into();
let fee_asset_item = 0;
let weight_limit = WeightLimit::Unlimited;
// Send XCM message from Relay Chain
Polkadot::execute_with(|| {
assert_ok!(<Polkadot as PolkadotPallet>::XcmPallet::limited_reserve_transfer_assets(
origin,
bx!(assets_para_destination),
bx!(beneficiary),
bx!(native_assets),
fee_asset_item,
weight_limit,
));
type RuntimeEvent = <Polkadot as Relay>::RuntimeEvent;
assert_expected_events!(
Polkadot,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Attempted(Outcome::Complete(weight))) => {
weight: weight_within_threshold((REF_TIME_THRESHOLD, PROOF_SIZE_THRESHOLD), Weight::from_parts(2_000_000_000, 0), *weight),
},
]
);
});
// Receive XCM message in Assets Parachain
Statemint::execute_with(|| {
type RuntimeEvent = <Statemint as Para>::RuntimeEvent;
assert_expected_events!(
Statemint,
vec![
RuntimeEvent::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward {
outcome: Outcome::Incomplete(_, Error::UntrustedReserveLocation),
..
}) => {},
]
);
});
// Check if balances are updated accordingly in Relay Chain and Assets Parachain
let relay_sender_balance_after = Polkadot::account_data_of(PolkadotSender::get()).free;
let para_sender_balance_after = Statemint::account_data_of(StatemintReceiver::get()).free;
assert_eq!(relay_sender_balance_before - amount, relay_sender_balance_after);
assert_eq!(para_sender_balance_after, para_receiver_balance_before);
}
@@ -0,0 +1,60 @@
use crate::*;
#[test]
fn teleport_native_assets_from_relay_to_assets_para() {
// Init tests variables
let amount = POLKADOT_ED * 1000;
let relay_sender_balance_before = Polkadot::account_data_of(PolkadotSender::get()).free;
let para_receiver_balance_before = Statemint::account_data_of(StatemintReceiver::get()).free;
let origin = <Polkadot as Relay>::RuntimeOrigin::signed(PolkadotSender::get());
let assets_para_destination: VersionedMultiLocation =
Polkadot::child_location_of(Statemint::para_id()).into();
let beneficiary: VersionedMultiLocation =
AccountId32 { network: None, id: StatemintReceiver::get().into() }.into();
let native_assets: VersionedMultiAssets = (Here, amount).into();
let fee_asset_item = 0;
let weight_limit = WeightLimit::Unlimited;
// Send XCM message from Relay Chain
Polkadot::execute_with(|| {
assert_ok!(<Polkadot as PolkadotPallet>::XcmPallet::limited_teleport_assets(
origin,
bx!(assets_para_destination),
bx!(beneficiary),
bx!(native_assets),
fee_asset_item,
weight_limit,
));
type RuntimeEvent = <Polkadot as Relay>::RuntimeEvent;
assert_expected_events!(
Polkadot,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Attempted(Outcome::Complete { .. })) => {},
]
);
});
// Receive XCM message in Assets Parachain
Statemint::execute_with(|| {
type RuntimeEvent = <Statemint as Para>::RuntimeEvent;
assert_expected_events!(
Statemint,
vec![
RuntimeEvent::Balances(pallet_balances::Event::Deposit { who, .. }) => {
who: *who == StatemineReceiver::get().into(),
},
]
);
});
// Check if balances are updated accordingly in Relay Chain and Assets Parachain
let relay_sender_balance_after = Polkadot::account_data_of(PolkadotSender::get()).free;
let para_sender_balance_after = Statemint::account_data_of(StatemintReceiver::get()).free;
assert_eq!(relay_sender_balance_before - amount, relay_sender_balance_after);
assert!(para_sender_balance_after > para_receiver_balance_before);
}
@@ -0,0 +1,58 @@
use crate::*;
#[test]
fn transact_sudo_from_relay_to_assets_para() {
// Init tests variables
// Call to be executed in Assets Parachain
const ASSET_ID: u32 = 1;
let call = <Statemint as Para>::RuntimeCall::Assets(pallet_assets::Call::<
<Statemint as Para>::Runtime,
Instance1,
>::force_create {
id: ASSET_ID.into(),
is_sufficient: true,
min_balance: 1000,
owner: StatemintSender::get().into(),
})
.encode()
.into();
// XcmPallet send arguments
let sudo_origin = <Polkadot as Relay>::RuntimeOrigin::root();
let assets_para_destination: VersionedMultiLocation =
Polkadot::child_location_of(Statemint::para_id()).into();
let weight_limit = WeightLimit::Unlimited;
let require_weight_at_most = Weight::from_parts(1000000000, 200000);
let origin_kind = OriginKind::Superuser;
let check_origin = None;
let xcm = VersionedXcm::from(Xcm(vec![
UnpaidExecution { weight_limit, check_origin },
Transact { require_weight_at_most, origin_kind, call },
]));
// Send XCM message from Relay Chain
Polkadot::execute_with(|| {
assert_ok!(<Polkadot as PolkadotPallet>::XcmPallet::send(
sudo_origin,
bx!(assets_para_destination),
bx!(xcm),
));
type RuntimeEvent = <Polkadot as Relay>::RuntimeEvent;
assert_expected_events!(
Polkadot,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
]
);
});
// Receive XCM message in Assets Parachain
Statemint::execute_with(|| {
assert!(<Statemint as StatemintPallet>::Assets::asset_exists(ASSET_ID));
});
}
@@ -0,0 +1,54 @@
[package]
name = "integration-tests-common"
version = "1.0.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
description = "Common resources for integration testing with xcm-emulator"
[dependencies]
codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false }
# Substrate
grandpa = { package = "sc-consensus-grandpa", git = "https://github.com/paritytech/substrate", branch = "master" }
sp-authority-discovery = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
sp-weights = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus-babe = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-assets = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-staking = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-im-online = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot
polkadot-core-primitives = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-parachain = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-service = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-primitives = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-runtime = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-runtime-constants = { git = "https://github.com/paritytech/polkadot", branch = "master" }
kusama-runtime = { git = "https://github.com/paritytech/polkadot", branch = "master" }
kusama-runtime-constants = { git = "https://github.com/paritytech/polkadot", branch = "master" }
xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
xcm-executor = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
pallet-xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
# Cumulus
parachains-common = { path = "../../../common" }
parachain-info = { path = "../../../pallets/parachain-info" }
cumulus-primitives-core = { path = "../../../../primitives/core" }
penpal-runtime = { path = "../../../runtimes/testing/penpal" }
statemint-runtime = { path = "../../../runtimes/assets/statemint" }
statemine-runtime = { path = "../../../runtimes/assets/statemine" }
collectives-polkadot-runtime = { path = "../../../runtimes/collectives/collectives-polkadot" }
bridge-hub-kusama-runtime = { path = "../../../runtimes/bridge-hubs/bridge-hub-kusama" }
bridge-hub-polkadot-runtime = { path = "../../../runtimes/bridge-hubs/bridge-hub-polkadot" }
xcm-emulator = { default-features = false, path = "../../../../xcm/xcm-emulator" }
[features]
runtime-benchmarks = [
"kusama-runtime/runtime-benchmarks",
]
@@ -0,0 +1,672 @@
use grandpa::AuthorityId as GrandpaId;
use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
pub use parachains_common::{AccountId, AuraId, Balance, BlockNumber, StatemintAuraId};
use polkadot_primitives::{AssignmentId, ValidatorId};
pub use polkadot_runtime_parachains::configuration::HostConfiguration;
use polkadot_service::chain_spec::get_authority_keys_from_seed_no_beefy;
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use sp_consensus_babe::AuthorityId as BabeId;
use sp_core::{sr25519, storage::Storage, Pair, Public};
use sp_runtime::{
traits::{IdentifyAccount, Verify},
BuildStorage, MultiSignature, Perbill,
};
pub use xcm;
pub const XCM_V2: u32 = 3;
pub const XCM_V3: u32 = 2;
pub const REF_TIME_THRESHOLD: u64 = 33;
pub const PROOF_SIZE_THRESHOLD: u64 = 33;
type AccountPublic = <MultiSignature as Verify>::Signer;
/// Helper function to generate a crypto pair from seed
fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
TPublic::Pair::from_string(&format!("//{}", seed), None)
.expect("static values are valid; qed")
.public()
}
/// Helper function to generate an account ID from seed.
fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
where
AccountPublic: From<<TPublic::Pair as Pair>::Public>,
{
AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
}
pub mod accounts {
use super::*;
pub const ALICE: &str = "Alice";
pub const BOB: &str = "Bob";
pub const CHARLIE: &str = "Charlie";
pub const DAVE: &str = "Dave";
pub const EVE: &str = "Eve";
pub const FERDIE: &str = "Ferdei";
pub const ALICE_STASH: &str = "Alice//stash";
pub const BOB_STASH: &str = "Bob//stash";
pub const CHARLIE_STASH: &str = "Charlie//stash";
pub const DAVE_STASH: &str = "Dave//stash";
pub const EVE_STASH: &str = "Eve//stash";
pub const FERDIE_STASH: &str = "Ferdie//stash";
pub fn init_balances() -> Vec<AccountId> {
vec![
get_account_id_from_seed::<sr25519::Public>(ALICE),
get_account_id_from_seed::<sr25519::Public>(BOB),
get_account_id_from_seed::<sr25519::Public>(CHARLIE),
get_account_id_from_seed::<sr25519::Public>(DAVE),
get_account_id_from_seed::<sr25519::Public>(EVE),
get_account_id_from_seed::<sr25519::Public>(FERDIE),
get_account_id_from_seed::<sr25519::Public>(ALICE_STASH),
get_account_id_from_seed::<sr25519::Public>(BOB_STASH),
get_account_id_from_seed::<sr25519::Public>(CHARLIE_STASH),
get_account_id_from_seed::<sr25519::Public>(DAVE_STASH),
get_account_id_from_seed::<sr25519::Public>(EVE_STASH),
get_account_id_from_seed::<sr25519::Public>(FERDIE_STASH),
]
}
}
pub mod collators {
use super::*;
pub fn invulnerables_statemint() -> Vec<(AccountId, StatemintAuraId)> {
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_from_seed::<StatemintAuraId>("Alice"),
),
(
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_from_seed::<StatemintAuraId>("Bob"),
),
]
}
pub fn invulnerables() -> Vec<(AccountId, AuraId)> {
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_from_seed::<AuraId>("Alice"),
),
(get_account_id_from_seed::<sr25519::Public>("Bob"), get_from_seed::<AuraId>("Bob")),
]
}
}
pub mod validators {
use super::*;
pub fn initial_authorities() -> Vec<(
AccountId,
AccountId,
BabeId,
GrandpaId,
ImOnlineId,
ValidatorId,
AssignmentId,
AuthorityDiscoveryId,
)> {
vec![get_authority_keys_from_seed_no_beefy("Alice")]
}
}
/// The default XCM version to set in genesis config.
const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION;
// Polkadot
pub mod polkadot {
use super::*;
pub const ED: Balance = polkadot_runtime_constants::currency::EXISTENTIAL_DEPOSIT;
const STASH: u128 = 100 * polkadot_runtime_constants::currency::UNITS;
pub fn get_host_config() -> HostConfiguration<BlockNumber> {
HostConfiguration {
max_upward_queue_count: 10,
max_upward_queue_size: 51200,
max_upward_message_size: 51200,
max_upward_message_num_per_candidate: 10,
max_downward_message_size: 51200,
..Default::default()
}
}
fn session_keys(
babe: BabeId,
grandpa: GrandpaId,
im_online: ImOnlineId,
para_validator: ValidatorId,
para_assignment: AssignmentId,
authority_discovery: AuthorityDiscoveryId,
) -> polkadot_runtime::SessionKeys {
polkadot_runtime::SessionKeys {
babe,
grandpa,
im_online,
para_validator,
para_assignment,
authority_discovery,
}
}
pub fn genesis() -> Storage {
let genesis_config = polkadot_runtime::GenesisConfig {
system: polkadot_runtime::SystemConfig {
code: polkadot_runtime::WASM_BINARY.unwrap().to_vec(),
},
balances: polkadot_runtime::BalancesConfig {
balances: accounts::init_balances()
.iter()
.cloned()
.map(|k| (k, ED * 4096))
.collect(),
},
indices: polkadot_runtime::IndicesConfig { indices: vec![] },
session: polkadot_runtime::SessionConfig {
keys: validators::initial_authorities()
.iter()
.map(|x| {
(
x.0.clone(),
x.0.clone(),
polkadot::session_keys(
x.2.clone(),
x.3.clone(),
x.4.clone(),
x.5.clone(),
x.6.clone(),
x.7.clone(),
),
)
})
.collect::<Vec<_>>(),
},
staking: polkadot_runtime::StakingConfig {
validator_count: validators::initial_authorities().len() as u32,
minimum_validator_count: 1,
stakers: validators::initial_authorities()
.iter()
.map(|x| {
(x.0.clone(), x.1.clone(), STASH, polkadot_runtime::StakerStatus::Validator)
})
.collect(),
invulnerables: validators::initial_authorities()
.iter()
.map(|x| x.0.clone())
.collect(),
force_era: pallet_staking::Forcing::ForceNone,
slash_reward_fraction: Perbill::from_percent(10),
..Default::default()
},
phragmen_election: Default::default(),
democracy: Default::default(),
council: polkadot_runtime::CouncilConfig {
members: vec![],
phantom: Default::default(),
},
technical_committee: polkadot_runtime::TechnicalCommitteeConfig {
members: vec![],
phantom: Default::default(),
},
technical_membership: Default::default(),
babe: polkadot_runtime::BabeConfig {
authorities: Default::default(),
epoch_config: Some(polkadot_runtime::BABE_GENESIS_EPOCH_CONFIG),
},
grandpa: Default::default(),
im_online: Default::default(),
authority_discovery: polkadot_runtime::AuthorityDiscoveryConfig { keys: vec![] },
claims: polkadot_runtime::ClaimsConfig { claims: vec![], vesting: vec![] },
vesting: polkadot_runtime::VestingConfig { vesting: vec![] },
treasury: Default::default(),
hrmp: Default::default(),
configuration: polkadot_runtime::ConfigurationConfig { config: get_host_config() },
paras: Default::default(),
xcm_pallet: Default::default(),
nomination_pools: Default::default(),
};
genesis_config.build_storage().unwrap()
}
}
// Kusama
pub mod kusama {
use super::*;
pub const ED: Balance = kusama_runtime_constants::currency::EXISTENTIAL_DEPOSIT;
const STASH: u128 = 100 * kusama_runtime_constants::currency::UNITS;
pub fn get_host_config() -> HostConfiguration<BlockNumber> {
HostConfiguration {
max_upward_queue_count: 10,
max_upward_queue_size: 51200,
max_upward_message_size: 51200,
max_upward_message_num_per_candidate: 10,
max_downward_message_size: 51200,
..Default::default()
}
}
fn session_keys(
babe: BabeId,
grandpa: GrandpaId,
im_online: ImOnlineId,
para_validator: ValidatorId,
para_assignment: AssignmentId,
authority_discovery: AuthorityDiscoveryId,
) -> kusama_runtime::SessionKeys {
kusama_runtime::SessionKeys {
babe,
grandpa,
im_online,
para_validator,
para_assignment,
authority_discovery,
}
}
pub fn genesis() -> Storage {
let genesis_config = kusama_runtime::GenesisConfig {
system: kusama_runtime::SystemConfig {
code: kusama_runtime::WASM_BINARY.unwrap().to_vec(),
},
balances: kusama_runtime::BalancesConfig {
balances: accounts::init_balances()
.iter()
.cloned()
.map(|k| (k, ED * 4096))
.collect(),
},
indices: kusama_runtime::IndicesConfig { indices: vec![] },
session: kusama_runtime::SessionConfig {
keys: validators::initial_authorities()
.iter()
.map(|x| {
(
x.0.clone(),
x.0.clone(),
kusama::session_keys(
x.2.clone(),
x.3.clone(),
x.4.clone(),
x.5.clone(),
x.6.clone(),
x.7.clone(),
),
)
})
.collect::<Vec<_>>(),
},
staking: kusama_runtime::StakingConfig {
minimum_validator_count: 1,
validator_count: validators::initial_authorities().len() as u32,
stakers: validators::initial_authorities()
.iter()
.map(|x| {
(x.0.clone(), x.1.clone(), STASH, kusama_runtime::StakerStatus::Validator)
})
.collect(),
invulnerables: validators::initial_authorities()
.iter()
.map(|x| x.0.clone())
.collect(),
force_era: pallet_staking::Forcing::NotForcing,
slash_reward_fraction: Perbill::from_percent(10),
..Default::default()
},
babe: kusama_runtime::BabeConfig {
authorities: Default::default(),
epoch_config: Some(kusama_runtime::BABE_GENESIS_EPOCH_CONFIG),
},
grandpa: Default::default(),
im_online: Default::default(),
authority_discovery: kusama_runtime::AuthorityDiscoveryConfig { keys: vec![] },
claims: kusama_runtime::ClaimsConfig { claims: vec![], vesting: vec![] },
vesting: kusama_runtime::VestingConfig { vesting: vec![] },
treasury: Default::default(),
hrmp: Default::default(),
configuration: kusama_runtime::ConfigurationConfig { config: get_host_config() },
paras: Default::default(),
xcm_pallet: Default::default(),
nomination_pools: Default::default(),
nis_counterpart_balances: Default::default(),
};
genesis_config.build_storage().unwrap()
}
}
// Statemint
pub mod statemint {
use super::*;
pub const PARA_ID: u32 = 1000;
pub const ED: Balance = statemint_runtime::constants::currency::EXISTENTIAL_DEPOSIT;
pub fn genesis() -> Storage {
let genesis_config = statemint_runtime::GenesisConfig {
system: statemint_runtime::SystemConfig {
code: statemint_runtime::WASM_BINARY
.expect("WASM binary was not build, please build it!")
.to_vec(),
},
balances: statemint_runtime::BalancesConfig {
balances: accounts::init_balances()
.iter()
.cloned()
.map(|k| (k, ED * 4096))
.collect(),
},
parachain_info: statemint_runtime::ParachainInfoConfig { parachain_id: PARA_ID.into() },
collator_selection: statemint_runtime::CollatorSelectionConfig {
invulnerables: collators::invulnerables_statemint()
.iter()
.cloned()
.map(|(acc, _)| acc)
.collect(),
candidacy_bond: ED * 16,
..Default::default()
},
session: statemint_runtime::SessionConfig {
keys: collators::invulnerables_statemint()
.into_iter()
.map(|(acc, aura)| {
(
acc.clone(), // account id
acc, // validator id
statemint_runtime::SessionKeys { aura }, // session keys
)
})
.collect(),
},
aura: Default::default(),
aura_ext: Default::default(),
parachain_system: Default::default(),
polkadot_xcm: statemint_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
},
};
genesis_config.build_storage().unwrap()
}
}
// Statemint
pub mod statemine {
use super::*;
pub const PARA_ID: u32 = 1000;
pub const ED: Balance = statemine_runtime::constants::currency::EXISTENTIAL_DEPOSIT;
pub fn genesis() -> Storage {
let genesis_config = statemine_runtime::GenesisConfig {
system: statemine_runtime::SystemConfig {
code: statemine_runtime::WASM_BINARY
.expect("WASM binary was not build, please build it!")
.to_vec(),
},
balances: statemine_runtime::BalancesConfig {
balances: accounts::init_balances()
.iter()
.cloned()
.map(|k| (k, ED * 4096))
.collect(),
},
parachain_info: statemine_runtime::ParachainInfoConfig { parachain_id: PARA_ID.into() },
collator_selection: statemine_runtime::CollatorSelectionConfig {
invulnerables: collators::invulnerables()
.iter()
.cloned()
.map(|(acc, _)| acc)
.collect(),
candidacy_bond: ED * 16,
..Default::default()
},
session: statemine_runtime::SessionConfig {
keys: collators::invulnerables()
.into_iter()
.map(|(acc, aura)| {
(
acc.clone(), // account id
acc, // validator id
statemine_runtime::SessionKeys { aura }, // session keys
)
})
.collect(),
},
aura: Default::default(),
aura_ext: Default::default(),
parachain_system: Default::default(),
polkadot_xcm: statemine_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
},
};
genesis_config.build_storage().unwrap()
}
}
// Penpal
pub mod penpal {
use super::*;
pub const PARA_ID: u32 = 2000;
pub const ED: Balance = penpal_runtime::EXISTENTIAL_DEPOSIT;
pub fn genesis(para_id: u32) -> Storage {
let genesis_config = penpal_runtime::GenesisConfig {
system: penpal_runtime::SystemConfig {
code: penpal_runtime::WASM_BINARY
.expect("WASM binary was not build, please build it!")
.to_vec(),
},
balances: penpal_runtime::BalancesConfig {
balances: accounts::init_balances()
.iter()
.cloned()
.map(|k| (k, ED * 4096))
.collect(),
},
parachain_info: penpal_runtime::ParachainInfoConfig { parachain_id: para_id.into() },
collator_selection: penpal_runtime::CollatorSelectionConfig {
invulnerables: collators::invulnerables()
.iter()
.cloned()
.map(|(acc, _)| acc)
.collect(),
candidacy_bond: ED * 16,
..Default::default()
},
session: penpal_runtime::SessionConfig {
keys: collators::invulnerables()
.into_iter()
.map(|(acc, aura)| {
(
acc.clone(), // account id
acc, // validator id
penpal_runtime::SessionKeys { aura }, // session keys
)
})
.collect(),
},
aura: Default::default(),
aura_ext: Default::default(),
parachain_system: Default::default(),
polkadot_xcm: penpal_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
},
sudo: penpal_runtime::SudoConfig {
key: Some(get_account_id_from_seed::<sr25519::Public>("Alice")),
},
};
genesis_config.build_storage().unwrap()
}
}
// Collectives
pub mod collectives {
use super::*;
pub const PARA_ID: u32 = 1001;
pub const ED: Balance = collectives_polkadot_runtime::constants::currency::EXISTENTIAL_DEPOSIT;
pub fn genesis() -> Storage {
let genesis_config = collectives_polkadot_runtime::GenesisConfig {
system: collectives_polkadot_runtime::SystemConfig {
code: collectives_polkadot_runtime::WASM_BINARY
.expect("WASM binary was not build, please build it!")
.to_vec(),
},
balances: collectives_polkadot_runtime::BalancesConfig {
balances: accounts::init_balances()
.iter()
.cloned()
.map(|k| (k, ED * 4096))
.collect(),
},
parachain_info: collectives_polkadot_runtime::ParachainInfoConfig {
parachain_id: PARA_ID.into(),
},
collator_selection: collectives_polkadot_runtime::CollatorSelectionConfig {
invulnerables: collators::invulnerables()
.iter()
.cloned()
.map(|(acc, _)| acc)
.collect(),
candidacy_bond: ED * 16,
..Default::default()
},
session: collectives_polkadot_runtime::SessionConfig {
keys: collators::invulnerables()
.into_iter()
.map(|(acc, aura)| {
(
acc.clone(), // account id
acc, // validator id
collectives_polkadot_runtime::SessionKeys { aura }, // session keys
)
})
.collect(),
},
// no need to pass anything to aura, in fact it will panic if we do. Session will take care
// of this.
aura: Default::default(),
aura_ext: Default::default(),
parachain_system: Default::default(),
polkadot_xcm: collectives_polkadot_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
},
alliance: Default::default(),
alliance_motion: Default::default(),
};
genesis_config.build_storage().unwrap()
}
}
pub mod bridge_hub_kusama {
use super::*;
pub const PARA_ID: u32 = 1002;
pub const ED: Balance = bridge_hub_kusama_runtime::constants::currency::EXISTENTIAL_DEPOSIT;
pub fn genesis() -> Storage {
let genesis_config = bridge_hub_kusama_runtime::GenesisConfig {
system: bridge_hub_kusama_runtime::SystemConfig {
code: bridge_hub_kusama_runtime::WASM_BINARY
.expect("WASM binary was not build, please build it!")
.to_vec(),
},
balances: bridge_hub_kusama_runtime::BalancesConfig {
balances: accounts::init_balances()
.iter()
.cloned()
.map(|k| (k, ED * 4096))
.collect(),
},
parachain_info: bridge_hub_kusama_runtime::ParachainInfoConfig {
parachain_id: PARA_ID.into(),
},
collator_selection: bridge_hub_kusama_runtime::CollatorSelectionConfig {
invulnerables: collators::invulnerables()
.iter()
.cloned()
.map(|(acc, _)| acc)
.collect(),
candidacy_bond: ED * 16,
..Default::default()
},
session: bridge_hub_kusama_runtime::SessionConfig {
keys: collators::invulnerables()
.into_iter()
.map(|(acc, aura)| {
(
acc.clone(), // account id
acc, // validator id
bridge_hub_kusama_runtime::SessionKeys { aura }, // session keys
)
})
.collect(),
},
aura: Default::default(),
aura_ext: Default::default(),
parachain_system: Default::default(),
polkadot_xcm: bridge_hub_kusama_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
},
};
genesis_config.build_storage().unwrap()
}
}
pub mod bridge_hub_polkadot {
use super::*;
pub const PARA_ID: u32 = 1002;
pub const ED: Balance = bridge_hub_polkadot_runtime::constants::currency::EXISTENTIAL_DEPOSIT;
pub fn genesis() -> Storage {
let genesis_config = bridge_hub_polkadot_runtime::GenesisConfig {
system: bridge_hub_polkadot_runtime::SystemConfig {
code: bridge_hub_polkadot_runtime::WASM_BINARY
.expect("WASM binary was not build, please build it!")
.to_vec(),
},
balances: bridge_hub_polkadot_runtime::BalancesConfig {
balances: accounts::init_balances()
.iter()
.cloned()
.map(|k| (k, ED * 4096))
.collect(),
},
parachain_info: bridge_hub_polkadot_runtime::ParachainInfoConfig {
parachain_id: PARA_ID.into(),
},
collator_selection: bridge_hub_polkadot_runtime::CollatorSelectionConfig {
invulnerables: collators::invulnerables()
.iter()
.cloned()
.map(|(acc, _)| acc)
.collect(),
candidacy_bond: ED * 16,
..Default::default()
},
session: bridge_hub_polkadot_runtime::SessionConfig {
keys: collators::invulnerables()
.into_iter()
.map(|(acc, aura)| {
(
acc.clone(), // account id
acc, // validator id
bridge_hub_polkadot_runtime::SessionKeys { aura }, // session keys
)
})
.collect(),
},
aura: Default::default(),
aura_ext: Default::default(),
parachain_system: Default::default(),
polkadot_xcm: bridge_hub_polkadot_runtime::PolkadotXcmConfig {
safe_xcm_version: Some(SAFE_XCM_VERSION),
},
};
genesis_config.build_storage().unwrap()
}
}
@@ -0,0 +1,253 @@
pub mod constants;
pub use constants::{
accounts::{ALICE, BOB},
bridge_hub_kusama, bridge_hub_polkadot, collectives, kusama, penpal, polkadot, statemine,
statemint,
};
use frame_support::{parameter_types, sp_io, sp_tracing};
pub use parachains_common::{AccountId, AuraId, Balance, BlockNumber, StatemintAuraId};
pub use sp_core::{sr25519, storage::Storage, Get};
use xcm::prelude::*;
use xcm_emulator::{
decl_test_networks, decl_test_parachains, decl_test_relay_chains, Parachain, RelayChain,
TestExt,
};
use xcm_executor::traits::Convert;
decl_test_relay_chains! {
pub struct Polkadot {
genesis = polkadot::genesis(),
on_init = (),
runtime = {
Runtime: polkadot_runtime::Runtime,
RuntimeOrigin: polkadot_runtime::RuntimeOrigin,
RuntimeCall: polkadot_runtime::RuntimeCall,
RuntimeEvent: polkadot_runtime::RuntimeEvent,
XcmConfig: polkadot_runtime::xcm_config::XcmConfig,
SovereignAccountOf: polkadot_runtime::xcm_config::SovereignAccountOf,
System: polkadot_runtime::System,
Balances: polkadot_runtime::Balances,
},
pallets_extra = {
XcmPallet: polkadot_runtime::XcmPallet,
}
},
pub struct Kusama {
genesis = kusama::genesis(),
on_init = (),
runtime = {
Runtime: kusama_runtime::Runtime,
RuntimeOrigin: kusama_runtime::RuntimeOrigin,
RuntimeCall: polkadot_runtime::RuntimeCall,
RuntimeEvent: kusama_runtime::RuntimeEvent,
XcmConfig: kusama_runtime::xcm_config::XcmConfig,
SovereignAccountOf: kusama_runtime::xcm_config::SovereignAccountOf,
System: kusama_runtime::System,
Balances: kusama_runtime::Balances,
},
pallets_extra = {
XcmPallet: kusama_runtime::XcmPallet,
}
}
}
decl_test_parachains! {
// Polkadot
pub struct Statemint {
genesis = statemint::genesis(),
on_init = (),
runtime = {
Runtime: statemint_runtime::Runtime,
RuntimeOrigin: statemint_runtime::RuntimeOrigin,
RuntimeCall: statemint_runtime::RuntimeCall,
RuntimeEvent: statemint_runtime::RuntimeEvent,
XcmpMessageHandler: statemint_runtime::XcmpQueue,
DmpMessageHandler: statemint_runtime::DmpQueue,
LocationToAccountId: statemint_runtime::xcm_config::LocationToAccountId,
System: statemint_runtime::System,
Balances: statemint_runtime::Balances,
ParachainSystem: statemint_runtime::ParachainSystem,
ParachainInfo: statemint_runtime::ParachainInfo,
},
pallets_extra = {
PolkadotXcm: statemint_runtime::PolkadotXcm,
Assets: statemint_runtime::Assets,
}
},
pub struct PenpalPolkadot {
genesis = penpal::genesis(penpal::PARA_ID),
on_init = (),
runtime = {
Runtime: penpal_runtime::Runtime,
RuntimeOrigin: penpal_runtime::RuntimeOrigin,
RuntimeCall: penpal_runtime::RuntimeEvent,
RuntimeEvent: penpal_runtime::RuntimeEvent,
XcmpMessageHandler: penpal_runtime::XcmpQueue,
DmpMessageHandler: penpal_runtime::DmpQueue,
LocationToAccountId: penpal_runtime::xcm_config::LocationToAccountId,
System: penpal_runtime::System,
Balances: penpal_runtime::Balances,
ParachainSystem: penpal_runtime::ParachainSystem,
ParachainInfo: penpal_runtime::ParachainInfo,
},
pallets_extra = {
PolkadotXcm: penpal_runtime::PolkadotXcm,
Assets: penpal_runtime::Assets,
}
},
// Kusama
pub struct Statemine {
genesis = statemine::genesis(),
on_init = (),
runtime = {
Runtime: statemine_runtime::Runtime,
RuntimeOrigin: statemine_runtime::RuntimeOrigin,
RuntimeCall: statemine_runtime::RuntimeEvent,
RuntimeEvent: statemine_runtime::RuntimeEvent,
XcmpMessageHandler: statemine_runtime::XcmpQueue,
DmpMessageHandler: statemine_runtime::DmpQueue,
LocationToAccountId: statemine_runtime::xcm_config::LocationToAccountId,
System: statemine_runtime::System,
Balances: statemine_runtime::Balances,
ParachainSystem: statemine_runtime::ParachainSystem,
ParachainInfo: statemine_runtime::ParachainInfo,
},
pallets_extra = {
PolkadotXcm: statemine_runtime::PolkadotXcm,
Assets: statemine_runtime::Assets,
ForeignAssets: statemine_runtime::Assets,
}
},
pub struct PenpalKusama {
genesis = penpal::genesis(penpal::PARA_ID),
on_init = (),
runtime = {
Runtime: penpal_runtime::Runtime,
RuntimeOrigin: penpal_runtime::RuntimeOrigin,
RuntimeCall: penpal_runtime::RuntimeEvent,
RuntimeEvent: penpal_runtime::RuntimeEvent,
XcmpMessageHandler: penpal_runtime::XcmpQueue,
DmpMessageHandler: penpal_runtime::DmpQueue,
LocationToAccountId: penpal_runtime::xcm_config::LocationToAccountId,
System: penpal_runtime::System,
Balances: penpal_runtime::Balances,
ParachainSystem: penpal_runtime::ParachainSystem,
ParachainInfo: penpal_runtime::ParachainInfo,
},
pallets_extra = {
PolkadotXcm: penpal_runtime::PolkadotXcm,
Assets: penpal_runtime::Assets,
}
},
pub struct Collectives {
genesis = collectives::genesis(),
on_init = (),
runtime = {
Runtime: collectives_polkadot_runtime::Runtime,
RuntimeOrigin: collectives_polkadot_runtime::RuntimeOrigin,
RuntimeCall: collectives_polkadot_runtime::RuntimeEvent,
RuntimeEvent: collectives_polkadot_runtime::RuntimeEvent,
XcmpMessageHandler: collectives_polkadot_runtime::XcmpQueue,
DmpMessageHandler: collectives_polkadot_runtime::DmpQueue,
LocationToAccountId: collectives_polkadot_runtime::xcm_config::LocationToAccountId,
System: collectives_polkadot_runtime::System,
Balances: collectives_polkadot_runtime::Balances,
ParachainSystem: collectives_polkadot_runtime::ParachainSystem,
ParachainInfo: collectives_polkadot_runtime::ParachainInfo,
},
pallets_extra = {
PolkadotXcm: collectives_polkadot_runtime::PolkadotXcm,
}
},
pub struct BHKusama {
genesis = bridge_hub_kusama::genesis(),
on_init = (),
runtime = {
Runtime: bridge_hub_kusama_runtime::Runtime,
RuntimeOrigin: bridge_hub_kusama_runtime::RuntimeOrigin,
RuntimeCall: bridge_hub_kusama_runtime::RuntimeEvent,
RuntimeEvent: bridge_hub_kusama_runtime::RuntimeEvent,
XcmpMessageHandler: bridge_hub_kusama_runtime::XcmpQueue,
DmpMessageHandler: bridge_hub_kusama_runtime::DmpQueue,
LocationToAccountId: bridge_hub_kusama_runtime::xcm_config::LocationToAccountId,
System: bridge_hub_kusama_runtime::System,
Balances: bridge_hub_kusama_runtime::Balances,
ParachainSystem: bridge_hub_kusama_runtime::ParachainSystem,
ParachainInfo:bridge_hub_kusama_runtime::ParachainInfo,
},
pallets_extra = {
PolkadotXcm: bridge_hub_kusama_runtime::PolkadotXcm,
}
},
pub struct BHPolkadot {
genesis = bridge_hub_polkadot::genesis(),
on_init = (),
runtime = {
Runtime: bridge_hub_polkadot_runtime::Runtime,
RuntimeOrigin: bridge_hub_polkadot_runtime::RuntimeOrigin,
RuntimeCall: bridge_hub_polkadot_runtime::RuntimeEvent,
RuntimeEvent: bridge_hub_polkadot_runtime::RuntimeEvent,
XcmpMessageHandler: bridge_hub_polkadot_runtime::XcmpQueue,
DmpMessageHandler: bridge_hub_polkadot_runtime::DmpQueue,
LocationToAccountId: bridge_hub_polkadot_runtime::xcm_config::LocationToAccountId,
System: bridge_hub_polkadot_runtime::System,
Balances: bridge_hub_polkadot_runtime::Balances,
ParachainSystem: bridge_hub_polkadot_runtime::ParachainSystem,
ParachainInfo:bridge_hub_polkadot_runtime::ParachainInfo,
},
pallets_extra = {
PolkadotXcm: bridge_hub_polkadot_runtime::PolkadotXcm,
}
}
}
decl_test_networks! {
pub struct PolkadotMockNet {
relay_chain = Polkadot,
parachains = vec![
Statemint,
PenpalPolkadot,
Collectives,
BHPolkadot,
],
},
pub struct KusamaMockNet {
relay_chain = Kusama,
parachains = vec![
Statemine,
PenpalKusama,
BHKusama,
],
}
}
parameter_types! {
// Polkadot
pub PolkadotSender: AccountId = Polkadot::account_id_of(ALICE);
pub PolkadotReceiver: AccountId = Polkadot::account_id_of(BOB);
// Kusama
pub KusamaSender: AccountId = Kusama::account_id_of(ALICE);
pub KusamaReceiver: AccountId = Kusama::account_id_of(BOB);
// Statemint
pub StatemintSender: AccountId = Statemint::account_id_of(ALICE);
pub StatemintReceiver: AccountId = Statemint::account_id_of(BOB);
// Statemine
pub StatemineSender: AccountId = Statemine::account_id_of(ALICE);
pub StatemineReceiver: AccountId = Statemine::account_id_of(BOB);
// Penpal Polkadot
pub PenpalPolkadotSender: AccountId = PenpalPolkadot::account_id_of(ALICE);
pub PenpalPolkadotReceiver: AccountId = PenpalPolkadot::account_id_of(BOB);
// Penpal Kusama
pub PenpalKusamaSender: AccountId = PenpalKusama::account_id_of(ALICE);
pub PenpalKusamaReceiver: AccountId = PenpalKusama::account_id_of(BOB);
// Collectives
pub CollectivesSender: AccountId = Collectives::account_id_of(ALICE);
pub CollectivesReceiver: AccountId = Collectives::account_id_of(BOB);
// Bridge Hub Polkadot
pub BHPolkadotSender: AccountId = BHPolkadot::account_id_of(ALICE);
pub BHPolkadotReceiver: AccountId = BHPolkadot::account_id_of(BOB);
// Bridge Hub Kusama
pub BHKusamaSender: AccountId = BHKusama::account_id_of(ALICE);
pub BHKusamaReceiver: AccountId = BHKusama::account_id_of(BOB);
}
@@ -1,49 +0,0 @@
[relaychain]
default_command = "./bin/polkadot"
default_args = [ "-lparachain=debug" ]
chain = "kusama-local"
[[relaychain.nodes]]
name = "alice"
ws_port = 9900
validator = true
[[relaychain.nodes]]
name = "bob"
validator = true
[[relaychain.nodes]]
name = "charlie"
validator = true
[[relaychain.nodes]]
name = "dave"
validator = true
[[parachains]]
id = 1000
chain = "statemine-local"
cumulus_based = true
[[parachains.collators]]
name = "collator1"
ws_port = 9910
command = "./bin/polkadot-parachain"
[[parachains.collators]]
name = "collator2"
command = "./bin/polkadot-parachain"
[[parachains]]
id = 2000
chain = "penpal-kusama-2000"
cumulus_based = true
[[parachains.collators]]
name = "collator3"
ws_port = 9920
command = "./bin/polkadot-parachain"
[[parachains.collators]]
name = "collator4"
command = "./bin/polkadot-parachain"
@@ -1,408 +0,0 @@
---
settings:
chains:
relay_chain: &relay_chain
wsPort: 9900
assets_parachain: &assets_parachain
wsPort: 9910
paraId: &ap_id 1000
penpal_parachain: &penpal_parachain
wsPort: 9920
paraId: &pp_id 2000
variables:
common:
amount: &amount 2000000000000
require_weight_at_most: &weight_at_most 1000000000
hrmp_channels:
proposed_max_capacity: &max_capacity 8
proposed_max_message_size: &max_message_size 8192
channel: &channel {
maxCapacity: 8,
maxTotalSize: 8192,
maxMessageSize: 8192,
msgCount: 0,
totalSize: 0,
mqcHead: null,
senderDeposit: 0,
recipientDeposit: 0
}
chains:
relay_chain:
signer: &rc_signer //Alice
assets_parachain_destination: &ap_dest { v1: { 0, interior: { x1: { parachain: *ap_id }}}}
assets_parachain_account: &ap_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'
assets_parachain_beneficiary: &ap_benf {v1: { parents: 0, interior: { x1: { accountId32: { network: { any: true }, id: *ap_acc }}}}}
ksm: &rc_ksm { concrete: { 0, interior: { here: true }}}
ksm_fungible: &rc_ksm_fungible { id: *rc_ksm, fun: { fungible: *amount }}
assets_parachain_account:
sovereign_account: &ap_sovereign F7fq1jSNVTPfJmaHaXCMtatT1EZefCUsa7rRiQVNR5efcah
relay_chain_destination: &rc_dest { v1: { parents: 1, interior: { here: true }}}
penpal_parachain:
sovereign_account: &pp_sovereign F7fq1jMZkfuCuoMTyiEVAP2DMpMt18WopgBqTJznLihLNbZ
signer: &pp_signer //Alice
decodedCalls:
init_open_channel_with_ap:
chain: *relay_chain
pallet: hrmp
call: hrmpInitOpenChannel
args: [
*ap_id, # recipient
*max_capacity, # proposedMaxCapacity
*max_message_size # proposedMaxMessageSize
]
init_open_channel_with_cp:
chain: *relay_chain
pallet: hrmp
call: hrmpInitOpenChannel
args: [
*pp_id, # recipient
*max_capacity, # proposedMaxCapacity
*max_message_size # proposedMaxMessageSize
]
accept_open_channel_with_ap:
chain: *relay_chain
pallet: hrmp
call: hrmpAcceptOpenChannel
args: [
*ap_id, # recipient
]
accept_init_open_request_from_cp:
chain: *relay_chain
pallet: hrmp
call: hrmpAcceptOpenChannel
args: [
*pp_id, # sender
]
xcm_accept_init_open_request_from_cp:
chain: *assets_parachain
pallet: polkadotXcm
call: send
args: [
*rc_dest, # destination
{
v2: [ #message
{
WithdrawAsset: [*rc_ksm_fungible]
},
{
BuyExecution: {
fees: *rc_ksm_fungible,
weightLimit: Unlimited
}
},
{
Transact: {
originType: Native,
requireWeightAtMost: *weight_at_most,
call: $accept_init_open_request_from_cp
}
}
]
}
]
xcm_init_open_channel_with_cp:
chain: *assets_parachain
pallet: polkadotXcm
call: send
args: [
*rc_dest, # destination
{
v2: [ #message
{
WithdrawAsset: [*rc_ksm_fungible]
},
{
BuyExecution: {
fees: *rc_ksm_fungible,
weightLimit: Unlimited
}
},
{
Transact: {
originType: Native,
requireWeightAtMost: *weight_at_most,
call: $init_open_channel_with_cp
}
}
]
}
]
tests:
- name: HRMP
beforeEach:
- name: DEPENDANCY | Penpal Parachain Sovereign account in the Relay Chain needs to be funded
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
pallet: balances
call: transfer
args: [
*pp_sovereign, # destination
*amount, # value
]
events:
- name: balances.Transfer
- name: DEPENDANCY | Assets Parachain Sovereign account in the Relay Chain needs to be funded
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
pallet: balances
call: transfer
args: [
*ap_sovereign, # destination
*amount, # value
]
events:
- name: balances.Transfer
describes:
- name: hrmp.hrmpInitOpenChannel (Penpal Parachain → Assets Parachain)
its:
- name: Penpal Parachain sends a request to the Relay Chain to open a channel with the Assets Parchain
actions:
- extrinsics:
- chain: *penpal_parachain
signer: *pp_signer
sudo: true
pallet: polkadotXcm
call: send
args: [
*rc_dest, # destination
{
v2: [ #message
{
WithdrawAsset: [*rc_ksm_fungible]
},
{
BuyExecution: {
fees: *rc_ksm_fungible,
weightLimit: Unlimited
}
},
{
Transact: {
originType: Native,
requireWeightAtMost: *weight_at_most,
call: $init_open_channel_with_ap
}
}
]
}
]
events:
- name: sudo.Sudid
attribute:
type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: polkadotXcm.Sent
- name: ump.ExecutedUpward
chain: *relay_chain
attribute:
type: XcmV2TraitsOutcome
isComplete: true
threshold: [10, 10]
value: 1,160,892,000
- name: hrmp.OpenChannelRequested
chain: *relay_chain
- queries:
requested_channels:
chain: *relay_chain
pallet: hrmp
call: hrmpOpenChannelRequestsList
args: []
- asserts:
equal:
args: [
$requested_channels,
[
{
sender: *pp_id,
recipient: *ap_id
}
]
]
- name: hrmp.hrmpAcceptOpenChannel (Assets Parachain → Penpal Parachain)
its:
- name: Assets Parachain sends a response to the Relay Chain accepting the Penpal Parachain's request for openning a HRMP channel
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
sudo: true
pallet: xcmPallet
call: send
args: [
*ap_dest, # destination
{
v2: [ #message
{
Transact: {
originType: Superuser,
requireWeightAtMost: *weight_at_most,
call: $xcm_accept_init_open_request_from_cp
}
}
]
}
]
events:
- name: sudo.Sudid
attribute:
type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: xcmPallet.Sent
- name: dmpQueue.ExecutedDownward
chain: *assets_parachain
attribute:
type: XcmV2TraitsOutcome
isComplete: true
threshold: [10, 10]
value: 1,021,258,000
- name: polkadotXcm.Sent
chain: *assets_parachain
- name: ump.ExecutedUpward
timeout: 40000
attribute:
type: XcmV2TraitsOutcome
isComplete: true
threshold: [10, 10]
value: 1,160,892,000
- name: hrmp.OpenChannelAccepted
timeout: 40000
- queries:
open_channels:
chain: *relay_chain
pallet: hrmp
call: hrmpChannels
delay: 80000
args: [
{
sender: *pp_id,
recipient: *ap_id
}
]
- asserts:
equal:
args: [
$open_channels,
*channel
]
- name: hrmp.hrmpInitOpenChannel (Assets Parachain → Penpal Parachain)
its:
- name: Assets Parchain sends a request to the Relay Chain to open a channel with a Penpal Parachain
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
sudo: true
pallet: xcmPallet
call: send
args: [
*ap_dest, # destination
{
v2: [ #message
{
Transact: {
originType: Superuser,
requireWeightAtMost: *weight_at_most,
call: $xcm_init_open_channel_with_cp
}
}
]
}
]
events:
- name: sudo.Sudid
attribute:
type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: xcmPallet.Sent
- name: dmpQueue.ExecutedDownward
chain: *assets_parachain
attribute:
type: XcmV2TraitsOutcome
isComplete: true
threshold: [10, 10]
value: 1,021,258,000
- name: polkadotXcm.Sent
chain: *assets_parachain
- name: ump.ExecutedUpward
timeout: 40000
attribute:
type: XcmV2TraitsOutcome
isComplete: true
threshold: [10, 10]
value: 1,160,892,000
- name: hrmp.OpenChannelRequested
timeout: 40000
- queries:
requested_channels:
chain: *relay_chain
pallet: hrmp
call: hrmpOpenChannelRequestsList
args: []
- asserts:
equal:
args: [
$requested_channels,
[
{
sender: *ap_id,
recipient: *pp_id
}
]
]
- name: hrmp.hrmpAcceptOpenChannel (Penpal Parachain → Assets Parachain)
its:
- name: Penpal Parachain sends a response to the Relay Chain accepting the Assets Parachain's request for openning a HRMP channel
actions:
- extrinsics:
- chain: *penpal_parachain
signer: *pp_signer
sudo: true
pallet: polkadotXcm
call: send
args: [
*rc_dest, # destination
{
v2: [ #message
{
WithdrawAsset: [*rc_ksm_fungible]
},
{
BuyExecution: {
fees: *rc_ksm_fungible,
weightLimit: Unlimited
}
},
{
Transact: {
originType: Native,
requireWeightAtMost: *weight_at_most,
call: $accept_open_channel_with_ap
}
}
]
}
]
events:
- name: sudo.Sudid
attribute:
type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: polkadotXcm.Sent
- name: ump.ExecutedUpward
chain: *relay_chain
attribute:
type: XcmV2TraitsOutcome
isComplete: true
threshold: [10, 10]
value: 1,160,892,000
- name: hrmp.OpenChannelAccepted
chain: *relay_chain
@@ -1,356 +0,0 @@
---
settings:
chains:
relay_chain: &relay_chain
wsPort: 9900
assets_parachain: &assets_parachain
wsPort: 9910
paraId: &ap_id 1000
penpal_parachain: &penpal_parachain
wsPort: 9920
paraId: &pp_id 2000
variables:
common:
amount: &amount 1000000000000
require_weight_at_most: &weight_at_most 1000000000
amount_to_send: &amount_to_send 500000000000
chains:
relay_chain:
signer: &rc_signer //Alice
assets_parachain_destination: &ap_dest { v1: { 0, interior: { x1: { parachain: *ap_id }}}}
assets_parachain_dest_routed: &ap_dest_routed { v1: { parents: 1, interior: { x1: { parachain: *ap_id } }}}
assets_parachain_account:
signer: &ap_signer //Alice
wallet: &ap_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F
asset_id: &asset_id 2
assets_pallet_id: &assets_pallet_id 50
asset_min_balance: &asset_ed 1000
penpal_parachain_destination: &pp_dest { v1: { parents: 1, interior: { x1: { parachain: *pp_id } }}}
ksm: &ap_ksm { concrete: { parents: 1, interior: { here: true }}}
ksm_fungible: &ap_ksm_fungible { id: *ap_ksm, fun: { fungible: *amount }}
suff_asset: &suff_asset { concrete: { parents: 0, interior: { x2: [ { PalletInstance: *assets_pallet_id }, { GeneralIndex: *asset_id } ] }}}
suff_asset_fail: &suff_asset_fail { concrete: { parents: 0, interior: { x2: [ { PalletInstance: *assets_pallet_id }, { GeneralIndex: 3 } ] }}}
suff_asset_fungible: &ap_suff_asset_fungible { id: *suff_asset, fun: { fungible: *weight_at_most }}
suff_asset_fungible_fail: &ap_suff_asset_fungible_fail { id: *suff_asset_fail, fun: { fungible: *weight_at_most }}
penpal_parachain:
sovereign_account: &pp_sovereign_sibl FBeL7EAeUroLWXW1yfKboiqTqVfbRBcsUKd6QqVf4kGBySS
signer: &pp_signer //Alice
penpal_parachain_account: &pp_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'
decodedCalls:
force_create_asset:
chain: *assets_parachain
pallet: assets
call: forceCreate
args: [
*asset_id,
{ Id: *ap_wallet }, # owner
true, # isSufficient
*asset_ed # minBalance
]
system_remark_with_event:
chain: *assets_parachain
pallet: system
call: remarkWithEvent
args: [ 0x0011 ]
tests:
- name: HRMP
describes:
- name: polkadotXcm.limitedReserveTransferAssets (Asset) | Assets Parachain -> Penpal Parachain
before:
- name: DEPENDANCY | A sufficient Asset should exist in the Assets Parachain
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
sudo: true
pallet: xcmPallet
call: send
args: [
*ap_dest, # destination
{
v2: [ #message
{
Transact: {
originType: Superuser,
requireWeightAtMost: *weight_at_most,
call: $force_create_asset
}
}
]
}
]
events:
- name: xcmPallet.Sent
- name: dmpQueue.ExecutedDownward
chain: *assets_parachain
attribute:
type: XcmV2TraitsOutcome
isComplete: true
threshold: [10, 10]
value: 1,021,258,000
- queries:
forced_created_asset:
chain: *assets_parachain
pallet: assets
call: asset
args: [ *asset_id ]
- asserts:
isSome:
args: [ $forced_created_asset ]
- name: DEPENDANCY | Some Assets should be minted for the sender
actions:
- extrinsics:
- chain: *assets_parachain
signer: *ap_signer
pallet: assets
call: mint
args: [
*asset_id,
*ap_wallet,
*amount
]
events:
- name: assets.Issued
its:
- name: Assets Parachain should be able to reserve transfer an Asset to Penpal Parachain
actions:
- extrinsics:
- chain: *assets_parachain
signer: *ap_signer
pallet: polkadotXcm
call: limitedReserveTransferAssets
args: [
*pp_dest, # destination
{ # beneficiary
V1: {
parents: 0,
interior: {
X1: {
AccountId32: {
network: Any,
id: *pp_acc
}
}
}
}
},
{ # assets
V1: [
{
id: {
Concrete: {
parents: 0,
interior: {
X2: [
{
PalletInstance: 50
},
{
GeneralIndex: *asset_id
}
]
}
}
},
fun: {
Fungible: *amount_to_send
}
}
]
},
0, # feeAssetItem
Unlimited # weightLimit
]
events:
- name: polkadotXcm.Attempted
attribute:
type: XcmV2TraitsOutcome
isComplete: true
threshold: [10, 10]
value: 654,608,000
- name: assets.Transferred
attribute:
type: AccountId32
value: *pp_sovereign_sibl
- name: assets.Transferred
attribute:
type: u128
value: *amount_to_send
- name: polkadotXcm.limitedReserveTransferAssets (KSM) | Assets Parachain -> Penpal Parachain
its:
- name: Assets Parachain should be able to reserve transfer KSM to Penpal Parachain
actions:
- extrinsics:
- chain: *assets_parachain
signer: *ap_signer
pallet: polkadotXcm
call: limitedReserveTransferAssets
args: [
*pp_dest, # destination
{ # beneficiary
V1: {
parents: 0,
interior: {
X1: {
AccountId32: {
network: Any,
id: *pp_acc
}
}
}
}
},
{ # assets
V1: [
*ap_ksm_fungible
]
},
0, # feeAssetItem
Unlimited # weightLimit
]
events:
- name: polkadotXcm.Attempted
attribute:
type: XcmV2TraitsOutcome
isComplete: true
threshold: [10, 10]
value: 654,608,000
- name: balances.Endowed
attribute:
type: AccountId32
value: *pp_sovereign_sibl
- name: balances.Endowed
attribute:
type: u128
value: *amount
- name: polkadotXcm.send( system.remarkWithEvent() ) | Penpal Parachain -> Assets Parachain
before:
- name: Get the asset balance of the Penpal Parachain Sovereign account in Assets Parachain
actions:
- queries:
assets_balance_pp_sovereign_before:
chain: *assets_parachain
pallet: assets
call: account
args: [
*asset_id,
*pp_sovereign_sibl
]
its:
- name: Penpal Parachain should be able to send XCM message paying its fee with sufficient asset in Assets Parachain
actions:
- extrinsics:
- chain: *penpal_parachain
signer: *pp_signer
sudo: true
pallet: polkadotXcm
call: send
args: [
*ap_dest_routed, # destination
{
v2: [ #message
{
WithdrawAsset: [*ap_suff_asset_fungible]
},
{
BuyExecution: {
fees: *ap_suff_asset_fungible,
weightLimit: Unlimited
}
},
{
Transact: {
originType: SovereignAccount,
requireWeightAtMost: *weight_at_most,
call: $system_remark_with_event
}
}
]
}
]
events:
- name: sudo.Sudid
attribute:
type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: polkadotXcm.Sent
- name: assets.Burned
chain: *assets_parachain
attribute:
type: AccountId32
value: *pp_sovereign_sibl
- name: assets.Issued
chain: *assets_parachain
attribute:
type: u32
value: *asset_id
- name: system.Remarked
chain: *assets_parachain
attribute:
type: AccountId32
value: *pp_sovereign_sibl
- queries:
assets_balance_pp_sovereign_after:
chain: *assets_parachain
pallet: assets
call: account
args: [
*asset_id,
*pp_sovereign_sibl
]
- name: Should reduce the assets balance of the Penpal Parachain's SovereignAccount in the Assets Parachain
actions:
- asserts:
assetsDecreased:
args: [
{
balances: {
before: $assets_balance_pp_sovereign_before,
after: $assets_balance_pp_sovereign_after,
},
}
]
- name: Penpal Parachain SHOULD NOT be able to send XCM message paying its fee with sufficient assets if not enough balance
actions:
- extrinsics:
- chain: *penpal_parachain
signer: *pp_signer
sudo: true
pallet: polkadotXcm
call: send
args: [
*ap_dest_routed, # destination
{
v2: [ #message
{
WithdrawAsset: [*ap_suff_asset_fungible_fail]
},
{
BuyExecution: {
fees: *ap_suff_asset_fungible_fail,
weightLimit: Unlimited
}
},
{
Transact: {
originType: SovereignAccount,
requireWeightAtMost: *weight_at_most,
call: $system_remark_with_event
}
}
]
}
]
events:
- name: xcmpQueue.Fail
chain: *assets_parachain
attribute:
type: XcmV2TraitsError
value: FailedToTransactAsset
@@ -1,49 +0,0 @@
[relaychain]
default_command = "./bin/polkadot"
default_args = [ "-lparachain=debug" ]
chain = "polkadot-local"
[[relaychain.nodes]]
name = "alice"
ws_port = 9900
validator = true
[[relaychain.nodes]]
name = "bob"
validator = true
[[relaychain.nodes]]
name = "charlie"
validator = true
[[relaychain.nodes]]
name = "dave"
validator = true
[[parachains]]
id = 1000
chain = "statemint-local"
cumulus_based = true
[[parachains.collators]]
name = "collator1"
ws_port = 9910
command = "./bin/polkadot-parachain"
[[parachains.collators]]
name = "collator2"
command = "./bin/polkadot-parachain"
[[parachains]]
id = 2000
chain = "penpal-polkadot-2000"
cumulus_based = true
[[parachains.collators]]
name = "collator3"
ws_port = 9920
command = "./bin/polkadot-parachain"
[[parachains.collators]]
name = "collator4"
command = "./bin/polkadot-parachain"
@@ -1,402 +0,0 @@
---
settings:
chains:
relay_chain: &relay_chain
wsPort: 9900
assets_parachain: &assets_parachain
wsPort: 9910
paraId: &ap_id 1000
penpal_parachain: &penpal_parachain
wsPort: 9920
paraId: &pp_id 2000
variables:
common:
amount: &amount 2000000000000
require_weight_at_most: &weight_at_most 1000000000
hrmp_channels:
proposed_max_capacity: &max_capacity 8
proposed_max_message_size: &max_message_size 8192
channel: &channel {
maxCapacity: 8,
maxTotalSize: 8192,
maxMessageSize: 8192,
msgCount: 0,
totalSize: 0,
mqcHead: null,
senderDeposit: 0,
recipientDeposit: 0
}
chains:
relay_chain:
signer: &rc_signer //Alice
assets_parachain_destination: &ap_dest { v1: { 0, interior: { x1: { parachain: *ap_id }}}}
ksm: &rc_ksm { concrete: { 0, interior: { here: true }}}
ksm_fungible: &rc_ksm_fungible { id: *rc_ksm, fun: { fungible: *amount }}
assets_parachain_account:
sovereign_account: &ap_sovereign F7fq1jSNVTPfJmaHaXCMtatT1EZefCUsa7rRiQVNR5efcah
relay_chain_destination: &rc_dest { v1: { parents: 1, interior: { here: true }}}
penpal_parachain:
sovereign_account: &pp_sovereign F7fq1jMZkfuCuoMTyiEVAP2DMpMt18WopgBqTJznLihLNbZ
signer: &pp_signer //Alice
decodedCalls:
init_open_channel_with_ap:
chain: *relay_chain
pallet: hrmp
call: hrmpInitOpenChannel
args: [
*ap_id, # recipient
*max_capacity, # proposedMaxCapacity
*max_message_size # proposedMaxMessageSize
]
init_open_channel_with_cp:
chain: *relay_chain
pallet: hrmp
call: hrmpInitOpenChannel
args: [
*pp_id, # recipient
*max_capacity, # proposedMaxCapacity
*max_message_size # proposedMaxMessageSize
]
accept_open_channel_with_ap:
chain: *relay_chain
pallet: hrmp
call: hrmpAcceptOpenChannel
args: [
*ap_id, # recipient
]
accept_init_open_request_from_cp:
chain: *relay_chain
pallet: hrmp
call: hrmpAcceptOpenChannel
args: [
*pp_id, # sender
]
xcm_accept_init_open_request_from_cp:
chain: *assets_parachain
pallet: polkadotXcm
call: send
args: [
*rc_dest, # destination
{
v2: [ #message
{
WithdrawAsset: [*rc_ksm_fungible]
},
{
BuyExecution: {
fees: *rc_ksm_fungible,
weightLimit: Unlimited
}
},
{
Transact: {
originType: Native,
requireWeightAtMost: *weight_at_most,
call: $accept_init_open_request_from_cp
}
}
]
}
]
xcm_init_open_channel_with_cp:
chain: *assets_parachain
pallet: polkadotXcm
call: send
args: [
*rc_dest, # destination
{
v2: [ #message
{
WithdrawAsset: [*rc_ksm_fungible]
},
{
BuyExecution: {
fees: *rc_ksm_fungible,
weightLimit: Unlimited
}
},
{
Transact: {
originType: Native,
requireWeightAtMost: *weight_at_most,
call: $init_open_channel_with_cp
}
}
]
}
]
tests:
- name: HRMP
beforeEach:
- name: DEPENDANCY | Penpal Parachain Sovereign account in the Relay Chain needs to be funded
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
pallet: balances
call: transfer
args: [
*pp_sovereign, # destination
*amount, # value
]
events:
- name: balances.Transfer
- name: DEPENDANCY | Assets Parachain Sovereign account in the Relay Chain needs to be funded
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
pallet: balances
call: transfer
args: [
*ap_sovereign, # destination
*amount, # value
]
events:
- name: balances.Transfer
describes:
- name: hrmp.hrmpInitOpenChannel (Penpal Parachain → Assets Parachain)
its:
- name: Penpal Parachain sends a request to the Relay Chain to open a channel with the Assets Parchain
actions:
- extrinsics:
- chain: *penpal_parachain
signer: *pp_signer
sudo: true
pallet: polkadotXcm
call: send
args: [
*rc_dest, # destination
{
v2: [ #message
{
WithdrawAsset: [*rc_ksm_fungible]
},
{
BuyExecution: {
fees: *rc_ksm_fungible,
weightLimit: Unlimited
}
},
{
Transact: {
originType: Native,
requireWeightAtMost: *weight_at_most,
call: $init_open_channel_with_ap
}
}
]
}
]
events:
- name: sudo.Sudid
attribute:
type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: polkadotXcm.Sent
- name: ump.ExecutedUpward
chain: *relay_chain
attribute:
type: XcmV2TraitsOutcome
isComplete: true
value: 4,000,000,000
- name: hrmp.OpenChannelRequested
chain: *relay_chain
- queries:
requested_channels:
chain: *relay_chain
pallet: hrmp
call: hrmpOpenChannelRequestsList
args: []
- asserts:
equal:
args: [
$requested_channels,
[
{
sender: *pp_id,
recipient: *ap_id
}
]
]
- name: hrmp.hrmpAcceptOpenChannel (Assets Parachain → Penpal Parachain)
its:
- name: Assets Parachain sends a response to the Relay Chain accepting the Penpal Parachain's request for openning a HRMP channel
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
sudo: true
pallet: xcmPallet
call: send
args: [
*ap_dest, # destination
{
v2: [ #message
{
Transact: {
originType: Superuser,
requireWeightAtMost: *weight_at_most,
call: $xcm_accept_init_open_request_from_cp
}
}
]
}
]
events:
- name: sudo.Sudid
attribute:
type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: xcmPallet.Sent
- name: dmpQueue.ExecutedDownward
chain: *assets_parachain
attribute:
type: XcmV2TraitsOutcome
isComplete: true
threshold: [10, 10]
value: 1,020,807,000
- name: polkadotXcm.Sent
chain: *assets_parachain
- name: ump.ExecutedUpward
timeout: 40000
attribute:
type: XcmV2TraitsOutcome
isComplete: true
value: 4,000,000,000
- name: hrmp.OpenChannelAccepted
timeout: 40000
- queries:
open_channels:
chain: *relay_chain
pallet: hrmp
call: hrmpChannels
delay: 80000
args: [
{
sender: *pp_id,
recipient: *ap_id
}
]
- asserts:
equal:
args: [
$open_channels,
*channel
]
- name: hrmp.hrmpInitOpenChannel (Assets Parachain → Penpal Parachain)
its:
- name: Assets Parchain sends a request to the Relay Chain to open a channel with a Penpal Parachain
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
sudo: true
pallet: xcmPallet
call: send
args: [
*ap_dest, # destination
{
v2: [ #message
{
Transact: {
originType: Superuser,
requireWeightAtMost: *weight_at_most,
call: $xcm_init_open_channel_with_cp
}
}
]
}
]
events:
- name: sudo.Sudid
attribute:
type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: xcmPallet.Sent
- name: dmpQueue.ExecutedDownward
chain: *assets_parachain
attribute:
type: XcmV2TraitsOutcome
isComplete: true
threshold: [10, 10]
value: 1,020,807,000
- name: polkadotXcm.Sent
chain: *assets_parachain
- name: ump.ExecutedUpward
timeout: 40000
attribute:
type: XcmV2TraitsOutcome
isComplete: true
value: 4,000,000,000
- name: hrmp.OpenChannelRequested
timeout: 40000
- queries:
requested_channels:
chain: *relay_chain
pallet: hrmp
call: hrmpOpenChannelRequestsList
args: []
- asserts:
equal:
args: [
$requested_channels,
[
{
sender: *ap_id,
recipient: *pp_id
}
]
]
- name: hrmp.hrmpAcceptOpenChannel (Penpal Parachain → Assets Parachain)
its:
- name: Penpal Parachain sends a response to the Relay Chain accepting the Assets Parachain's request for openning a HRMP channel
actions:
- extrinsics:
- chain: *penpal_parachain
signer: *pp_signer
sudo: true
pallet: polkadotXcm
call: send
args: [
*rc_dest, # destination
{
v2: [ #message
{
WithdrawAsset: [*rc_ksm_fungible]
},
{
BuyExecution: {
fees: *rc_ksm_fungible,
weightLimit: Unlimited
}
},
{
Transact: {
originType: Native,
requireWeightAtMost: *weight_at_most,
call: $accept_open_channel_with_ap
}
}
]
}
]
events:
- name: sudo.Sudid
attribute:
type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: polkadotXcm.Sent
- name: ump.ExecutedUpward
chain: *relay_chain
attribute:
type: XcmV2TraitsOutcome
isComplete: true
value: 4,000,000,000
- name: hrmp.OpenChannelAccepted
chain: *relay_chain
@@ -1,356 +0,0 @@
---
settings:
chains:
relay_chain: &relay_chain
wsPort: 9900
assets_parachain: &assets_parachain
wsPort: 9910
paraId: &ap_id 1000
penpal_parachain: &penpal_parachain
wsPort: 9920
paraId: &pp_id 2000
variables:
common:
amount: &amount 1000000000000
require_weight_at_most: &weight_at_most 1000000000
amount_to_send: &amount_to_send 500000000000
chains:
relay_chain:
signer: &rc_signer //Alice
assets_parachain_destination: &ap_dest { v1: { 0, interior: { x1: { parachain: *ap_id }}}}
assets_parachain_dest_routed: &ap_dest_routed { v1: { parents: 1, interior: { x1: { parachain: *ap_id } }}}
assets_parachain_account:
signer: &ap_signer //Alice
wallet: &ap_wallet HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F
asset_id: &asset_id 2
assets_pallet_id: &assets_pallet_id 50
asset_min_balance: &asset_ed 1000
penpal_parachain_destination: &pp_dest { v1: { parents: 1, interior: { x1: { parachain: *pp_id } }}}
ksm: &ap_ksm { concrete: { parents: 1, interior: { here: true }}}
ksm_fungible: &ap_ksm_fungible { id: *ap_ksm, fun: { fungible: *amount }}
suff_asset: &suff_asset { concrete: { parents: 0, interior: { x2: [ { PalletInstance: *assets_pallet_id }, { GeneralIndex: *asset_id } ] }}}
suff_asset_fail: &suff_asset_fail { concrete: { parents: 0, interior: { x2: [ { PalletInstance: *assets_pallet_id }, { GeneralIndex: 3 } ] }}}
suff_asset_fungible: &ap_suff_asset_fungible { id: *suff_asset, fun: { fungible: *weight_at_most }}
suff_asset_fungible_fail: &ap_suff_asset_fungible_fail { id: *suff_asset_fail, fun: { fungible: *weight_at_most }}
penpal_parachain:
sovereign_account: &pp_sovereign_sibl 13cKp89Msu7M2PiaCuuGr1BzAsD5V3vaVbDMs3YtjMZHdGwR
signer: &pp_signer //Alice
penpal_parachain_account: &pp_acc '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d'
decodedCalls:
force_create_asset:
chain: *assets_parachain
pallet: assets
call: forceCreate
args: [
*asset_id,
{ Id: *ap_wallet }, # owner
true, # isSufficient
*asset_ed # minBalance
]
system_remark_with_event:
chain: *assets_parachain
pallet: system
call: remarkWithEvent
args: [ 0x0011 ]
tests:
- name: HRMP
describes:
- name: polkadotXcm.limitedReserveTransferAssets (Asset) | Assets Parachain -> Penpal Parachain
before:
- name: DEPENDANCY | A sufficient Asset should exist in the Assets Parachain
actions:
- extrinsics:
- chain: *relay_chain
signer: *rc_signer
sudo: true
pallet: xcmPallet
call: send
args: [
*ap_dest, # destination
{
v2: [ #message
{
Transact: {
originType: Superuser,
requireWeightAtMost: *weight_at_most,
call: $force_create_asset
}
}
]
}
]
events:
- name: xcmPallet.Sent
- name: dmpQueue.ExecutedDownward
chain: *assets_parachain
attribute:
type: XcmV2TraitsOutcome
isComplete: true
threshold: [10, 10]
value: 1,020,807,000
- queries:
forced_created_asset:
chain: *assets_parachain
pallet: assets
call: asset
args: [ *asset_id ]
- asserts:
isSome:
args: [ $forced_created_asset ]
- name: DEPENDANCY | Some Assets should be minted for the sender
actions:
- extrinsics:
- chain: *assets_parachain
signer: *ap_signer
pallet: assets
call: mint
args: [
*asset_id,
*ap_wallet,
*amount
]
events:
- name: assets.Issued
its:
- name: Assets Parachain should be able to reserve transfer an Asset to Penpal Parachain
actions:
- extrinsics:
- chain: *assets_parachain
signer: *ap_signer
pallet: polkadotXcm
call: limitedReserveTransferAssets
args: [
*pp_dest, # destination
{ # beneficiary
V1: {
parents: 0,
interior: {
X1: {
AccountId32: {
network: Any,
id: *pp_acc
}
}
}
}
},
{ # assets
V1: [
{
id: {
Concrete: {
parents: 0,
interior: {
X2: [
{
PalletInstance: 50
},
{
GeneralIndex: *asset_id
}
]
}
}
},
fun: {
Fungible: *amount_to_send
}
}
]
},
0, # feeAssetItem
Unlimited # weightLimit
]
events:
- name: polkadotXcm.Attempted
attribute:
type: XcmV2TraitsOutcome
isComplete: true
threshold: [10, 10]
value: 654,404,000
- name: assets.Transferred
attribute:
type: AccountId32
value: *pp_sovereign_sibl
- name: assets.Transferred
attribute:
type: u128
value: *amount_to_send
- name: polkadotXcm.limitedReserveTransferAssets (KSM) | Assets Parachain -> Penpal Parachain
its:
- name: Assets Parachain should be able to reserve transfer KSM to Penpal Parachain
actions:
- extrinsics:
- chain: *assets_parachain
signer: *ap_signer
pallet: polkadotXcm
call: limitedReserveTransferAssets
args: [
*pp_dest, # destination
{ # beneficiary
V1: {
parents: 0,
interior: {
X1: {
AccountId32: {
network: Any,
id: *pp_acc
}
}
}
}
},
{ # assets
V1: [
*ap_ksm_fungible
]
},
0, # feeAssetItem
Unlimited # weightLimit
]
events:
- name: polkadotXcm.Attempted
attribute:
type: XcmV2TraitsOutcome
isComplete: true
threshold: [10, 10]
value: 654,404,000
- name: balances.Endowed
attribute:
type: AccountId32
value: *pp_sovereign_sibl
- name: balances.Endowed
attribute:
type: u128
value: *amount
- name: polkadotXcm.send( system.remarkWithEvent() ) | Penpal Parachain -> Assets Parachain
before:
- name: Get the asset balance of the Penpal Parachain Sovereign account in Assets Parachain
actions:
- queries:
assets_balance_pp_sovereign_before:
chain: *assets_parachain
pallet: assets
call: account
args: [
*asset_id,
*pp_sovereign_sibl
]
its:
- name: Penpal Parachain should be able to send XCM message paying its fee with sufficient asset in Assets Parachain
actions:
- extrinsics:
- chain: *penpal_parachain
signer: *pp_signer
sudo: true
pallet: polkadotXcm
call: send
args: [
*ap_dest_routed, # destination
{
v2: [ #message
{
WithdrawAsset: [*ap_suff_asset_fungible]
},
{
BuyExecution: {
fees: *ap_suff_asset_fungible,
weightLimit: Unlimited
}
},
{
Transact: {
originType: SovereignAccount,
requireWeightAtMost: *weight_at_most,
call: $system_remark_with_event
}
}
]
}
]
events:
- name: sudo.Sudid
attribute:
type: Result<Null, SpRuntimeDispatchError>
value: Ok
- name: polkadotXcm.Sent
- name: assets.Burned
chain: *assets_parachain
attribute:
type: AccountId32
value: *pp_sovereign_sibl
- name: assets.Issued
chain: *assets_parachain
attribute:
type: u32
value: *asset_id
- name: system.Remarked
chain: *assets_parachain
attribute:
type: AccountId32
value: *pp_sovereign_sibl
- queries:
assets_balance_pp_sovereign_after:
chain: *assets_parachain
pallet: assets
call: account
args: [
*asset_id,
*pp_sovereign_sibl
]
- name: Should reduce the assets balance of the Penpal Parachain's SovereignAccount in the Assets Parachain
actions:
- asserts:
assetsDecreased:
args: [
{
balances: {
before: $assets_balance_pp_sovereign_before,
after: $assets_balance_pp_sovereign_after,
},
}
]
- name: Penpal Parachain SHOULD NOT be able to send XCM message paying its fee with sufficient assets if not enough balance
actions:
- extrinsics:
- chain: *penpal_parachain
signer: *pp_signer
sudo: true
pallet: polkadotXcm
call: send
args: [
*ap_dest_routed, # destination
{
v2: [ #message
{
WithdrawAsset: [*ap_suff_asset_fungible_fail]
},
{
BuyExecution: {
fees: *ap_suff_asset_fungible_fail,
weightLimit: Unlimited
}
},
{
Transact: {
originType: SovereignAccount,
requireWeightAtMost: *weight_at_most,
call: $system_remark_with_event
}
}
]
}
]
events:
- name: xcmpQueue.Fail
chain: *assets_parachain
attribute:
type: XcmV2TraitsError
value: FailedToTransactAsset
+37
View File
@@ -0,0 +1,37 @@
[package]
name = "xcm-emulator"
description = "Test kit to emulate XCM program execution."
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0" }
paste = "1.0.5"
quote = "1.0.23"
casey = "0.3.3"
log = { version = "0.4.17", default-features = false }
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" }
cumulus-primitives-core = { path = "../../primitives/core"}
cumulus-pallet-xcmp-queue = { path = "../../pallets/xcmp-queue" }
cumulus-pallet-dmp-queue = { path = "../../pallets/dmp-queue" }
cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system" }
cumulus-test-service = { path = "../../test/service" }
parachain-info = { path = "../../parachains/pallets/parachain-info" }
cumulus-primitives-parachain-inherent = { path = "../../primitives/parachain-inherent" }
cumulus-test-relay-sproof-builder = { path = "../../test/relay-sproof-builder" }
parachains-common = { path = "../../parachains/common" }
xcm = { git = "https://github.com/paritytech/polkadot", branch = "master" }
xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" }
polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" }
+20
View File
@@ -0,0 +1,20 @@
# xcm-emulator
XCM-Emulator is a tool to emulate XCM program execution using
pre-configured runtimes, including those used to run on live
networks, such as Kusama, Polkadot, Statemine et cetera.
This allows for testing cross-chain message passing and verifying
outcomes, weights, and side-effects. It is faster than spinning up
a zombienet and as all the chains are in one process debugging using Clion is easy.
## Limitations
As the messages do not physically go through the same messaging infrastructure
there is some code that is not being tested compared to using slower E2E tests.
In future it may be possible to run these XCM emulated tests as E2E tests (without changes).
## Alternatives
If you just wish to test execution of various XCM instructions
against the XCM VM then the `xcm-simulator` (in the polkadot
repo) is the perfect tool for this.
+939
View File
@@ -0,0 +1,939 @@
// Copyright 2023 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
pub use casey::pascal;
pub use codec::Encode;
pub use frame_support::{
sp_runtime::BuildStorage,
traits::{Get, Hooks},
weights::Weight,
};
pub use frame_system::AccountInfo;
pub use log;
pub use pallet_balances::AccountData;
pub use paste;
pub use sp_arithmetic::traits::Bounded;
pub use sp_core::storage::Storage;
pub use sp_io::TestExternalities;
pub use sp_std::{cell::RefCell, collections::vec_deque::VecDeque, marker::PhantomData};
pub use sp_trie::StorageProof;
pub use cumulus_pallet_dmp_queue;
pub use cumulus_pallet_parachain_system;
pub use cumulus_pallet_xcmp_queue;
pub use cumulus_primitives_core::{
self, relay_chain::BlockNumber as RelayBlockNumber, DmpMessageHandler, ParaId,
PersistedValidationData, XcmpMessageHandler,
};
pub use cumulus_primitives_parachain_inherent::ParachainInherentData;
pub use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
pub use cumulus_test_service::get_account_id_from_seed;
pub use parachain_info;
pub use parachains_common::{AccountId, BlockNumber};
pub use polkadot_primitives;
pub use polkadot_runtime_parachains::{
dmp,
ump::{MessageId, UmpSink, XcmSink},
};
pub use std::{collections::HashMap, thread::LocalKey};
pub use xcm::{v3::prelude::*, VersionedXcm};
pub use xcm_executor::XcmExecutor;
thread_local! {
/// Downward messages, each message is: `(to_para_id, [(relay_block_number, msg)])`
#[allow(clippy::type_complexity)]
pub static DOWNWARD_MESSAGES: RefCell<HashMap<String, VecDeque<(u32, Vec<(RelayBlockNumber, Vec<u8>)>)>>>
= RefCell::new(HashMap::new());
/// Downward messages that already processed by parachains, each message is: `(to_para_id, relay_block_number, Vec<u8>)`
#[allow(clippy::type_complexity)]
pub static DMP_DONE: RefCell<HashMap<String, VecDeque<(u32, RelayBlockNumber, Vec<u8>)>>>
= RefCell::new(HashMap::new());
/// Horizontal messages, each message is: `(to_para_id, [(from_para_id, relay_block_number, msg)])`
#[allow(clippy::type_complexity)]
pub static HORIZONTAL_MESSAGES: RefCell<HashMap<String, VecDeque<(u32, Vec<(ParaId, RelayBlockNumber, Vec<u8>)>)>>>
= RefCell::new(HashMap::new());
/// Upward messages, each message is: `(from_para_id, msg)
pub static UPWARD_MESSAGES: RefCell<HashMap<String, VecDeque<(u32, Vec<u8>)>>> = RefCell::new(HashMap::new());
/// Global incremental relay chain block number
pub static RELAY_BLOCK_NUMBER: RefCell<HashMap<String, u32>> = RefCell::new(HashMap::new());
/// Parachains Ids a the Network
pub static PARA_IDS: RefCell<HashMap<String, Vec<u32>>> = RefCell::new(HashMap::new());
/// Flag indicating if global variables have been initialized for a certain Network
pub static INITIALIZED: RefCell<HashMap<String, bool>> = RefCell::new(HashMap::new());
}
pub trait TestExt {
fn build_new_ext(storage: Storage) -> sp_io::TestExternalities;
fn new_ext() -> sp_io::TestExternalities;
fn reset_ext();
fn execute_with<R>(execute: impl FnOnce() -> R) -> R;
fn ext_wrapper<R>(func: impl FnOnce() -> R) -> R;
}
pub trait Network {
fn _init();
fn _para_ids() -> Vec<u32>;
fn _relay_block_number() -> u32;
fn _set_relay_block_number(block_number: u32);
fn _process_messages();
fn _has_unprocessed_messages() -> bool;
fn _process_downward_messages();
fn _process_horizontal_messages();
fn _process_upward_messages();
fn _hrmp_channel_parachain_inherent_data(
para_id: u32,
relay_parent_number: u32,
) -> ParachainInherentData;
}
pub trait NetworkComponent<N: Network> {
fn network_name() -> &'static str;
fn init() {
N::_init();
}
fn relay_block_number() -> u32 {
N::_relay_block_number()
}
fn set_relay_block_number(block_number: u32) {
N::_set_relay_block_number(block_number);
}
fn para_ids() -> Vec<u32> {
N::_para_ids()
}
fn send_horizontal_messages<I: Iterator<Item = (ParaId, RelayBlockNumber, Vec<u8>)>>(
to_para_id: u32,
iter: I,
) {
HORIZONTAL_MESSAGES.with(|b| {
b.borrow_mut()
.get_mut(Self::network_name())
.unwrap()
.push_back((to_para_id, iter.collect()))
});
}
fn send_upward_message(from_para_id: u32, msg: Vec<u8>) {
UPWARD_MESSAGES.with(|b| {
b.borrow_mut()
.get_mut(Self::network_name())
.unwrap()
.push_back((from_para_id, msg))
});
}
fn send_downward_messages(
to_para_id: u32,
iter: impl Iterator<Item = (RelayBlockNumber, Vec<u8>)>,
) {
DOWNWARD_MESSAGES.with(|b| {
b.borrow_mut()
.get_mut(Self::network_name())
.unwrap()
.push_back((to_para_id, iter.collect()))
});
}
fn hrmp_channel_parachain_inherent_data(
para_id: u32,
relay_parent_number: u32,
) -> ParachainInherentData {
N::_hrmp_channel_parachain_inherent_data(para_id, relay_parent_number)
}
fn process_messages() {
N::_process_messages();
}
}
pub trait RelayChain: UmpSink {
type Runtime;
type RuntimeOrigin;
type RuntimeCall;
type RuntimeEvent;
type XcmConfig;
type SovereignAccountOf;
type System;
type Balances;
}
pub trait Parachain: XcmpMessageHandler + DmpMessageHandler {
type Runtime;
type RuntimeOrigin;
type RuntimeCall;
type RuntimeEvent;
type XcmpMessageHandler;
type DmpMessageHandler;
type LocationToAccountId;
type System;
type Balances;
type ParachainSystem;
type ParachainInfo;
}
// Relay Chain Implementation
#[macro_export]
macro_rules! decl_test_relay_chains {
(
$(
pub struct $name:ident {
genesis = $genesis:expr,
on_init = $on_init:expr,
runtime = {
Runtime: $($runtime:tt)::*,
RuntimeOrigin: $($runtime_origin:tt)::*,
RuntimeCall: $($runtime_call:tt)::*,
RuntimeEvent: $($runtime_event:tt)::*,
XcmConfig: $($xcm_config:tt)::*,
SovereignAccountOf: $($sovereign_acc_of:tt)::*,
System: $($system:tt)::*,
Balances: $($balances:tt)::*,
},
pallets_extra = {
$($pallet_name:ident: $pallet_path:path,)*
}
}
),
+
) => {
$(
pub struct $name;
impl RelayChain for $name {
type Runtime = $($runtime)::*;
type RuntimeOrigin = $($runtime_origin)::*;
type RuntimeCall = $($runtime_call)::*;
type RuntimeEvent = $($runtime_event)::*;
type XcmConfig = $($xcm_config)::*;
type SovereignAccountOf = $($sovereign_acc_of)::*;
type System = $($system)::*;
type Balances = $($balances)::*;
}
$crate::paste::paste! {
pub trait [<$name Pallet>] {
$(
type $pallet_name;
)?
}
impl [<$name Pallet>] for $name {
$(
type $pallet_name = $pallet_path;
)?
}
}
$crate::__impl_xcm_handlers_for_relay_chain!($name);
$crate::__impl_test_ext_for_relay_chain!($name, $genesis, $on_init);
)+
};
}
#[macro_export]
macro_rules! __impl_xcm_handlers_for_relay_chain {
($name:ident) => {
impl $crate::UmpSink for $name {
fn process_upward_message(
origin: $crate::ParaId,
msg: &[u8],
max_weight: $crate::Weight,
) -> Result<$crate::Weight, ($crate::MessageId, $crate::Weight)> {
use $crate::{TestExt, UmpSink};
Self::execute_with(|| {
$crate::XcmSink::<
$crate::XcmExecutor<<Self as RelayChain>::XcmConfig>,
<Self as RelayChain>::Runtime,
>::process_upward_message(origin, msg, max_weight)
})
}
}
};
}
#[macro_export]
macro_rules! __impl_test_ext_for_relay_chain {
// entry point: generate ext name
($name:ident, $genesis:expr, $on_init:expr) => {
$crate::paste::paste! {
$crate::__impl_test_ext_for_relay_chain!(@impl $name, $genesis, $on_init, [<EXT_ $name:upper>]);
}
};
// impl
(@impl $name:ident, $genesis:expr, $on_init:expr, $ext_name:ident) => {
thread_local! {
pub static $ext_name: $crate::RefCell<$crate::TestExternalities>
= $crate::RefCell::new(<$name>::build_new_ext($genesis));
}
impl TestExt for $name {
fn build_new_ext(storage: $crate::Storage) -> $crate::TestExternalities {
let mut ext = sp_io::TestExternalities::new(storage);
ext.execute_with(|| {
#[allow(clippy::no_effect)]
$on_init;
sp_tracing::try_init_simple();
<Self as RelayChain>::System::set_block_number(1);
});
ext
}
fn new_ext() -> $crate::TestExternalities {
<$name>::build_new_ext($genesis)
}
fn reset_ext() {
$ext_name.with(|v| *v.borrow_mut() = <$name>::build_new_ext($genesis));
}
fn execute_with<R>(execute: impl FnOnce() -> R) -> R {
use $crate::{NetworkComponent};
// Make sure the Network is initialized
<$name>::init();
let r = $ext_name.with(|v| v.borrow_mut().execute_with(execute));
// send messages if needed
$ext_name.with(|v| {
v.borrow_mut().execute_with(|| {
use $crate::polkadot_primitives::runtime_api::runtime_decl_for_parachain_host::ParachainHostV4;
//TODO: mark sent count & filter out sent msg
for para_id in <$name>::para_ids() {
// downward messages
let downward_messages = <Self as RelayChain>::Runtime::dmq_contents(para_id.into())
.into_iter()
.map(|inbound| (inbound.sent_at, inbound.msg));
if downward_messages.len() == 0 {
continue;
}
<$name>::send_downward_messages(para_id, downward_messages.into_iter());
// Note: no need to handle horizontal messages, as the
// simulator directly sends them to dest (not relayed).
}
})
});
<$name>::process_messages();
r
}
fn ext_wrapper<R>(func: impl FnOnce() -> R) -> R {
$ext_name.with(|v| {
v.borrow_mut().execute_with(|| {
func()
})
})
}
}
};
}
#[macro_export]
macro_rules! __impl_relay {
($network_name:ident, $relay_chain:ty) => {
impl $crate::NetworkComponent<$network_name> for $relay_chain {
fn network_name() -> &'static str {
stringify!($network_name)
}
}
impl $relay_chain {
pub fn child_location_of(id: $crate::ParaId) -> MultiLocation {
(Ancestor(0), Parachain(id.into())).into()
}
pub fn account_id_of(seed: &str) -> $crate::AccountId {
$crate::get_account_id_from_seed::<sr25519::Public>(seed)
}
pub fn account_data_of(account: AccountId) -> $crate::AccountData<Balance> {
Self::ext_wrapper(|| <Self as RelayChain>::System::account(account).data)
}
pub fn sovereign_account_id_of(location: $crate::MultiLocation) -> $crate::AccountId {
<Self as RelayChain>::SovereignAccountOf::convert(location.into()).unwrap()
}
pub fn fund_accounts(accounts: Vec<(AccountId, Balance)>) {
Self::ext_wrapper(|| {
for account in accounts {
let _ = <Self as RelayChain>::Balances::force_set_balance(
<Self as RelayChain>::RuntimeOrigin::root(),
account.0.into(),
account.1.into(),
);
}
});
}
pub fn events() -> Vec<<Self as RelayChain>::RuntimeEvent> {
<Self as RelayChain>::System::events()
.iter()
.map(|record| record.event.clone())
.collect()
}
}
};
}
// Parachain Implementation
#[macro_export]
macro_rules! decl_test_parachains {
(
$(
pub struct $name:ident {
genesis = $genesis:expr,
on_init = $on_init:expr,
runtime = {
Runtime: $runtime:path,
RuntimeOrigin: $runtime_origin:path,
RuntimeCall: $runtime_call:path,
RuntimeEvent: $runtime_event:path,
XcmpMessageHandler: $xcmp_message_handler:path,
DmpMessageHandler: $dmp_message_handler:path,
LocationToAccountId: $location_to_account:path,
System: $system:path,
Balances: $balances_pallet:path,
ParachainSystem: $parachain_system:path,
ParachainInfo: $parachain_info:path,
},
pallets_extra = {
$($pallet_name:ident: $pallet_path:path,)*
}
}
),
+
) => {
$(
pub struct $name;
impl Parachain for $name {
type Runtime = $runtime;
type RuntimeOrigin = $runtime_origin;
type RuntimeCall = $runtime_call;
type RuntimeEvent = $runtime_event;
type XcmpMessageHandler = $xcmp_message_handler;
type DmpMessageHandler = $dmp_message_handler;
type LocationToAccountId = $location_to_account;
type System = $system;
type Balances = $balances_pallet;
type ParachainSystem = $parachain_system;
type ParachainInfo = $parachain_info;
}
$crate::paste::paste! {
pub trait [<$name Pallet>] {
$(
type $pallet_name;
)*
}
impl [<$name Pallet>] for $name {
$(
type $pallet_name = $pallet_path;
)*
}
}
$crate::__impl_xcm_handlers_for_parachain!($name);
$crate::__impl_test_ext_for_parachain!($name, $genesis, $on_init);
)+
};
}
#[macro_export]
macro_rules! __impl_xcm_handlers_for_parachain {
($name:ident) => {
impl $crate::XcmpMessageHandler for $name {
fn handle_xcmp_messages<
'a,
I: Iterator<Item = ($crate::ParaId, $crate::RelayBlockNumber, &'a [u8])>,
>(
iter: I,
max_weight: $crate::Weight,
) -> $crate::Weight {
use $crate::{TestExt, XcmpMessageHandler};
$name::execute_with(|| {
<Self as Parachain>::XcmpMessageHandler::handle_xcmp_messages(iter, max_weight)
})
}
}
impl $crate::DmpMessageHandler for $name {
fn handle_dmp_messages(
iter: impl Iterator<Item = ($crate::RelayBlockNumber, Vec<u8>)>,
max_weight: $crate::Weight,
) -> $crate::Weight {
use $crate::{DmpMessageHandler, TestExt};
$name::execute_with(|| {
<Self as Parachain>::DmpMessageHandler::handle_dmp_messages(iter, max_weight)
})
}
}
};
}
#[macro_export]
macro_rules! __impl_test_ext_for_parachain {
// entry point: generate ext name
($name:ident, $genesis:expr, $on_init:expr) => {
$crate::paste::paste! {
$crate::__impl_test_ext_for_parachain!(@impl $name, $genesis, $on_init, [<EXT_ $name:upper>]);
}
};
// impl
(@impl $name:ident, $genesis:expr, $on_init:expr, $ext_name:ident) => {
thread_local! {
pub static $ext_name: $crate::RefCell<$crate::TestExternalities>
= $crate::RefCell::new(<$name>::build_new_ext($genesis));
}
impl TestExt for $name {
fn build_new_ext(storage: $crate::Storage) -> $crate::TestExternalities {
let mut ext = sp_io::TestExternalities::new(storage);
ext.execute_with(|| {
#[allow(clippy::no_effect)]
$on_init;
sp_tracing::try_init_simple();
<Self as Parachain>::System::set_block_number(1);
});
ext
}
fn new_ext() -> $crate::TestExternalities {
<$name>::build_new_ext($genesis)
}
fn reset_ext() {
$ext_name.with(|v| *v.borrow_mut() = <$name>::build_new_ext($genesis));
}
fn execute_with<R>(execute: impl FnOnce() -> R) -> R {
use $crate::{Get, Hooks, NetworkComponent};
// Make sure the Network is initialized
<$name>::init();
let mut relay_block_number = <$name>::relay_block_number();
relay_block_number += 1;
<$name>::set_relay_block_number(relay_block_number);
let para_id = <$name>::para_id().into();
$ext_name.with(|v| {
v.borrow_mut().execute_with(|| {
// Make sure it has been recorded properly
let relay_block_number = <$name>::relay_block_number();
let _ = <Self as Parachain>::ParachainSystem::set_validation_data(
<Self as Parachain>::RuntimeOrigin::none(),
<$name>::hrmp_channel_parachain_inherent_data(para_id, relay_block_number),
);
})
});
let r = $ext_name.with(|v| v.borrow_mut().execute_with(execute));
// send messages if needed
$ext_name.with(|v| {
v.borrow_mut().execute_with(|| {
use sp_runtime::traits::Header as HeaderT;
let block_number = <Self as Parachain>::System::block_number();
let mock_header = HeaderT::new(
0,
Default::default(),
Default::default(),
Default::default(),
Default::default(),
);
// get messages
<Self as Parachain>::ParachainSystem::on_finalize(block_number);
let collation_info = <Self as Parachain>::ParachainSystem::collect_collation_info(&mock_header);
// send upward messages
let relay_block_number = <$name>::relay_block_number();
for msg in collation_info.upward_messages.clone() {
<$name>::send_upward_message(para_id, msg);
}
// send horizontal messages
for msg in collation_info.horizontal_messages {
<$name>::send_horizontal_messages(
msg.recipient.into(),
vec![(para_id.into(), relay_block_number, msg.data)].into_iter(),
);
}
// clean messages
<Self as Parachain>::ParachainSystem::on_initialize(block_number);
})
});
<$name>::process_messages();
r
}
fn ext_wrapper<R>(func: impl FnOnce() -> R) -> R {
$ext_name.with(|v| {
v.borrow_mut().execute_with(|| {
func()
})
})
}
}
};
}
#[macro_export]
macro_rules! __impl_parachain {
($network_name:ident, $parachain:ty) => {
impl $crate::NetworkComponent<$network_name> for $parachain {
fn network_name() -> &'static str {
stringify!($network_name)
}
}
impl $parachain {
pub fn para_id() -> $crate::ParaId {
Self::ext_wrapper(|| <Self as Parachain>::ParachainInfo::get())
}
pub fn parent_location() -> $crate::MultiLocation {
(Parent).into()
}
pub fn account_id_of(seed: &str) -> $crate::AccountId {
$crate::get_account_id_from_seed::<sr25519::Public>(seed)
}
pub fn account_data_of(account: AccountId) -> $crate::AccountData<Balance> {
Self::ext_wrapper(|| <Self as Parachain>::System::account(account).data)
}
pub fn sovereign_account_id_of(location: $crate::MultiLocation) -> $crate::AccountId {
<Self as Parachain>::LocationToAccountId::convert(location.into()).unwrap()
}
pub fn fund_accounts(accounts: Vec<(AccountId, Balance)>) {
Self::ext_wrapper(|| {
for account in accounts {
let _ = <Self as Parachain>::Balances::force_set_balance(
<Self as Parachain>::RuntimeOrigin::root(),
account.0.into(),
account.1.into(),
);
}
});
}
pub fn events() -> Vec<<Self as Parachain>::RuntimeEvent> {
<Self as Parachain>::System::events()
.iter()
.map(|record| record.event.clone())
.collect()
}
fn prepare_for_xcmp() {
use $crate::NetworkComponent;
let para_id = Self::para_id();
<Self as TestExt>::ext_wrapper(|| {
use $crate::{Get, Hooks};
let block_number = <Self as Parachain>::System::block_number();
let _ = <Self as Parachain>::ParachainSystem::set_validation_data(
<Self as Parachain>::RuntimeOrigin::none(),
Self::hrmp_channel_parachain_inherent_data(para_id.into(), 1),
);
// set `AnnouncedHrmpMessagesPerCandidate`
<Self as Parachain>::ParachainSystem::on_initialize(block_number);
});
}
}
};
}
// Network Implementation
#[macro_export]
macro_rules! decl_test_networks {
(
$(
pub struct $name:ident {
relay_chain = $relay_chain:ty,
parachains = vec![ $( $parachain:ty, )* ],
}
),
+
) => {
$(
pub struct $name;
impl $name {
pub fn reset() {
use $crate::{TestExt, VecDeque};
$crate::INITIALIZED.with(|b| b.borrow_mut().remove(stringify!($name)));
$crate::DOWNWARD_MESSAGES.with(|b| b.borrow_mut().remove(stringify!($name)));
$crate::DMP_DONE.with(|b| b.borrow_mut().remove(stringify!($name)));
$crate::UPWARD_MESSAGES.with(|b| b.borrow_mut().remove(stringify!($name)));
$crate::HORIZONTAL_MESSAGES.with(|b| b.borrow_mut().remove(stringify!($name)));
$crate::RELAY_BLOCK_NUMBER.with(|b| b.borrow_mut().remove(stringify!($name)));
<$relay_chain>::reset_ext();
$( <$parachain>::reset_ext(); )*
$( <$parachain>::prepare_for_xcmp(); )*
}
}
impl $crate::Network for $name {
fn _init() {
// If Network has not been itialized yet, it gets initialized
if $crate::INITIALIZED.with(|b| b.borrow_mut().get(stringify!($name)).is_none()) {
$crate::INITIALIZED.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), true));
$crate::DOWNWARD_MESSAGES.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), $crate::VecDeque::new()));
$crate::DMP_DONE.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), $crate::VecDeque::new()));
$crate::UPWARD_MESSAGES.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), $crate::VecDeque::new()));
$crate::HORIZONTAL_MESSAGES.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), $crate::VecDeque::new()));
$crate::RELAY_BLOCK_NUMBER.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), 1));
$crate::PARA_IDS.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), Self::_para_ids()));
}
}
fn _para_ids() -> Vec<u32> {
vec![$(
<$parachain>::para_id().into(),
)*]
}
fn _relay_block_number() -> u32 {
$crate::RELAY_BLOCK_NUMBER.with(|v| *v.clone().borrow().get(stringify!($name)).unwrap())
}
fn _set_relay_block_number(block_number: u32) {
$crate::RELAY_BLOCK_NUMBER.with(|v| v.borrow_mut().insert(stringify!($name).to_string(), block_number));
}
fn _process_messages() {
while Self::_has_unprocessed_messages() {
Self::_process_upward_messages();
Self::_process_horizontal_messages();
Self::_process_downward_messages();
}
}
fn _has_unprocessed_messages() -> bool {
$crate::DOWNWARD_MESSAGES.with(|b| !b.borrow_mut().get_mut(stringify!($name)).unwrap().is_empty())
|| $crate::HORIZONTAL_MESSAGES.with(|b| !b.borrow_mut().get_mut(stringify!($name)).unwrap().is_empty())
|| $crate::UPWARD_MESSAGES.with(|b| !b.borrow_mut().get_mut(stringify!($name)).unwrap().is_empty())
}
fn _process_downward_messages() {
use $crate::{DmpMessageHandler, Bounded};
use polkadot_parachain::primitives::RelayChainBlockNumber;
while let Some((to_para_id, messages))
= $crate::DOWNWARD_MESSAGES.with(|b| b.borrow_mut().get_mut(stringify!($name)).unwrap().pop_front()) {
$(
if $crate::PARA_IDS.with(|b| b.borrow_mut().get_mut(stringify!($name)).unwrap().contains(&to_para_id)) {
let mut msg_dedup: Vec<(RelayChainBlockNumber, Vec<u8>)> = Vec::new();
for m in &messages {
msg_dedup.push((m.0, m.1.clone()));
}
msg_dedup.dedup();
let msgs = msg_dedup.clone().into_iter().filter(|m| {
!$crate::DMP_DONE.with(|b| b.borrow_mut().get_mut(stringify!($name)).unwrap_or(&mut $crate::VecDeque::new()).contains(&(to_para_id, m.0, m.1.clone())))
}).collect::<Vec<(RelayChainBlockNumber, Vec<u8>)>>();
if msgs.len() != 0 {
<$parachain>::handle_dmp_messages(msgs.clone().into_iter(), $crate::Weight::max_value());
for m in msgs {
$crate::DMP_DONE.with(|b| b.borrow_mut().get_mut(stringify!($name)).unwrap().push_back((to_para_id, m.0, m.1)));
}
}
} else {
unreachable!();
}
)*
}
}
fn _process_horizontal_messages() {
use $crate::{XcmpMessageHandler, Bounded};
while let Some((to_para_id, messages))
= $crate::HORIZONTAL_MESSAGES.with(|b| b.borrow_mut().get_mut(stringify!($name)).unwrap().pop_front()) {
let iter = messages.iter().map(|(p, b, m)| (*p, *b, &m[..])).collect::<Vec<_>>().into_iter();
$(
if $crate::PARA_IDS.with(|b| b.borrow_mut().get_mut(stringify!($name)).unwrap().contains(&to_para_id)) {
<$parachain>::handle_xcmp_messages(iter.clone(), $crate::Weight::max_value());
}
)*
}
}
fn _process_upward_messages() {
use $crate::{UmpSink, Bounded};
while let Some((from_para_id, msg)) = $crate::UPWARD_MESSAGES.with(|b| b.borrow_mut().get_mut(stringify!($name)).unwrap().pop_front()) {
let _ = <$relay_chain>::process_upward_message(
from_para_id.into(),
&msg[..],
$crate::Weight::max_value(),
);
}
}
fn _hrmp_channel_parachain_inherent_data(
para_id: u32,
relay_parent_number: u32,
) -> $crate::ParachainInherentData {
use $crate::cumulus_primitives_core::{relay_chain::HrmpChannelId, AbridgedHrmpChannel};
let mut sproof = $crate::RelayStateSproofBuilder::default();
sproof.para_id = para_id.into();
// egress channel
let e_index = sproof.hrmp_egress_channel_index.get_or_insert_with(Vec::new);
for recipient_para_id in $crate::PARA_IDS.with(|b| b.borrow_mut().get_mut(stringify!($name)).unwrap().clone()) {
let recipient_para_id = $crate::ParaId::from(recipient_para_id);
if let Err(idx) = e_index.binary_search(&recipient_para_id) {
e_index.insert(idx, recipient_para_id);
}
sproof
.hrmp_channels
.entry(HrmpChannelId {
sender: sproof.para_id,
recipient: recipient_para_id,
})
.or_insert_with(|| AbridgedHrmpChannel {
max_capacity: 1024,
max_total_size: 1024 * 1024,
max_message_size: 1024 * 1024,
msg_count: 0,
total_size: 0,
mqc_head: Option::None,
});
}
let (relay_storage_root, proof) = sproof.into_state_root_and_proof();
$crate::ParachainInherentData {
validation_data: $crate::PersistedValidationData {
parent_head: Default::default(),
relay_parent_number,
relay_parent_storage_root: relay_storage_root,
max_pov_size: Default::default(),
},
relay_chain_state: proof,
downward_messages: Default::default(),
horizontal_messages: Default::default(),
}
}
}
$crate::__impl_relay!($name, $relay_chain);
$(
$crate::__impl_parachain!($name, $parachain);
)*
)+
};
}
#[macro_export]
macro_rules! assert_expected_events {
( $chain:ident, vec![$( $event_pat:pat => { $($attr:ident : $condition:expr, )* }, )*] ) => {
let mut message: Vec<String> = Vec::new();
$(
let mut meet_conditions = true;
let mut event_message: Vec<String> = Vec::new();
let event_received = <$chain>::events().iter().any(|event| {
$crate::log::debug!(target: format!("events::{}", stringify!($chain)).to_lowercase().as_str(), "{:?}", event);
match event {
$event_pat => {
$(
if !$condition {
event_message.push(format!(" - The attribute {:?} = {:?} did not met the condition {:?}\n", stringify!($attr), $attr, stringify!($condition)));
meet_conditions &= $condition
}
)*
true
},
_ => false
}
});
if event_received && !meet_conditions {
message.push(format!("\n\nEvent \x1b[31m{}\x1b[0m was received but some of its attributes did not meet the conditions:\n{}", stringify!($event_pat), event_message.concat()));
} else if !event_received {
message.push(format!("\n\nEvent \x1b[31m{}\x1b[0m was never received", stringify!($event_pat)));
}
)*
if !message.is_empty() {
panic!("{}", message.concat())
}
}
}
#[macro_export]
macro_rules! bx {
($e:expr) => {
Box::new($e)
};
}
pub mod helpers {
use super::Weight;
pub fn within_threshold(threshold: u64, expected_value: u64, current_value: u64) -> bool {
let margin = (current_value * threshold) / 100;
let lower_limit = expected_value - margin;
let upper_limit = expected_value + margin;
current_value >= lower_limit && current_value <= upper_limit
}
pub fn weight_within_threshold(
(threshold_time, threshold_size): (u64, u64),
expected_weight: Weight,
weight: Weight,
) -> bool {
let ref_time_within =
within_threshold(threshold_time, expected_weight.ref_time(), weight.ref_time());
let proof_size_within =
within_threshold(threshold_size, expected_weight.proof_size(), weight.proof_size());
ref_time_within && proof_size_within
}
}