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
3
#[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
	TransactorOf<Runtime>: TryFrom<u8>,
41
	Runtime::AccountId: Into<H160>,
42
	Runtime: AccountIdToCurrencyId<Runtime::AccountId, CurrencyIdOf<Runtime>>,
43
	<Runtime as pallet_evm::Config>::AddressMapping: AddressMapping<Runtime::AccountId>,
44
{
45
	#[precompile::public("indexToAccount(uint16)")]
46
	#[precompile::view]
47
	fn index_to_account(handle: &mut impl PrecompileHandle, index: u16) -> EvmResult<Address> {
48
		XcmTransactorWrapper::<Runtime>::account_index(handle, index)
49
	}
50

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

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

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

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

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

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

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