referrerpolicy=no-referrer-when-downgrade

pallet_revive/evm/
tx_extension.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Contains transaction extensions needed for ethereum compatability.
19
20use crate::{CallOf, Config, Origin, OriginFor};
21use codec::{Decode, DecodeWithMemTracking, Encode};
22use frame_support::{
23	pallet_prelude::{InvalidTransaction, TransactionSource},
24	DebugNoBound, DefaultNoBound,
25};
26use scale_info::TypeInfo;
27use sp_runtime::{
28	impl_tx_ext_default,
29	traits::{DispatchInfoOf, TransactionExtension, ValidateResult},
30	Weight,
31};
32
33/// An extension that sets the origin to [`Origin::EthTransaction`] in case it originated from an
34/// eth transaction.
35///
36/// This extension needs to be put behind any other extension that relies on a signed origin.
37#[derive(
38	Encode,
39	Decode,
40	DecodeWithMemTracking,
41	Clone,
42	Eq,
43	PartialEq,
44	DefaultNoBound,
45	TypeInfo,
46	DebugNoBound,
47)]
48#[scale_info(skip_type_params(T))]
49pub struct SetOrigin<T: Config + Send + Sync> {
50	/// Skipped as can only be set by runtime code.
51	#[codec(skip)]
52	is_eth_transaction: bool,
53	_phantom: core::marker::PhantomData<T>,
54}
55
56impl<T: Config + Send + Sync> SetOrigin<T> {
57	/// Create the extension so that it will transform the origin.
58	///
59	/// If the extension is default constructed it will do nothing.
60	pub fn new_from_eth_transaction() -> Self {
61		Self { is_eth_transaction: true, _phantom: Default::default() }
62	}
63}
64
65impl<T> TransactionExtension<CallOf<T>> for SetOrigin<T>
66where
67	T: Config + Send + Sync,
68	OriginFor<T>: From<Origin<T>>,
69{
70	const IDENTIFIER: &'static str = "EthSetOrigin";
71	type Implicit = ();
72	type Pre = ();
73	type Val = ();
74
75	fn weight(&self, _: &CallOf<T>) -> Weight {
76		Default::default()
77	}
78
79	fn validate(
80		&self,
81		origin: OriginFor<T>,
82		_call: &CallOf<T>,
83		_info: &DispatchInfoOf<CallOf<T>>,
84		_len: usize,
85		_self_implicit: Self::Implicit,
86		_inherited_implication: &impl Encode,
87		_source: TransactionSource,
88	) -> ValidateResult<Self::Val, CallOf<T>> {
89		let origin = if self.is_eth_transaction {
90			let signer =
91				frame_system::ensure_signed(origin).map_err(|_| InvalidTransaction::BadProof)?;
92			Origin::EthTransaction(signer).into()
93		} else {
94			origin
95		};
96		Ok((Default::default(), Default::default(), origin))
97	}
98
99	impl_tx_ext_default!(CallOf<T>; prepare);
100}