Newer
Older
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use crate::{
mock::*, AssetTraps, CurrentMigration, Error, LatestVersionedMultiLocation, Queries,
QueryStatus, VersionDiscoveryQueue, VersionNotifiers, VersionNotifyTargets,
};
use frame_support::{
assert_noop, assert_ok,
traits::{Currency, Hooks},
use polkadot_parachain::primitives::Id as ParaId;
use sp_runtime::traits::{AccountIdConversion, BlakeTwo256, Hash};
use xcm::prelude::*;
use xcm_builder::AllowKnownQueryResponses;
use xcm_executor::{traits::ShouldExecute, XcmExecutor};
const ALICE: AccountId = AccountId::new([0u8; 32]);
const BOB: AccountId = AccountId::new([1u8; 32]);
const PARA_ID: u32 = 2000;
const INITIAL_BALANCE: u128 = 100;
const SEND_AMOUNT: u128 = 10;
Gavin Wood
committed
#[test]
fn report_outcome_notify_works() {
let balances = vec![
(ALICE, INITIAL_BALANCE),
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
];
Gavin Wood
committed
let sender = AccountId32 { network: AnyNetwork::get(), id: ALICE.into() }.into();
let mut message = Xcm(vec![TransferAsset {
assets: (Here, SEND_AMOUNT).into(),
beneficiary: sender.clone(),
}]);
let call = pallet_test_notifier::Call::notification_received {
query_id: 0,
response: Default::default(),
};
let notify = RuntimeCall::TestNotifier(call);
Gavin Wood
committed
new_test_ext_with_balances(balances).execute_with(|| {
XcmPallet::report_outcome_notify(&mut message, Parachain(PARA_ID).into(), notify, 100)
.unwrap();
Gavin Wood
committed
assert_eq!(
message,
Xcm(vec![
SetAppendix(Xcm(vec![ReportError {
query_id: 0,
dest: Parent.into(),
max_response_weight: 1_000_000
},])),
TransferAsset { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender.clone() },
])
);
let status = QueryStatus::Pending {
responder: MultiLocation::from(Parachain(PARA_ID)).into(),
maybe_notify: Some((4, 2)),
timeout: 100,
};
assert_eq!(crate::Queries::<Test>::iter().collect::<Vec<_>>(), vec![(0, status)]);
let r = XcmExecutor::<XcmConfig>::execute_xcm(
Parachain(PARA_ID).into(),
Xcm(vec![QueryResponse {
query_id: 0,
response: Response::ExecutionResult(None),
Gavin Wood
committed
max_weight: 1_000_000,
}]),
1_000_000_000,
);
assert_eq!(r, Outcome::Complete(1_000));
assert_eq!(
last_events(2),
vec![
RuntimeEvent::TestNotifier(pallet_test_notifier::Event::ResponseReceived(
Gavin Wood
committed
Parachain(PARA_ID).into(),
0,
Response::ExecutionResult(None),
Gavin Wood
committed
)),
RuntimeEvent::XcmPallet(crate::Event::Notified(0, 4, 2)),
Gavin Wood
committed
]
);
assert_eq!(crate::Queries::<Test>::iter().collect::<Vec<_>>(), vec![]);
});
}
#[test]
fn report_outcome_works() {
let balances = vec![
(ALICE, INITIAL_BALANCE),
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
];
Gavin Wood
committed
let sender = AccountId32 { network: AnyNetwork::get(), id: ALICE.into() }.into();
let mut message = Xcm(vec![TransferAsset {
assets: (Here, SEND_AMOUNT).into(),
beneficiary: sender.clone(),
}]);
new_test_ext_with_balances(balances).execute_with(|| {
XcmPallet::report_outcome(&mut message, Parachain(PARA_ID).into(), 100).unwrap();
Gavin Wood
committed
assert_eq!(
message,
Xcm(vec![
SetAppendix(Xcm(vec![ReportError {
query_id: 0,
dest: Parent.into(),
max_response_weight: 0
},])),
TransferAsset { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender.clone() },
])
);
let status = QueryStatus::Pending {
responder: MultiLocation::from(Parachain(PARA_ID)).into(),
maybe_notify: None,
timeout: 100,
};
assert_eq!(crate::Queries::<Test>::iter().collect::<Vec<_>>(), vec![(0, status)]);
let r = XcmExecutor::<XcmConfig>::execute_xcm(
Parachain(PARA_ID).into(),
Xcm(vec![QueryResponse {
query_id: 0,
response: Response::ExecutionResult(None),
Gavin Wood
committed
max_weight: 0,
}]),
1_000_000_000,
);
assert_eq!(r, Outcome::Complete(1_000));
assert_eq!(
last_event(),
RuntimeEvent::XcmPallet(crate::Event::ResponseReady(
0,
Response::ExecutionResult(None),
))
Gavin Wood
committed
);
let response = Some((Response::ExecutionResult(None), 1));
Gavin Wood
committed
assert_eq!(XcmPallet::take_response(0), response);
});
}
/// Test sending an `XCM` message (`XCM::ReserveAssetDeposit`)
///
/// Asserts that the expected message is sent and the event is emitted
#[test]
fn send_works() {
let balances = vec![
(ALICE, INITIAL_BALANCE),
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
];
new_test_ext_with_balances(balances).execute_with(|| {
let sender: MultiLocation =
AccountId32 { network: AnyNetwork::get(), id: ALICE.into() }.into();
Gavin Wood
committed
let message = Xcm(vec![
ReserveAssetDeposited((Parent, SEND_AMOUNT).into()),
ClearOrigin,
buy_execution((Parent, SEND_AMOUNT)),
DepositAsset { assets: All.into(), max_assets: 1, beneficiary: sender.clone() },
]);
let versioned_dest = Box::new(RelayLocation::get().into());
let versioned_message = Box::new(VersionedXcm::from(message.clone()));
assert_ok!(XcmPallet::send(Origin::signed(ALICE), versioned_dest, versioned_message));
assert_eq!(
sent_xcm(),
vec![(
Here.into(),
Gavin Wood
committed
Xcm(Some(DescendOrigin(sender.clone().try_into().unwrap()))
.into_iter()
.chain(message.0.clone().into_iter())
.collect())
)],
RuntimeEvent::XcmPallet(crate::Event::Sent(sender, RelayLocation::get(), message))
);
});
}
/// Test that sending an `XCM` message fails when the `XcmRouter` blocks the
/// matching message format
///
/// Asserts that `send` fails with `Error::SendFailure`
#[test]
fn send_fails_when_xcm_router_blocks() {
let balances = vec![
(ALICE, INITIAL_BALANCE),
(ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE),
Loading full blame...