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