From f879297d59dbe957f5dc16c841563d3568f8ec77 Mon Sep 17 00:00:00 2001 From: ron Date: Mon, 6 Nov 2023 11:44:28 +0800 Subject: [PATCH 1/4] Change to Ethereum sovereign --- .../emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs index 35f9c7e06de9..155e4d914d3f 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -167,7 +167,7 @@ fn register_token() { // Fund gateway sovereign in asset hub AssetHubRococo::fund_accounts(vec![( - hex!("c9794dd8013efb2ad83f668845c62b373c16ad33971745731408058e4d0c6ff5").into(), + hex!("da4d66c3651dc151264eee5460493210338e41a7bbfca91a520e438daf180bf5").into(), 5_000_000_000_000 * ROCOCO_ED, )]); @@ -178,7 +178,6 @@ fn register_token() { let message = VersionedMessage::V1(MessageV1 { chain_id: 15, command: Command::RegisterToken { - gateway: hex!("EDa338E4dC46038493b885327842fD3E301CaB39").into(), token: hex!("87d1f7fdfEe7f651FaBc8bFCB6E086C278b77A7d").into(), }, }); From a1ff98b740ae018a564a1cdd69cdd274141f9209 Mon Sep 17 00:00:00 2001 From: ron Date: Mon, 6 Nov 2023 11:47:46 +0800 Subject: [PATCH 2/4] chore --- .../emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs index 155e4d914d3f..c6e04c1fd344 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -165,7 +165,7 @@ fn register_token() { 5_000_000 * ROCOCO_ED, )]); - // Fund gateway sovereign in asset hub + // Fund ethereum sovereign in asset hub AssetHubRococo::fund_accounts(vec![( hex!("da4d66c3651dc151264eee5460493210338e41a7bbfca91a520e438daf180bf5").into(), 5_000_000_000_000 * ROCOCO_ED, From 589033bffc4a90b7b8885823cc6901a0762d1ac6 Mon Sep 17 00:00:00 2001 From: ron Date: Tue, 7 Nov 2023 07:49:02 +0800 Subject: [PATCH 3/4] Tests for token transfer --- Cargo.lock | 1 + .../bridges/bridge-hub-rococo/Cargo.toml | 1 + .../bridge-hub-rococo/src/tests/snowbridge.rs | 213 ++++++++++++++++-- 3 files changed, 196 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ddfee9873aa8..f1e45240e64e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2124,6 +2124,7 @@ dependencies = [ "snowbridge-control", "snowbridge-core", "snowbridge-inbound-queue", + "snowbridge-outbound-queue", "snowbridge-router-primitives", "staging-xcm", "staging-xcm-executor", diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml index 90eb7738876a..c6578570393b 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml @@ -45,3 +45,4 @@ snowbridge-core = { path = "../../../../../../../parachain/primitives/core", def snowbridge-router-primitives = { path = "../../../../../../../parachain/primitives/router", default-features = false } snowbridge-control = { path = "../../../../../../../parachain/pallets/control", default-features = false } snowbridge-inbound-queue = { path = "../../../../../../../parachain/pallets/inbound-queue", default-features = false } +snowbridge-outbound-queue = { path = "../../../../../../../parachain/pallets/outbound-queue", default-features = false } diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs index c6e04c1fd344..8f436d5a12ef 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -15,18 +15,28 @@ use crate::*; use hex_literal::hex; -use integration_tests_common::BridgeHubRococoPallet; +use integration_tests_common::{AssetHubRococoPallet, BridgeHubRococoPallet}; use snowbridge_control; -use snowbridge_router_primitives::inbound::{Command, MessageV1, VersionedMessage}; +use snowbridge_router_primitives::inbound::{Command, Destination, MessageV1, VersionedMessage}; + +const INITIAL_FUND: u128 = 5_000_000_000 * ROCOCO_ED; +const CHAIN_ID: u64 = 15; +const DEST_PARA_ID: u32 = 1000; +const ETHEREUM_SOVEREIGN: [u8; 32] = + hex!("da4d66c3651dc151264eee5460493210338e41a7bbfca91a520e438daf180bf5"); +const WETH: [u8; 20] = hex!("87d1f7fdfEe7f651FaBc8bFCB6E086C278b77A7d"); +const ASSETHUB_SOVEREIGN: [u8; 32] = + hex!("7369626ce8030000000000000000000000000000000000000000000000000000"); +const ETHEREUM_DESTINATION_ADDRESS: [u8; 20] = hex!("44a57ee2f2FCcb85FDa2B0B18EBD0D8D2333700e"); #[test] fn create_agent() { BridgeHubRococo::fund_accounts(vec![( BridgeHubRococo::sovereign_account_id_of(MultiLocation { parents: 1, - interior: X1(Parachain(1000)), + interior: X1(Parachain(DEST_PARA_ID)), }), - 5_000_000 * ROCOCO_ED, + INITIAL_FUND, )]); let sudo_origin = ::RuntimeOrigin::root(); @@ -34,7 +44,7 @@ fn create_agent() { let remote_xcm = VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - DescendOrigin(X1(Parachain(1000))), + DescendOrigin(X1(Parachain(DEST_PARA_ID))), Transact { require_weight_at_most: 3000000000.into(), origin_kind: OriginKind::Xcm, @@ -81,11 +91,11 @@ fn create_agent() { #[test] fn create_channel() { - let source_location = MultiLocation { parents: 1, interior: X1(Parachain(1000)) }; + let source_location = MultiLocation { parents: 1, interior: X1(Parachain(DEST_PARA_ID)) }; BridgeHubRococo::fund_accounts(vec![( BridgeHubRococo::sovereign_account_id_of(source_location), - 5_000_000 * ROCOCO_ED, + INITIAL_FUND, )]); let sudo_origin = ::RuntimeOrigin::root(); @@ -94,7 +104,7 @@ fn create_channel() { let create_agent_xcm = VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - DescendOrigin(X1(Parachain(1000))), + DescendOrigin(X1(Parachain(DEST_PARA_ID))), Transact { require_weight_at_most: 3000000000.into(), origin_kind: OriginKind::Xcm, @@ -104,7 +114,7 @@ fn create_channel() { let create_channel_xcm = VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - DescendOrigin(X1(Parachain(1000))), + DescendOrigin(X1(Parachain(DEST_PARA_ID))), Transact { require_weight_at_most: 3000000000.into(), origin_kind: OriginKind::Xcm, @@ -160,29 +170,83 @@ fn register_token() { BridgeHubRococo::fund_accounts(vec![( BridgeHubRococo::sovereign_account_id_of(MultiLocation { parents: 1, - interior: X1(Parachain(1000)), + interior: X1(Parachain(DEST_PARA_ID)), }), - 5_000_000 * ROCOCO_ED, + INITIAL_FUND, )]); // Fund ethereum sovereign in asset hub - AssetHubRococo::fund_accounts(vec![( - hex!("da4d66c3651dc151264eee5460493210338e41a7bbfca91a520e438daf180bf5").into(), - 5_000_000_000_000 * ROCOCO_ED, + AssetHubRococo::fund_accounts(vec![(ETHEREUM_SOVEREIGN.into(), 5_000_000_000_000 * ROCOCO_ED)]); + + BridgeHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type EthereumInboundQueue = + ::EthereumInboundQueue; + let message = VersionedMessage::V1(MessageV1 { + chain_id: CHAIN_ID, + command: Command::RegisterToken { token: WETH.into() }, + }); + let xcm = EthereumInboundQueue::do_convert(message).unwrap(); + let _ = EthereumInboundQueue::send_xcm(xcm, DEST_PARA_ID.into()).unwrap(); + + assert_expected_events!( + BridgeHubRococo, + vec![ + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {}, + ] + ); + }); + + AssetHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + AssetHubRococo, + vec![ + RuntimeEvent::ForeignAssets(pallet_assets::Event::Created { .. }) => {}, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) => {}, + ] + ); + }); +} + +#[test] +fn send_token() { + BridgeHubRococo::fund_accounts(vec![( + BridgeHubRococo::sovereign_account_id_of(MultiLocation { + parents: 1, + interior: X1(Parachain(DEST_PARA_ID)), + }), + INITIAL_FUND, )]); + // Fund ethereum sovereign in asset hub + AssetHubRococo::fund_accounts(vec![ + (ETHEREUM_SOVEREIGN.into(), INITIAL_FUND), + (ASSETHUB_SOVEREIGN.into(), INITIAL_FUND), + (AssetHubRococoReceiver::get(), INITIAL_FUND), + ]); + BridgeHubRococo::execute_with(|| { type RuntimeEvent = ::RuntimeEvent; type EthereumInboundQueue = ::EthereumInboundQueue; let message = VersionedMessage::V1(MessageV1 { - chain_id: 15, - command: Command::RegisterToken { - token: hex!("87d1f7fdfEe7f651FaBc8bFCB6E086C278b77A7d").into(), + chain_id: CHAIN_ID, + command: Command::RegisterToken { token: WETH.into() }, + }); + let xcm = EthereumInboundQueue::do_convert(message).unwrap(); + let _ = EthereumInboundQueue::send_xcm(xcm, DEST_PARA_ID.into()).unwrap(); + let message = VersionedMessage::V1(MessageV1 { + chain_id: CHAIN_ID, + command: Command::SendToken { + token: WETH.into(), + destination: Destination::AccountId32 { id: AssetHubRococoReceiver::get().into() }, + amount: 1_000_000_000, }, }); let xcm = EthereumInboundQueue::do_convert(message).unwrap(); - let _ = EthereumInboundQueue::send_xcm(xcm, 1000.into()).unwrap(); + let _ = EthereumInboundQueue::send_xcm(xcm, DEST_PARA_ID.into()).unwrap(); assert_expected_events!( BridgeHubRococo, @@ -198,7 +262,118 @@ fn register_token() { assert_expected_events!( AssetHubRococo, vec![ - RuntimeEvent::ForeignAssets(pallet_assets::Event::Created { .. }) => {}, + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { .. }) => {}, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) => {}, + ] + ); + }); +} + +#[test] +fn reserve_transfer_token() { + BridgeHubRococo::fund_accounts(vec![( + BridgeHubRococo::sovereign_account_id_of(MultiLocation { + parents: 1, + interior: X1(Parachain(DEST_PARA_ID)), + }), + INITIAL_FUND, + )]); + + // Fund ethereum sovereign in asset hub + AssetHubRococo::fund_accounts(vec![ + (ETHEREUM_SOVEREIGN.into(), INITIAL_FUND), + (ASSETHUB_SOVEREIGN.into(), INITIAL_FUND), + (AssetHubRococoReceiver::get(), INITIAL_FUND), + ]); + + const WETH_AMOUNT: u128 = 1_000_000_000; + + BridgeHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type EthereumInboundQueue = + ::EthereumInboundQueue; + let message = VersionedMessage::V1(MessageV1 { + chain_id: CHAIN_ID, + command: Command::RegisterToken { token: WETH.into() }, + }); + let xcm = EthereumInboundQueue::do_convert(message).unwrap(); + let _ = EthereumInboundQueue::send_xcm(xcm, DEST_PARA_ID.into()).unwrap(); + let message = VersionedMessage::V1(MessageV1 { + chain_id: CHAIN_ID, + command: Command::SendToken { + token: WETH.into(), + destination: Destination::AccountId32 { id: AssetHubRococoReceiver::get().into() }, + amount: WETH_AMOUNT, + }, + }); + let xcm = EthereumInboundQueue::do_convert(message).unwrap(); + let _ = EthereumInboundQueue::send_xcm(xcm, DEST_PARA_ID.into()).unwrap(); + + assert_expected_events!( + BridgeHubRococo, + vec![ + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {}, + ] + ); + }); + + AssetHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type RuntimeOrigin = ::RuntimeOrigin; + + assert_expected_events!( + AssetHubRococo, + vec![ + RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { .. }) => {}, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) => {}, + ] + ); + let fee_asset = MultiAsset { + id: Concrete(MultiLocation { parents: 1, interior: Here }), + fun: Fungible(1_000_000_000_000), //1 ROC + }; + let assets = vec![ + fee_asset, + MultiAsset { + id: Concrete(MultiLocation { + parents: 2, + interior: X2( + GlobalConsensus(Ethereum { chain_id: CHAIN_ID }), + AccountKey20 { network: None, key: WETH }, + ), + }), + fun: Fungible(WETH_AMOUNT), + }, + ]; + let multi_assets = VersionedMultiAssets::V3(MultiAssets::from(assets)); + + let destination = VersionedMultiLocation::V3(MultiLocation { + parents: 2, + interior: X1(GlobalConsensus(Ethereum { chain_id: CHAIN_ID })), + }); + + let beneficiary = VersionedMultiLocation::V3(MultiLocation { + parents: 0, + interior: X1(AccountKey20 { network: None, key: ETHEREUM_DESTINATION_ADDRESS.into() }), + }); + + ::PolkadotXcm::reserve_transfer_assets( + RuntimeOrigin::signed(AssetHubRococoReceiver::get()), + Box::new(destination), + Box::new(beneficiary), + Box::new(multi_assets), + 0, + ) + .unwrap(); + }); + + BridgeHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + BridgeHubRococo, + vec![ + RuntimeEvent::EthereumOutboundQueue(snowbridge_outbound_queue::Event::MessageQueued {..}) => {}, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) => {}, ] ); From 2edb0e6bedb0b80013c6dfe806db57282d9eeee2 Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Tue, 7 Nov 2023 12:22:53 +0200 Subject: [PATCH 4/4] fix tests --- .../bridge-hub-rococo/src/tests/snowbridge.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs index 8f436d5a12ef..67f7e1c7c53e 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -22,7 +22,7 @@ use snowbridge_router_primitives::inbound::{Command, Destination, MessageV1, Ver const INITIAL_FUND: u128 = 5_000_000_000 * ROCOCO_ED; const CHAIN_ID: u64 = 15; const DEST_PARA_ID: u32 = 1000; -const ETHEREUM_SOVEREIGN: [u8; 32] = +const SNOWBRIDGE_SOVEREIGN: [u8; 32] = hex!("da4d66c3651dc151264eee5460493210338e41a7bbfca91a520e438daf180bf5"); const WETH: [u8; 20] = hex!("87d1f7fdfEe7f651FaBc8bFCB6E086C278b77A7d"); const ASSETHUB_SOVEREIGN: [u8; 32] = @@ -176,7 +176,7 @@ fn register_token() { )]); // Fund ethereum sovereign in asset hub - AssetHubRococo::fund_accounts(vec![(ETHEREUM_SOVEREIGN.into(), 5_000_000_000_000 * ROCOCO_ED)]); + AssetHubRococo::fund_accounts(vec![(SNOWBRIDGE_SOVEREIGN.into(), 5_000_000_000_000 * ROCOCO_ED)]); BridgeHubRococo::execute_with(|| { type RuntimeEvent = ::RuntimeEvent; @@ -222,7 +222,7 @@ fn send_token() { // Fund ethereum sovereign in asset hub AssetHubRococo::fund_accounts(vec![ - (ETHEREUM_SOVEREIGN.into(), INITIAL_FUND), + (SNOWBRIDGE_SOVEREIGN.into(), INITIAL_FUND), (ASSETHUB_SOVEREIGN.into(), INITIAL_FUND), (AssetHubRococoReceiver::get(), INITIAL_FUND), ]); @@ -281,7 +281,7 @@ fn reserve_transfer_token() { // Fund ethereum sovereign in asset hub AssetHubRococo::fund_accounts(vec![ - (ETHEREUM_SOVEREIGN.into(), INITIAL_FUND), + (SNOWBRIDGE_SOVEREIGN.into(), INITIAL_FUND), (ASSETHUB_SOVEREIGN.into(), INITIAL_FUND), (AssetHubRococoReceiver::get(), INITIAL_FUND), ]); @@ -328,12 +328,7 @@ fn reserve_transfer_token() { RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) => {}, ] ); - let fee_asset = MultiAsset { - id: Concrete(MultiLocation { parents: 1, interior: Here }), - fun: Fungible(1_000_000_000_000), //1 ROC - }; let assets = vec![ - fee_asset, MultiAsset { id: Concrete(MultiLocation { parents: 2,