Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::{
use bridge_hub_westend_runtime::xcm_config::LocationToAccountId;
use snowbridge_core::AssetMetadata;
use snowbridge_pallet_system::Error;
use testnet_parachains_constants::westend::snowbridge::EthereumNetwork;
use xcm_executor::traits::ConvertLocation;

// The user origin should be banned in ethereum_blob_exporter with error logs
Expand Down Expand Up @@ -123,3 +124,176 @@ fn test_register_ena_on_bh_will_fail() {
);
});
}

#[test]
fn user_exploit_with_arbitrary_message_will_fail() {
fund_on_bh();
register_assets_on_ah();
fund_on_ah();
AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;
type RuntimeOrigin = <AssetHubWestend as Chain>::RuntimeOrigin;

let remote_fee_asset_location: Location =
Location::new(2, [EthereumNetwork::get().into()]).into();

let remote_fee_asset: Asset = (remote_fee_asset_location.clone(), 1).into();

let assets = VersionedAssets::from(vec![remote_fee_asset]);

let exploited_weth = Asset {
id: AssetId(Location::new(0, [AccountKey20 { network: None, key: WETH.into() }])),
// A big amount without burning
fun: Fungible(TOKEN_AMOUNT * 1_000_000_000),
};

assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::transfer_assets_using_type_and_then(
RuntimeOrigin::signed(AssetHubWestendSender::get()),
bx!(VersionedLocation::from(ethereum())),
bx!(assets),
bx!(TransferType::DestinationReserve),
bx!(VersionedAssetId::from(remote_fee_asset_location.clone())),
bx!(TransferType::DestinationReserve),
// exploited_weth here is far more than the burnt, which means instructions inner
// are user provided and untrustworthy/dangerous!
// Currently it depends on EthereumBlobExporter on BH to check the message is legal
// and convert to Ethereum command.
bx!(VersionedXcm::from(Xcm(vec![
WithdrawAsset(exploited_weth.clone().into()),
DepositAsset { assets: Wild(All), beneficiary: beneficiary() },
SetTopic([0; 32]),
]))),
Unlimited
));

assert_expected_events!(
AssetHubWestend,
vec![RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent{ .. }) => {},]
);
});

BridgeHubWestend::execute_with(|| {
type RuntimeEvent = <BridgeHubWestend as Chain>::RuntimeEvent;
assert_expected_events!(
BridgeHubWestend,
vec![RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed{ success:false, .. }) => {},]
);
});
}

#[test]
fn export_from_non_system_parachain_will_fail() {
let penpal_sovereign = BridgeHubWestend::sovereign_account_id_of(Location::new(
1,
[Parachain(PenpalB::para_id().into())],
));
BridgeHubWestend::fund_accounts(vec![(penpal_sovereign.clone(), INITIAL_FUND)]);

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

let local_fee_asset =
Asset { id: AssetId(Location::here()), fun: Fungible(1_000_000_000_000) };

let weth_location_reanchored =
Location::new(0, [AccountKey20 { network: None, key: WETH.into() }]);

let weth_asset =
Asset { id: AssetId(weth_location_reanchored.clone()), fun: Fungible(TOKEN_AMOUNT) };

assert_ok!(<PenpalB as PenpalBPallet>::PolkadotXcm::send(
RuntimeOrigin::root(),
bx!(VersionedLocation::from(bridge_hub())),
bx!(VersionedXcm::from(Xcm(vec![
WithdrawAsset(local_fee_asset.clone().into()),
BuyExecution { fees: local_fee_asset.clone(), weight_limit: Unlimited },
ExportMessage {
network: Ethereum { chain_id: CHAIN_ID },
destination: Here,
xcm: Xcm(vec![
WithdrawAsset(weth_asset.clone().into()),
DepositAsset { assets: Wild(All), beneficiary: beneficiary() },
SetTopic([0; 32]),
]),
},
]))),
));

assert_expected_events!(
PenpalB,
vec![RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent{ .. }) => {},]
);
});

BridgeHubWestend::execute_with(|| {
type RuntimeEvent = <BridgeHubWestend as Chain>::RuntimeEvent;
assert_expected_events!(
BridgeHubWestend,
vec![RuntimeEvent::MessageQueue(pallet_message_queue::Event::ProcessingFailed{ .. }) => {},]
);
});
}

#[test]
fn export_from_system_parachain_but_not_root_will_fail() {
fund_on_bh();
register_assets_on_ah();
fund_on_ah();
create_pools_on_ah();

let sub_location = PalletInstance(100);
let assethub_pallet_sovereign = BridgeHubWestend::sovereign_account_id_of(Location::new(
1,
[Parachain(AssetHubWestend::para_id().into()), sub_location.clone()],
));
BridgeHubWestend::fund_accounts(vec![(assethub_pallet_sovereign.clone(), INITIAL_FUND)]);

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

let local_fee_asset =
Asset { id: AssetId(Location::parent()), fun: Fungible(1_000_000_000_000) };

let weth_location_reanchored =
Location::new(0, [AccountKey20 { network: None, key: WETH.into() }]);

let weth_asset = Asset {
id: AssetId(weth_location_reanchored.clone()),
fun: Fungible(TOKEN_AMOUNT * 1_000_000_000),
};

assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::send(
RuntimeOrigin::root(),
bx!(VersionedLocation::from(bridge_hub())),
bx!(VersionedXcm::from(Xcm(vec![
DescendOrigin(sub_location.into()),
WithdrawAsset(local_fee_asset.clone().into()),
BuyExecution { fees: local_fee_asset.clone(), weight_limit: Unlimited },
ExportMessage {
network: Ethereum { chain_id: CHAIN_ID },
destination: Here,
xcm: Xcm(vec![
WithdrawAsset(weth_asset.clone().into()),
DepositAsset { assets: Wild(All), beneficiary: beneficiary() },
SetTopic([0; 32]),
]),
},
]))),
));

assert_expected_events!(
AssetHubWestend,
vec![RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent{ .. }) => {},]
);
});

BridgeHubWestend::execute_with(|| {
type RuntimeEvent = <BridgeHubWestend as Chain>::RuntimeEvent;
assert_expected_events!(
BridgeHubWestend,
vec![RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed{ success:false, .. }) => {},]
);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@ use super::{
ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
TransactionByteFee, WeightToFee, XcmOverBridgeHubRococo, XcmpQueue,
};
use crate::bridge_to_ethereum_config::SnowbridgeFrontendLocation;
use crate::bridge_to_ethereum_config::{AssethubLocation, SnowbridgeFrontendLocation};
use bridge_hub_common::DenyExportMessageFrom;
use frame_support::{
parameter_types,
traits::{tokens::imbalance::ResolveTo, ConstU32, Contains, Equals, Everything, Nothing},
traits::{
tokens::imbalance::ResolveTo, ConstU32, Contains, Equals, Everything, EverythingBut,
Nothing,
},
};
use frame_system::EnsureRoot;
use pallet_collator_selection::StakingPotAccountId;
Expand Down Expand Up @@ -130,7 +134,15 @@ impl Contains<Location> for ParentOrParentsPlurality {

pub type Barrier = TrailingSetTopicAsId<
DenyThenTry<
DenyRecursively<DenyReserveTransferToRelayChain>,
(
DenyRecursively<DenyReserveTransferToRelayChain>,
DenyRecursively<
DenyExportMessageFrom<
EverythingBut<Equals<AssethubLocation>>,
Equals<EthereumNetwork>,
>,
>,
),
(
// Allow local users to buy weight credit.
TakeWeightCredit,
Expand Down