Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
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
46 changes: 46 additions & 0 deletions integration-tests/src/global_withdraw_limit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1528,3 +1528,49 @@ fn inbound_xcm_incomplete_message_still_accounts_egress() {
);
});
}

#[test]
fn polkadot_xcm_execute_withdraw_external_asset_succeeds_when_oracle_cannot_price_route() {
TestNet::reset();
Hydra::execute_with(|| {
init_global_withdraw_limit_params();

assert_ok!(CircuitBreaker::set_asset_category(
hydradx_runtime::RuntimeOrigin::root(),
DOT,
Some(GlobalAssetCategory::External)
));
// XCM asset transactor needs a location -> asset id mapping for DOT.
assert_ok!(hydradx_runtime::AssetRegistry::set_location(DOT, DOT_ASSET_LOCATION));
assert_ok!(hydradx_runtime::MultiTransactionPayment::add_currency(
hydradx_runtime::RuntimeOrigin::root(),
DOT,
FixedU128::from_rational(50, 100),
));
pallet_transaction_multi_payment::AcceptedCurrencyPrice::<hydradx_runtime::Runtime>::insert(
DOT,
FixedU128::from_rational(50, 100),
);

let alice: AccountId = ALICE.into();
let amount = 10 * UNITS;
let alice_dot_before = Currencies::free_balance(DOT, &alice);
assert!(alice_dot_before >= amount);

//Act
let message = xcm_message_withdraw_deposit(Location::parent(), amount);
let call = RuntimeCall::PolkadotXcm(pallet_xcm::Call::execute {
message: Box::new(VersionedXcm::from(message)),
max_weight: Weight::from_parts(1_000_000_000_000, 0),
});

assert_ok!(call.dispatch(hydradx_runtime::RuntimeOrigin::signed(ALICE.into())));

//Assert
assert!(
Currencies::free_balance(DOT, &alice) <= alice_dot_before - amount,
"DOT must have been withdrawn from Alice for the outbound XCM; before={alice_dot_before}, after={}",
Currencies::free_balance(DOT, &alice)
);
});
}
14 changes: 9 additions & 5 deletions runtime/hydradx/src/circuit_breaker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use pallet_asset_registry::AssetType;
use pallet_circuit_breaker::types::EgressOperationKind;
use pallet_circuit_breaker::GlobalAssetCategory;
use primitives::Balance;
use sp_runtime::helpers_128bit::multiply_by_rational_with_rounding;
use sp_runtime::traits::Convert;
use sp_runtime::DispatchResult;
use sp_runtime::{DispatchResult, FixedPointNumber, FixedU128, Rounding};
use sp_std::marker::PhantomData;

pub struct WithdrawLimitHandler<RC>(PhantomData<RC>);
Expand All @@ -26,14 +27,17 @@ impl<ReferenceCurrencyId: Get<AssetId>> WithdrawCircuitBreaker<ReferenceCurrency
return Ok(amount);
}

let (converted, _) = ConvertBalance::<TenMinutesOraclePrice, XykPaymentAssetSupport, DotAssetId>::convert((
ConvertBalance::<TenMinutesOraclePrice, XykPaymentAssetSupport, DotAssetId>::convert((
Comment thread
F3Joule marked this conversation as resolved.
Outdated
asset_id,
ref_currency,
amount,
))
.ok_or(pallet_circuit_breaker::Error::<Runtime>::FailedToConvertAsset)?;

Ok(converted)
.map(|(converted, _)| converted)
.or_else(|| {
let price = MultiTransactionPayment::currency_price(asset_id)?;
multiply_by_rational_with_rounding(amount, FixedU128::DIV, price.into_inner(), Rounding::Up)
})
.ok_or_else(|| pallet_circuit_breaker::Error::<Runtime>::FailedToConvertAsset.into())
}

pub fn global_asset_category(asset_id: AssetId) -> Option<GlobalAssetCategory> {
Expand Down
Loading