1234567891011121314151617pub mod sponsoring;1819use fp_evm::PrecompileResult;20use pallet_common::{21 CollectionById,22 erc::CommonEvmHandler,23 eth::{map_eth_to_id, map_eth_to_token_id},24};25use pallet_fungible::FungibleHandle;26use pallet_nonfungible::NonfungibleHandle;27use pallet_refungible::{RefungibleHandle, erc::RefungibleTokenHandle};28use sp_std::borrow::ToOwned;29use sp_std::vec::Vec;30use sp_core::{H160, U256};31use crate::{CollectionMode, Config, dispatch::Dispatched};32use pallet_common::CollectionHandle;3334pub struct UniqueErcSupport<T: Config>(core::marker::PhantomData<T>);3536impl<T: Config> pallet_evm::OnMethodCall<T> for UniqueErcSupport<T> {37 fn is_reserved(target: &H160) -> bool {38 map_eth_to_id(target).is_some()39 }40 fn is_used(target: &H160) -> bool {41 map_eth_to_id(target)42 .map(<CollectionById<T>>::contains_key)43 .unwrap_or(false)44 }45 fn get_code(target: &H160) -> Option<Vec<u8>> {46 if let Some(collection_id) = map_eth_to_id(target) {47 let collection = <CollectionById<T>>::get(collection_id)?;48 Some(49 match collection.mode {50 CollectionMode::NFT => <NonfungibleHandle<T>>::CODE,51 CollectionMode::Fungible(_) => <FungibleHandle<T>>::CODE,52 CollectionMode::ReFungible => <RefungibleHandle<T>>::CODE,53 }54 .to_owned(),55 )56 } else if let Some((collection_id, _token_id)) = map_eth_to_token_id(target) {57 let collection = <CollectionById<T>>::get(collection_id)?;58 if collection.mode != CollectionMode::ReFungible {59 return None;60 }61 62 Some(<RefungibleTokenHandle<T>>::CODE.to_owned())63 } else {64 None65 }66 }67 fn call(68 source: &H160,69 target: &H160,70 gas_limit: u64,71 input: &[u8],72 value: U256,73 ) -> Option<PrecompileResult> {74 if let Some(collection_id) = map_eth_to_id(target) {75 let collection = <CollectionHandle<T>>::new_with_gas_limit(collection_id, gas_limit)?;76 let dispatched = Dispatched::dispatch(collection);7778 match dispatched {79 Dispatched::Fungible(h) => h.call(source, input, value),80 Dispatched::Nonfungible(h) => h.call(source, input, value),81 Dispatched::Refungible(h) => h.call(source, input, value),82 }83 } else if let Some((collection_id, token_id)) = map_eth_to_token_id(target) {84 let collection = <CollectionHandle<T>>::new_with_gas_limit(collection_id, gas_limit)?;85 if collection.mode != CollectionMode::ReFungible {86 return None;87 }8889 let handle = RefungibleHandle::cast(collection);90 91 RefungibleTokenHandle(handle, token_id).call(source, input, value)92 } else {93 None94 }95 }96}