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/ERC721.bin") as &[u8],100 CollectionMode::Fungible(_) => include_bytes!("stubs/ERC20.bin") as &[u8],101 CollectionMode::ReFungible => include_bytes!("stubs/ERC1633.bin") as &[u8],102 CollectionMode::Invalid => include_bytes!("stubs/Invalid.bin") as &[u8],103 }104 .to_owned()105 })106 }107 fn call(108 source: &H160,109 target: &H160,110 gas_limit: u64,111 input: &[u8],112 value: U256,113 ) -> Option<PrecompileOutput> {114 let mut collection = map_eth_to_id(target)115 .and_then(|id| <CollectionHandle<T>>::get_with_gas_limit(id, gas_limit))?;116 let result = match collection.mode {117 CollectionMode::NFT => {118 call_internal::<UniqueNFTCall, _>(*source, &mut collection, value, input)119 }120 CollectionMode::Fungible(_) => {121 call_internal::<UniqueFungibleCall, _>(*source, &mut collection, value, input)122 }123 _ => return None,124 };125 collection.recorder.evm_to_precompile_output(result)126 }127}