1
// Copyright 2019-2025 PureStake Inc.
2
// This file is part of Moonbeam.
3

            
4
// Moonbeam 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
// Moonbeam 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 Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
use crate::xcm_mock::*;
18
use frame_support::assert_ok;
19
use pallet_xcm_transactor::{
20
	Currency, CurrencyPayment, HrmpInitParams, HrmpOperation, TransactWeights,
21
};
22
use sp_std::boxed::Box;
23
use xcm::latest::prelude::{Limited, Location};
24
use xcm_simulator::TestExt;
25

            
26
use cumulus_primitives_core::relay_chain::HrmpChannelId;
27

            
28
#[test]
29
1
fn hrmp_init_accept_through_root() {
30
1
	MockNet::reset();
31
1

            
32
1
	Relay::execute_with(|| {
33
1
		assert_ok!(RelayBalances::transfer_allow_death(
34
1
			relay_chain::RuntimeOrigin::signed(RELAYALICE),
35
1
			para_a_account(),
36
1
			1000u128
37
1
		));
38
1
		assert_ok!(RelayBalances::transfer_allow_death(
39
1
			relay_chain::RuntimeOrigin::signed(RELAYALICE),
40
1
			para_b_account(),
41
1
			1000u128
42
1
		));
43
1
	});
44
1

            
45
1
	ParaA::execute_with(|| {
46
1
		let total_fee = 1_000u128;
47
1
		let total_weight: u64 = 1_000_000_000;
48
1
		let tx_weight: u64 = 500_000_000;
49
1
		// Root can send hrmp init channel
50
1
		assert_ok!(XcmTransactor::hrmp_manage(
51
1
			parachain::RuntimeOrigin::root(),
52
1
			HrmpOperation::InitOpen(HrmpInitParams {
53
1
				para_id: 2u32.into(),
54
1
				proposed_max_capacity: 1,
55
1
				proposed_max_message_size: 1
56
1
			}),
57
1
			CurrencyPayment {
58
1
				currency: Currency::AsMultiLocation(Box::new(xcm::VersionedLocation::from(
59
1
					Location::parent()
60
1
				))),
61
1
				fee_amount: Some(total_fee)
62
1
			},
63
1
			TransactWeights {
64
1
				transact_required_weight_at_most: tx_weight.into(),
65
1
				overall_weight: Some(Limited(total_weight.into()))
66
1
			}
67
1
		));
68
1
	});
69
1
	Relay::execute_with(|| {
70
1
		let expected_event: relay_chain::RuntimeEvent =
71
1
			polkadot_runtime_parachains::hrmp::Event::OpenChannelRequested {
72
1
				sender: 1u32.into(),
73
1
				recipient: 2u32.into(),
74
1
				proposed_max_capacity: 1u32,
75
1
				proposed_max_message_size: 1u32,
76
1
			}
77
1
			.into();
78
1
		assert!(relay_chain::relay_events().contains(&expected_event));
79
1
	});
80
1
	ParaB::execute_with(|| {
81
1
		let total_fee = 1_000u128;
82
1
		let total_weight: u64 = 1_000_000_000;
83
1
		let tx_weight: u64 = 500_000_000;
84
1
		// Root can send hrmp accept channel
85
1
		assert_ok!(XcmTransactor::hrmp_manage(
86
1
			parachain::RuntimeOrigin::root(),
87
1
			HrmpOperation::Accept {
88
1
				para_id: 1u32.into()
89
1
			},
90
1
			CurrencyPayment {
91
1
				currency: Currency::AsMultiLocation(Box::new(xcm::VersionedLocation::from(
92
1
					Location::parent()
93
1
				))),
94
1
				fee_amount: Some(total_fee)
95
1
			},
96
1
			TransactWeights {
97
1
				transact_required_weight_at_most: tx_weight.into(),
98
1
				overall_weight: Some(Limited(total_weight.into()))
99
1
			}
100
1
		));
101
1
	});
102
1

            
103
1
	Relay::execute_with(|| {
104
1
		let expected_event: relay_chain::RuntimeEvent =
105
1
			polkadot_runtime_parachains::hrmp::Event::OpenChannelAccepted {
106
1
				sender: 1u32.into(),
107
1
				recipient: 2u32.into(),
108
1
			}
109
1
			.into();
110
1
		assert!(relay_chain::relay_events().contains(&expected_event));
111
1
	});
112
1
}
113

            
114
#[test]
115
1
fn hrmp_close_works() {
116
1
	MockNet::reset();
117
1

            
118
1
	Relay::execute_with(|| {
119
1
		assert_ok!(RelayBalances::transfer_allow_death(
120
1
			relay_chain::RuntimeOrigin::signed(RELAYALICE),
121
1
			para_a_account(),
122
1
			1000u128
123
1
		));
124
1
		assert_ok!(Hrmp::force_open_hrmp_channel(
125
1
			relay_chain::RuntimeOrigin::root(),
126
1
			1u32.into(),
127
1
			2u32.into(),
128
1
			1u32,
129
1
			1u32
130
1
		));
131
1
		assert_ok!(Hrmp::force_process_hrmp_open(
132
1
			relay_chain::RuntimeOrigin::root(),
133
1
			1u32
134
1
		));
135
1
	});
136
1

            
137
1
	ParaA::execute_with(|| {
138
1
		let total_fee = 1_000u128;
139
1
		let total_weight: u64 = 1_000_000_000;
140
1
		let tx_weight: u64 = 500_000_000;
141
1
		assert_ok!(XcmTransactor::hrmp_manage(
142
1
			parachain::RuntimeOrigin::root(),
143
1
			HrmpOperation::Close(HrmpChannelId {
144
1
				sender: 1u32.into(),
145
1
				recipient: 2u32.into()
146
1
			}),
147
1
			CurrencyPayment {
148
1
				currency: Currency::AsMultiLocation(Box::new(xcm::VersionedLocation::from(
149
1
					Location::parent()
150
1
				))),
151
1
				fee_amount: Some(total_fee)
152
1
			},
153
1
			TransactWeights {
154
1
				transact_required_weight_at_most: tx_weight.into(),
155
1
				overall_weight: Some(Limited(total_weight.into()))
156
1
			}
157
1
		));
158
1
	});
159
1
	Relay::execute_with(|| {
160
1
		let expected_event: relay_chain::RuntimeEvent =
161
1
			polkadot_runtime_parachains::hrmp::Event::ChannelClosed {
162
1
				by_parachain: 1u32.into(),
163
1
				channel_id: HrmpChannelId {
164
1
					sender: 1u32.into(),
165
1
					recipient: 2u32.into(),
166
1
				},
167
1
			}
168
1
			.into();
169
1
		assert!(relay_chain::relay_events().contains(&expected_event));
170
1
	});
171
1
}