pallet_xcm_transactor/
encode.rs

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//! # Encode Module
18//!
19//! ## Overview
20//!
21//! Module to provide `StakeEncodeCall`, `HrmpEncodeCall` and `UtilityEncodeCall` implementations
22//! for the Xcm Transactor pallet
23
24use frame_support::pallet_prelude::*;
25use sp_runtime::traits::{AccountIdLookup, StaticLookup};
26use sp_std::prelude::*;
27use xcm_primitives::{
28	AvailableStakeCalls, HrmpAvailableCalls, HrmpEncodeCall, StakeEncodeCall,
29	UtilityAvailableCalls, UtilityEncodeCall, XcmTransact,
30};
31
32pub use crate::pallet::*;
33
34pub use crate::weights::WeightInfo;
35
36impl<T: Config> UtilityEncodeCall for Pallet<T> {
37	fn encode_call<Transactor: XcmTransact>(
38		transactor: Transactor,
39		call: UtilityAvailableCalls,
40	) -> Vec<u8> {
41		let mut encoded_call: Vec<u8> = Vec::new();
42		// pallet index
43		encoded_call.push(transactor.utility_pallet_index());
44
45		match call {
46			UtilityAvailableCalls::AsDerivative(a, b) => {
47				// call index
48				encoded_call.push(RelayIndices::<T>::get().as_derivative);
49				// encoded argument
50				encoded_call.append(&mut a.encode());
51				encoded_call.append(&mut b.clone());
52			}
53		}
54
55		encoded_call
56	}
57}
58
59impl<T: Config> HrmpEncodeCall for Pallet<T> {
60	fn hrmp_encode_call(call: HrmpAvailableCalls) -> Result<Vec<u8>, xcm::latest::Error> {
61		let mut encoded_call: Vec<u8> = Vec::new();
62		// pallet index
63		encoded_call.push(RelayIndices::<T>::get().hrmp);
64
65		match call {
66			HrmpAvailableCalls::InitOpenChannel(a, b, c) => {
67				// call index
68				encoded_call.push(RelayIndices::<T>::get().init_open_channel);
69				// encoded arguments
70				encoded_call.append(&mut a.encode());
71				encoded_call.append(&mut b.encode());
72				encoded_call.append(&mut c.encode());
73			}
74			HrmpAvailableCalls::AcceptOpenChannel(a) => {
75				// call index
76				encoded_call.push(RelayIndices::<T>::get().accept_open_channel);
77				// encoded argument
78				encoded_call.append(&mut a.encode());
79			}
80			HrmpAvailableCalls::CloseChannel(a) => {
81				// call index
82				encoded_call.push(RelayIndices::<T>::get().close_channel);
83				// encoded argument
84				encoded_call.append(&mut a.encode());
85			}
86			HrmpAvailableCalls::CancelOpenRequest(a, b) => {
87				// call index
88				encoded_call.push(RelayIndices::<T>::get().cancel_open_request);
89				// encoded argument
90				encoded_call.append(&mut a.encode());
91				encoded_call.append(&mut b.encode());
92			}
93		}
94
95		Ok(encoded_call)
96	}
97}
98
99fn encode_compact_arg<T: parity_scale_codec::HasCompact>(input: T) -> Vec<u8> {
100	#[derive(Encode)]
101	struct CompactWrapper<T: parity_scale_codec::HasCompact> {
102		#[codec(compact)]
103		input: T,
104	}
105	CompactWrapper { input }.encode()
106}
107
108impl<T: Config> StakeEncodeCall for Pallet<T> {
109	fn encode_call<Transactor: XcmTransact>(
110		transactor: Transactor,
111		call: AvailableStakeCalls,
112	) -> Vec<u8> {
113		let mut encoded_call: Vec<u8> = Vec::new();
114		// pallet index
115		encoded_call.push(transactor.staking_pallet_index());
116
117		match call {
118			AvailableStakeCalls::Bond(b, c) => {
119				// call index
120				encoded_call.push(RelayIndices::<T>::get().bond);
121				// encoded arguments
122				encoded_call.append(&mut encode_compact_arg(b));
123				encoded_call.append(&mut c.encode());
124			}
125			AvailableStakeCalls::BondExtra(a) => {
126				// call index
127				encoded_call.push(RelayIndices::<T>::get().bond_extra);
128				// encoded argument
129				encoded_call.append(&mut encode_compact_arg(a));
130			}
131			AvailableStakeCalls::Unbond(a) => {
132				// call index
133				encoded_call.push(RelayIndices::<T>::get().unbond);
134				// encoded argument
135				encoded_call.append(&mut encode_compact_arg(a));
136			}
137			AvailableStakeCalls::WithdrawUnbonded(a) => {
138				// call index
139				encoded_call.push(RelayIndices::<T>::get().withdraw_unbonded);
140				// encoded argument
141				encoded_call.append(&mut a.encode());
142			}
143			AvailableStakeCalls::Validate(a) => {
144				// call index
145				encoded_call.push(RelayIndices::<T>::get().validate);
146				// encoded argument
147				encoded_call.append(&mut a.encode());
148			}
149			AvailableStakeCalls::Chill => {
150				// call index
151				encoded_call.push(RelayIndices::<T>::get().chill);
152			}
153			AvailableStakeCalls::SetPayee(a) => {
154				// call index
155				encoded_call.push(RelayIndices::<T>::get().set_payee);
156				// encoded argument
157				encoded_call.append(&mut a.encode());
158			}
159			AvailableStakeCalls::SetController => {
160				// call index
161				encoded_call.push(RelayIndices::<T>::get().set_controller);
162			}
163			AvailableStakeCalls::Rebond(a) => {
164				// call index
165				encoded_call.push(RelayIndices::<T>::get().rebond);
166				// encoded argument
167				encoded_call.append(&mut encode_compact_arg(a));
168			}
169			AvailableStakeCalls::Nominate(a) => {
170				// call index
171				encoded_call.push(RelayIndices::<T>::get().nominate);
172				let nominated: Vec<
173					<AccountIdLookup<sp_runtime::AccountId32, ()> as StaticLookup>::Source,
174				> = a.iter().map(|add| (*add).clone().into()).collect();
175				encoded_call.append(&mut nominated.encode());
176			}
177		}
178
179		encoded_call
180	}
181}