Skip to content

Commit

Permalink
Adds emulated test comments (#97)
Browse files Browse the repository at this point in the history
* adds emulated test comments

* pr comments

* rename XCMs

---------

Co-authored-by: claravanstaden <Cats 4 life!>
  • Loading branch information
claravanstaden authored and claravanstaden committed Jan 22, 2024
1 parent 8328a24 commit 088a3b0
Showing 1 changed file with 80 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,19 @@ pub enum SnowbridgeControl {
Control(ControlCall),
}

/// Create an agent on Ethereum. An agent is a representation of an entity in the Polkadot
/// ecosystem (like a parachain) on Ethereum.
#[test]
fn create_agent() {
let origin_para: u32 = 1001;

// Fund the origin parachain sovereign account so that it can pay execution fees.
BridgeHubRococo::fund_para_sovereign(origin_para.into(), INITIAL_FUND);

let sudo_origin = <Rococo as Chain>::RuntimeOrigin::root();
let destination = Rococo::child_location_of(BridgeHubRococo::para_id()).into();

let create_agent_call = SnowbridgeControl::Control(ControlCall::CreateAgent {});

// Construct XCM to create an agent for para 1001
let remote_xcm = VersionedXcm::from(Xcm(vec![
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
DescendOrigin(Parachain(origin_para).into()),
Expand All @@ -69,7 +71,7 @@ fn create_agent() {
},
]));

//Rococo Global Consensus
// Rococo Global Consensus
// Send XCM message from Relay Chain to Bridge Hub source Parachain
Rococo::execute_with(|| {
assert_ok!(<Rococo as RococoPallet>::XcmPallet::send(
Expand All @@ -79,7 +81,7 @@ fn create_agent() {
));

type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;

// Check that the Transact message was sent
assert_expected_events!(
Rococo,
vec![
Expand All @@ -90,7 +92,7 @@ fn create_agent() {

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

// Check that a message was sent to Ethereum to create the agent
assert_expected_events!(
BridgeHubRococo,
vec![
Expand All @@ -102,18 +104,20 @@ fn create_agent() {
});
}

/// Create a channel for a consensus system. A channel is a bidirectional messaging channel
/// between BridgeHub and Ethereum.
#[test]
fn create_channel() {
let origin_para: u32 = 1001;

// Fund AssetHub sovereign account so that it can pay execution fees.
BridgeHubRococo::fund_para_sovereign(origin_para.into(), INITIAL_FUND);

let sudo_origin = <Rococo as Chain>::RuntimeOrigin::root();
let destination: VersionedLocation =
Rococo::child_location_of(BridgeHubRococo::para_id()).into();

let create_agent_call = SnowbridgeControl::Control(ControlCall::CreateAgent {});

// Construct XCM to create an agent for para 1001
let create_agent_xcm = VersionedXcm::from(Xcm(vec![
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
DescendOrigin(Parachain(origin_para).into()),
Expand All @@ -126,7 +130,7 @@ fn create_channel() {

let create_channel_call =
SnowbridgeControl::Control(ControlCall::CreateChannel { mode: OperatingMode::Normal });

// Construct XCM to create a channel for para 1001
let create_channel_xcm = VersionedXcm::from(Xcm(vec![
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
DescendOrigin(Parachain(origin_para).into()),
Expand All @@ -137,7 +141,7 @@ fn create_channel() {
},
]));

//Rococo Global Consensus
// Rococo Global Consensus
// Send XCM message from Relay Chain to Bridge Hub source Parachain
Rococo::execute_with(|| {
assert_ok!(<Rococo as RococoPallet>::XcmPallet::send(
Expand Down Expand Up @@ -165,6 +169,7 @@ fn create_channel() {
BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;

// Check that the Channel was created
assert_expected_events!(
BridgeHubRococo,
vec![
Expand All @@ -176,11 +181,13 @@ fn create_channel() {
});
}

/// Tests the registering of a token as an asset on AssetHub.
#[test]
fn register_weth_token_from_ethereum_to_asset_hub() {
// Fund AssetHub sovereign account so that it can pay execution fees.
BridgeHubRococo::fund_para_sovereign(AssetHubRococo::para_id().into(), INITIAL_FUND);

let message_id_: H256 = [1; 32].into();
let message_id: H256 = [1; 32].into();

BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
Expand All @@ -190,7 +197,7 @@ fn register_weth_token_from_ethereum_to_asset_hub() {
chain_id: CHAIN_ID,
command: Command::RegisterToken { token: WETH.into(), fee: XCM_FEE },
});
let (xcm, fee) = EthereumInboundQueue::do_convert(message_id_, message).unwrap();
let (xcm, fee) = EthereumInboundQueue::do_convert(message_id, message).unwrap();

assert_ok!(EthereumInboundQueue::burn_fees(AssetHubRococo::para_id().into(), fee));

Expand All @@ -216,32 +223,38 @@ fn register_weth_token_from_ethereum_to_asset_hub() {
});
}

/// Tests sending a token to a 3rd party parachain, called PenPal. The token reserve is
/// still located on AssetHub.
#[test]
fn send_token_from_ethereum_to_penpal() {
let asset_hub_sovereign = BridgeHubRococo::sovereign_account_id_of(Location::new(
1,
[Parachain(AssetHubRococo::para_id().into())],
));
// Fund AssetHub sovereign account so it can pay execution fees for the asset transfer
BridgeHubRococo::fund_accounts(vec![(asset_hub_sovereign.clone(), INITIAL_FUND)]);

// Fund PenPal sender and receiver
PenpalA::fund_accounts(vec![
(PenpalAReceiver::get(), INITIAL_FUND),
(PenpalASender::get(), INITIAL_FUND),
(PenpalAReceiver::get(), INITIAL_FUND), // for receiving the sent asset on PenPal
(PenpalASender::get(), INITIAL_FUND), // for creating the asset on PenPal
]);

// The Weth asset location, identified by the contract address on Ethereum
let weth_asset_location: Location =
(Parent, Parent, EthereumNetwork::get(), AccountKey20 { network: None, key: WETH }).into();
// Converts the Weth asset location into an asset ID
let weth_asset_id: v3::Location = weth_asset_location.try_into().unwrap();

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

// Fund ethereum sovereign in asset hub
// Fund ethereum sovereign on AssetHub
let ethereum_sovereign: AccountId =
GlobalConsensusEthereumConvertsFor::<AccountId>::convert_location(&origin_location)
.unwrap();
AssetHubRococo::fund_accounts(vec![(ethereum_sovereign.clone(), INITIAL_FUND)]);

// Create asset on assethub.
// Create asset on AssetHub, since that is where the asset reserve is located
AssetHubRococo::execute_with(|| {
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::ForeignAssets::create(
pallet_xcm::Origin::Xcm(origin_location).into(),
Expand All @@ -255,7 +268,7 @@ fn send_token_from_ethereum_to_penpal() {
));
});

// Create asset on penpal.
// Create asset on the Penpal parachain.
PenpalA::execute_with(|| {
assert_ok!(<PenpalA as PenpalAPallet>::ForeignAssets::create(
<PenpalA as Chain>::RuntimeOrigin::signed(PenpalASender::get()),
Expand All @@ -267,12 +280,13 @@ fn send_token_from_ethereum_to_penpal() {
assert!(<PenpalA as PenpalAPallet>::ForeignAssets::asset_exists(weth_asset_id));
});

let message_id_: H256 = [1; 32].into();
let message_id: H256 = [1; 32].into();

BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
type EthereumInboundQueue =
<BridgeHubRococo as BridgeHubRococoPallet>::EthereumInboundQueue;
// Construct SendToken message
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::SendToken {
Expand All @@ -286,7 +300,9 @@ fn send_token_from_ethereum_to_penpal() {
fee: XCM_FEE,
},
});
let (xcm, _) = EthereumInboundQueue::do_convert(message_id_, message).unwrap();
// Convert the message to XCM
let (xcm, _) = EthereumInboundQueue::do_convert(message_id, message).unwrap();
// Send the XCM
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubRococo::para_id().into()).unwrap();

assert_expected_events!(
Expand All @@ -299,7 +315,7 @@ fn send_token_from_ethereum_to_penpal() {

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

// Check that the assets were issued on AssetHub
assert_expected_events!(
AssetHubRococo,
vec![
Expand All @@ -311,7 +327,7 @@ fn send_token_from_ethereum_to_penpal() {

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

// Check that the assets were issued on PenPal
assert_expected_events!(
PenpalA,
vec![
Expand All @@ -321,25 +337,32 @@ fn send_token_from_ethereum_to_penpal() {
});
}

/// Tests the registering of a token as an asset on AssetHub, and then subsequently sending
/// a token from Ethereum to AssetHub.
#[test]
fn send_token_from_ethereum_to_asset_hub() {
BridgeHubRococo::fund_para_sovereign(AssetHubRococo::para_id().into(), INITIAL_FUND);

// Fund ethereum sovereign in asset hub
// Fund ethereum sovereign on AssetHub
AssetHubRococo::fund_accounts(vec![(AssetHubRococoReceiver::get(), INITIAL_FUND)]);

let message_id_: H256 = [1; 32].into();
let message_id: H256 = [1; 32].into();

BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
type EthereumInboundQueue =
<BridgeHubRococo as BridgeHubRococoPallet>::EthereumInboundQueue;
// Construct RegisterToken message
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::RegisterToken { token: WETH.into(), fee: XCM_FEE },
});
let (xcm, _) = EthereumInboundQueue::do_convert(message_id_, message).unwrap();
// Convert the message to XCM
let (xcm, _) = EthereumInboundQueue::do_convert(message_id, message).unwrap();
// Send the XCM
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubRococo::para_id().into()).unwrap();

// Construct SendToken message
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::SendToken {
Expand All @@ -349,9 +372,12 @@ fn send_token_from_ethereum_to_asset_hub() {
fee: XCM_FEE,
},
});
let (xcm, _) = EthereumInboundQueue::do_convert(message_id_, message).unwrap();
// Convert the message to XCM
let (xcm, _) = EthereumInboundQueue::do_convert(message_id, message).unwrap();
// Send the XCM
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubRococo::para_id().into()).unwrap();

// Check that the message was sent
assert_expected_events!(
BridgeHubRococo,
vec![
Expand All @@ -363,6 +389,7 @@ fn send_token_from_ethereum_to_asset_hub() {
AssetHubRococo::execute_with(|| {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;

// Check that the token was received and issued as a foreign asset on AssetHub
assert_expected_events!(
AssetHubRococo,
vec![
Expand All @@ -372,6 +399,10 @@ fn send_token_from_ethereum_to_asset_hub() {
});
}

/// 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() {
use asset_hub_rococo_runtime::xcm_config::bridging::to_ethereum::DefaultBridgeHubEthereumBaseFee;
Expand All @@ -391,19 +422,32 @@ fn send_weth_asset_from_asset_hub_to_ethereum() {
AssetHubRococo::fund_accounts(vec![(AssetHubRococoReceiver::get(), INITIAL_FUND)]);

const WETH_AMOUNT: u128 = 1_000_000_000;
let message_id_: H256 = [1; 32].into();
let message_id_register_token: H256 = [1; 32].into();
let message_id_send_token: H256 = [2; 32].into();

BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
type EthereumInboundQueue =
<BridgeHubRococo as BridgeHubRococoPallet>::EthereumInboundQueue;

// Register ERC-20 token on AssetHub
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::RegisterToken { token: WETH.into(), fee: XCM_FEE },
});
let (xcm, _) = EthereumInboundQueue::do_convert(message_id_, message).unwrap();
// Converts the versioned message to XCM
let (xcm, _) = EthereumInboundQueue::do_convert(message_id_register_token, message).unwrap();
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubRococo::para_id().into()).unwrap();

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

// Send ERC-20 token to AssetHub
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::SendToken {
Expand All @@ -413,9 +457,11 @@ fn send_weth_asset_from_asset_hub_to_ethereum() {
fee: XCM_FEE,
},
});
let (xcm, _) = EthereumInboundQueue::do_convert(message_id_, message).unwrap();
// Converts the versioned message to XCM
let (xcm, _) = EthereumInboundQueue::do_convert(message_id_send_token, message).unwrap();
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubRococo::para_id().into()).unwrap();

// Check that the send token message was sent using xcm
assert_expected_events!(
BridgeHubRococo,
vec![
Expand All @@ -428,6 +474,7 @@ fn send_weth_asset_from_asset_hub_to_ethereum() {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
type RuntimeOrigin = <AssetHubRococo as Chain>::RuntimeOrigin;

// Check that AssetHub has issued the foreign asset
assert_expected_events!(
AssetHubRococo,
vec![
Expand Down Expand Up @@ -459,6 +506,7 @@ fn send_weth_asset_from_asset_hub_to_ethereum() {
let free_balance_before = <AssetHubRococo as AssetHubRococoPallet>::Balances::free_balance(
AssetHubRococoReceiver::get(),
);
// Send the Weth back to Ethereum
<AssetHubRococo as AssetHubRococoPallet>::PolkadotXcm::reserve_transfer_assets(
RuntimeOrigin::signed(AssetHubRococoReceiver::get()),
Box::new(destination),
Expand All @@ -470,21 +518,23 @@ fn send_weth_asset_from_asset_hub_to_ethereum() {
let free_balance_after = <AssetHubRococo as AssetHubRococoPallet>::Balances::free_balance(
AssetHubRococoReceiver::get(),
);
// assert at least DefaultBridgeHubEthereumBaseFee charged from the sender
// Assert at least DefaultBridgeHubEthereumBaseFee charged from the sender
let free_balance_diff = free_balance_before - free_balance_after;
assert!(free_balance_diff > DefaultBridgeHubEthereumBaseFee::get());
});

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

// Check that the transfer token back to Ethereum message was queue in the Ethereum
// Outbound Queue
assert_expected_events!(
BridgeHubRococo,
vec![
RuntimeEvent::EthereumOutboundQueue(snowbridge_pallet_outbound_queue::Event::MessageQueued {..}) => {},
]
);
let events = BridgeHubRococo::events();
// Check that the local fee was credited to the Snowbridge sovereign account
assert!(
events.iter().any(|event| matches!(
event,
Expand All @@ -493,6 +543,7 @@ fn send_weth_asset_from_asset_hub_to_ethereum() {
)),
"Snowbridge sovereign takes local fee."
);
// Check that the remote fee was credited to the AssetHub sovereign account
assert!(
events.iter().any(|event| matches!(
event,
Expand Down

0 comments on commit 088a3b0

Please sign in to comment.