Skip to content

Commit

Permalink
Asset Hub: Asset Conversion and Swap Weight Trader (#218)
Browse files Browse the repository at this point in the history
Asset Conversion instance for Polkadot Asset Hub and XCM Swap Weight
Trader for both Asset Hubs.


TODO:
- [x] update treasury account when this PR merged -
#191
- [x] define account deposit for pool assets, liquidity withdrawal fee,
pool setup fee;

---------

Co-authored-by: joe petrowski <[email protected]>
Co-authored-by: Sergej Sakac <[email protected]>
  • Loading branch information
3 people authored Mar 18, 2024
1 parent 6d93705 commit 49c6d6d
Show file tree
Hide file tree
Showing 26 changed files with 3,709 additions and 784 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Upgrade encointer protocol to 6.1.0 ([polkadot-fellows/runtimes#236](https://github.com/polkadot-fellows/runtimes/pull/236))
- Update NFT deposits according to RFC-45 ([polkadot-fellows/runtimes#237](https://github.com/polkadot-fellows/runtimes/pull/237))
- Add Kusama People Chain ([polkadot-fellows/runtimes#217](https://github.com/polkadot-fellows/runtimes/pull/217))
- Asset Conversion setup for Polkadot Asset Hub, and XCM Swap Weight Trader for both Asset Hubs ([polkadot-fellows/runtimes#218](https://github.com/polkadot-fellows/runtimes/pull/218))

### Changed

Expand Down
7 changes: 6 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ decl_test_parachains! {
Balances: asset_hub_polkadot_runtime::Balances,
Assets: asset_hub_polkadot_runtime::Assets,
ForeignAssets: asset_hub_polkadot_runtime::ForeignAssets,
PoolAssets: asset_hub_polkadot_runtime::PoolAssets,
AssetConversion: asset_hub_polkadot_runtime::AssetConversion,
}
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ fn swap_locally_on_chain_using_local_assets() {
2_000_000_000_000,
0,
0,
AssetHubKusamaSender::get().into()
AssetHubKusamaSender::get()
));

assert_expected_events!(
Expand All @@ -89,7 +89,7 @@ fn swap_locally_on_chain_using_local_assets() {
path,
100,
1,
AssetHubKusamaSender::get().into(),
AssetHubKusamaSender::get(),
true
)
);
Expand All @@ -112,7 +112,7 @@ fn swap_locally_on_chain_using_local_assets() {
* retrieved. */
0,
0,
AssetHubKusamaSender::get().into(),
AssetHubKusamaSender::get(),
));
});
}
Expand Down Expand Up @@ -150,8 +150,9 @@ fn swap_locally_on_chain_using_foreign_assets() {
let penpal_as_seen_by_ah = AssetHubKusama::sibling_location_of(PenpalA::para_id());
let sov_penpal_on_ahk = AssetHubKusama::sovereign_account_id_of(penpal_as_seen_by_ah);
AssetHubKusama::fund_accounts(vec![
(AssetHubKusamaSender::get().into(), 5_000_000 * KUSAMA_ED), /* An account to swap dot
* for something else. */
(AssetHubKusamaSender::get(), 5_000_000 * ASSET_HUB_KUSAMA_ED), /* An account to swap
* ksm
* for something else. */
]);

AssetHubKusama::execute_with(|| {
Expand All @@ -163,7 +164,7 @@ fn swap_locally_on_chain_using_foreign_assets() {
type RuntimeEvent = <AssetHubKusama as Chain>::RuntimeEvent;
// 3. Mint foreign asset (in reality this should be a teleport or some such)
assert_ok!(<AssetHubKusama as AssetHubKusamaPallet>::ForeignAssets::mint(
<AssetHubKusama as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahk.clone().into()),
<AssetHubKusama as Chain>::RuntimeOrigin::signed(sov_penpal_on_ahk.clone()),
foreign_asset_at_asset_hub_kusama,
sov_penpal_on_ahk.clone().into(),
3_000_000_000_000,
Expand Down Expand Up @@ -199,7 +200,7 @@ fn swap_locally_on_chain_using_foreign_assets() {
2_000_000_000_000,
0,
0,
sov_penpal_on_ahk.clone().into()
sov_penpal_on_ahk.clone()
));

assert_expected_events!(
Expand All @@ -220,7 +221,7 @@ fn swap_locally_on_chain_using_foreign_assets() {
path,
100000,
1000,
AssetHubKusamaSender::get().into(),
AssetHubKusamaSender::get(),
true
)
);
Expand All @@ -243,7 +244,7 @@ fn swap_locally_on_chain_using_foreign_assets() {
1414213562273 - 2_000_000_000, // all but the 2 EDs can't be retrieved.
0,
0,
sov_penpal_on_ahk.clone().into(),
sov_penpal_on_ahk.clone(),
));
});
}
Expand All @@ -264,15 +265,15 @@ fn cannot_create_pool_from_pool_assets() {

assert_ok!(<AssetHubKusama as AssetHubKusamaPallet>::PoolAssets::create(
<AssetHubKusama as Chain>::RuntimeOrigin::signed(pool_owner_account_id.clone()),
ASSET_ID.into(),
ASSET_ID,
pool_owner_account_id.clone().into(),
1000,
));
assert!(<AssetHubKusama as AssetHubKusamaPallet>::PoolAssets::asset_exists(ASSET_ID));

assert_ok!(<AssetHubKusama as AssetHubKusamaPallet>::PoolAssets::mint(
<AssetHubKusama as Chain>::RuntimeOrigin::signed(pool_owner_account_id),
ASSET_ID.into(),
ASSET_ID,
AssetHubKusamaSender::get().into(),
3_000_000_000_000,
));
Expand All @@ -287,3 +288,135 @@ fn cannot_create_pool_from_pool_assets() {
);
});
}

#[test]
fn pay_xcm_fee_with_some_asset_swapped_for_native() {
let asset_native: xcm::v3::Location = asset_hub_kusama_runtime::xcm_config::KsmLocation::get()
.try_into()
.expect("conversion works");
let asset_one = xcm::v3::Location {
parents: 0,
interior: [
xcm::v3::Junction::PalletInstance(ASSETS_PALLET_ID),
xcm::v3::Junction::GeneralIndex(ASSET_ID.into()),
]
.into(),
};
let penpal = AssetHubKusama::sovereign_account_id_of(AssetHubKusama::sibling_location_of(
PenpalA::para_id(),
));

AssetHubKusama::execute_with(|| {
type RuntimeEvent = <AssetHubKusama as Chain>::RuntimeEvent;

// set up pool with ASSET_ID <> NATIVE pair
assert_ok!(<AssetHubKusama as AssetHubKusamaPallet>::Assets::create(
<AssetHubKusama as Chain>::RuntimeOrigin::signed(AssetHubKusamaSender::get()),
ASSET_ID.into(),
AssetHubKusamaSender::get().into(),
ASSET_MIN_BALANCE,
));
assert!(<AssetHubKusama as AssetHubKusamaPallet>::Assets::asset_exists(ASSET_ID));

assert_ok!(<AssetHubKusama as AssetHubKusamaPallet>::Assets::mint(
<AssetHubKusama as Chain>::RuntimeOrigin::signed(AssetHubKusamaSender::get()),
ASSET_ID.into(),
AssetHubKusamaSender::get().into(),
3_000_000_000_000,
));

assert_ok!(<AssetHubKusama as AssetHubKusamaPallet>::AssetConversion::create_pool(
<AssetHubKusama as Chain>::RuntimeOrigin::signed(AssetHubKusamaSender::get()),
Box::new(asset_native),
Box::new(asset_one),
));

assert_expected_events!(
AssetHubKusama,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::PoolCreated { .. }) => {},
]
);

assert_ok!(<AssetHubKusama as AssetHubKusamaPallet>::AssetConversion::add_liquidity(
<AssetHubKusama as Chain>::RuntimeOrigin::signed(AssetHubKusamaSender::get()),
Box::new(asset_native),
Box::new(asset_one),
1_000_000_000_000,
2_000_000_000_000,
0,
0,
AssetHubKusamaSender::get()
));

assert_expected_events!(
AssetHubKusama,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::LiquidityAdded {lp_token_minted, .. }) => { lp_token_minted: *lp_token_minted == 1414213562273, },
]
);

// ensure `penpal` sovereign account has no native tokens and mint some `ASSET_ID`
assert_eq!(
<AssetHubKusama as AssetHubKusamaPallet>::Balances::free_balance(penpal.clone()),
0
);

assert_ok!(<AssetHubKusama as AssetHubKusamaPallet>::Assets::touch_other(
<AssetHubKusama as Chain>::RuntimeOrigin::signed(AssetHubKusamaSender::get()),
ASSET_ID.into(),
penpal.clone().into(),
));

assert_ok!(<AssetHubKusama as AssetHubKusamaPallet>::Assets::mint(
<AssetHubKusama as Chain>::RuntimeOrigin::signed(AssetHubKusamaSender::get()),
ASSET_ID.into(),
penpal.clone().into(),
10_000_000_000_000,
));
});

PenpalA::execute_with(|| {
// send xcm transact from `penpal` account which has only `ASSET_ID` tokens on
// `AssetHubKusama`
let call = AssetHubKusama::force_create_asset_call(
ASSET_ID + 1000,
penpal.clone(),
true,
ASSET_MIN_BALANCE,
);

let penpal_root = <PenpalA as Chain>::RuntimeOrigin::root();
let fee_amount = 4_000_000_000_000u128;
let asset_one =
([PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())], fee_amount).into();
let asset_hub_location = PenpalA::sibling_location_of(AssetHubKusama::para_id()).into();
let xcm = xcm_transact_paid_execution(
call,
OriginKind::SovereignAccount,
asset_one,
penpal.clone(),
);

assert_ok!(<PenpalA as PenpalAPallet>::PolkadotXcm::send(
penpal_root,
bx!(asset_hub_location),
bx!(xcm),
));

PenpalA::assert_xcm_pallet_sent();
});

AssetHubKusama::execute_with(|| {
type RuntimeEvent = <AssetHubKusama as Chain>::RuntimeEvent;

AssetHubKusama::assert_xcmp_queue_success(None);
assert_expected_events!(
AssetHubKusama,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapCreditExecuted { .. },) => {},
RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: true,.. }) => {},
]
);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ sp-runtime = { version = "32.0.0" }
frame-support = { version = "29.0.0" }
pallet-balances = { version = "29.0.0" }
pallet-assets = { version = "30.0.0" }
pallet-asset-conversion = { version = "11.0.0" }
pallet-treasury = { version = "28.0.0" }
pallet-message-queue = { version = "32.0.0" }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod fellowship_treasury;
mod reserve_transfer;
mod send;
mod set_xcm_versions;
mod swap;
mod teleport;
mod treasury;

Expand Down
Loading

0 comments on commit 49c6d6d

Please sign in to comment.