Skip to content

Commit

Permalink
factor test
Browse files Browse the repository at this point in the history
  • Loading branch information
alistair-singh committed Jan 24, 2025
1 parent e946e28 commit 798229c
Showing 1 changed file with 66 additions and 215 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,12 @@ fn send_weth_from_ethereum_to_asset_hub() {
});
}

/// Tests sending ether from Ethereum to Asset Hub and back to Ethereum
#[test]
fn send_eth_asset_from_asset_hub_to_ethereum() {
// Performs a round trip tansfer of a token, asseting success.
fn send_token_from_ethereum_to_asset_hub_and_back_works(
token_address: H160,
amount: u128,
asset_location: Location,
) {
let assethub_sovereign = BridgeHubPolkadot::sovereign_account_id_of(
BridgeHubPolkadot::sibling_location_of(AssetHubPolkadot::para_id()),
);
Expand All @@ -477,40 +480,35 @@ fn send_eth_asset_from_asset_hub_to_ethereum() {
(ethereum_sovereign_account(), INITIAL_FUND),
]);

let ether_location: Location = (Parent, Parent, EthereumNetwork::get()).into();

// Register Ether as foreign asset on AH.
// Set base transfer fee to Ethereum on AH.
AssetHubPolkadot::execute_with(|| {
type RuntimeEvent = <AssetHubPolkadot as Chain>::RuntimeEvent;
type RuntimeOrigin = <AssetHubPolkadot as Chain>::RuntimeOrigin;

// Set base transfer fee to Ethereum on AH.
assert_ok!(<AssetHubPolkadot as Chain>::System::set_storage(
<AssetHubPolkadot as Chain>::RuntimeOrigin::root(),
vec![(BridgeHubEthereumBaseFee::key().to_vec(), AH_BASE_FEE.encode())],
));

// Register Ether
assert_ok!(<AssetHubPolkadot as AssetHubPolkadotPallet>::ForeignAssets::force_create(
RuntimeOrigin::root(),
ether_location.clone(),
ethereum_sovereign_account().into(),
true,
MIN_ETHER_BALANCE,
vec![(BridgeHubEthereumBaseFee::key().to_vec(), AH_BASE_FEE.encode())],
));

assert_expected_events!(
AssetHubPolkadot,
vec![
RuntimeEvent::ForeignAssets(pallet_assets::Event::ForceCreated { .. }) => {},
]
);
});

// Send Ether from Bridge Hub (simulates received Command from Ethereum)
// Send Token from Bridge Hub (simulates received Command from Ethereum)
BridgeHubPolkadot::execute_with(|| {
type RuntimeEvent = <BridgeHubPolkadot as Chain>::RuntimeEvent;

assert_ok!(
<BridgeHubPolkadot as BridgeHubPolkadotPallet>::EthereumSystem::set_pricing_parameters(
<BridgeHubPolkadot as Chain>::RuntimeOrigin::root(),
PricingParametersOf::<Runtime> {
exchange_rate: FixedU128::from_rational(1, 75),
fee_per_gas: gwei(20),
rewards: Rewards {
local: (UNITS / 100), // 0.01 DOT
remote: meth(1),
},
multiplier: FixedU128::from_rational(1, 1),
}
)
);

assert_ok!(<BridgeHubPolkadot as Chain>::System::set_storage(
<BridgeHubPolkadot as Chain>::RuntimeOrigin::root(),
vec![(EthereumGatewayAddress::key().to_vec(), H160(GATEWAY_ADDRESS).encode())],
Expand All @@ -521,11 +519,11 @@ fn send_eth_asset_from_asset_hub_to_ethereum() {
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::SendToken {
token: ETHER_TOKEN_ADDRESS.into(),
token: token_address,
destination: Destination::AccountId32 {
id: AssetHubPolkadotReceiver::get().into(),
},
amount: MIN_ETHER_BALANCE + TOKEN_AMOUNT,
amount,
fee: XCM_FEE,
},
});
Expand All @@ -543,15 +541,17 @@ fn send_eth_asset_from_asset_hub_to_ethereum() {
);
});

// Receive Ether on Asset Hub.
// Receive Token on Asset Hub.
AssetHubPolkadot::execute_with(|| {
type RuntimeEvent = <AssetHubPolkadot as Chain>::RuntimeEvent;

// Check that the token was received and issued as a foreign asset on AssetHub
assert_expected_events!(
AssetHubPolkadot,
vec![
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { .. }) => {},
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { asset_id, .. }) => {
asset_id: *asset_id == asset_location,
},
]
);
});
Expand All @@ -560,11 +560,11 @@ fn send_eth_asset_from_asset_hub_to_ethereum() {
<<BridgeHubPolkadot as BridgeHubPolkadotPallet>::Balances as frame_support::traits::fungible::Inspect<_>>::balance(&RelayTreasuryPalletAccount::get())
});

// Send Ether from Asset Hub back to Ethereum.
// Send Token from Asset Hub back to Ethereum.
AssetHubPolkadot::execute_with(|| {
type RuntimeOrigin = <AssetHubPolkadot as Chain>::RuntimeOrigin;

let assets = vec![Asset { id: AssetId(ether_location), fun: Fungible(TOKEN_AMOUNT) }];
let assets = vec![Asset { id: AssetId(asset_location), fun: Fungible(amount) }];
let versioned_assets = VersionedAssets::from(Assets::from(assets));

let destination = VersionedLocation::from(Location::new(
Expand All @@ -581,7 +581,7 @@ fn send_eth_asset_from_asset_hub_to_ethereum() {
<AssetHubPolkadot as AssetHubPolkadotPallet>::Balances::free_balance(
AssetHubPolkadotReceiver::get(),
);
// Send the Ether back to Ethereum
// Send the Token back to Ethereum
assert_ok!(
<AssetHubPolkadot as AssetHubPolkadotPallet>::PolkadotXcm::limited_reserve_transfer_assets(
RuntimeOrigin::signed(AssetHubPolkadotReceiver::get()),
Expand All @@ -602,7 +602,7 @@ fn send_eth_asset_from_asset_hub_to_ethereum() {
assert!(free_balance_diff > AH_BASE_FEE);
});

// Check that message with Ether was queued on the BridgeHub
// Check that message with Token was queued on the BridgeHub
BridgeHubPolkadot::execute_with(|| {
type RuntimeEvent = <BridgeHubPolkadot as Chain>::RuntimeEvent;
// check the outbound queue
Expand All @@ -622,8 +622,8 @@ fn send_eth_asset_from_asset_hub_to_ethereum() {
assert!(
events.iter().any(|event| matches!(
event,
RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount })
if *who == RelayTreasuryPalletAccount::get() && *amount == local_fee
RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount: fee_minted })
if *who == RelayTreasuryPalletAccount::get() && *fee_minted == local_fee
)),
"Snowbridge sovereign takes local fee."
);
Expand All @@ -639,199 +639,50 @@ fn send_eth_asset_from_asset_hub_to_ethereum() {
});
}

/// Tests the full cycle of token transfers:
/// - registering a token on AssetHub
/// - sending a token to AssetHub
/// - returning the token to Ethereum
/// Tests sending Ether from Ethereum to Asset Hub and back to Ethereum
#[test]
fn send_weth_asset_from_asset_hub_to_ethereum() {
let assethub_sovereign = BridgeHubPolkadot::sovereign_account_id_of(Location::new(
1,
[Parachain(AssetHubPolkadot::para_id().into())],
));

BridgeHubPolkadot::fund_accounts(vec![
(assethub_sovereign.clone(), INITIAL_FUND),
(RelayTreasuryPalletAccount::get(), INITIAL_FUND),
]);
AssetHubPolkadot::fund_accounts(vec![
(AssetHubPolkadotReceiver::get(), INITIAL_FUND),
(ethereum_sovereign_account(), INITIAL_FUND),
]);

// Set base transfer fee to Ethereum on AH.
AssetHubPolkadot::execute_with(|| {
assert_ok!(<AssetHubPolkadot as Chain>::System::set_storage(
<AssetHubPolkadot as Chain>::RuntimeOrigin::root(),
vec![(BridgeHubEthereumBaseFee::key().to_vec(), AH_BASE_FEE.encode())],
));
});

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

assert_ok!(
<BridgeHubPolkadot as BridgeHubPolkadotPallet>::EthereumSystem::set_pricing_parameters(
<BridgeHubPolkadot as Chain>::RuntimeOrigin::root(),
PricingParametersOf::<Runtime> {
exchange_rate: FixedU128::from_rational(1, 75),
fee_per_gas: gwei(20),
rewards: Rewards {
local: (UNITS / 100), // 0.01 DOT
remote: meth(1),
},
multiplier: FixedU128::from_rational(1, 1),
}
)
);

assert_ok!(<BridgeHubPolkadot as Chain>::System::set_storage(
<BridgeHubPolkadot as Chain>::RuntimeOrigin::root(),
vec![(EthereumGatewayAddress::key().to_vec(), H160(GATEWAY_ADDRESS).encode())],
));

let message_id: H256 = [1; 32].into();
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::RegisterToken { token: WETH.into(), fee: XCM_FEE },
});
// Convert the message to XCM
let (xcm, _) = EthereumInboundQueue::do_convert(message_id, message).unwrap();
// Send the XCM
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubPolkadot::para_id()).unwrap();

// Check that the register token message was sent using xcm
assert_expected_events!(
BridgeHubPolkadot,
vec![
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
]
);

// Construct SendToken message and sent to inbound queue
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::SendToken {
token: WETH.into(),
destination: Destination::AccountId32 {
id: AssetHubPolkadotReceiver::get().into(),
},
amount: TOKEN_AMOUNT,
fee: XCM_FEE,
},
});
// Convert the message to XCM
let (xcm, _) = EthereumInboundQueue::do_convert(message_id, message).unwrap();
// Send the XCM
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubPolkadot::para_id()).unwrap();

// Check that the send token message was sent using xcm
assert_expected_events!(
BridgeHubPolkadot,
vec![
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
]
);
});

// check treasury account balance on BH before
let treasury_account_before = BridgeHubPolkadot::execute_with(|| {
<<BridgeHubPolkadot as BridgeHubPolkadotPallet>::Balances as frame_support::traits::fungible::Inspect<_>>::balance(&RelayTreasuryPalletAccount::get())
});
fn send_eth_asset_from_asset_hub_to_ethereum() {
let ether_location: Location = (Parent, Parent, EthereumNetwork::get()).into();

// Register Ether as foreign asset on AH.
AssetHubPolkadot::execute_with(|| {
type RuntimeEvent = <AssetHubPolkadot as Chain>::RuntimeEvent;
type RuntimeOrigin = <AssetHubPolkadot as Chain>::RuntimeOrigin;

// Check that AssetHub has issued the foreign asset
assert_expected_events!(
AssetHubPolkadot,
vec![
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { .. }) => {},
]
);
let assets = vec![Asset {
id: AssetId(Location::new(
2,
[
GlobalConsensus(Ethereum { chain_id: CHAIN_ID }),
AccountKey20 { network: None, key: WETH },
],
)),
fun: Fungible(TOKEN_AMOUNT),
}];
let versioned_assets = VersionedAssets::from(Assets::from(assets));

let destination = VersionedLocation::from(Location::new(
2,
[GlobalConsensus(Ethereum { chain_id: CHAIN_ID })],
));

let beneficiary = VersionedLocation::from(Location::new(
0,
[AccountKey20 { network: None, key: ETHEREUM_DESTINATION_ADDRESS }],
assert_ok!(<AssetHubPolkadot as AssetHubPolkadotPallet>::ForeignAssets::force_create(
RuntimeOrigin::root(),
ether_location.clone(),
ethereum_sovereign_account().into(),
true,
MIN_ETHER_BALANCE,
));

let free_balance_before =
<AssetHubPolkadot as AssetHubPolkadotPallet>::Balances::free_balance(
AssetHubPolkadotReceiver::get(),
);
// Send the Weth back to Ethereum
assert_ok!(
<AssetHubPolkadot as AssetHubPolkadotPallet>::PolkadotXcm::limited_reserve_transfer_assets(
RuntimeOrigin::signed(AssetHubPolkadotReceiver::get()),
Box::new(destination),
Box::new(beneficiary),
Box::new(versioned_assets),
0,
Unlimited,
)
);

let free_balance_after =
<AssetHubPolkadot as AssetHubPolkadotPallet>::Balances::free_balance(
AssetHubPolkadotReceiver::get(),
);
// Assert at least DefaultBridgeHubEthereumBaseFee charged from the sender
let free_balance_diff = free_balance_before - free_balance_after;
assert!(free_balance_diff > AH_BASE_FEE);
});

BridgeHubPolkadot::execute_with(|| {
type RuntimeEvent = <BridgeHubPolkadot as Chain>::RuntimeEvent;
// Check that the transfer token back to Ethereum message was queue in the Ethereum
// Outbound Queue
assert_expected_events!(
BridgeHubPolkadot,
AssetHubPolkadot,
vec![
RuntimeEvent::EthereumOutboundQueue(snowbridge_pallet_outbound_queue::Event::MessageQueued {..}) => {},
RuntimeEvent::ForeignAssets(pallet_assets::Event::ForceCreated { .. }) => {},
]
);
});

// check treasury account balance on BH after (should receive some fees)
let treasury_account_after = <<BridgeHubPolkadot as BridgeHubPolkadotPallet>::Balances as frame_support::traits::fungible::Inspect<_>>::balance(&RelayTreasuryPalletAccount::get());
let local_fee = treasury_account_after - treasury_account_before;
// Perform a roundtrip transfer of Ether
send_token_from_ethereum_to_asset_hub_and_back_works(
ETHER_TOKEN_ADDRESS.into(),
MIN_ETHER_BALANCE + TOKEN_AMOUNT,
ether_location,
);
}

let events = BridgeHubPolkadot::events();
// Check that the local fee was credited to the Snowbridge sovereign account
assert!(
events.iter().any(|event| matches!(
event,
RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount })
if *who == RelayTreasuryPalletAccount::get() && *amount == local_fee
)),
"Snowbridge sovereign takes local fee."
);
// Check that the remote delivery fee was credited to the AssetHub sovereign account
assert!(
events.iter().any(|event| matches!(
event,
RuntimeEvent::Balances(pallet_balances::Event::Minted { who, .. })
if *who == assethub_sovereign,
)),
"AssetHub sovereign takes remote fee."
);
});
/// Tests the full cycle of token transfers:
/// - registering a token on AssetHub
/// - sending a token to AssetHub
/// - returning the token to Ethereum
#[test]
fn send_weth_asset_from_asset_hub_to_ethereum() {
let weth_location: Location =
(Parent, Parent, EthereumNetwork::get(), AccountKey20 { network: None, key: WETH }).into();
// Perform a roundtrip transfer of WETH
send_token_from_ethereum_to_asset_hub_and_back_works(WETH.into(), TOKEN_AMOUNT, weth_location);
}

#[test]
Expand Down

0 comments on commit 798229c

Please sign in to comment.