1use crate::{AccountId, AssetId};
20
21use fp_evm::AccountProvider;
22use frame_support::{
23 ensure,
24 traits::{
25 fungible::{Balanced, Credit},
26 tokens::{fungible::Inspect, imbalance::OnUnbalanced},
27 },
28};
29use pallet_evm::OnChargeEVMTransaction;
30pub use sp_core::{H160, H256, U256};
31use sp_runtime::traits::UniqueSaturatedInto;
32use sp_std::marker::PhantomData;
33
34use pallet_assets::AssetsCallback;
35use pallet_evm_precompile_assets_erc20::AddressToAssetId;
36
37pub type EvmAddress = H160;
38
39pub const EVM_REVERT_CODE: &[u8] = &[0x60, 0x00, 0x60, 0x00, 0xfd];
41
42pub struct EvmRevertCodeHandler<A, R>(PhantomData<(A, R)>);
50impl<A, R> AssetsCallback<AssetId, AccountId> for EvmRevertCodeHandler<A, R>
51where
52 A: AddressToAssetId<AssetId>,
53 R: pallet_evm::Config,
54{
55 fn created(id: &AssetId, _: &AccountId) -> Result<(), ()> {
56 let address = A::asset_id_to_address(*id);
57 ensure!(!pallet_evm::AccountCodes::<R>::contains_key(&address), ());
59 pallet_evm::AccountCodes::<R>::insert(address, EVM_REVERT_CODE.to_vec());
60 Ok(())
61 }
62
63 fn destroyed(id: &AssetId) -> Result<(), ()> {
64 let address = A::asset_id_to_address(*id);
65 pallet_evm::AccountCodes::<R>::remove(address);
66 Ok(())
67 }
68}
69
70pub struct EVMFungibleAdapterWrapper<F, FeeHandler, TipHandler>(
80 core::marker::PhantomData<(F, FeeHandler, TipHandler)>,
81);
82impl<T, F, FeeHandler, TipHandler> OnChargeEVMTransaction<T>
83 for EVMFungibleAdapterWrapper<F, FeeHandler, TipHandler>
84where
85 T: pallet_evm::Config,
86 F: Balanced<<T::AccountProvider as AccountProvider>::AccountId>,
87 FeeHandler: OnUnbalanced<Credit<<T::AccountProvider as AccountProvider>::AccountId, F>>,
88 TipHandler: OnUnbalanced<Credit<<T::AccountProvider as AccountProvider>::AccountId, F>>,
89 U256: UniqueSaturatedInto<
90 <F as Inspect<<T::AccountProvider as AccountProvider>::AccountId>>::Balance,
91 >,
92{
93 type LiquidityInfo = Option<Credit<<T::AccountProvider as AccountProvider>::AccountId, F>>;
95
96 fn withdraw_fee(who: &H160, fee: U256) -> Result<Self::LiquidityInfo, pallet_evm::Error<T>> {
97 pallet_evm::EVMFungibleAdapter::<F, FeeHandler>::withdraw_fee(who, fee)
98 }
99
100 fn can_withdraw(who: &H160, amount: U256) -> Result<(), pallet_evm::Error<T>> {
101 pallet_evm::EVMFungibleAdapter::<F, FeeHandler>::can_withdraw(who, amount)
102 }
103
104 fn correct_and_deposit_fee(
105 who: &H160,
106 corrected_fee: U256,
107 base_fee: U256,
108 already_withdrawn: Self::LiquidityInfo,
109 ) -> Self::LiquidityInfo {
110 <pallet_evm::EVMFungibleAdapter::<F, FeeHandler> as OnChargeEVMTransaction<T>>::correct_and_deposit_fee(
111 who,
112 corrected_fee,
113 base_fee,
114 already_withdrawn,
115 )
116 }
117
118 fn pay_priority_fee(tip: Self::LiquidityInfo) {
119 if let Some(tip) = tip {
120 TipHandler::on_unbalanceds(Some(tip).into_iter());
121 }
122 }
123}