Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
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
135 changes: 127 additions & 8 deletions xcm/xcm-simulator/example/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
mod parachain;
mod relay_chain;

use polkadot_parachain::primitives::Id as ParaId;
use sp_runtime::traits::AccountIdConversion;
use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain};

pub const ALICE: sp_runtime::AccountId32 = sp_runtime::AccountId32::new([0u8; 32]);
pub const INITIAL_BALANCE: u128 = 1_000_000_000;

decl_test_parachain! {
pub struct ParaA {
Expand Down Expand Up @@ -57,7 +60,9 @@ decl_test_network! {
}
}

pub const INITIAL_BALANCE: u128 = 1_000_000_000;
pub fn para_account_id(id: u32) -> relay_chain::AccountId {
ParaId::from(id).into_account()
}

pub fn para_ext(para_id: u32) -> sp_io::TestExternalities {
use parachain::{MsgQueue, Runtime, System};
Expand All @@ -81,9 +86,11 @@ pub fn relay_ext() -> sp_io::TestExternalities {

let mut t = frame_system::GenesisConfig::default().build_storage::<Runtime>().unwrap();

pallet_balances::GenesisConfig::<Runtime> { balances: vec![(ALICE, INITIAL_BALANCE)] }
.assimilate_storage(&mut t)
.unwrap();
pallet_balances::GenesisConfig::<Runtime> {
balances: vec![(ALICE, INITIAL_BALANCE), (para_account_id(1), INITIAL_BALANCE)],
}
.assimilate_storage(&mut t)
.unwrap();

let mut ext = sp_io::TestExternalities::new(t);
ext.execute_with(|| System::set_block_number(1));
Expand All @@ -98,10 +105,21 @@ mod tests {
use super::*;

use codec::Encode;
use frame_support::assert_ok;
use frame_support::{assert_ok, weights::Weight};
use xcm::latest::prelude::*;
use xcm_simulator::TestExt;

// Helper function for forming buy execution message
fn buy_execution<C>(fees: impl Into<MultiAsset>, debt: Weight) -> Order<C> {
Order::BuyExecution {
fees: fees.into(),
weight: 0,
debt,
halt_on_error: false,
instructions: vec![],
}
}

#[test]
fn dmp() {
MockNet::reset();
Expand Down Expand Up @@ -187,22 +205,123 @@ mod tests {
fn reserve_transfer() {
MockNet::reset();

let withdraw_amount = 123;
let max_weight_for_execution = 3;

Relay::execute_with(|| {
assert_ok!(RelayChainPalletXcm::reserve_transfer_assets(
relay_chain::Origin::signed(ALICE),
Box::new(X1(Parachain(1)).into()),
Box::new(X1(AccountId32 { network: Any, id: ALICE.into() }).into()),
(Here, 123).into(),
(Here, withdraw_amount).into(),
0,
3,
max_weight_for_execution,
));
assert_eq!(
parachain::Balances::free_balance(&para_account_id(1)),
INITIAL_BALANCE + withdraw_amount
);
});

ParaA::execute_with(|| {
// free execution, full amount received
assert_eq!(
pallet_balances::Pallet::<parachain::Runtime>::free_balance(&ALICE),
INITIAL_BALANCE + 123
INITIAL_BALANCE + withdraw_amount
);
});
}

/// Scenario:
/// A parachain transfers funds on the relay chain to another parachain account.
///
/// Asserts that the parachain accounts are updated as expected.
#[test]
fn withdraw_and_deposit() {
MockNet::reset();

let send_amount = 10;
let weight_for_execution = 3 * relay_chain::BaseXcmWeight::get();

ParaA::execute_with(|| {
let message = WithdrawAsset {
assets: (Here, send_amount).into(),
effects: vec![
buy_execution((Here, send_amount), weight_for_execution),
Order::DepositAsset {
assets: All.into(),
max_assets: 1,
beneficiary: Parachain(2).into(),
},
],
};
// Send withdraw and deposit
assert_ok!(ParachainPalletXcm::send_xcm(Here, Parent.into(), message.clone()));
});

Relay::execute_with(|| {
assert_eq!(
relay_chain::Balances::free_balance(para_account_id(1)),
INITIAL_BALANCE - send_amount
);
assert_eq!(relay_chain::Balances::free_balance(para_account_id(2)), send_amount);
});
}

/// Scenario:
/// A parachain wants to be notified that a transfer worked correctly.
/// It sends a `QueryHolding` after the deposit to get notified on success.
///
/// Asserts that the balances are updated correctly and the expected XCM is sent.
#[test]
fn query_holding() {
MockNet::reset();

let send_amount = 10;
let weight_for_execution = 3 * relay_chain::BaseXcmWeight::get();
let query_id_set = 1234;

// Send a message which fully succeeds on the relay chain
ParaA::execute_with(|| {
let message = WithdrawAsset {
assets: (Here, send_amount).into(),
effects: vec![
buy_execution((Here, send_amount), weight_for_execution),
Order::DepositAsset {
assets: All.into(),
max_assets: 1,
beneficiary: Parachain(2).into(),
},
Order::QueryHolding {
query_id: query_id_set,
dest: Parachain(1).into(),
assets: All.into(),
},
],
};
// Send withdraw and deposit with query holding
assert_ok!(ParachainPalletXcm::send_xcm(Here, Parent.into(), message.clone(),));
});

// Check that transfer was executed
Relay::execute_with(|| {
// Withdraw executed
assert_eq!(
relay_chain::Balances::free_balance(para_account_id(1)),
INITIAL_BALANCE - send_amount
);
// Deposit executed
assert_eq!(relay_chain::Balances::free_balance(para_account_id(2)), send_amount);
});

// Check that QueryResponse message was received
ParaA::execute_with(|| {
assert_eq!(
parachain::MsgQueue::received_dmp(),
vec![QueryResponse {
query_id: query_id_set,
response: Response::Assets(MultiAssets::new())
}]
);
});
}
Expand Down
8 changes: 7 additions & 1 deletion xcm/xcm-simulator/example/src/parachain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ pub mod mock_msg_queue {
#[pallet::getter(fn parachain_id)]
pub(super) type ParachainId<T: Config> = StorageValue<_, ParaId, ValueQuery>;

#[pallet::storage]
#[pallet::getter(fn received_dmp)]
/// A queue of received DMP messages
pub(super) type ReceivedDmp<T: Config> = StorageValue<_, Vec<Xcm<T::Call>>, ValueQuery>;

impl<T: Config> Get<ParaId> for Pallet<T> {
fn get() -> ParaId {
Self::parachain_id()
Expand Down Expand Up @@ -266,7 +271,8 @@ pub mod mock_msg_queue {
Self::deposit_event(Event::UnsupportedVersion(id));
},
Ok(Ok(x)) => {
let outcome = T::XcmExecutor::execute_xcm(Parent.into(), x, limit);
let outcome = T::XcmExecutor::execute_xcm(Parent.into(), x.clone(), limit);
<ReceivedDmp<T>>::append(x);
Self::deposit_event(Event::ExecutedDownward(id, outcome));
},
}
Expand Down
Loading