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_common::account::CrossAccountId;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::CrossAccountId::from_eth(*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 let token_id: TokenId = token_id.try_into().ok()?;36 withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)37 }38 UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, from, .. }) => {39 let token_id: TokenId = token_id.try_into().ok()?;40 let from = T::CrossAccountId::from_eth(from);41 withdraw_transfer::<T>(&collection, &from, &token_id).map(|()| sponsor)42 }43 UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {44 let token_id: TokenId = token_id.try_into().ok()?;45 withdraw_approve::<T>(&collection, who.as_sub(), &token_id)46 .map(|()| sponsor)47 }48 _ => None,49 }50 }51 crate::CollectionMode::Fungible(_) => {52 let call = UniqueFungibleCall::parse(method_id, &mut reader).ok()??;53 #[allow(clippy::single_match)]54 match call {55 UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {56 withdraw_transfer::<T>(&collection, &who, &TokenId::default())57 .map(|()| sponsor)58 }59 UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {60 let from = T::CrossAccountId::from_eth(from);61 withdraw_transfer::<T>(&collection, &from, &TokenId::default())62 .map(|()| sponsor)63 }64 UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {65 withdraw_approve::<T>(&collection, who.as_sub(), &TokenId::default())66 .map(|()| sponsor)67 }68 _ => None,69 }70 }71 _ => None,72 }73 }74}