1234567891011121314151617#![doc = include_str!("../README.md")]18#![cfg_attr(not(feature = "std"), no_std)]19#![deny(missing_docs)]2021use core::marker::PhantomData;22use fp_evm::WithdrawReason;23use frame_support::traits::IsSubType;24pub use pallet::*;25use pallet_evm::{EnsureAddressOrigin, account::CrossAccountId};26use sp_core::H160;27use sp_runtime::{TransactionOutcome, DispatchError};28use up_sponsorship::SponsorshipHandler;2930#[frame_support::pallet]31pub mod pallet {32 use super::*;3334 use sp_std::vec::Vec;3536 #[pallet::config]37 pub trait Config: frame_system::Config + pallet_evm::account::Config {38 39 type EvmSponsorshipHandler: SponsorshipHandler<Self::CrossAccountId, (H160, Vec<u8>)>;40 }4142 #[pallet::pallet]43 #[pallet::generate_store(pub(super) trait Store)]44 pub struct Pallet<T>(_);45}464748pub struct TransactionValidityHack<T: Config>(PhantomData<*const T>);49impl<T: Config> fp_evm::TransactionValidityHack<T::CrossAccountId> for TransactionValidityHack<T> {50 fn who_pays_fee(origin: H160, reason: &WithdrawReason) -> Option<T::CrossAccountId> {51 match reason {52 WithdrawReason::Call { target, input } => {53 let origin_sub = T::CrossAccountId::from_eth(origin);54 T::EvmSponsorshipHandler::get_sponsor(&origin_sub, &(*target, input.clone()))55 }56 _ => None,57 }58 }59}606162pub struct BridgeSponsorshipHandler<T>(PhantomData<T>);63impl<T, C> SponsorshipHandler<T::AccountId, C> for BridgeSponsorshipHandler<T>64where65 T: Config + pallet_evm::Config,66 C: IsSubType<pallet_evm::Call<T>>,67{68 fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {69 match call.is_sub_type()? {70 pallet_evm::Call::call {71 source,72 target,73 input,74 ..75 } => {76 let _ = T::CallOrigin::ensure_address_origin(77 source,78 <frame_system::RawOrigin<T::AccountId>>::Signed(who.clone()).into(),79 )80 .ok()?;81 let who = T::CrossAccountId::from_sub(who.clone());82 83 84 let sponsor = frame_support::storage::with_transaction(|| {85 TransactionOutcome::Rollback(Ok::<_, DispatchError>(86 T::EvmSponsorshipHandler::get_sponsor(&who, &(*target, input.clone())),87 ))88 })89 90 .ok()??;91 Some(sponsor.as_sub().clone())92 }93 _ => None,94 }95 }96}