1pub mod account;2pub mod erc;3pub mod sponsoring;45use pallet_evm_coder_substrate::call_internal;6use sp_std::borrow::ToOwned;7use sp_std::vec::Vec;8use pallet_evm::{PrecompileOutput};9use sp_core::{H160, U256};10use frame_support::storage::StorageMap;11use crate::{Config, CollectionById, CollectionHandle, CollectionId, CollectionMode};12use erc::{UniqueFungibleCall, UniqueNFTCall};1314pub struct NftErcSupport<T: Config>(core::marker::PhantomData<T>);15161718const ETH_ACCOUNT_PREFIX: [u8; 16] = [19 0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,20];2122fn map_eth_to_id(eth: &H160) -> Option<CollectionId> {23 if eth[0..16] != ETH_ACCOUNT_PREFIX {24 return None;25 }26 let mut id_bytes = [0; 4];27 id_bytes.copy_from_slice(ð[16..20]);28 Some(u32::from_be_bytes(id_bytes))29}30pub fn collection_id_to_address(id: u32) -> H160 {31 let mut out = [0; 20];32 out[0..16].copy_from_slice(Ð_ACCOUNT_PREFIX);33 out[16..20].copy_from_slice(&u32::to_be_bytes(id));34 H160(out)35}3637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485impl<T: Config> pallet_evm::OnMethodCall<T> for NftErcSupport<T> {86 fn is_reserved(target: &H160) -> bool {87 map_eth_to_id(target).is_some()88 }89 fn is_used(target: &H160) -> bool {90 map_eth_to_id(target)91 .map(<CollectionById<T>>::contains_key)92 .unwrap_or(false)93 }94 fn get_code(target: &H160) -> Option<Vec<u8>> {95 map_eth_to_id(target)96 .and_then(<CollectionById<T>>::get)97 .map(|collection| {98 match collection.mode {99 CollectionMode::NFT => include_bytes!("stubs/UniqueNFT.raw") as &[u8],100 CollectionMode::Fungible(_) => {101 include_bytes!("stubs/UniqueFungible.raw") as &[u8]102 }103 CollectionMode::ReFungible => {104 include_bytes!("stubs/UniqueRefungible.raw") as &[u8]105 }106 }107 .to_owned()108 })109 }110 fn call(111 source: &H160,112 target: &H160,113 gas_limit: u64,114 input: &[u8],115 value: U256,116 ) -> Option<PrecompileOutput> {117 let mut collection = map_eth_to_id(target)118 .and_then(|id| <CollectionHandle<T>>::get_with_gas_limit(id, gas_limit))?;119 let result = match collection.mode {120 CollectionMode::NFT => {121 call_internal::<UniqueNFTCall, _>(*source, &mut collection, value, input)122 }123 CollectionMode::Fungible(_) => {124 call_internal::<UniqueFungibleCall, _>(*source, &mut collection, value, input)125 }126 _ => return None,127 };128 collection.recorder.evm_to_precompile_output(result)129 }130}