1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>
16

            
17
use crate::tests::common::xcm::*;
18

            
19
use {
20
    crate::{
21
        assert_expected_events,
22
        tests::common::xcm::mocknets::{
23
            DanceboxPara as Dancebox, FrontierTemplatePara as FrontierTemplate,
24
            FrontierTemplateParaPallet, SimpleTemplatePara as SimpleTemplate,
25
            SimpleTemplateParaPallet, WestendRelay as Westend, WestendRelayPallet,
26
        },
27
    },
28
    frame_support::{
29
        assert_ok,
30
        weights::{Weight, WeightToFee},
31
    },
32
    parity_scale_codec::Encode,
33
    staging_xcm::{
34
        latest::prelude::{Junctions::*, *},
35
        VersionedLocation, VersionedXcm,
36
    },
37
    staging_xcm_builder::{ParentIsPreset, SiblingParachainConvertsVia},
38
    staging_xcm_executor::traits::ConvertLocation,
39
    xcm_emulator::Chain,
40
};
41

            
42
#[test]
43
1
fn transact_sudo_from_relay_hits_barrier_dancebox_without_buy_exec() {
44
1
    let call = <Dancebox as Chain>::RuntimeCall::Configuration(pallet_configuration::Call::<
45
1
        <Dancebox as Chain>::Runtime,
46
1
    >::set_max_collators {
47
1
        new: 50,
48
1
    })
49
1
    .encode()
50
1
    .into();
51
1

            
52
1
    // XcmPallet send arguments
53
1
    let sudo_origin = <Westend as Chain>::RuntimeOrigin::root();
54
1
    let dancebox_para_destination: VersionedLocation =
55
1
        Westend::child_location_of(Dancebox::para_id()).into();
56
1

            
57
1
    let weight_limit = WeightLimit::Unlimited;
58
1
    let require_weight_at_most = Weight::from_parts(1000000000, 200000);
59
1
    let origin_kind = OriginKind::Superuser;
60
1
    let check_origin = None;
61
1

            
62
1
    let xcm = VersionedXcm::from(Xcm(vec![
63
1
        UnpaidExecution {
64
1
            weight_limit,
65
1
            check_origin,
66
1
        },
67
1
        Transact {
68
1
            require_weight_at_most,
69
1
            origin_kind,
70
1
            call,
71
1
        },
72
1
    ]));
73
1

            
74
1
    // Send XCM message from Relay Chain
75
1
    Westend::execute_with(|| {
76
1
        assert_ok!(<Westend as WestendRelayPallet>::XcmPallet::send(
77
1
            sudo_origin,
78
1
            bx!(dancebox_para_destination),
79
1
            bx!(xcm),
80
1
        ));
81

            
82
        type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
83

            
84
1
        assert_expected_events!(
85
            Westend,
86
            vec![
87
1
                RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
88
            ]
89
        );
90
1
    });
91
1

            
92
1
    // Receive XCM message in Assets Parachain
93
1
    Dancebox::execute_with(|| {
94
1
        Dancebox::assert_dmp_queue_error();
95
1
    });
96
1
}
97

            
98
#[test]
99
1
fn transact_sudo_from_relay_does_not_have_sudo_power() {
100
1
    let call = <Dancebox as Chain>::RuntimeCall::Configuration(pallet_configuration::Call::<
101
1
        <Dancebox as Chain>::Runtime,
102
1
    >::set_max_collators {
103
1
        new: 50,
104
1
    })
105
1
    .encode()
106
1
    .into();
107
1

            
108
1
    // XcmPallet send arguments
109
1
    let sudo_origin = <Westend as Chain>::RuntimeOrigin::root();
110
1
    let dancebox_para_destination: VersionedLocation =
111
1
        Westend::child_location_of(Dancebox::para_id()).into();
112
1

            
113
1
    let require_weight_at_most = Weight::from_parts(1000000000, 200000);
114
1
    let origin_kind = OriginKind::Superuser;
115
1

            
116
1
    let buy_execution_fee_amount =
117
1
        crate::WeightToFee::weight_to_fee(&Weight::from_parts(10_000_000_000, 300_000));
118
1

            
119
1
    let buy_execution_fee = Asset {
120
1
        id: crate::xcm_config::SelfReserve::get().into(),
121
1
        fun: Fungible(buy_execution_fee_amount),
122
1
    };
123
1

            
124
1
    let xcm = VersionedXcm::from(Xcm(vec![
125
1
        WithdrawAsset(vec![buy_execution_fee.clone()].into()),
126
1
        BuyExecution {
127
1
            fees: buy_execution_fee.clone(),
128
1
            weight_limit: Unlimited,
129
1
        },
130
1
        Transact {
131
1
            require_weight_at_most,
132
1
            origin_kind,
133
1
            call,
134
1
        },
135
1
    ]));
136
1

            
137
1
    // Send XCM message from Relay Chain
138
1
    Westend::execute_with(|| {
139
1
        assert_ok!(<Westend as WestendRelayPallet>::XcmPallet::send(
140
1
            sudo_origin,
141
1
            bx!(dancebox_para_destination),
142
1
            bx!(xcm),
143
1
        ));
144

            
145
        type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
146

            
147
1
        assert_expected_events!(
148
            Westend,
149
            vec![
150
1
                RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
151
            ]
152
        );
153
1
    });
154
1

            
155
1
    // Receive XCM message in Assets Parachain
156
1
    Dancebox::execute_with(|| {
157
1
        Dancebox::assert_dmp_queue_incomplete(None);
158
1
    });
159
1
}
160

            
161
#[test]
162
1
fn transact_sudo_from_relay_has_signed_origin_powers() {
163
1
    let call = <Dancebox as Chain>::RuntimeCall::System(frame_system::Call::<
164
1
        <Dancebox as Chain>::Runtime,
165
1
    >::remark_with_event {
166
1
        remark: b"Test".to_vec(),
167
1
    })
168
1
    .encode()
169
1
    .into();
170
1

            
171
1
    // XcmPallet send arguments
172
1
    let sudo_origin = <Westend as Chain>::RuntimeOrigin::root();
173
1
    let dancebox_para_destination: VersionedLocation =
174
1
        Westend::child_location_of(Dancebox::para_id()).into();
175
1

            
176
1
    let require_weight_at_most = Weight::from_parts(1000000000, 200000);
177
1
    let origin_kind = OriginKind::SovereignAccount;
178
1

            
179
1
    let buy_execution_fee_amount =
180
1
        crate::WeightToFee::weight_to_fee(&Weight::from_parts(10_000_000_000_000, 300_000));
181
1

            
182
1
    let buy_execution_fee = Asset {
183
1
        id: crate::xcm_config::SelfReserve::get().into(),
184
1
        fun: Fungible(buy_execution_fee_amount),
185
1
    };
186
1

            
187
1
    let xcm = VersionedXcm::from(Xcm(vec![
188
1
        WithdrawAsset(vec![buy_execution_fee.clone()].into()),
189
1
        BuyExecution {
190
1
            fees: buy_execution_fee.clone(),
191
1
            weight_limit: Unlimited,
192
1
        },
193
1
        Transact {
194
1
            require_weight_at_most,
195
1
            origin_kind,
196
1
            call,
197
1
        },
198
1
    ]));
199
1

            
200
1
    // Send XCM message from Relay Chain
201
1
    Westend::execute_with(|| {
202
1
        assert_ok!(<Westend as WestendRelayPallet>::XcmPallet::send(
203
1
            sudo_origin,
204
1
            bx!(dancebox_para_destination),
205
1
            bx!(xcm),
206
1
        ));
207

            
208
        type RuntimeEvent = <Westend as Chain>::RuntimeEvent;
209

            
210
1
        assert_expected_events!(
211
            Westend,
212
            vec![
213
1
                RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
214
            ]
215
        );
216
1
    });
217
1

            
218
1
    // Receive XCM message in Assets Parachain
219
1
    Dancebox::execute_with(|| {
220
        type RuntimeEvent = <Dancebox as Chain>::RuntimeEvent;
221
1
        assert_expected_events!(
222
            Dancebox,
223
            vec![
224
1
                RuntimeEvent::System(
225
1
                    frame_system::Event::Remarked {
226
1
                        sender,
227
1
                        ..
228
1
                    }) => {
229
1
                    sender: *sender == ParentIsPreset::<crate::AccountId>::convert_location(&Location::parent()).unwrap(),
230
                },
231
            ]
232
        );
233
1
    });
234
1
}
235

            
236
#[test]
237
1
fn transact_sudo_from_frontier_has_signed_origin_powers() {
238
1
    let call = <Dancebox as Chain>::RuntimeCall::System(frame_system::Call::<
239
1
        <Dancebox as Chain>::Runtime,
240
1
    >::remark_with_event {
241
1
        remark: b"Test".to_vec(),
242
1
    })
243
1
    .encode()
244
1
    .into();
245
1

            
246
1
    // XcmPallet send arguments
247
1
    let sudo_origin = <FrontierTemplate as Chain>::RuntimeOrigin::root();
248
1
    let dancebox_para_destination: VersionedLocation = Location {
249
1
        parents: 1,
250
1
        interior: X1([Parachain(Dancebox::para_id().into())].into()),
251
1
    }
252
1
    .into();
253
1

            
254
1
    let require_weight_at_most = Weight::from_parts(1000000000, 200000);
255
1
    let origin_kind = OriginKind::SovereignAccount;
256
1

            
257
1
    let buy_execution_fee_amount =
258
1
        crate::WeightToFee::weight_to_fee(&Weight::from_parts(10_000_000_000_000, 300_000));
259
1

            
260
1
    let buy_execution_fee = Asset {
261
1
        id: crate::xcm_config::SelfReserve::get().into(),
262
1
        fun: Fungible(buy_execution_fee_amount),
263
1
    };
264
1

            
265
1
    let xcm = VersionedXcm::from(Xcm(vec![
266
1
        WithdrawAsset(vec![buy_execution_fee.clone()].into()),
267
1
        BuyExecution {
268
1
            fees: buy_execution_fee.clone(),
269
1
            weight_limit: Unlimited,
270
1
        },
271
1
        Transact {
272
1
            require_weight_at_most,
273
1
            origin_kind,
274
1
            call,
275
1
        },
276
1
    ]));
277
1

            
278
1
    // Send XCM message from Frontier Template
279
1
    FrontierTemplate::execute_with(|| {
280
1
        assert_ok!(
281
1
            <FrontierTemplate as FrontierTemplateParaPallet>::PolkadotXcm::send(
282
1
                sudo_origin,
283
1
                bx!(dancebox_para_destination),
284
1
                bx!(xcm),
285
1
            )
286
1
        );
287

            
288
        type RuntimeEvent = <FrontierTemplate as Chain>::RuntimeEvent;
289

            
290
1
        assert_expected_events!(
291
            FrontierTemplate,
292
            vec![
293
1
                RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {},
294
            ]
295
        );
296
1
    });
297
1

            
298
1
    // Receive XCM message in Assets Parachain
299
1
    Dancebox::execute_with(|| {
300
        type RuntimeEvent = <Dancebox as Chain>::RuntimeEvent;
301
1
        assert_expected_events!(
302
            Dancebox,
303
            vec![
304
1
                RuntimeEvent::System(
305
1
                    frame_system::Event::Remarked {
306
1
                        sender,
307
1
                        ..
308
1
                    }) => {
309
1
                    sender: *sender ==  SiblingParachainConvertsVia::<polkadot_parachain_primitives::primitives::Sibling, crate::AccountId>::convert_location(
310
1
                        &Location{ parents: 1, interior: X1([Parachain(2001u32)].into())}
311
1
                    ).unwrap(),
312
                },
313
            ]
314
        );
315
1
    });
316
1
}
317

            
318
#[test]
319
1
fn transact_sudo_from_simple_has_signed_origin_powers() {
320
1
    let call = <Dancebox as Chain>::RuntimeCall::System(frame_system::Call::<
321
1
        <Dancebox as Chain>::Runtime,
322
1
    >::remark_with_event {
323
1
        remark: b"Test".to_vec(),
324
1
    })
325
1
    .encode()
326
1
    .into();
327
1

            
328
1
    // XcmPallet send arguments
329
1
    let sudo_origin = <SimpleTemplate as Chain>::RuntimeOrigin::root();
330
1
    let dancebox_para_destination: VersionedLocation = Location {
331
1
        parents: 1,
332
1
        interior: X1([Parachain(Dancebox::para_id().into())].into()),
333
1
    }
334
1
    .into();
335
1

            
336
1
    let require_weight_at_most = Weight::from_parts(1000000000, 200000);
337
1
    let origin_kind = OriginKind::SovereignAccount;
338
1

            
339
1
    let buy_execution_fee_amount =
340
1
        crate::WeightToFee::weight_to_fee(&Weight::from_parts(10_000_000_000_000, 300_000));
341
1

            
342
1
    let buy_execution_fee = Asset {
343
1
        id: crate::xcm_config::SelfReserve::get().into(),
344
1
        fun: Fungible(buy_execution_fee_amount),
345
1
    };
346
1

            
347
1
    let xcm = VersionedXcm::from(Xcm(vec![
348
1
        WithdrawAsset(vec![buy_execution_fee.clone()].into()),
349
1
        BuyExecution {
350
1
            fees: buy_execution_fee.clone(),
351
1
            weight_limit: Unlimited,
352
1
        },
353
1
        Transact {
354
1
            require_weight_at_most,
355
1
            origin_kind,
356
1
            call,
357
1
        },
358
1
    ]));
359
1

            
360
1
    // Send XCM message from Relay Chain
361
1
    SimpleTemplate::execute_with(|| {
362
1
        assert_ok!(
363
1
            <SimpleTemplate as SimpleTemplateParaPallet>::PolkadotXcm::send(
364
1
                sudo_origin,
365
1
                bx!(dancebox_para_destination),
366
1
                bx!(xcm),
367
1
            )
368
1
        );
369

            
370
        type RuntimeEvent = <SimpleTemplate as Chain>::RuntimeEvent;
371

            
372
1
        assert_expected_events!(
373
            SimpleTemplate,
374
            vec![
375
1
                RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {},
376
            ]
377
        );
378
1
    });
379
1

            
380
1
    // Receive XCM message in Assets Parachain
381
1
    Dancebox::execute_with(|| {
382
        type RuntimeEvent = <Dancebox as Chain>::RuntimeEvent;
383
1
        assert_expected_events!(
384
            Dancebox,
385
            vec![
386
1
                RuntimeEvent::System(
387
1
                    frame_system::Event::Remarked {
388
1
                        sender,
389
1
                        ..
390
1
                    }) => {
391
1
                    sender: *sender ==  SiblingParachainConvertsVia::<polkadot_parachain_primitives::primitives::Sibling, crate::AccountId>::convert_location(
392
1
                        &Location{ parents: 1, interior: X1([Parachain(2002u32)].into())}
393
1
                    ).unwrap(),
394
                },
395
            ]
396
        );
397
1
    });
398
1
}