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
//! Precompile to xcm transactor runtime methods via the EVM
18

            
19
use crate::functions::{CurrencyIdOf, GetDataLimit, TransactorOf, XcmTransactorWrapper};
20
use fp_evm::PrecompileHandle;
21
use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo};
22
use pallet_evm::AddressMapping;
23
use precompile_utils::prelude::*;
24
use sp_core::{H160, U256};
25
use sp_runtime::traits::Dispatchable;
26
use sp_std::{convert::TryFrom, marker::PhantomData};
27
use sp_weights::Weight;
28
use xcm::latest::Location;
29
use xcm_primitives::AccountIdToCurrencyId;
30

            
31
/// A precompile to wrap the functionality from xcm transactor
32
pub struct XcmTransactorPrecompileV3<Runtime>(PhantomData<Runtime>);
33

            
34
47
#[precompile_utils::precompile]
35
impl<Runtime> XcmTransactorPrecompileV3<Runtime>
36
where
37
	Runtime: pallet_xcm_transactor::Config + pallet_evm::Config + frame_system::Config,
38
	Runtime::RuntimeCall: Dispatchable<PostInfo = PostDispatchInfo> + GetDispatchInfo,
39
	Runtime::RuntimeCall: From<pallet_xcm_transactor::Call<Runtime>>,
40
	<Runtime::RuntimeCall as Dispatchable>::RuntimeOrigin: From<Option<Runtime::AccountId>>,
41
	TransactorOf<Runtime>: TryFrom<u8>,
42
	Runtime::AccountId: Into<H160>,
43
	Runtime: AccountIdToCurrencyId<Runtime::AccountId, CurrencyIdOf<Runtime>>,
44
	<Runtime as pallet_evm::Config>::AddressMapping: AddressMapping<Runtime::AccountId>,
45
{
46
	#[precompile::public("indexToAccount(uint16)")]
47
	#[precompile::view]
48
	fn index_to_account(handle: &mut impl PrecompileHandle, index: u16) -> EvmResult<Address> {
49
		XcmTransactorWrapper::<Runtime>::account_index(handle, index)
50
	}
51

            
52
	#[precompile::public("transactInfoWithSigned((uint8,bytes[]))")]
53
	#[precompile::view]
54
2
	fn transact_info_with_signed(
55
2
		handle: &mut impl PrecompileHandle,
56
2
		location: Location,
57
2
	) -> EvmResult<(Weight, Weight, Weight)> {
58
2
		XcmTransactorWrapper::<Runtime>::transact_info_with_signed_v3(handle, location)
59
2
	}
60

            
61
	#[precompile::public("feePerSecond((uint8,bytes[]))")]
62
	#[precompile::view]
63
	fn fee_per_second(handle: &mut impl PrecompileHandle, location: Location) -> EvmResult<U256> {
64
		XcmTransactorWrapper::<Runtime>::fee_per_second(handle, location)
65
	}
66

            
67
	#[precompile::public(
68
		"transactThroughDerivativeMultilocation(\
69
		uint8,\
70
		uint16,\
71
		(uint8,bytes[]),\
72
		(uint64,uint64),\
73
		bytes,\
74
		uint256,\
75
		(uint64,uint64),\
76
		bool)"
77
	)]
78
1
	fn transact_through_derivative_multilocation(
79
1
		handle: &mut impl PrecompileHandle,
80
1
		transactor: u8,
81
1
		index: u16,
82
1
		fee_asset: Location,
83
1
		weight: Weight,
84
1
		inner_call: BoundedBytes<GetDataLimit>,
85
1
		fee_amount: Convert<U256, u128>,
86
1
		overall_weight: Weight,
87
1
		refund: bool,
88
1
	) -> EvmResult {
89
1
		XcmTransactorWrapper::<Runtime>::transact_through_derivative_multilocation_v3(
90
1
			handle,
91
1
			transactor,
92
1
			index,
93
1
			fee_asset,
94
1
			weight,
95
1
			inner_call,
96
1
			fee_amount.converted(),
97
1
			overall_weight,
98
1
			refund,
99
1
		)
100
1
	}
101

            
102
	#[precompile::public(
103
		"transactThroughDerivative(\
104
		uint8,\
105
		uint16,\
106
		address,\
107
		(uint64,uint64),\
108
		bytes,\
109
		uint256,\
110
		(uint64,uint64),\
111
		bool)"
112
	)]
113
1
	fn transact_through_derivative(
114
1
		handle: &mut impl PrecompileHandle,
115
1
		transactor: u8,
116
1
		index: u16,
117
1
		fee_asset: Address,
118
1
		weight: Weight,
119
1
		inner_call: BoundedBytes<GetDataLimit>,
120
1
		fee_amount: Convert<U256, u128>,
121
1
		overall_weight: Weight,
122
1
		refund: bool,
123
1
	) -> EvmResult {
124
1
		XcmTransactorWrapper::<Runtime>::transact_through_derivative_v3(
125
1
			handle,
126
1
			transactor,
127
1
			index,
128
1
			fee_asset,
129
1
			weight,
130
1
			inner_call,
131
1
			fee_amount.converted(),
132
1
			overall_weight,
133
1
			refund,
134
1
		)
135
1
	}
136

            
137
	#[precompile::public(
138
		"transactThroughSignedMultilocation(\
139
		(uint8,bytes[]),\
140
		(uint8,bytes[]),\
141
		(uint64,uint64),\
142
		bytes,\
143
		uint256,\
144
		(uint64,uint64),\
145
		bool)"
146
	)]
147
1
	fn transact_through_signed_multilocation(
148
1
		handle: &mut impl PrecompileHandle,
149
1
		dest: Location,
150
1
		fee_asset: Location,
151
1
		weight: Weight,
152
1
		call: BoundedBytes<GetDataLimit>,
153
1
		fee_amount: Convert<U256, u128>,
154
1
		overall_weight: Weight,
155
1
		refund: bool,
156
1
	) -> EvmResult {
157
1
		XcmTransactorWrapper::<Runtime>::transact_through_signed_multilocation_v3(
158
1
			handle,
159
1
			dest,
160
1
			fee_asset,
161
1
			weight,
162
1
			call,
163
1
			fee_amount.converted(),
164
1
			overall_weight,
165
1
			refund,
166
1
		)
167
1
	}
168

            
169
	#[precompile::public(
170
		"transactThroughSigned(\
171
		(uint8,bytes[]),\
172
		address,\
173
		(uint64,uint64),\
174
		bytes,\
175
		uint256,\
176
		(uint64,uint64),\
177
		bool)"
178
	)]
179
1
	fn transact_through_signed(
180
1
		handle: &mut impl PrecompileHandle,
181
1
		dest: Location,
182
1
		fee_asset: Address,
183
1
		weight: Weight,
184
1
		call: BoundedBytes<GetDataLimit>,
185
1
		fee_amount: Convert<U256, u128>,
186
1
		overall_weight: Weight,
187
1
		refund: bool,
188
1
	) -> EvmResult {
189
1
		XcmTransactorWrapper::<Runtime>::transact_through_signed_v3(
190
1
			handle,
191
1
			dest,
192
1
			fee_asset,
193
1
			weight,
194
1
			call,
195
1
			fee_amount.converted(),
196
1
			overall_weight,
197
1
			refund,
198
1
		)
199
1
	}
200

            
201
	#[precompile::public("encodeUtilityAsDerivative(uint8,uint16,bytes)")]
202
	#[precompile::public("encode_utility_as_derivative(uint8,uint16,bytes)")]
203
	#[precompile::view]
204
	fn encode_utility_as_derivative(
205
		handle: &mut impl PrecompileHandle,
206
		transactor: u8,
207
		index: u16,
208
		inner_call: BoundedBytes<GetDataLimit>,
209
	) -> EvmResult<UnboundedBytes> {
210
		XcmTransactorWrapper::<Runtime>::encode_utility_as_derivative(
211
			handle, transactor, index, inner_call,
212
		)
213
	}
214
}