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 xcm::latest::Location;
28
use xcm_primitives::AccountIdToCurrencyId;
29

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

            
33
124
#[precompile_utils::precompile]
34
impl<Runtime> XcmTransactorPrecompileV2<Runtime>
35
where
36
	Runtime: pallet_xcm_transactor::Config + pallet_evm::Config + frame_system::Config,
37
	Runtime::RuntimeCall: Dispatchable<PostInfo = PostDispatchInfo> + GetDispatchInfo,
38
	Runtime::RuntimeCall: From<pallet_xcm_transactor::Call<Runtime>>,
39
	<Runtime::RuntimeCall as Dispatchable>::RuntimeOrigin: From<Option<Runtime::AccountId>>,
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
	fn transact_info_with_signed(
54
		handle: &mut impl PrecompileHandle,
55
		location: Location,
56
	) -> EvmResult<(u64, u64, u64)> {
57
		XcmTransactorWrapper::<Runtime>::transact_info_with_signed(handle, location)
58
	}
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,bytes,\
72
		uint256,\
73
		uint64)"
74
	)]
75
1
	fn transact_through_derivative_multilocation(
76
1
		handle: &mut impl PrecompileHandle,
77
1
		transactor: u8,
78
1
		index: u16,
79
1
		fee_asset: Location,
80
1
		weight: u64,
81
1
		inner_call: BoundedBytes<GetDataLimit>,
82
1
		fee_amount: Convert<U256, u128>,
83
1
		overall_weight: u64,
84
1
	) -> EvmResult {
85
1
		XcmTransactorWrapper::<Runtime>::transact_through_derivative_multilocation_fee_weight(
86
1
			handle,
87
1
			transactor,
88
1
			index,
89
1
			fee_asset,
90
1
			weight,
91
1
			inner_call,
92
1
			fee_amount.converted(),
93
1
			overall_weight,
94
1
		)
95
1
	}
96

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

            
129
	#[precompile::public(
130
		"transactThroughSignedMultilocation(\
131
		(uint8,bytes[]),\
132
		(uint8,bytes[]),\
133
		uint64,\
134
		bytes,\
135
		uint256,\
136
		uint64)"
137
	)]
138
7
	fn transact_through_signed_multilocation(
139
7
		handle: &mut impl PrecompileHandle,
140
7
		dest: Location,
141
7
		fee_asset: Location,
142
7
		weight: u64,
143
7
		call: BoundedBytes<GetDataLimit>,
144
7
		fee_amount: Convert<U256, u128>,
145
7
		overall_weight: u64,
146
7
	) -> EvmResult {
147
7
		XcmTransactorWrapper::<Runtime>::transact_through_signed_multilocation_fee_weight(
148
7
			handle,
149
7
			dest,
150
7
			fee_asset,
151
7
			weight,
152
7
			call,
153
7
			fee_amount.converted(),
154
7
			overall_weight,
155
7
		)
156
7
	}
157

            
158
	#[precompile::public(
159
		"transactThroughSigned((uint8,bytes[]),address,uint64,bytes,uint256,uint64)"
160
	)]
161
1
	fn transact_through_signed(
162
1
		handle: &mut impl PrecompileHandle,
163
1
		dest: Location,
164
1
		fee_asset: Address,
165
1
		weight: u64,
166
1
		call: BoundedBytes<GetDataLimit>,
167
1
		fee_amount: Convert<U256, u128>,
168
1
		overall_weight: u64,
169
1
	) -> EvmResult {
170
1
		XcmTransactorWrapper::<Runtime>::transact_through_signed_fee_weight(
171
1
			handle,
172
1
			dest,
173
1
			fee_asset,
174
1
			weight,
175
1
			call,
176
1
			fee_amount.converted(),
177
1
			overall_weight,
178
1
		)
179
1
	}
180

            
181
	#[precompile::public("encodeUtilityAsDerivative(uint8,uint16,bytes)")]
182
	#[precompile::public("encode_utility_as_derivative(uint8,uint16,bytes)")]
183
	#[precompile::view]
184
	fn encode_utility_as_derivative(
185
		handle: &mut impl PrecompileHandle,
186
		transactor: u8,
187
		index: u16,
188
		inner_call: BoundedBytes<GetDataLimit>,
189
	) -> EvmResult<UnboundedBytes> {
190
		XcmTransactorWrapper::<Runtime>::encode_utility_as_derivative(
191
			handle, transactor, index, inner_call,
192
		)
193
	}
194
}