Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Accept DOT as reserve from AH
  • Loading branch information
dmoka committed Aug 28, 2024
commit e044ec3e9c3d17e8dc97df234aa1611b35517bd7
168 changes: 147 additions & 21 deletions integration-tests/src/cross_chain_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -648,46 +648,45 @@ fn transfer_foreign_asset_from_acala_to_hydra_should_not_work() {
}

#[test]
fn transfer_dot_reserve_from_asset_hub_to_hydra_should_not_work() {
fn transfer_dot_reserve_from_asset_hub_to_hydra_should_work() {
//Arrange
TestNet::reset();

Hydra::execute_with(|| {
let _ = with_transaction(|| {
register_foreign_asset();
assert_ok!(hydradx_runtime::AssetRegistry::set_location(
DOT,
hydradx_runtime::AssetLocation(MultiLocation::new(1, polkadot_xcm::opaque::v3::Junctions::Here))
));
add_currency_price(DOT, FixedU128::from(1));

add_currency_price(FOREIGN_ASSET, FixedU128::from(1));
add_currency_price(DOT, FixedU128::from(1));
assert_ok!(hydradx_runtime::Tokens::deposit(
DOT,
&AccountId::from(ALICE),
3000 * UNITS
));

TransactionOutcome::Commit(DispatchResult::Ok(()))
});
assert_ok!(hydradx_runtime::AssetRegistry::set_location(
DOT,
hydradx_runtime::AssetLocation(MultiLocation::new(
1,
polkadot_xcm::opaque::v3::Junctions::Here
))
));
});

AssetHub::execute_with(|| {
let _ = with_transaction(|| {
register_foreign_asset();
register_dot();
TransactionOutcome::Commit(DispatchResult::Ok(()))
});

assert_ok!(hydradx_runtime::Tokens::deposit(
FOREIGN_ASSET,
&AccountId::from(ALICE),
3000 * UNITS
));

assert_ok!(hydradx_runtime::Tokens::deposit(
DOT,
&AccountId::from(ALICE),
3000 * UNITS
));

let dot: Asset = Asset {
id: cumulus_primitives_core::AssetId(Location::new(1, cumulus_primitives_core::Junctions::Here)),
id: cumulus_primitives_core::AssetId(Location::new(
1,
cumulus_primitives_core::Junctions::Here
)),
fun: Fungible(100 * UNITS),
};

Expand All @@ -699,7 +698,8 @@ fn transfer_dot_reserve_from_asset_hub_to_hydra_should_not_work() {
}])),
);

let xcm = xcm_for_deposit_reserve_asset_to_hydra::<hydradx_runtime::RuntimeCall>(dot, bob_beneficiary);
let xcm =
xcm_transfer_reserve_asset_and_deposit_asset_to_hydra::<hydradx_runtime::RuntimeCall>(dot, bob_beneficiary);

//Act
let res = hydradx_runtime::PolkadotXcm::execute(
Expand All @@ -719,10 +719,77 @@ fn transfer_dot_reserve_from_asset_hub_to_hydra_should_not_work() {

//Assert
Hydra::execute_with(|| {
assert_xcm_message_processing_failed();
assert_xcm_message_processing_passed();

let fee = hydradx_runtime::Tokens::free_balance(DOT, &hydradx_runtime::Treasury::account_id());
assert!(fee > 0, "treasury should have received fees");
//Check if the foreign asset from Assethub has been deposited successfully
assert_eq!(
hydradx_runtime::Currencies::free_balance(DOT, &AccountId::from(BOB)),
100 * UNITS - fee
);
});
}

#[test]
fn transfer_dot_from_hydra_to_asset_hub() {
AssetHub::execute_with(|| {
let _ = with_transaction(|| {
register_dot();
add_currency_price(DOT, FixedU128::from(1));
TransactionOutcome::Commit(DispatchResult::Ok(()))
});
});

//Arrange
Hydra::execute_with(|| {
assert_ok!(hydradx_runtime::AssetRegistry::set_location(
DOT,
hydradx_runtime::AssetLocation(MultiLocation::new(
1,
polkadot_xcm::opaque::v3::Junctions::Here
))
));

//Act
assert_ok!(hydradx_runtime::XTokens::transfer(
hydradx_runtime::RuntimeOrigin::signed(ALICE.into()),
DOT,
3 * UNITS,
Box::new(
MultiLocation::new(
1,
X2(
Junction::Parachain(ASSET_HUB_PARA_ID),
Junction::AccountId32 { id: BOB, network: None }
)
)
.into_versioned()
),
WeightLimit::Unlimited,
));

//Assert
assert_eq!(
hydradx_runtime::Tokens::free_balance(DOT, &AccountId::from(ALICE)),
2000 * UNITS - 3 * UNITS
);
});

//Needed to process horizontal xcm messages
Rococo::execute_with(|| {});

AssetHub::execute_with(|| {
assert_xcm_message_processing_passed();

assert_eq!(
hydradx_runtime::Currencies::free_balance(DOT, &AccountId::from(BOB)),
2_899_374_643_624 // 3 * HDX - fee
);
});
}


#[test]
fn transfer_dot_reserve_from_non_asset_hub_chain_to_hydra_should_not_work() {
//Arrange
Expand Down Expand Up @@ -862,6 +929,65 @@ fn xcm_for_deposit_reserve_asset_to_hydra<RC: Decode + GetDispatchInfo>(
VersionedXcm::from(message)
}

fn xcm_transfer_reserve_asset_and_deposit_asset_to_hydra<RC: Decode + GetDispatchInfo>(
assets: Asset,
beneficiary: Location,
) -> VersionedXcm<RC> {
use rococo_runtime::xcm_config::BaseXcmWeight;
use xcm_builder::FixedWeightBounds;
use xcm_executor::traits::WeightBounds;

type Weigher<RC> = FixedWeightBounds<BaseXcmWeight, RC, ConstU32<100>>;

let dest = Location::new(
1,
cumulus_primitives_core::Junctions::X1(Arc::new([cumulus_primitives_core::Junction::Parachain(HYDRA_PARA_ID)])),
);

let max_assets = 1 + 1;

let context = cumulus_primitives_core::Junctions::X2(Arc::new([
cumulus_primitives_core::Junction::GlobalConsensus(cumulus_primitives_core::NetworkId::Polkadot),
cumulus_primitives_core::Junction::Parachain(ASSET_HUB_PARA_ID),
]));

let fee_asset = assets.clone().reanchored(&dest, &context).expect("should reanchor");
let fees = fee_asset.clone();

let weight_limit = {
let mut remote_message = Xcm(vec![
ReserveAssetDeposited::<RC>(assets.clone().into()),
ClearOrigin,
BuyExecution {
fees: fees.clone(),
weight_limit: Limited(Weight::zero()),
},
DepositAsset {
assets: Wild(AllCounted(max_assets)),
beneficiary: beneficiary.clone(),
},
]);
// use local weight for remote message and hope for the best.
let remote_weight = Weigher::weight(&mut remote_message).expect("weighing should not fail");
Limited(remote_weight)
};
// executed on remote (on hydra)
let xcm = Xcm(vec![
//ReserveAssetDeposited(assets.clone()),
BuyExecution { fees, weight_limit },
DepositAsset {
assets: Wild(AllCounted(max_assets)),
beneficiary,
},
]);
// executed on local (AssetHub)
let message = Xcm(vec![
SetFeesMode { jit_withdraw: true },
TransferReserveAsset { assets: assets.into(), dest, xcm },
]);
VersionedXcm::from(message)
}

fn register_foreign_asset() {
assert_ok!(AssetRegistry::register_sufficient_asset(
Some(FOREIGN_ASSET),
Expand Down
19 changes: 19 additions & 0 deletions runtime/hydradx/src/xcm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,26 @@ where
}
}

pub struct IsDotFrom<Origin>(PhantomData<Origin>);
impl<Origin> ContainsPair<Asset, Location> for IsDotFrom<Origin>
where
Origin: Get<Location>,
{
fn contains(asset: &Asset, origin: &Location) -> bool {
let loc = Origin::get();
&loc == origin
&& matches!(
asset,
Asset {
id: AssetId(Location { parents: 1, interior: Here }),
fun: Fungible(_),
},
)
}
}

pub type Reserves = (
IsDotFrom<AssetHubLocation>,
IsForeignNativeAssetFrom<AssetHubLocation>,
MultiNativeAsset<AbsoluteReserveProvider>,
);
Expand Down