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 {
18
    crate::{
19
        assert_expected_events,
20
        tests::common::xcm::{
21
            mocknets::{
22
                DanceboxPara as Dancebox, DanceboxParaPallet, DanceboxSender,
23
                EthereumSender as FrontierTemplateSender, FrontierTemplatePara as FrontierTemplate,
24
                FrontierTemplateParaPallet, SimpleTemplatePara as SimpleTemplate,
25
                SimpleTemplateParaPallet, SimpleTemplateSender,
26
            },
27
            *,
28
        },
29
    },
30
    frame_support::{assert_ok, traits::EnsureOrigin},
31
    paste::paste,
32
    staging_xcm::{
33
        latest::prelude::{Junctions::X1, *},
34
        VersionedLocation, VersionedXcm,
35
    },
36
    xcm_emulator::Chain,
37
};
38

            
39
#[test]
40
1
fn ump_delivery_fees_charged_dancebox() {
41
1
    let dest = Location::parent();
42
1
    // Send XCM message from Dancebox
43
1
    Dancebox::execute_with(|| {
44
1
        crate::assert_delivery_fees_test!(Dancebox, dest);
45
1
    });
46
1
}
47

            
48
#[test]
49
1
fn ump_delivery_fees_charged_simple_template() {
50
1
    let dest = Location::parent();
51
1

            
52
1
    // Send XCM message from SimpleTemplate
53
1
    SimpleTemplate::execute_with(|| {
54
1
        crate::assert_delivery_fees_test!(SimpleTemplate, dest);
55
1
    });
56
1
}
57

            
58
#[test]
59
1
fn ump_delivery_fees_charged_frontier_template() {
60
1
    let dest = Location::parent();
61
1

            
62
1
    // Send XCM message from FrontierTemplate
63
1
    FrontierTemplate::execute_with(|| {
64
1
        crate::assert_delivery_fees_test!(FrontierTemplate, dest);
65
1
    });
66
1
}
67

            
68
#[test]
69
1
fn hrmp_delivery_fees_charged_dancebox() {
70
1
    let dest = Location::new(1, X1([Parachain(2001)].into()));
71
1
    // Send XCM message from Dancebox
72
1
    Dancebox::execute_with(|| {
73
1
        crate::assert_delivery_fees_test!(Dancebox, dest);
74
1
    });
75
1
}
76

            
77
#[test]
78
1
fn hrmp_delivery_fees_charged_simple_template() {
79
1
    let dest = Location::new(1, X1([Parachain(2000)].into()));
80
1

            
81
1
    // Send XCM message from SimpleTemplate
82
1
    SimpleTemplate::execute_with(|| {
83
1
        crate::assert_delivery_fees_test!(SimpleTemplate, dest);
84
1
    });
85
1
}
86

            
87
#[test]
88
1
fn hrmp_delivery_fees_charged_frontier_template() {
89
1
    let dest = Location::new(1, X1([Parachain(2000)].into()));
90
1

            
91
1
    // Send XCM message from FrontierTemplate
92
1
    FrontierTemplate::execute_with(|| {
93
1
        crate::assert_delivery_fees_test!(FrontierTemplate, dest);
94
1
    });
95
1
}
96

            
97
#[macro_export]
98
macro_rules! assert_delivery_fees_test {
99
    ( $chain:ident, $dest:ident ) => {
100
        paste! {
101
            type RuntimeEvent = <$chain as Chain>::RuntimeEvent;
102
            let xcm = Xcm(vec![
103
                RefundSurplus,
104
            ]);
105

            
106
            let versioned_xcm: VersionedXcm<()> = VersionedXcm::V4(xcm.clone());
107
            let sender_account =  [<$chain Sender>]::get();
108

            
109
            let balance_sender_before = <$chain as [<$chain ParaPallet>]>::Balances::free_balance(sender_account.clone());
110

            
111
            let origin = <$chain as Chain>::RuntimeOrigin::signed(sender_account.clone());
112
            let origin_location = <<$chain as Chain>::Runtime as pallet_xcm::Config>::SendXcmOrigin::ensure_origin(origin.clone()).expect("cannot conver origin into junctions");
113
			let interior: Junctions =
114
				origin_location.clone().try_into().unwrap();
115

            
116
            let final_xcm: Xcm<()> = Xcm(vec![
117
                DescendOrigin(interior),
118
                RefundSurplus,
119
            ]);
120
            let dest: VersionedLocation = $dest.into();
121

            
122
            assert_ok!(<$chain as [<$chain ParaPallet>]>::PolkadotXcm::send(
123
                origin,
124
                bx!(dest),
125
                bx!(versioned_xcm)
126
            ));
127
            let (_, price) = validate_send::<<<$chain as Chain>::Runtime as pallet_xcm::Config>::XcmRouter>(Location::parent(), final_xcm.clone()).unwrap();
128
            let balance_sender_after = <$chain as [<$chain ParaPallet>]>::Balances::free_balance(&sender_account);
129
            assert!(balance_sender_after < balance_sender_before);
130
            // assert there is at least an asset
131
            assert!(!price.is_none());
132

            
133
            assert_expected_events!(
134
                $chain,
135
                vec![
136
                    RuntimeEvent::PolkadotXcm(pallet_xcm::Event::FeesPaid { paying: _, fees }) => {
137
                        fees: *fees == price,
138
                    },
139
                ]
140
            );
141
            // We check the first asset, and make sure we at least have charged the fees
142
            match price.into_inner().first().unwrap().fun {
143
                Fungible(amount) => assert!(balance_sender_after <= balance_sender_before - amount),
144
                _ => panic!("Charged amount should be fungible")
145
            };
146
        }
147
    };
148
}