Skip to content

Commit 3056831

Browse files
Snowbridge - Integration test for 2-hop transfer from Ethereum to AHP to AHK (#625)
Adds a test to send Weth bridge from Ethereum to Polkadot AH to Kusama AH, in a second transaction. This shows how we could support bridging to Kusama in a 2-step fashion until Snowbridge V2 is released. - [x] Does not require a CHANGELOG entry --------- Co-authored-by: Adrian Catangiu <adrian@parity.io>
1 parent 7023441 commit 3056831

File tree

13 files changed

+488
-88
lines changed

13 files changed

+488
-88
lines changed

Cargo.lock

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

integration-tests/emulated/chains/parachains/assets/asset-hub-kusama/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,27 @@ parachains-common = { workspace = true, default-features = true }
1919
cumulus-primitives-core = { workspace = true, default-features = true }
2020
emulated-integration-tests-common = { workspace = true }
2121
xcm = { workspace = true, default-features = true }
22+
xcm-builder = { workspace = true, default-features = true }
2223
polkadot-parachain-primitives = { workspace = true }
2324

2425
# Runtimes
2526
asset-hub-kusama-runtime = { workspace = true }
2627
kusama-emulated-chain = { workspace = true }
2728
penpal-emulated-chain = { workspace = true }
2829

30+
31+
# Emulated tests
32+
integration-tests-helpers = { workspace = true }
33+
2934
[features]
3035
runtime-benchmarks = [
3136
"asset-hub-kusama-runtime/runtime-benchmarks",
3237
"cumulus-primitives-core/runtime-benchmarks",
3338
"frame-support/runtime-benchmarks",
39+
"integration-tests-helpers/runtime-benchmarks",
3440
"kusama-emulated-chain/runtime-benchmarks",
3541
"parachains-common/runtime-benchmarks",
3642
"penpal-emulated-chain/runtime-benchmarks",
3743
"polkadot-parachain-primitives/runtime-benchmarks",
44+
"xcm-builder/runtime-benchmarks",
3845
]

integration-tests/emulated/chains/parachains/assets/asset-hub-kusama/src/genesis.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,17 @@ use sp_keyring::Sr25519Keyring as Keyring;
1818

1919
// Cumulus
2020
use emulated_integration_tests_common::{
21-
accounts, build_genesis_storage, collators, RESERVABLE_ASSET_ID, SAFE_XCM_VERSION,
21+
accounts, build_genesis_storage, collators, xcm_emulator::ConvertLocation, RESERVABLE_ASSET_ID,
22+
SAFE_XCM_VERSION,
2223
};
2324
use frame_support::sp_runtime::traits::AccountIdConversion;
25+
use integration_tests_helpers::common::snowbridge::{
26+
EthLocationXcmV4, WethLocationXcmV4, MIN_ETHER_BALANCE,
27+
};
2428
use parachains_common::{AccountId, Balance};
2529
use polkadot_parachain_primitives::primitives::Sibling;
30+
use xcm::prelude::*;
31+
use xcm_builder::GlobalConsensusParachainConvertsFor;
2632

2733
pub const PARA_ID: u32 = 1000;
2834
pub const ED: Balance = asset_hub_kusama_runtime::ExistentialDeposit::get();
@@ -37,7 +43,12 @@ frame_support::parameter_types! {
3743
xcm::v4::Junction::GeneralIndex(penpal_emulated_chain::TELEPORTABLE_ASSET_ID.into()),
3844
]
3945
);
46+
pub UniversalLocation: InteriorLocation = [GlobalConsensus(Kusama), Parachain(PARA_ID)].into();
47+
pub AssetHubPolkadotLocation: Location = Location::new(2, [GlobalConsensus(Polkadot), Parachain(1000)]);
4048
pub PenpalASiblingSovereignAccount: AccountId = Sibling::from(penpal_emulated_chain::PARA_ID_A).into_account_truncating();
49+
pub AssetHubPolkadotSovereignAccount: AccountId = GlobalConsensusParachainConvertsFor::<UniversalLocation, AccountId>::convert_location(
50+
&AssetHubPolkadotLocation::get(),
51+
).unwrap();
4152
}
4253

4354
pub fn genesis() -> sp_core::storage::Storage {
@@ -92,6 +103,20 @@ pub fn genesis() -> sp_core::storage::Storage {
92103
false,
93104
ED,
94105
),
106+
// Ether
107+
(
108+
EthLocationXcmV4::get(),
109+
AssetHubPolkadotSovereignAccount::get(),
110+
true,
111+
MIN_ETHER_BALANCE,
112+
),
113+
// Weth
114+
(
115+
WethLocationXcmV4::get(),
116+
AssetHubPolkadotSovereignAccount::get(),
117+
true,
118+
MIN_ETHER_BALANCE,
119+
),
95120
],
96121
..Default::default()
97122
},

integration-tests/emulated/chains/parachains/assets/asset-hub-polkadot/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,21 @@ asset-hub-polkadot-runtime = { workspace = true }
2626
polkadot-emulated-chain = { workspace = true }
2727
penpal-emulated-chain = { workspace = true }
2828

29+
# Bridges
30+
snowbridge-router-primitives = { workspace = true, default-features = true }
31+
32+
# Emulated tests
33+
integration-tests-helpers = { workspace = true }
34+
2935
[features]
3036
runtime-benchmarks = [
3137
"asset-hub-polkadot-runtime/runtime-benchmarks",
3238
"cumulus-primitives-core/runtime-benchmarks",
3339
"frame-support/runtime-benchmarks",
40+
"integration-tests-helpers/runtime-benchmarks",
3441
"parachains-common/runtime-benchmarks",
3542
"penpal-emulated-chain/runtime-benchmarks",
3643
"polkadot-emulated-chain/runtime-benchmarks",
3744
"polkadot-parachain-primitives/runtime-benchmarks",
45+
"snowbridge-router-primitives/runtime-benchmarks",
3846
]

integration-tests/emulated/chains/parachains/assets/asset-hub-polkadot/src/genesis.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,19 @@
1717
use sp_keyring::{Ed25519Keyring, Sr25519Keyring};
1818

1919
// Cumulus
20+
use asset_hub_polkadot_runtime::xcm_config::bridging::to_ethereum::EthereumNetwork;
2021
use emulated_integration_tests_common::{
21-
accounts, build_genesis_storage, RESERVABLE_ASSET_ID, SAFE_XCM_VERSION,
22+
accounts, build_genesis_storage, xcm_emulator::ConvertLocation, RESERVABLE_ASSET_ID,
23+
SAFE_XCM_VERSION,
2224
};
2325
use frame_support::sp_runtime::traits::AccountIdConversion;
26+
use integration_tests_helpers::common::snowbridge::{
27+
EthLocationXcmV4, WethLocationXcmV4, MIN_ETHER_BALANCE,
28+
};
2429
use parachains_common::{AccountId, Balance};
2530
use polkadot_parachain_primitives::primitives::Sibling;
31+
use snowbridge_router_primitives::inbound::EthereumLocationsConverterFor;
32+
use xcm::prelude::*;
2633

2734
pub const PARA_ID: u32 = 1000;
2835
pub const ED: Balance = asset_hub_polkadot_runtime::ExistentialDeposit::get();
@@ -46,6 +53,12 @@ frame_support::parameter_types! {
4653
);
4754
pub PenpalASiblingSovereignAccount: AccountId = Sibling::from(penpal_emulated_chain::PARA_ID_A).into_account_truncating();
4855
pub PenpalBSiblingSovereignAccount: AccountId = Sibling::from(penpal_emulated_chain::PARA_ID_B).into_account_truncating();
56+
pub EthereumSovereignAccount: AccountId = EthereumLocationsConverterFor::<AccountId>::convert_location(
57+
&Location::new(
58+
2,
59+
[GlobalConsensus(EthereumNetwork::get())],
60+
),
61+
).unwrap();
4962
}
5063

5164
pub mod collators {
@@ -120,6 +133,15 @@ pub fn genesis() -> sp_core::storage::Storage {
120133
false,
121134
ED,
122135
),
136+
// Ether
137+
(EthLocationXcmV4::get(), EthereumSovereignAccount::get(), true, MIN_ETHER_BALANCE),
138+
// Weth
139+
(
140+
WethLocationXcmV4::get(),
141+
EthereumSovereignAccount::get(),
142+
true,
143+
MIN_ETHER_BALANCE,
144+
),
123145
],
124146
..Default::default()
125147
},

integration-tests/emulated/helpers/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ publish = false
99

1010
[dependencies]
1111
paste = { workspace = true }
12+
hex-literal = { workspace = true }
1213

1314
# Substrate
15+
frame-support = { workspace = true, default-features = true }
1416
pallet-balances = { workspace = true, default-features = true }
1517
pallet-message-queue = { workspace = true, default-features = true }
1618

@@ -26,6 +28,7 @@ asset-test-utils = { workspace = true }
2628
[features]
2729
runtime-benchmarks = [
2830
"cumulus-pallet-xcmp-queue/runtime-benchmarks",
31+
"frame-support/runtime-benchmarks",
2932
"pallet-balances/runtime-benchmarks",
3033
"pallet-message-queue/runtime-benchmarks",
3134
"pallet-xcm/runtime-benchmarks",
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (C) Parity Technologies (UK) Ltd.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
pub mod snowbridge {
17+
use hex_literal::hex;
18+
use xcm_emulator::parameter_types;
19+
20+
// Weth (Wrapped Ether) contract address on Ethereum mainnet.
21+
pub const WETH: [u8; 20] = hex!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2");
22+
// The minimum Ether balance required for an account to exist. Matches value on Polkadot
23+
// mainnet.
24+
pub const MIN_ETHER_BALANCE: u128 = 15_000_000_000_000;
25+
26+
parameter_types! {
27+
pub EthereumNetworkXcmV4: xcm::v4::NetworkId = xcm::v4::NetworkId::Ethereum { chain_id: 1 };
28+
pub WethLocationXcmV4: xcm::v4::Location = xcm::v4::Location::new(2, [xcm::v4::Junction::GlobalConsensus(EthereumNetworkXcmV4::get()), xcm::v4::Junction::AccountKey20 { network: None, key: WETH }]);
29+
pub EthLocationXcmV4: xcm::v4::Location = xcm::v4::Location::new(2, [xcm::v4::Junction::GlobalConsensus(EthereumNetworkXcmV4::get())]);
30+
}
31+
}

integration-tests/emulated/helpers/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ pub use asset_test_utils;
2828
pub use cumulus_pallet_xcmp_queue;
2929
pub use xcm_emulator::Chain;
3030

31+
pub mod common;
32+
3133
/// TODO: when bumping to polkadot-sdk v1.8.0,
3234
/// remove this crate altogether and get the macros from `emulated-integration-tests-common`.
3335
/// TODO: backport this macros to polkadot-sdk

integration-tests/emulated/tests/bridges/bridge-hub-polkadot/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pub use emulated_integration_tests_common::{
4444
xcm_helpers::{xcm_transact_paid_execution, xcm_transact_unpaid_execution},
4545
ASSETS_PALLET_ID, PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V4,
4646
};
47+
pub use integration_tests_helpers::common::snowbridge::{MIN_ETHER_BALANCE, WETH};
4748
pub use kusama_polkadot_system_emulated_network::{
4849
asset_hub_kusama_emulated_chain::{
4950
genesis::ED as ASSET_HUB_KUSAMA_ED, AssetHubKusamaParaPallet as AssetHubKusamaPallet,

integration-tests/emulated/tests/bridges/bridge-hub-polkadot/src/tests/asset_transfers.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
// limitations under the License.
1515

1616
use crate::tests::*;
17+
use bp_bridge_hub_polkadot::snowbridge::EthereumNetwork;
18+
use snowbridge_router_primitives::inbound::EthereumLocationsConverterFor;
19+
use xcm_executor::traits::ConvertLocation;
1720

1821
fn send_assets_over_bridge<F: FnOnce()>(send_fn: F) {
1922
// fund the PAH's SA on PBH for paying bridge transport fees
@@ -183,7 +186,7 @@ fn send_dot_usdt_and_weth_from_asset_hub_polkadot_to_asset_hub_kusama() {
183186
let receiver_dot_after =
184187
foreign_balance_on_ah_kusama(bridged_dot_at_asset_hub_kusama, &receiver);
185188
let dot_in_reserve_on_pah_after =
186-
<AssetHubPolkadot as Chain>::account_data_of(sov_kah_on_pah).free;
189+
<AssetHubPolkadot as Chain>::account_data_of(sov_kah_on_pah.clone()).free;
187190

188191
// Sender's balance is reduced
189192
assert!(sender_dot_before > sender_dot_after);
@@ -203,20 +206,27 @@ fn send_dot_usdt_and_weth_from_asset_hub_polkadot_to_asset_hub_kusama() {
203206
let bridged_weth_at_ah = weth_at_asset_hubs();
204207
let bridged_weth_at_ah_latest: Location = bridged_weth_at_ah.clone().try_into().unwrap();
205208

209+
let snowbridge_sovereign: AccountId =
210+
EthereumLocationsConverterFor::<[u8; 32]>::convert_location(&Location::new(
211+
2,
212+
[GlobalConsensus(EthereumNetwork::get())],
213+
))
214+
.unwrap()
215+
.into();
216+
206217
// mint USDT in sender's account (USDT already created in genesis)
207218
AssetHubPolkadot::mint_asset(
208219
<AssetHubPolkadot as Chain>::RuntimeOrigin::signed(AssetHubPolkadotAssetOwner::get()),
209220
USDT_ID,
210221
sender.clone(),
211222
amount * 2,
212223
);
213-
// create wETH at src and dest and prefund sender's account
214-
create_foreign_on_ah_polkadot(
224+
AssetHubPolkadot::mint_foreign_asset(
225+
<AssetHubPolkadot as Chain>::RuntimeOrigin::signed(snowbridge_sovereign),
215226
bridged_weth_at_ah.clone(),
216-
true,
217-
vec![(sender.clone(), amount * 2)],
227+
sender.clone(),
228+
MIN_ETHER_BALANCE,
218229
);
219-
create_foreign_on_ah_kusama(bridged_weth_at_ah.clone(), true);
220230
create_foreign_on_ah_kusama(bridged_usdt_at_asset_hub_kusama.clone(), true);
221231
set_up_pool_with_ksm_on_ah_kusama(bridged_usdt_at_asset_hub_kusama.clone(), true);
222232

@@ -227,7 +237,7 @@ fn send_dot_usdt_and_weth_from_asset_hub_polkadot_to_asset_hub_kusama() {
227237
// send USDTs and wETHs
228238
let assets: Assets = vec![
229239
(usdt_at_asset_hub_polkadot_latest.clone(), amount).into(),
230-
(bridged_weth_at_ah_latest.clone(), amount).into(),
240+
(bridged_weth_at_ah_latest.clone(), MIN_ETHER_BALANCE).into(),
231241
]
232242
.into();
233243
// use USDT for fees
@@ -265,7 +275,7 @@ fn send_dot_usdt_and_weth_from_asset_hub_polkadot_to_asset_hub_kusama() {
265275
assert!(receiver_usdts_after > receiver_usdts_before);
266276
assert!(receiver_usdts_after < receiver_usdts_before + amount);
267277
// Receiver's wETH balance is increased by sent amount
268-
assert_eq!(receiver_weth_after, receiver_weth_before + amount);
278+
assert_eq!(receiver_weth_after, receiver_weth_before + MIN_ETHER_BALANCE);
269279
}
270280

271281
#[test]

0 commit comments

Comments
 (0)