12345678910111213141516171819use core::{convert::TryInto, marker::PhantomData};20use evm_coder::{Call, abi::AbiReader};21use pallet_common::{CollectionHandle, eth::map_eth_to_id};22use pallet_evm::account::CrossAccountId;23use pallet_evm_transaction_payment::CallContext;24use pallet_nonfungible::{25 Config as NonfungibleConfig,26 erc::{27 UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721UniqueMintableCall, ERC721Call,28 TokenPropertiesCall,29 },30};31use pallet_fungible::{32 Config as FungibleConfig,33 erc::{UniqueFungibleCall, ERC20Call},34};35use pallet_refungible::Config as RefungibleConfig;36use pallet_unique::Config as UniqueConfig;37use sp_std::prelude::*;38use up_data_structs::{CollectionMode, CreateItemData, CreateNftData, TokenId};39use up_sponsorship::SponsorshipHandler;4041use crate::{Runtime, runtime_common::sponsoring::*};4243pub type EvmSponsorshipHandler = (44 UniqueEthSponsorshipHandler<Runtime>,45 pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,46);4748pub struct UniqueEthSponsorshipHandler<T: UniqueConfig>(PhantomData<*const T>);49impl<T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig>50 SponsorshipHandler<T::CrossAccountId, CallContext> for UniqueEthSponsorshipHandler<T>51{52 fn get_sponsor(53 who: &T::CrossAccountId,54 call_context: &CallContext,55 ) -> Option<T::CrossAccountId> {56 let collection_id = map_eth_to_id(&call_context.contract_address)?;57 let collection = <CollectionHandle<T>>::new(collection_id)?;58 let sponsor = collection.sponsorship.sponsor()?.clone();59 let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?;60 Some(T::CrossAccountId::from_sub(match &collection.mode {61 CollectionMode::NFT => {62 let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;63 match call {64 UniqueNFTCall::TokenProperties(TokenPropertiesCall::SetProperty {65 token_id,66 key,67 value,68 ..69 }) => {70 let token_id: TokenId = token_id.try_into().ok()?;71 withdraw_set_token_property::<T>(72 &collection,73 &who,74 &token_id,75 key.len() + value.len(),76 )77 .map(|()| sponsor)78 }79 UniqueNFTCall::ERC721UniqueExtensions(80 ERC721UniqueExtensionsCall::Transfer { token_id, .. },81 ) => {82 let token_id: TokenId = token_id.try_into().ok()?;83 withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)84 }85 UniqueNFTCall::ERC721UniqueMintable(86 ERC721UniqueMintableCall::Mint { .. }87 | ERC721UniqueMintableCall::MintCheckId { .. }88 | ERC721UniqueMintableCall::MintWithTokenUri { .. }89 | ERC721UniqueMintableCall::MintWithTokenUriCheckId { .. },90 ) => withdraw_create_item::<T>(91 &collection,92 &who,93 &CreateItemData::NFT(CreateNftData::default()),94 )95 .map(|()| sponsor),96 UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, from, .. }) => {97 let token_id: TokenId = token_id.try_into().ok()?;98 let from = T::CrossAccountId::from_eth(from);99 withdraw_transfer::<T>(&collection, &from, &token_id).map(|()| sponsor)100 }101 UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {102 let token_id: TokenId = token_id.try_into().ok()?;103 withdraw_approve::<T>(&collection, who.as_sub(), &token_id)104 .map(|()| sponsor)105 }106 _ => None,107 }108 }109 CollectionMode::Fungible(_) => {110 let call = <UniqueFungibleCall<T>>::parse(method_id, &mut reader).ok()??;111 #[allow(clippy::single_match)]112 match call {113 UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {114 withdraw_transfer::<T>(&collection, who, &TokenId::default())115 .map(|()| sponsor)116 }117 UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {118 let from = T::CrossAccountId::from_eth(from);119 withdraw_transfer::<T>(&collection, &from, &TokenId::default())120 .map(|()| sponsor)121 }122 UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {123 withdraw_approve::<T>(&collection, who.as_sub(), &TokenId::default())124 .map(|()| sponsor)125 }126 _ => None,127 }128 }129 _ => None,130 }?))131 }132}