use crate::{CallOf, Config, Origin, OriginFor};
use codec::{Decode, DecodeWithMemTracking, Encode};
use frame_support::{
pallet_prelude::{InvalidTransaction, TransactionSource},
DebugNoBound, DefaultNoBound,
};
use scale_info::TypeInfo;
use sp_runtime::{
impl_tx_ext_default,
traits::{DispatchInfoOf, TransactionExtension, ValidateResult},
Weight,
};
#[derive(
Encode,
Decode,
DecodeWithMemTracking,
Clone,
Eq,
PartialEq,
DefaultNoBound,
TypeInfo,
DebugNoBound,
)]
#[scale_info(skip_type_params(T))]
pub struct SetOrigin<T: Config + Send + Sync> {
#[codec(skip)]
is_eth_transaction: bool,
_phantom: core::marker::PhantomData<T>,
}
impl<T: Config + Send + Sync> SetOrigin<T> {
pub fn new_from_eth_transaction() -> Self {
Self { is_eth_transaction: true, _phantom: Default::default() }
}
}
impl<T> TransactionExtension<CallOf<T>> for SetOrigin<T>
where
T: Config + Send + Sync,
OriginFor<T>: From<Origin<T>>,
{
const IDENTIFIER: &'static str = "EthSetOrigin";
type Implicit = ();
type Pre = ();
type Val = ();
fn weight(&self, _: &CallOf<T>) -> Weight {
Default::default()
}
fn validate(
&self,
origin: OriginFor<T>,
_call: &CallOf<T>,
_info: &DispatchInfoOf<CallOf<T>>,
_len: usize,
_self_implicit: Self::Implicit,
_inherited_implication: &impl Encode,
_source: TransactionSource,
) -> ValidateResult<Self::Val, CallOf<T>> {
let origin = if self.is_eth_transaction {
let signer =
frame_system::ensure_signed(origin).map_err(|_| InvalidTransaction::BadProof)?;
Origin::EthTransaction(signer).into()
} else {
origin
};
Ok((Default::default(), Default::default(), origin))
}
impl_tx_ext_default!(CallOf<T>; prepare);
}