1#![cfg_attr(not(feature = "std"), no_std)]23pub use pallet::*;45#[frame_support::pallet]6pub mod pallet {7 use core::marker::PhantomData;8 use frame_support::traits::Currency;9 use pallet_evm::EVMCurrencyAdapter;10 use fp_evm::WithdrawReason;11 use sp_core::{H160, U256};12 use sp_runtime::TransactionOutcome;13 use up_sponsorship::SponsorshipHandler;14 use sp_std::vec::Vec;1516 type NegativeImbalanceOf<C, T> =17 <C as Currency<<T as frame_system::Config>::AccountId>>::NegativeImbalance;1819 #[pallet::config]20 pub trait Config: frame_system::Config {21 type SponsorshipHandler: SponsorshipHandler<H160, (H160, Vec<u8>)>;22 type Currency: Currency<Self::AccountId>;23 }2425 #[pallet::pallet]26 #[pallet::generate_store(pub(super) trait Store)]27 pub struct Pallet<T>(_);2829 pub struct ChargeEvmLiquidityInfo<T>30 where31 T: Config,32 T: pallet_evm::Config,33 {34 who: H160,35 negative_imbalance: NegativeImbalanceOf<<T as Config>::Currency, T>,36 }3738 pub struct TransactionValidityHack<T: Config>(PhantomData<*const T>);39 impl<T: Config> fp_evm::TransactionValidityHack for TransactionValidityHack<T> {40 fn who_pays_fee(origin: H160, reason: &WithdrawReason) -> Option<H160> {41 match reason {42 WithdrawReason::Call { target, input } => {43 44 frame_support::storage::with_transaction(|| {45 TransactionOutcome::Rollback(T::SponsorshipHandler::get_sponsor(46 &origin,47 &(*target, input.clone()),48 ))49 })50 }51 _ => None,52 }53 }54 }5556 pub struct OnChargeTransaction<T: Config>(PhantomData<*const T>);57 impl<T> pallet_evm::OnChargeEVMTransaction<T> for OnChargeTransaction<T>58 where59 T: Config,60 T: pallet_evm::Config,61 {62 type LiquidityInfo = Option<ChargeEvmLiquidityInfo<T>>;6364 fn withdraw_fee(65 who: &H160,66 reason: WithdrawReason,67 fee: U256,68 ) -> core::result::Result<Self::LiquidityInfo, pallet_evm::Error<T>> {69 let mut who_pays_fee = *who;70 if let WithdrawReason::Call { target, input } = &reason {71 who_pays_fee = T::SponsorshipHandler::get_sponsor(who, &(*target, input.clone()))72 .unwrap_or(who_pays_fee);73 }74 let negative_imbalance =75 EVMCurrencyAdapter::<<T as Config>::Currency, ()>::withdraw_fee(76 &who_pays_fee,77 reason,78 fee,79 )?;80 Ok(negative_imbalance.map(|i| ChargeEvmLiquidityInfo {81 who: who_pays_fee,82 negative_imbalance: i,83 }))84 }8586 fn correct_and_deposit_fee(87 who: &H160,88 corrected_fee: U256,89 already_withdrawn: Self::LiquidityInfo,90 ) {91 <EVMCurrencyAdapter<<T as Config>::Currency, ()> as pallet_evm::OnChargeEVMTransaction<T>>::correct_and_deposit_fee(92 &already_withdrawn.as_ref().map(|e| e.who).unwrap_or(*who),93 corrected_fee,94 already_withdrawn.map(|e| e.negative_imbalance),95 )96 }97 }98}