123use crate::{Config, sponsorship::*};4use evm_coder::{Call, abi::AbiReader};5use pallet_common::{CollectionHandle, eth::map_eth_to_id};6use sp_core::H160;7use sp_std::prelude::*;8use up_sponsorship::SponsorshipHandler;9use core::marker::PhantomData;10use core::convert::TryInto;11use nft_data_structs::TokenId;12use up_evm_mapping::EvmBackwardsAddressMapping;13use pallet_evm::AddressMapping;1415use pallet_nonfungible::erc::{UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721Call};16use pallet_fungible::erc::{UniqueFungibleCall, ERC20Call};1718pub struct NftEthSponsorshipHandler<T: Config>(PhantomData<*const T>);19impl<T: Config> SponsorshipHandler<H160, (H160, Vec<u8>)> for NftEthSponsorshipHandler<T> {20 fn get_sponsor(who: &H160, call: &(H160, Vec<u8>)) -> Option<H160> {21 let collection_id = map_eth_to_id(&call.0)?;22 let collection = <CollectionHandle<T>>::new(collection_id)?;23 let sponsor = collection.sponsorship.sponsor()?.clone();24 let sponsor =25 <T as pallet_common::Config>::EvmBackwardsAddressMapping::from_account_id(sponsor);26 let who = <T as pallet_common::Config>::EvmAddressMapping::into_account_id(*who);27 let (method_id, mut reader) = AbiReader::new_call(&call.1).ok()?;28 match &collection.mode {29 crate::CollectionMode::NFT => {30 let call = UniqueNFTCall::parse(method_id, &mut reader).ok()??;31 match call {32 UniqueNFTCall::ERC721UniqueExtensions(33 ERC721UniqueExtensionsCall::Transfer { token_id, .. },34 )35 | UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, .. }) => {36 let token_id: TokenId = token_id.try_into().ok()?;37 withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)38 }39 UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {40 let token_id: TokenId = token_id.try_into().ok()?;41 withdraw_approve::<T>(&collection, &who, &token_id).map(|()| sponsor)42 }43 _ => None,44 }45 }46 crate::CollectionMode::Fungible(_) => {47 let call = UniqueFungibleCall::parse(method_id, &mut reader).ok()??;48 #[allow(clippy::single_match)]49 match call {50 UniqueFungibleCall::ERC20(51 ERC20Call::Transfer { .. } | ERC20Call::TransferFrom { .. },52 ) => withdraw_transfer::<T>(&collection, &who, &TokenId::default())53 .map(|()| sponsor),54 UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {55 withdraw_approve::<T>(&collection, &who, &TokenId::default())56 .map(|()| sponsor)57 }58 _ => None,59 }60 }61 _ => None,62 }63 }64}