Skip to content

Commit 1803bdf

Browse files
Merge pull request #1241 from galacticcouncil/feat/xcm-hollar
feat: hollar xcm location conversion
2 parents 3d35606 + 119e60c commit 1803bdf

3 files changed

Lines changed: 144 additions & 1 deletion

File tree

integration-tests/src/cross_chain_transfer.rs

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use frame_support::{assert_noop, assert_ok};
1010

1111
use polkadot_xcm::{v4::prelude::*, VersionedAssetId, VersionedAssets, VersionedXcm};
1212

13+
use crate::utils::accounts::MockAccount;
1314
use cumulus_primitives_core::ParaId;
1415
use frame_support::dispatch::GetDispatchInfo;
1516
use frame_support::storage::with_transaction;
@@ -1019,6 +1020,19 @@ fn register_dot() {
10191020
));
10201021
}
10211022

1023+
fn register_hollar() {
1024+
assert_ok!(AssetRegistry::register_sufficient_asset(
1025+
Some(222),
1026+
Some(b"HOLLAR".to_vec().try_into().unwrap()),
1027+
AssetKind::Token,
1028+
1_000_000,
1029+
None,
1030+
None,
1031+
None,
1032+
None,
1033+
));
1034+
}
1035+
10221036
fn add_currency_price(asset_id: u32, price: FixedU128) {
10231037
assert_ok!(hydradx_runtime::MultiTransactionPayment::add_currency(
10241038
hydradx_runtime::RuntimeOrigin::root(),
@@ -1199,3 +1213,117 @@ fn xcm_transfer_reserve_asset_and_deposit_asset_to_hydra<RC: Decode + GetDispatc
11991213
]);
12001214
VersionedXcm::from(message)
12011215
}
1216+
1217+
#[test]
1218+
fn hollar_xcm_transfer_should_work() {
1219+
// Arrange
1220+
TestNet::reset();
1221+
1222+
let bob_acc = MockAccount::new(AccountId::from(BOB));
1223+
let alice_acc = MockAccount::new(AccountId::from(ALICE));
1224+
let treasury_acc = MockAccount::new(Treasury::account_id());
1225+
1226+
// Register hollar on a parachain
1227+
Acala::execute_with(|| {
1228+
let _ = with_transaction(|| {
1229+
assert_ok!(AssetRegistry::register_sufficient_asset(
1230+
Some(223),
1231+
Some(b"HOLLAR".to_vec().try_into().unwrap()),
1232+
AssetKind::Token,
1233+
1_000_000,
1234+
None,
1235+
None,
1236+
None,
1237+
None,
1238+
));
1239+
1240+
add_currency_price(223, FixedU128::from(1));
1241+
TransactionOutcome::Commit(DispatchResult::Ok(()))
1242+
});
1243+
assert_ok!(hydradx_runtime::AssetRegistry::set_location(
1244+
223,
1245+
hydradx_runtime::AssetLocation(MultiLocation::new(
1246+
1,
1247+
X2(Junction::Parachain(HYDRA_PARA_ID), Junction::GeneralIndex(222))
1248+
))
1249+
));
1250+
});
1251+
1252+
// Send Hollar out from Hydration to a parachain
1253+
Hydra::execute_with(|| {
1254+
let _ = with_transaction(|| {
1255+
register_hollar();
1256+
add_currency_price(222, FixedU128::from(1));
1257+
TransactionOutcome::Commit(DispatchResult::Ok(()))
1258+
});
1259+
assert_ok!(hydradx_runtime::Tokens::set_balance(
1260+
RawOrigin::Root.into(),
1261+
ALICE.into(),
1262+
222,
1263+
100_000_000_000_000,
1264+
0,
1265+
));
1266+
1267+
let alice_initial_hollar_balance = alice_acc.balance(222);
1268+
// Act
1269+
assert_ok!(hydradx_runtime::XTokens::transfer(
1270+
hydradx_runtime::RuntimeOrigin::signed(ALICE.into()),
1271+
222,
1272+
30 * UNITS,
1273+
Box::new(
1274+
MultiLocation::new(
1275+
1,
1276+
X2(
1277+
Junction::Parachain(ACALA_PARA_ID),
1278+
Junction::AccountId32 { id: BOB, network: None }
1279+
)
1280+
)
1281+
.into_versioned()
1282+
),
1283+
WeightLimit::Limited(Weight::from_parts(399_600_000_000, 0))
1284+
));
1285+
1286+
// Assert
1287+
assert_eq!(alice_acc.balance(222), alice_initial_hollar_balance - 30 * UNITS);
1288+
});
1289+
1290+
// Assert that parachain received hollar from hydration
1291+
Acala::execute_with(|| {
1292+
let fee = treasury_acc.balance(223);
1293+
assert!(fee > 0, "Fee is not sent to treasury");
1294+
assert_eq!(bob_acc.balance(223), 30 * UNITS - fee);
1295+
});
1296+
1297+
// Send some HOLLAR back to hydration
1298+
Acala::execute_with(|| {
1299+
let bob_initial_hollar_balance = bob_acc.balance(223);
1300+
// Act
1301+
assert_ok!(hydradx_runtime::XTokens::transfer(
1302+
hydradx_runtime::RuntimeOrigin::signed(BOB.into()),
1303+
223,
1304+
10 * UNITS,
1305+
Box::new(
1306+
MultiLocation::new(
1307+
1,
1308+
X2(
1309+
Junction::Parachain(HYDRA_PARA_ID),
1310+
Junction::AccountId32 {
1311+
id: ALICE,
1312+
network: None
1313+
}
1314+
)
1315+
)
1316+
.into_versioned()
1317+
),
1318+
WeightLimit::Limited(Weight::from_parts(399_600_000_000, 0))
1319+
));
1320+
1321+
// Assert
1322+
assert_eq!(bob_acc.balance(223), bob_initial_hollar_balance - 10 * UNITS);
1323+
});
1324+
Hydra::execute_with(|| {
1325+
let fee = treasury_acc.balance(222);
1326+
assert!(fee > 0, "Fee is not sent to treasury");
1327+
assert_eq!(alice_acc.balance(222), 79922172204893);
1328+
});
1329+
}

primitives/src/constants.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ pub mod chain {
7272

7373
/// Core asset id
7474
pub const CORE_ASSET_ID: AssetId = 0;
75+
pub const HOLLAR_ASSET_ID: AssetId = 222;
7576

7677
/// We allow for 2 seconds of compute with a 6 seconds average block.
7778
pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(

runtime/hydradx/src/xcm.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ impl pallet_message_queue::Config for Runtime {
482482

483483
pub struct CurrencyIdConvert;
484484
use crate::evm::ExtendedAddressMapping;
485-
use primitives::constants::chain::CORE_ASSET_ID;
485+
use primitives::constants::chain::{CORE_ASSET_ID, HOLLAR_ASSET_ID};
486486

487487
impl Convert<AssetId, Option<Location>> for CurrencyIdConvert {
488488
fn convert(id: AssetId) -> Option<Location> {
@@ -491,6 +491,10 @@ impl Convert<AssetId, Option<Location>> for CurrencyIdConvert {
491491
parents: 1,
492492
interior: [Parachain(ParachainInfo::get().into()), GeneralIndex(id.into())].into(),
493493
}),
494+
HOLLAR_ASSET_ID => Some(Location {
495+
parents: 1,
496+
interior: [Parachain(ParachainInfo::get().into()), GeneralIndex(id.into())].into(),
497+
}),
494498
_ => {
495499
let loc = AssetRegistry::asset_to_location(id);
496500
if let Some(location) = loc {
@@ -515,7 +519,17 @@ impl Convert<Location, Option<AssetId>> for CurrencyIdConvert {
515519
{
516520
Some(CORE_ASSET_ID)
517521
}
522+
Junctions::X2(a)
523+
if parents == 1
524+
&& a.contains(&GeneralIndex(HOLLAR_ASSET_ID.into()))
525+
&& a.contains(&Parachain(ParachainInfo::get().into())) =>
526+
{
527+
Some(HOLLAR_ASSET_ID)
528+
}
518529
Junctions::X1(a) if parents == 0 && a.contains(&GeneralIndex(CORE_ASSET_ID.into())) => Some(CORE_ASSET_ID),
530+
Junctions::X1(a) if parents == 0 && a.contains(&GeneralIndex(HOLLAR_ASSET_ID.into())) => {
531+
Some(HOLLAR_ASSET_ID)
532+
}
519533
_ => {
520534
let location: Option<AssetLocation> = location.try_into().ok();
521535
if let Some(location) = location {

0 commit comments

Comments
 (0)