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::{account::CrossAccountId, EnsureAddressOrigin, FeeCalculator};26use sp_core::{H160, U256};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>), u128>;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(51 origin: H160,52 max_fee: U256,53 reason: &WithdrawReason,54 ) -> Option<T::CrossAccountId> {55 match reason {56 WithdrawReason::Call { target, input } => {57 let origin_sub = T::CrossAccountId::from_eth(origin);58 T::EvmSponsorshipHandler::get_sponsor(59 &origin_sub,60 &(*target, input.clone()),61 &max_fee.as_u128(),62 )63 }64 _ => None,65 }66 }67}686970pub struct BridgeSponsorshipHandler<T>(PhantomData<T>);71impl<T, C> SponsorshipHandler<T::AccountId, C, u128> for BridgeSponsorshipHandler<T>72where73 T: Config + pallet_evm::Config,74 C: IsSubType<pallet_evm::Call<T>>,75{76 fn get_sponsor(who: &T::AccountId, call: &C, _fee_limit: &u128) -> Option<T::AccountId> {77 match call.is_sub_type()? {78 pallet_evm::Call::call {79 source,80 target,81 input,82 gas_limit,83 max_fee_per_gas,84 ..85 } => {86 let _ = T::CallOrigin::ensure_address_origin(87 source,88 <frame_system::RawOrigin<T::AccountId>>::Signed(who.clone()).into(),89 )90 .ok()?;91 let who = T::CrossAccountId::from_sub(who.clone());92 let max_fee = max_fee_per_gas.saturating_mul((*gas_limit).into());93 94 95 let sponsor = frame_support::storage::with_transaction(|| {96 TransactionOutcome::Rollback(Ok::<_, DispatchError>(97 T::EvmSponsorshipHandler::get_sponsor(98 &who,99 &(*target, input.clone()),100 &max_fee.try_into().unwrap(),101 ),102 ))103 })104 105 .ok()??;106 Some(sponsor.as_sub().clone())107 }108 _ => None,109 }110 }111}