1
// Copyright 2019-2022 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 precompile_utils::prelude::*;
23
use sp_core::{H160, U256};
24
use sp_runtime::traits::Dispatchable;
25
use sp_std::{convert::TryFrom, marker::PhantomData};
26
use sp_weights::Weight;
27
use xcm::latest::Location;
28
use xcm_primitives::AccountIdToCurrencyId;
29

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

            
33
47
#[precompile_utils::precompile]
34
impl<Runtime> XcmTransactorPrecompileV3<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
{
44
	#[precompile::public("indexToAccount(uint16)")]
45
	#[precompile::view]
46
	fn index_to_account(handle: &mut impl PrecompileHandle, index: u16) -> EvmResult<Address> {
47
		XcmTransactorWrapper::<Runtime>::account_index(handle, index)
48
	}
49

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

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

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

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

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

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

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