git.delta.rocks / unique-network / refs/commits / b3ebe07cdd5d

difftreelog

source

pallets/evm-transaction-payment/src/lib.rs4.3 KiBsourcehistory
1#![cfg_attr(not(feature = "std"), no_std)]23use core::marker::PhantomData;4use fp_evm::WithdrawReason;5use frame_support::traits::{Currency, IsSubType};6pub use pallet::*;7use pallet_evm::{EVMCurrencyAdapter, EnsureAddressOrigin};8use sp_core::{H160, U256};9use sp_runtime::TransactionOutcome;10use up_sponsorship::SponsorshipHandler;11use up_evm_mapping::EvmBackwardsAddressMapping;12use pallet_evm::AddressMapping;1314#[frame_support::pallet]15pub mod pallet {16	use super::*;1718	use frame_support::traits::Currency;19	use sp_std::vec::Vec;2021	#[pallet::config]22	pub trait Config: frame_system::Config {23		type EvmSponsorshipHandler: SponsorshipHandler<H160, (H160, Vec<u8>)>;24		type Currency: Currency<Self::AccountId>;25		type EvmBackwardsAddressMapping: EvmBackwardsAddressMapping<Self::AccountId>;26		type EvmAddressMapping: AddressMapping<Self::AccountId>;27	}2829	#[pallet::pallet]30	#[pallet::generate_store(pub(super) trait Store)]31	pub struct Pallet<T>(_);32}3334type NegativeImbalanceOf<C, T> =35	<C as Currency<<T as frame_system::Config>::AccountId>>::NegativeImbalance;3637pub struct ChargeEvmLiquidityInfo<T>38where39	T: Config,40	T: pallet_evm::Config,41{42	who: H160,43	negative_imbalance: NegativeImbalanceOf<<T as Config>::Currency, T>,44}4546pub struct TransactionValidityHack<T: Config>(PhantomData<*const T>);47impl<T: Config> fp_evm::TransactionValidityHack for TransactionValidityHack<T> {48	fn who_pays_fee(origin: H160, reason: &WithdrawReason) -> Option<H160> {49		match reason {50			WithdrawReason::Call { target, input } => {51				// This method is only used for checking, we shouldn't touch storage in it52				frame_support::storage::with_transaction(|| {53					TransactionOutcome::Rollback(T::EvmSponsorshipHandler::get_sponsor(54						&origin,55						&(*target, input.clone()),56					))57				})58			}59			_ => None,60		}61	}62}63pub struct OnChargeTransaction<T: Config>(PhantomData<*const T>);64impl<T> pallet_evm::OnChargeEVMTransaction<T> for OnChargeTransaction<T>65where66	T: Config,67	T: pallet_evm::Config,68{69	type LiquidityInfo = Option<ChargeEvmLiquidityInfo<T>>;7071	fn withdraw_fee(72		who: &H160,73		reason: WithdrawReason,74		fee: U256,75	) -> core::result::Result<Self::LiquidityInfo, pallet_evm::Error<T>> {76		let mut who_pays_fee = *who;77		if let WithdrawReason::Call { target, input } = &reason {78			who_pays_fee = T::EvmSponsorshipHandler::get_sponsor(who, &(*target, input.clone()))79				.unwrap_or(who_pays_fee);80		}81		let negative_imbalance = EVMCurrencyAdapter::<<T as Config>::Currency, ()>::withdraw_fee(82			&who_pays_fee,83			reason,84			fee,85		)?;86		Ok(negative_imbalance.map(|i| ChargeEvmLiquidityInfo {87			who: who_pays_fee,88			negative_imbalance: i,89		}))90	}9192	fn correct_and_deposit_fee(93		who: &H160,94		corrected_fee: U256,95		already_withdrawn: Self::LiquidityInfo,96	) {97		<EVMCurrencyAdapter<<T as Config>::Currency, ()> as pallet_evm::OnChargeEVMTransaction<T>>::correct_and_deposit_fee(98			&already_withdrawn.as_ref().map(|e| e.who).unwrap_or(*who),99			corrected_fee,100			already_withdrawn.map(|e| e.negative_imbalance),101		)102	}103104	fn pay_priority_fee(tip: U256) {105		<EVMCurrencyAdapter<<T as Config>::Currency, ()> as pallet_evm::OnChargeEVMTransaction<T>>::pay_priority_fee(tip)106	}107}108109/// Implements sponsoring for evm calls performed from pallet-evm (via api.tx.ethereum.transact/api.tx.evm.call)110pub struct BridgeSponsorshipHandler<T>(PhantomData<T>);111impl<T, C> SponsorshipHandler<T::AccountId, C> for BridgeSponsorshipHandler<T>112where113	T: Config + pallet_evm::Config,114	C: IsSubType<pallet_evm::Call<T>>,115{116	fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {117		match call.is_sub_type()? {118			pallet_evm::Call::call {119				source,120				target,121				input,122				..123			} => {124				let _ = T::CallOrigin::ensure_address_origin(125					source,126					<frame_system::RawOrigin<T::AccountId>>::Signed(who.clone()).into(),127				)128				.ok()?;129				let who = T::EvmBackwardsAddressMapping::from_account_id(who.clone());130				// Effects from EvmSponsorshipHandler are applied in OnChargeEvmTransaction by pallet_evm::runner131				// TODO: Should we implement simulation mode (test, but do not apply effects) in `up-sponsorship`?132				let sponsor = frame_support::storage::with_transaction(|| {133					TransactionOutcome::Rollback(T::EvmSponsorshipHandler::get_sponsor(134						&who,135						&(*target, input.clone()),136					))137				})?;138				let sponsor = T::EvmAddressMapping::into_account_id(sponsor);139				Some(sponsor)140			}141			_ => None,142		}143	}144}